Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 127
Domain
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 8
1640
0.00% covered (danger)
0.00%
0 / 127
 getDomain
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 1
 setDomain
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 check
0.00% covered (danger)
0.00%
0 / 1
210
0.00% covered (danger)
0.00%
0 / 43
 checkbulk
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 6
 getSuggestions
0.00% covered (danger)
0.00%
0 / 1
72
0.00% covered (danger)
0.00%
0 / 33
 getAuthCode
0.00% covered (danger)
0.00%
0 / 1
72
0.00% covered (danger)
0.00%
0 / 24
 getIDNLanguage
0.00% covered (danger)
0.00%
0 / 1
12
0.00% covered (danger)
0.00%
0 / 13
 getNameservers
0.00% covered (danger)
0.00%
0 / 1
12
0.00% covered (danger)
0.00%
0 / 5
1<?php
2
3/**
4 * CNIC\HEXONET
5 * Copyright © CentralNic Group PLC
6 */
7
8namespace CNIC\HEXONET;
9
10use CNIC\HEXONET\ResponseTemplateManager as RTM;
11use CNIC\HEXONET\Logger as L;
12
13/**
14 * HEXONET API Client
15 *
16 * @package CNIC\HEXONET
17 */
18
19class Domain extends ApiObject
20{
21    /**
22     * IDN Lanuage
23     * @var array|null
24     */
25    protected $idnLanguage = null;
26
27    /**
28     * Get the Domain Name
29     * @return string
30     */
31    public function getDomain()
32    {
33        return $this->id;
34    }
35    /**
36     * Set the Domain Name
37     * @param string $domain
38     * @return $this
39     */
40    public function setDomain($domain)
41    {
42        $this->setId($domain);
43        return $this->setClass("DOMAIN");
44    }
45    /**
46     * Get Availability Check results for a given list of domain names
47     * @param array $grp list of domain names
48     * @param bool $premiumEnabled toggle premium domain check on/off
49     * @return array
50     */
51    private function check($grp, $premiumEnabled)
52    {
53        $r = $this->cl->request([
54            "COMMAND" => "CheckDomains",
55            "PREMIUMCHANNELS" => $premiumEnabled ? "*" : "",
56            "DOMAIN" => $grp
57        ]);
58        // prefill with default data
59        $results = array_fill(0, count($grp), [
60            "REASON" => "",
61            "CLASS" => "",
62            "CURRENCY" => "",
63            "PRICE" => "",
64            "PREMIUMCHANNEL" => "",
65            "DOMAINCHECK" => "421 Temporary issue",
66            "STATUS" => "UNKNOWN",
67            "ISPREMIUM" => false
68        ]);
69        // add domain, sld, tld
70        array_walk($results, function (&$sr, $idx, $grp) {
71            $sr["DOMAIN"] = $grp[$idx];
72            list(
73                $sr["SLD"],
74                $sr["TLD"]
75            ) = explode(".", $grp[$idx], 2);
76        }, $grp);
77        // command failed, goodbye
78        if (!$r->isSuccess()) {
79            return $results;
80        }
81        // command succeeded
82        array_walk($results, function (&$sr, $idx, $r) {
83            $rec = $r->getRecord($idx);
84            if (is_null($rec)) {
85                return;
86            }
87            // replace row defaults with API Data
88            $sr = array_merge($sr, $rec->getData());
89            if (empty($sr["DOMAINCHECK"])) {
90                $sr["DOMAINCHECK"] = "421 Temporary issue";
91            }
92
93            // set availability status
94            $code = (int)substr($sr["DOMAINCHECK"], 0, 3);
95            $check = substr($sr["DOMAINCHECK"], 3);
96
97            // TLD not supported at HEXONET or check failed
98            // e.g. WHMCS does fallback to whois lookup
99            if ($code === 549) {
100                $sr["STATUS"] = "NOTSUPPORTED";
101                return;
102            }
103
104            //DOMAIN AVAILABLE
105            if ($code === 210) {
106                $sr["STATUS"] = "AVAILABLE";
107                return;
108            }
109
110            if ($code === 211) {
111                // $sr::STATUS_REGISTERED already set
112                // PREMIUM DOMAINS
113                $sr["STATUS"] = "NOTAVAILABLE";
114                $sr["ISPREMIUM"] = preg_match("/^PREMIUM_/i", $sr["CLASS"]);
115                if (
116                    // DOMAIN BLOCKS
117                    stripos($sr["REASON"], "block")
118                    // RESERVER DOMAIN NAMES
119                    || stripos($sr["REASON"], "reserved")
120                    // NXD DOMAINS
121                    || preg_match("/^collision domain name available \{/i", $check)
122                ) {
123                    $sr["STATUS"] = "RESERVED";
124                    return;
125                }
126
127                if (
128                    empty($sr["PREMIUMCHANNEL"])
129                    || !$sr["ISPREMIUM"]
130                    || !preg_match("/^premium domain name available/i", $check)
131                ) {
132                    return;
133                }
134                // CASE: PREMIUM / PREMIUM AFTERMARKET
135                // available premium domain
136                // ----------------------------------------------------
137                // TODO premium domain price calculation
138                // ----------------------------------------------------
139                /*try {
140                    $prices = ispapi_GetPremiumPrice($params);
141                    $sr["price"] = var_export($prices, true);
142                    $sr->setPremiumCostPricing($prices);
143                    // TODO why prices empty?
144                    if (isset($prices["register"])) {
145                        //PREMIUM DOMAIN AVAILABLE
146                        $sr->setStatus($sr::STATUS_NOT_REGISTERED);
147                    }
148                } catch (\Exception $e) {
149                    $sr->setPremiumCostPricing([]);
150                    $sr->setStatus($sr::STATUS_RESERVED);
151                }*/
152            }
153        }, $r);
154        return $results;
155    }
156    /**
157     * Perform Bulk Availability Check
158     * @param array $domains list of domain names
159     * @param bool $premiumEnabled toggle for premium data/check, by default false
160     * @return array
161     */
162    public function checkbulk($domains, $premiumEnabled = false)
163    {
164        $maxSearchGroupSize = $this->cl->settings["maxSearchGroupSize"];
165        $query = array_map("mb_strtolower", $domains);
166        $results = [];
167        foreach (array_chunk($domains, $maxSearchGroupSize) as $grp) {
168            $results = array_merge($results, $this->check($grp, $premiumEnabled));
169        }
170        return array_change_key_case($results, CASE_LOWER);
171    }
172    /**
173     * Get List of Domain Name Suggestions
174     * @param string $searchTerm keyword of the search
175     * @param array $tlds List of TLDs to include
176     * @param bool $premiumEnabled toggle for premium data/check, by default false
177     * @param array $settings Suggestion Engine settings
178     * @return array
179     */
180    public function getSuggestions($searchTerm, $tlds, $premiumEnabled = false, $settings = [])
181    {
182        // build zone list parameter
183        $zones = array_filter($tlds, function ($tld) use ($settings) {
184            // IGNORE 3RD LEVEL TLDS - NOT FULLY SUPPORTED BY QueryDomainSuggestionList
185            // Suppress .com, .net by configuration
186            return (
187                !preg_match("/\./", $tld)
188                && (
189                    empty($settings["suppressWeigthed"])
190                    || !preg_match("/^(com|net)$/", $tld)
191                )
192            );
193        });
194
195        // identify maximum no. of results
196        $maxDNSuggestions = $this->cl->settings["maxDNSuggestions"];
197        $limit = (
198            !isset($settings["suggestionsLimit"])
199            || $maxDNSuggestions < $settings["suggestionsLimit"]
200        ) ? $maxDNSuggestions : $settings["suggestionsLimit"];
201
202        // request domain name suggestions from engine
203        $first = 0;
204        $command = [
205            "COMMAND" => "QueryDomainSuggestionList",
206            "KEYWORD" => $searchTerm,
207            "ZONE" => $zones,
208            "SOURCE" => "ISPAPI-SUGGESTIONS",
209            "LIMIT" => $limit
210        ];
211        $dnsuggestions = [];
212        do {
213            $command["FIRST"] = $first;
214            $r = $this->cl->request($command);
215            if (!$r->isSuccess()) {
216                break;
217            }
218            $col = $r->getColumn("DOMAIN");
219            if (is_null($col)) {
220                break;
221            }
222            $dnsuggestions = array_merge(
223                $dnsuggestions,
224                array_values( // re-index
225                    array_unique( // filter duplicates
226                        array_filter( // remove empty entries
227                            $col->getData()
228                        )
229                    )
230                )
231            );
232            $first += $limit;
233        } while (
234            (count($dnsuggestions) < $limit)
235            && ($r->getRecordsTotalCount() > $first)
236        );
237
238        // check the availability, as also taken/reserved/blocked domains could be returned
239        return $this->checkbulk($dnsuggestions, $premiumEnabled);
240    }
241
242    /**
243     * Get the domain's assigned auth code.
244     * @return array
245     */
246    public function getAuthCode()
247    {
248        // Expiring Authorization Codes
249        // https://confluence.centralnic.com/display/RSR/Expiring+Authcodes
250        if (preg_match("/\.de$/i", $this->id)) {
251            $r = $this->cl->request([
252                "COMMAND" => "DENIC_CreateAuthInfo1",
253                "DOMAIN" => $this->id
254            ]);
255        } elseif (preg_match("/\.(eu|be)$/i", $this->id)) {
256            $r = $this->cl->request([
257                "COMMAND" => "RequestDomainAuthInfo",
258                "DOMAIN" => $this->id
259            ]);
260            // TODO -> PENDING = 1|0
261        } else {
262            // default case for all other tlds
263            $r = $this->status;
264        }
265
266        // check response
267        if ($r->isSuccess()) {
268            if (
269                preg_match("/\.(fi|nz)$/i", $this->id)
270                && $r->getColumnIndex("TRANSFERLOCK", 0) === "1"
271            ) {
272                return [
273                    "success" => false,
274                    "reason" => "LOCKED"
275                ];
276            }
277            $col = $r->getColumn("AUTH");
278            if (is_null($col)) {
279                return [
280                    "success" => false,
281                    "reason" => "SENDTOREGISTRANT"
282                ];
283            }
284            if (!strlen($col->getDataByIndex(0))) {
285                return [
286                    "success" => false,
287                    "reason" => "CONTACTSUPPORT"
288                ];
289            }
290            return [
291                "success" => true,
292                "eppcode" => $col->getDataByIndex(0)
293            ];
294        }
295        return [
296            "success" => false,
297            "reason" => "ERROR",
298            "description" => $r->getDescription(),
299            "code" => $r->getCode()
300        ];
301    }
302
303    /**
304     * Get IDN Language
305     * @return array
306     */
307    private function getIDNLanguage()
308    {
309        if (isset($this->idnLanguage)) {
310            $r = $this->cl->request([
311                "COMMAND" => "CheckIDNLanguage",
312                "DOMAIN" => $this->id
313            ]);
314            if ($r->isSuccess()) {
315                $this->idnLanguage = [
316                    "success" => true,
317                    "language" => strtolower($r->getColumnIndex("LANGUAGE", 0))
318                ];
319            } else {
320                $this->idnLanguage = [
321                    "success" => false,
322                    "reason" => $r->getDescription(),
323                    "code" => $r->getCode()
324                ];
325            }
326        }
327        return $this->idnLanguage;
328    }
329
330    /**
331     * Get List of assigned Nameservers
332     * @return array
333     */
334    public function getNameservers()
335    {
336        if ($this->status->isSuccess()) {
337            $col = $this->status->getColumn("NAMESERVER");
338            if (!is_null($col)) {
339                return $col->getData();
340            }
341        }
342        return [];
343    }
344}