Example code
The code for this domain module can be found in:
/custom/modules/HwCpsDatensysteme/Domain/HwCpsDatensystemeDomainHandlerFor each domain module, you have a php class, for example the HwCpsDatensystemeDomainHandler.php.
Example (CPS Datensysteme)
<?php
namespace custom\modules\HwCpsDatensysteme\Domain;
use App\Enums\Domain\ContactSexEnum;
use App\Enums\Domain\ContactTypeEnum;
use App\Exceptions\CouldNotCreateDomainContact;
use App\Exceptions\InvalidAuthInfo;
use App\Exceptions\StorefrontException;
use App\Framework\Core\ConfigService;
use App\Framework\Core\Hosting\Domain\DnsRecordItem;
use App\Framework\Core\Hosting\Domain\DomainHandlerAbstract;
use App\Framework\Core\Hosting\Domain\DomainHandlerInterface;
use App\Framework\Core\Hosting\Domain\DomainSyncItem;
use App\Framework\Core\Hosting\Domain\PriceSyncItem;
use App\Framework\Core\Hosting\Domain\Responses\DomainAuthcodeResponse;
use App\Framework\Core\Hosting\Domain\Responses\DomainCheckResponse;
use App\Framework\Core\Hosting\Domain\Responses\DomainDeletedResponse;
use App\Framework\Core\Hosting\Domain\Responses\DomainNameserverResponse;
use App\Framework\Core\Hosting\Domain\Responses\DomainRegisteredResponse;
use App\Framework\Core\Hosting\Domain\Responses\DomainSyncResponse;
use App\Framework\Core\Hosting\Domain\Responses\DomainSyncStatusEnum;
use App\Framework\Core\Hosting\Domain\Responses\DomainTransferredResponse;
use App\Framework\Core\Hosting\Domain\Responses\DomainTransferSyncResponse;
use App\Framework\Core\Hosting\Domain\Whois\WhoisService;
use App\Models\Domain\Domain;
use App\Models\Domain\DomainContact;
use Carbon\Carbon;
use Exception;
use custom\modules\HwCpsDatensysteme\Domain\lib\ApiClient;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberUtil;
use Throwable;
class HwCpsDatensystemeDomainHandler extends DomainHandlerAbstract implements DomainHandlerInterface {
public static $cps;
public bool $supportsHandleFilter = true;
public bool $supportsDnsPriorityField = true;
public bool $cacheGetDomainResponse = false;
public function __construct(?int $salesChannelId = null) {
parent::__construct($salesChannelId);
}
public array $availableTypes = [
'A' => 'A',
'AAAA' => 'AAAA',
'CAA' => 'CAA',
'CNAME' => 'CNAME',
'MX' => 'MX',
'SRV' => 'SRV',
'TXT' => 'TXT'
];
public function checkDomain(string $sld, string $tld): ?DomainCheckResponse
{
try {
// Cache for 1 Hour
$response = Cache::remember('hwcps_rdap_check_' . $sld . '.' . $tld, 1 * 60 * 60, function () use ($sld, $tld) {
$ch = curl_init("https://rdap.cps-datensysteme.de/check/{$sld}.{$tld}");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_USERPWD => $this->config['rdap_user'] . ':' . $this->config['rdap_password'],
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_TIMEOUT => 30,
]);
return json_decode(curl_exec($ch));
});
return new DomainCheckResponse(
$response->is_available,
null,
"HwCpsDatensysteme_RDAP"
);
} catch (Exception|Throwable $e) {
$response = app(WhoisService::class)->checkDomain($sld, $tld);
$response->checker = "WhoisService_Backup";
return $response;
}
}
public function getPrices(): array {
$xml = <<<XML
<?xml version="1.0" encoding="utf-8" ?>
<request>
{$this->getXmlHeader()}
<transaction>
<report>
<group>account</group>
<data_type>csv</data_type>
</report>
</transaction>
</request>
XML;
$explodedresponse = Cache::remember('hwcps_prices', 5 * 60, function () use ($xml) {
$response = $this->getClient()->callreportRaw($xml, $this->config['sandbox']);
return explode("\n", $response->result->detail->report->pricing->data);
});
$priceSyncItems = [];
$priceitems = [];
foreach ($explodedresponse as $singlePrice) {
$values = explode(";", $singlePrice);
if ($values[0] == "") continue;
$tldstring = explode(".", $values[3]);
$tld = strtolower($tldstring[1] ?? "");
if (!isset($priceitems[$tld])) {
$priceitems[$tld] = [];
$priceitems[$tld]['tld'] = $tld;
}
if ($values[10] == "create" && $values[11] == "domain") {
$priceitems[$tld]['create'] = $values[16];
}
if ($values[10] == "renew" && $values[11] == "domain") {
$priceitems[$tld]['renew'] = $values[16];
}
if ($values[10] == "transfer" && $values[11] == "domain") {
$priceitems[$tld]['transfer'] = $values[16];
}
if ($values[10] == "create" && $values[11] == "restore") {
$priceitems[$tld]['restore'] = $values[16];
}
if ($values[10] == "modify" && $values[11] == "domain") {
$priceitems[$tld]['modify'] = $values[16];
}
}
foreach ($priceitems as $singlePriceItem) {
if (str_contains($singlePriceItem['tld'], " ") || $singlePriceItem['tld'] === "") {
continue;
}
$priceSyncItems[] = new PriceSyncItem(
$singlePriceItem['tld'],
$singlePriceItem['create'] ?? 0,
$singlePriceItem['renew'] ?? 0,
$singlePriceItem['transfer'] ?? 0,
0,
$singlePriceItem['modify'] ?? 0,
$singlePriceItem['restore'] ?? 0,
);
}
return $priceSyncItems;
}
public function syncDomains(Collection $domains): array {
$responseData = [];
$xml = <<<XML
<?xml version="1.0" encoding="utf-8" ?>
<request>
{$this->getXmlHeader()}
<transaction>
<report>
<group>domain</group>
<data_type>csv</data_type>
</report>
</transaction>
</request>
XML;
$response = $this->getClient()->callreportRaw($xml, $this->config['sandbox']);
$explode = explode("\n", $response->result->detail->report->domain->data);
foreach ($explode as $domainItem) {
$domainItemExploded = explode(';', $domainItem);
if ($domainItemExploded[0] == 'domain') continue;
if ($domainItemExploded[0] == '') continue;
$allDomainsStructured[strtolower($domainItemExploded[0])] = $domainItemExploded;
}
foreach ($domains as $domain) {
$resItem = $allDomainsStructured[strtolower($domain->fqdn)] ?? $allDomainsStructured[strtolower($domain->punycode_fqdn)] ?? null;
if ($resItem === null) {
$responseData[$domain->id] = new DomainSyncResponse(DomainSyncStatusEnum::INACTIVE);
continue;
}
// dump($resItem);
// DNS sec active:
// $resItem[30] !== "not found"
$responseData[$domain->id] = new DomainSyncResponse(
DomainSyncStatusEnum::ACTIVE,
$resItem[16] === "active",
Carbon::parse($resItem[10]),
Carbon::parse($resItem[7]),
$resItem[14] === "active",
);
}
// dd($responseData);
return $responseData;
}
public function register(Domain $domain, array $nameservers, DomainContact $ownerC, DomainContact $adminC, DomainContact $techC, DomainContact $zoneC): DomainRegisteredResponse {
/**
* Nameservers.
*/
$ns[] = $nameservers[0] ?? "";
$ns[] = $nameservers[1] ?? "";
$ns[] = $nameservers[2] ?? "";
$ns[] = $nameservers[3] ?? "";
$ns[] = $nameservers[4] ?? "";
$nsstring = '';
foreach ($ns as $value) {
if ($value != '') {
$nsstring .= '<dns>
<hostname>' . $value . '</hostname>
</dns>';
}
}
// get the actual handles from the contacts
$ownerC = $this->getDomainHandle($ownerC);
$adminC = $this->getDomainHandle($adminC);
$techC = $this->getDomainHandle($techC);
$zoneC = $this->getDomainHandle($zoneC);
$xml = <<<XML
<?xml version="1.0" encoding="utf-8" ?>
<request>
{$this->getXmlHeader()}
<transaction>
<group>domain</group>
<action>create</action>
<attribute>domain</attribute>
<object>{$domain->punycode_fqdn}</object>
<values>
{$nsstring}
<adminc>{$adminC}</adminc>
<techc>{$techC}</techc>
<billc>{$zoneC}</billc>
<ownerc>{$ownerC}</ownerc>
</values>
</transaction>
</request>
XML;
try {
$response = $this->getClient()->callRaw($xml, $this->config['sandbox']);
} catch (Exception $e) {
if(str_contains($e->getMessage(), "domain already maintained by registrar")) {
// Handle as registered
return new DomainRegisteredResponse($domain->fqdn);
}
throw $e;
}
// dd($response);
if ($response->result->code != "1000") {
throw new Exception("Got API error: " . implode(", ", $response->result->message));
}
return new DomainRegisteredResponse(
$domain->sld . '.' . $domain->tld,
);
}
public function createZone(Domain $domain, array $nameservers) {
$xml = <<<XML
<?xml version="1.0" encoding="utf-8" ?>
<request>
{$this->getXmlHeader()}
<transaction>
<group>dns</group>
<action>create</action>
<attribute>managed</attribute>
<object>{$domain->punycode_fqdn}</object>
<values>
{$this->_getZoneXml($domain)}
</values>
</transaction>
</request>
XML;
$this->getClient()->callRaw($xml, $this->config['sandbox']);
}
private function _getZoneXml(Domain $domain) {
$primaryNs = $domain->nameservers[0];
$nsstring = "";
foreach (array_filter($domain->nameservers) as $value) {
$nsstring .= '<ns>' . $value . '</ns>';
}
$defaultTtl = 600;
try {
$defaultTtl = app(ConfigService::class)->get('core.domain.default_ttl', $domain->sales_channel_id, 600);
} catch (Exception $e) {
}
return "{$nsstring}
<soa>
<ttl>{$defaultTtl}</ttl>
<primary_ns>{$primaryNs}</primary_ns>
</soa>";
}
public function transfer(Domain $domain, array $nameservers, DomainContact $ownerC, DomainContact $adminC, DomainContact $techC, DomainContact $zoneC): DomainTransferredResponse {
// throw new Exception("test");
/**
* Nameservers.
*/
$ns[] = $nameservers[0] ?? "";
$ns[] = $nameservers[1] ?? "";
$ns[] = $nameservers[2] ?? "";
$ns[] = $nameservers[3] ?? "";
$ns[] = $nameservers[4] ?? "";
$nsstring = '';
foreach ($ns as $value) {
if ($value != '') {
$nsstring .= '<dns>
<hostname>' . $value . '</hostname>
</dns>';
}
}
// get the actual handles from the contacts
$ownerC = $this->getDomainHandle($ownerC);
$adminC = $this->getDomainHandle($adminC);
$techC = $this->getDomainHandle($techC);
$zoneC = $this->getDomainHandle($zoneC);
$auth = htmlspecialchars($domain->transfer_authcode);
$xml = <<<XML
<?xml version="1.0" encoding="utf-8" ?>
<request>
{$this->getXmlHeader()}
<transaction>
<group>domain</group>
<action>transfer</action>
<attribute>domain</attribute>
<object>{$domain->punycode_fqdn}</object>
<values>
{$nsstring}
<adminc>{$adminC}</adminc>
<techc>{$techC}</techc>
<billc>{$zoneC}</billc>
<ownerc>{$ownerC}</ownerc>
<auth_info>{$auth}</auth_info>
</values>
</transaction>
</request>
XML;
try {
$response = $this->getClient()->callRaw($xml, $this->config['sandbox']);
} catch (Exception $e) {
if (str_contains($e->getMessage(), "AuthInfo does not match")) {
throw new InvalidAuthInfo();
}
throw $e;
}
Log::debug("CPS transfer response", [
'response' => (array)$response,
"message" => (string)$response->result->message,
"code" => (string)$response->result->code,
]);
if (str_contains((string)$response->result->message, "AuthInfo does not match")) {
throw new InvalidAuthInfo();
}
if (!in_array((string)$response->result->code, ["1000", "1001"])) {
throw new Exception("Got API error: " . implode(", ", $response->result->message));
}
return new DomainTransferredResponse(
$domain->sld . '.' . $domain->tld,
null,
strtotime('+1 year', strtotime($response->transaction->created)),
);
}
public function syncTransfer(Domain $domain): DomainTransferSyncResponse {
$xml = <<<XML
<?xml version="1.0" encoding="utf-8" ?>
<request>
{$this->getXmlHeader()}
<transaction>
<group>domain</group>
<action>info</action>
<attribute>domain</attribute>
<object>{$domain->punycode_fqdn}</object>
</transaction>
</request>
XML;
try {
$response = $this->getClient()->callRaw($xml, $this->config['sandbox']);
} catch (Exception $e) {
return new DomainTransferSyncResponse(
false,
null,
true,
$e->getMessage()
);
}
/**
* Transfer is still pending
*/
try {
if (((array)$response->result->detail->values->transaction_lock_status)[0] === "pendingTransfer") {
return new DomainTransferSyncResponse(
false
);
}
} catch (Throwable $e) {
}
return new DomainTransferSyncResponse(
true,
Carbon::parse($response->expire),
);
}
public function getAuthcode(Domain $domain): DomainAuthcodeResponse {
$xml = <<<XML
<?xml version="1.0" encoding="utf-8" ?>
<request>
{$this->getXmlHeader()}
<transaction>
<group>domain</group>
<action>info</action>
<attribute>domain</attribute>
<object>{$domain->punycode_fqdn}</object>
</transaction>
</request>
XML;
$response = $this->getClient()->callRaw($xml, $this->config['sandbox']);
$eppCode = (string)$response->result->detail->values->auth_info;
$transferLock = (string)$response->result->detail->values->transfer_lock;
if ($eppCode == '' && $transferLock == 'disabled') {
throw new StorefrontException('Authcode is not available for this domain');
} elseif ($transferLock == 'active') {
throw new StorefrontException('Transferlock is active. Please disable to view the authcode.');
}
return new DomainAuthcodeResponse($eppCode);
}
public function setTransferLock(Domain $domain, bool $transferLockEnabled) {
$status = $transferLockEnabled ? "active" : "disabled";
$xml = <<<XML
<?xml version="1.0" encoding="utf-8" ?>
<request>
{$this->getXmlHeader()}
<transaction>
<group>domain</group>
<action>modify</action>
<attribute>transfer_lock</attribute>
<object>{$domain->punycode_fqdn}</object>
<values>
<status>{$status}</status>
</values>
</transaction>
</request>
XML;
$this->getClient()->callRaw($xml, $this->config['sandbox']);
}
public function delete(Domain $domain): DomainDeletedResponse {
$postfields = [
'customerNumber' => $this->config['cnumber'],
'password' => $this->config['password'],
'testMode' => $this->config['sandbox'] ? 'on' : 'off',
'user' => $this->config['user'],
'domain' => $domain->sld . '.' . $domain->tld,
];
try {
$response = $this->getClient()->call('domainDelete', $postfields);
} catch (Exception|Throwable $e) {
if (!$this->shouldTreatDeleteNotActiveAsSuccess($e)) {
throw $e;
}
}
try {
$xml = <<<XML
<?xml version="1.0" encoding="utf-8" ?>
<request>
{$this->getXmlHeader()}
<transaction>
<group>dns</group>
<action>delete</action>
<attribute>managed</attribute>
<object>{$domain->punycode_fqdn}</object>
</transaction>
</request>
XML;
$this->getClient()->callRaw($xml, $this->config['sandbox']);
} catch (Exception|Throwable $e) {
// Silence
}
return new DomainDeletedResponse();
}
private function shouldTreatDeleteNotActiveAsSuccess(Throwable $e): bool
{
if (empty($this->config['deleteNotActiveAsSuccess'])) {
return false;
}
$message = $e->getMessage();
return Str::contains($message, [
'domain not active within this user account',
'Die Domain wird nicht vom anfragenden User verwaltet oder existiert nicht',
]);
}
public function getDns(Domain $domain): ?array {
try {
$xml = <<<XML
<?xml version="1.0" encoding="utf-8" ?>
<request>
{$this->getXmlHeader()}
<transaction>
<group>dns</group>
<action>info</action>
<attribute>dnszone_records</attribute>
<object>{$domain->punycode_fqdn}</object>
</transaction>
</request>
XML;
$response = $this->getClient()->callRaw($xml, $this->config['sandbox']);
} catch (Exception $e) {
if (config('app.debug')) throw $e;
Log::error($e);
return null;
}
$index = 0;
$output = [];
foreach ((array)$response->result->detail->values as $type => $items) {
$items = (array)$items;
if (!in_array(strtoupper($type), $this->availableTypes)) {
continue;
}
if (isset($items['rr_value'])) {
$items = [$items];
}
foreach ($items as $item) {
$item = (array)$item;
$output[$index] = new DnsRecordItem(
$index,
strtoupper($type),
$item['rr_name'],
$item['rr_value'],
null,
$item['rr_preference'] ?? null,
);
$index++;
}
}
return $output;
}
public function saveDns(Domain $domain, array $records) {
$recordString = "";
/** @var DnsRecordItem $recordItem */
foreach ($records as $recordItem) {
$type = strtolower($recordItem->type);
$priority = "";
if($recordItem->type === "MX" || $recordItem->type === "SRV") {
$priority = "<rr_preference>{$recordItem->priority}</rr_preference>";
}
$preference = "";
$recordString .= "<{$type}>
<rr_name>{$recordItem->hostname}</rr_name>
<rr_value>{$recordItem->content}</rr_value>
{$priority}
</{$type}>";
}
$recordString = trim(preg_replace('/[\t\r\n]/', '', $recordString));
$xml = <<<XML
<?xml version="1.0" encoding="utf-8" ?>
<request>
{$this->getXmlHeader()}
<transaction>
<group>dns</group>
<action>modify</action>
<attribute>managed</attribute>
<object>{$domain->punycode_fqdn}</object>
<values>
{$this->_getZoneXml($domain)}
{$recordString}
</values>
</transaction>
</request>
XML;
// try {
$this->getClient()->callRaw($xml, $this->config['sandbox']);
// } catch (Exception $e) {
// dd($e->getMessage());
// }
}
public function deleteDns(Domain $domain, DnsRecordItem $record) {
$currentDns = $this->getDns($domain);
$wasFound = false;
foreach ($currentDns as $index => $currentDnsRecord) {
if($currentDnsRecord->type === $record->type && $currentDnsRecord->hostname === $record->hostname) {
$wasFound = true;
unset($currentDns[$index]);
}
}
if(!$wasFound) {
throw new Exception("hostware-IX: Could not determine the original dns record. Please contact support!");
}
$this->saveDns($domain, $currentDns);
}
public function createDns(Domain $domain, DnsRecordItem $record, array $multipleRecords = []) {
$currentDns = $this->getDns($domain);
if(count($multipleRecords) > 0) {
/**
* Special Treatment for CPS rate limit for DNS templates
*/
foreach ($multipleRecords as $additionalRecord) {
$currentDns[] = $additionalRecord;
}
} else {
/**
* Add and save the record to the existing ones
*/
$currentDns[] = $record;
}
$this->saveDns($domain, $currentDns);
}
public function updateDns(Domain $domain, DnsRecordItem $originalRecord, DnsRecordItem $updatedRecord) {
$currentDns = $this->getDns($domain);
$wasFound = false;
foreach ($currentDns as $index => $currentDnsRecord) {
if($currentDnsRecord->type === $originalRecord->type && $currentDnsRecord->hostname === $originalRecord->hostname) {
$wasFound = true;
unset($currentDns[$index]);
}
}
if(!$wasFound) {
throw new Exception("hostware-IX: Could not determine the original dns record. Please contact support!");
}
$currentDns[] = $updatedRecord;
$this->saveDns($domain, $currentDns);
}
public function getNameservers(Domain $domain): DomainNameserverResponse {
$xml = <<<XML
<?xml version="1.0" encoding="utf-8" ?>
<request>
{$this->getXmlHeader()}
<transaction>
<group>domain</group>
<action>info</action>
<attribute>domain</attribute>
<object>{$domain->punycode_fqdn}</object>
</transaction>
</request>
XML;
$response = $this->getClient()->callRaw($xml, $this->config['sandbox']);
return new DomainNameserverResponse(
$response->result->detail->values->dns[0]->hostname,
$response->result->detail->values->dns[1]->hostname,
$response->result->detail->values->dns[2]->hostname,
$response->result->detail->values->dns[3]->hostname,
$response->result->detail->values->dns[4]->hostname
);
}
private function _getNameservers(array $nameservers) {
$dnsString = '';
foreach ($nameservers as $value) {
if ($value != '') {
$dnsString .= '<dns><hostname>' . $value . '</hostname></dns>
';
}
}
return $dnsString;
}
public function saveNameservers(Domain $domain, array $nameservers) {
$dnsString = $this->_getNameservers($nameservers);
$postfields = [
'customerNumber' => $this->config['cnumber'],
'password' => $this->config['password'],
'testMode' => $this->config['sandbox'] ? 'on' : 'off',
'user' => $this->config['user'],
'domain' => $domain->punycode_fqdn,
'ns' => $dnsString
];
$response = $this->getClient()->call('domainInfo', $postfields);
$adminC = (string)$response->result->detail->values->adminc;
$billc = (string)$response->result->detail->values->billc;
$ownerc = (string)$response->result->detail->values->ownerc;
$techc = (string)$response->result->detail->values->techc;
$postfields['adminc'] = $adminC;
$postfields['billc'] = $billc;
$postfields['ownerc'] = $ownerc;
$postfields['techc'] = $techc;
$this->getClient()->call('changeNameservers', $postfields);
}
public function updateDomainHandles(Domain $domain, DomainContact $ownerC, DomainContact $adminC, DomainContact $techC, DomainContact $zoneC) {
// get the actual handles from the contacts
$ownerC = $this->getDomainHandle($ownerC);
$adminC = $this->getDomainHandle($adminC);
$techC = $this->getDomainHandle($techC);
$zoneC = $this->getDomainHandle($zoneC);
$xml = <<<XML
<?xml version="1.0" encoding="utf-8" ?>
<request>
{$this->getXmlHeader()}
<transaction>
<group>domain</group>
<action>modify</action>
<attribute>domain</attribute>
<object>{$domain->punycode_fqdn}</object>
<values>
<adminc>{$adminC}</adminc>
<techc>{$techC}</techc>
<billc>{$zoneC}</billc>
<ownerc>{$ownerC}</ownerc>
{$this->_getNameservers($domain->nameservers)}
</values>
</transaction>
</request>
XML;
// dd($xml);
$response = $this->getClient()->callRaw($xml, $this->config['sandbox']);
if ($response->result->code != "1000") {
throw new Exception("Got API error: " . implode(", ", $response->result->message));
}
}
public function getDomainPageSize(): ?int {
return 250;
}
public function getDomains(): ?array {
// return [];
// dd($this->getDomainsOwnerHandle);
$postfields = [
'customerNumber' => $this->config['cnumber'],
'password' => $this->config['password'],
'testMode' => $this->config['sandbox'] ? 'on' : 'off',
'user' => $this->config['user'],
];
$explode = Cache::remember("hw-CPS-listDomains", 60 * 5, function () use ($postfields) {
$response = $this->getClient()->callreport('listDomains', $postfields);
return explode("\n", $response->result->detail->report->domain->data);
});
$this->getDomainsTotalCount = count($explode);
$explode = array_slice($explode, ($this->getDomainsPage - 1) * $this->getDomainPageSize(), $this->getDomainPageSize());
/**
* Get all domain handles
*/
$xml = <<<XML
<?xml version="1.0" encoding="utf-8" ?>
<request>
{$this->getXmlHeader()}
<transaction>
<report>
<group>contact</group>
<data_type>csv</data_type>
</report>
</transaction>
</request>
XML;
$explodedresponse = Cache::remember("hw-CPS-contactCsv", 60 * 5, function () use ($xml) {
$response = $this->getClient()->callreportRaw($xml, $this->config['sandbox']);
return explode("\n", $response->result->detail->report->contact->data);
});
$contacts = collect([]);
foreach ($explodedresponse as $lineItem) {
$lineItem = explode(";", $lineItem);
if($lineItem[0] === "cid") continue;
if(count($lineItem) !== 16) continue;
// dd($lineItem);
$contacts->add($this->_getContactFromHandle($lineItem));
}
$contacts = $contacts->keyBy(function ($item) {
return (string)$item->getAttributes()['id'];
});
$output = [];
foreach ($explode as $domainItem) {
$domainItemExploded = explode(';', $domainItem);
if ($domainItemExploded[0] == 'domain') continue;
if ($domainItemExploded[0] == '') continue;
if($this->getDomainsOwnerHandle !== null && $domainItemExploded[20] !== $this->getDomainsOwnerHandle) {
continue;
}
$domainParts = explode('.', $domainItemExploded[0]);
$sld = array_shift($domainParts);
$tld = implode('.', $domainParts);
$output[] = new DomainSyncItem(
$sld,
$tld,
array_filter([$domainItemExploded[24], $domainItemExploded[25], $domainItemExploded[26], $domainItemExploded[27], $domainItemExploded[28]]),
$domainItemExploded[1],
0,
Carbon::parse($domainItemExploded[10]),
Carbon::parse($domainItemExploded[7]),
$contacts->get($domainItemExploded[20]),
$contacts->get($domainItemExploded[21]),
$contacts->get($domainItemExploded[22]),
$contacts->get($domainItemExploded[23]),
);
}
return $output;
}
/**
* Helper below
*/
private function _getContactFromHandle(array $reportLine) {
$type = ContactTypeEnum::PERSON;
if ($reportLine[4] === "organisation") {
$type = ContactTypeEnum::ORG;
} elseif ($reportLine[4] === "role") {
$type = ContactTypeEnum::ROLE;
}
return new DomainContact([
"id" => $reportLine[2],
"type" => $type,
"sex" => ContactSexEnum::MALE,
"first_name" => $reportLine[5],
"last_name" => $reportLine[6],
"organisation" => $reportLine[7],
"street" => $reportLine[8],
"zipcode" => $reportLine[9],
"city" => $reportLine[10],
"state" => $reportLine[11],
"country" => $reportLine[12],
"telephone" => $reportLine[13],
"telefax" => $reportLine[14],
"email" => $reportLine[15]
]);
}
/**
* @param $salesChannelId
* @return ApiClient
*/
public function getClient() {
if (!isset(self::$cps)) {
self::$cps = new ApiClient();
}
return self::$cps;
}
private function _getHandleFromContact(DomainContact $domainContact) {
$domainContact->refresh();
if ($domainContact->getModuleHandle('HwCpsDatensysteme') !== null) {
return $domainContact->getModuleHandle('HwCpsDatensysteme');
}
// lumaserv requires another name for persons
$type = "PERS";
if ($domainContact->type !== ContactTypeEnum::PERSON) {
$type = $domainContact->type->name;
}
$output = $this->getClient($domainContact->sales_channel_id)->domains()->handles()->create(
$type,
$domainContact->sex->name,
$domainContact->first_name,
$domainContact->last_name,
$domainContact->organisation,
$domainContact->street,
$domainContact->street_number,
$domainContact->zipcode,
$domainContact->city,
$domainContact->state,
$domainContact->country,
$domainContact->telephone ?? "+49.0000000",
$domainContact->telefax,
$domainContact->email,
);
if (!$output->success)
throw new CouldNotCreateDomainContact($output->errors[0]);
$domainContact->addModuleHandle('HwCpsDatensysteme', $output->data->handle);
return $output->data->handle;
}
public function createHandle(DomainContact $contact) {
$xml = <<<XML
<?xml version="1.0" encoding="utf-8" ?>
<request>
{$this->getXmlHeader()}
<transaction>
<group>contact</group>
<action>create</action>
<attribute>contact</attribute>
<object>%%AUTO%%</object>
<values>
{$this->getXmlContactStructure($contact)}
</values>
</transaction>
</request>
XML;
$response = $this->getClient()->callRaw($xml, $this->config['sandbox']);
return ((array)$response->result->auto_values->contact_id)[0];
}
public function updateHandle(DomainContact $contact) {
$handle = $contact->getModuleHandle($this->customFieldsKey);
$xml = <<<XML
<?xml version="1.0" encoding="utf-8" ?>
<request>
{$this->getXmlHeader()}
<transaction>
<group>contact</group>
<action>modify</action>
<attribute>replacement</attribute>
<object>{$handle}:%%AUTO%%</object>
<values>
{$this->getXmlContactStructure($contact)}
</values>
</transaction>
</request>
XML;
$response = $this->getClient()->callRaw($xml, $this->config['sandbox']);
try {
$newHandleId = ((array)$response->result->auto_values->contact_id)[0];
$contact->update([
"modules" => array_merge($contact->modules, [
$this->customFieldsKey => $newHandleId
]),
]);
} catch (Exception|Throwable $e) {
Log::error($e->getMessage());
}
}
public function getXmlHeader() {
return <<<XML
<auth>
<cid>{$this->config['cnumber']}</cid>
<user>{$this->config['user']}</user>
<pwd>{$this->config['password']}</pwd>
</auth>
XML;
}
function _formatiere_telefonnummer($telefonnummer, DomainContact $domainContact) {
$phoneLib = PhoneNumberUtil::getInstance();
// Input e.g. "+4915151150554"
if (PhoneNumberUtil::isViablePhoneNumber($telefonnummer)) {
$parsedNumber = $phoneLib->parse($telefonnummer, $domainContact->country);
// This returns "tel:+49-1515-1150554"
$nummer = $phoneLib->format($parsedNumber, PhoneNumberFormat::RFC3966);
// Remove the library prefix, value "+49-1515-1150554"
$nummer = str_replace("tel:", "", $nummer);
// Replace the first dash with a dot, value after: "+49.1515-1150554"
$pos = strpos($nummer, "-");
if ($pos !== false) {
$nummer = substr_replace($nummer, ".", $pos, strlen("-"));
}
// Remove the second dash, value after: "+49.15151150554"
$nummer = str_replace("-", "", $nummer);
// Finished
return $nummer;
}
return $telefonnummer;
}
private function getXmlContactStructure(DomainContact $contact) {
$type = $contact->type == ContactTypeEnum::PERSON ? 'person' : 'organisation';
$phone = $contact->telephone ? $this->_formatiere_telefonnummer($contact->telephone, $contact) : "+49.00000000";
$org = htmlspecialchars($this->germanAscii($contact->organisation ?? "")); // Prevents "XML validity error - encoding is invalid"
$lastName = $this->germanAscii($contact->last_name);
$firstName = $this->germanAscii($contact->first_name);
$street = $this->germanAscii($contact->street_full);
$postal = $contact->zipcode;
$city = $this->germanAscii($contact->city);
$state = $this->clean($this->germanAscii($contact->state));
$country = $contact->country;
$fax = $contact->telefax ? "<fax>" .$this->_formatiere_telefonnummer($contact->telefax, $contact) . "</fax>" : null;
// $fax = $contact->telefax;
$email = $contact->email;
if(isset($this->config) && isset($this->config['overwriteContactEmail']) && $this->config['overwriteContactEmail'] !== "") {
$email = $this->config['overwriteContactEmail'];
}
$org = str_replace("&", "und", $org);
$org = preg_replace('/[^-A-Za-z0-9\.\,\&\+\/\(\) ]+/', '', $org);
$firstName = preg_replace('/[^-A-Za-z0-9\. ]+/', '', $firstName);
$lastName = preg_replace('/[^-A-Za-z0-9\. ]+/', '', $lastName);
return "<lastname>{$lastName}</lastname>
<firstname>{$firstName}</firstname>
<orgname>{$org}</orgname>
<street>{$street}</street>
<postal>{$postal}</postal>
<city>{$city}</city>
<state>{$state}</state>
<iso_country>{$country}</iso_country>
<phone>{$phone}</phone>
{$fax}
<email>{$email}</email>
<contact_type>{$type}</contact_type>";
}
public function clean($string) {
$string = str_replace(' ', '-', $string); // Replaces all spaces with hyphens.
return preg_replace('/[^A-Za-z0-9\-]/', '', $string); // Removes special chars.
}
private function germanAscii($string) {
$string = str_replace(
['ä','ö','ü','Ä','Ö','Ü','ß'],
['ae','oe','ue','Ae','Oe','Ue','ss'],
$string
);
return Str::ascii($string);
}
}Was this helpful?