array( 'friendlyName' => 'Access Token', 'name' => 'apikey', // 1 'type' => 'text', ), 'default_ip' => array( 'friendlyName' => 'Default IP', 'name' => 'ip', // 1 'type' => 'text', ) ); protected $hostname = 'https://api.digitalocean.com/v2/'; public $availableTypes = array('A', 'AAAA', 'NS', 'MX', 'CNAME', 'SRV', 'TXT'); public function testConnection() { $connection = $this->get('domains'); if ($connection === false) { return array( 'status' => false, 'error' => $this->error ); } else { return array( 'status' => true, 'error' => '' ); } } private function addDot(&$record) { $record['type'] = strtoupper($record['type']); if ($record['data'] != '@' && ($record['type'] == 'SRV' || $record['type'] == 'MX' || $record['type'] == 'NS' || $record['type'] == 'CNAME')) { $record['data'] = trim($record['data']); if (substr($record['data'], strlen($record['data']) - 1) != '.') { $record['data'] = $record['data'] . '.'; } } } private function processRecordParams($record, &$params) { $method = 'process' . $record->type . 'RecordParams'; if (method_exists($this, $method)) { $this->$method($record, $params); } else { $params['data'] = $record->rdata->toString(); } $this->addDot($params); } private function processMXRecordParams($record, &$params) { $params['priority'] = $record->rdata->preference; $params['data'] = $record->rdata->exchange; } private function processRecord(dns\record\Record $record, $data) { $method = 'process' . $record->type . 'Record'; if (method_exists($this, $method)) { $this->$method($record, $data); } } private function processMXRecord(dns\record\Record $record, $data) { $record->rdata->preference = $data['priority']; $record->rdata->exchange = ($data['data'] == '@') ? $this->domain : $data['data']; } private function processSRVRecord(dns\record\Record $record, $data) { $record->rdata->priority = $data['priority']; $record->rdata->weight = $data['weight']; $record->rdata->port = $data['port']; $record->rdata->target = ($data['data'] == '@') ? $this->domain : $data['data']; } private function processSRVRecordParams(dns\record\Record $record, &$params) { $params['data'] = ($record->rdata->target == $this->domain . '.' || $record->rdata->target == $this->domain) ? '@' : $record->rdata->target; } public function getRecords($recordType = false) { $return = $this->getRecordsArray($this->getDomainUrl($this->domain, array('records')), $recordType); return $return; } protected function getRecordsArray($url, $recordType = false) { $result = $this->get($url); if ($result == FALSE) { throw new exceptions\DNSSubmoduleException('Unable to fetch records from server', dns\SubmoduleExceptionCodes::COMMAND_ERROR); } $return = array(); foreach ($result['domain_records'] as $item) { if (in_array((string) $item['type'], $recordType !== false ? array(strtoupper($recordType)) : $this->getAvailableRecordTypes() )) { $item['data'] = ($item['data'] == '@') ? $this->domain : $item['data']; $this->addDot($item); $record = dns\record\Record::tryToCreateFromArray((array) $item); $record->line = $item['id']; $record->rdata->fromString((string) $item['data']); $this->processRecord($record, $item); $return[] = $record; } } if ((int) $result['meta']['total'] > count($result['domain_records']) && isset($result['links']['pages']['next'])) { $moreRecords = $this->getRecordsArray(array('fullurl' => $result['links']['pages']['next'])); if (!empty($moreRecords)) { $return = array_merge($return, $moreRecords); } } return $return; } public function addRecord(dns\record\Record $record) { $params = array( 'type' => $record->type, 'name' => $record->nameToAbsolute($this->domain), 'data' => $record->rdata->toString(), 'port' => $record->rdata->port, 'priority' => $record->rdata->priority, 'ttl' => $record->ttl, 'weight' => $record->rdata->weight, ); $this->processRecordParams($record, $params); $this->get($this->getDomainUrl($this->domain, array('records')), $this->setPOSTparams($params), 'POST'); return true; } public function editRecord(dns\record\Record $record) { $records = $this->getRecords(); if (empty($records)) { return false; } $lines = array(); foreach ($records as $r) { $lines[$r['line']] = $r; } if (!isset($lines[$record['line']]) || !$record->isEqualTo($lines[$record['line']])) { $input = $record->toMergedArray(false); $input['domain'] = $this->domain; $input['name'] = $record->nameToAbsolute($this->domain); $this->processRecordParams($record, $input); $this->get($this->getDomainUrl($this->domain, array('records', $record->line)), $this->setPOSTparams($input), 'PUT'); } } public function deleteRecord(dns\record\Record $record) { $this->get($this->getDomainUrl($this->domain, array('records', $record->line)), array(), 'DELETE'); return true; } public function zoneExists() { try { return $this->getZoneID() !== false; } catch (\Exception $ex) { return false; } } public function getZoneID() { try { $out = $this->get($this->getDomainUrl($this->domain, array('records'))); } catch (\Exception $ex) { return false; } if ($out === false) { return false; } foreach ($out['domains'] as $key => $domain) { if ($domain == $this->domain) { return $domain; } } } public function activateZone() { $params = array('name' => $this->domain, 'ip_address' => $this->config['default_ip']); $this->get('domains', $this->setPOSTparams($params), 'POST'); return true; } public function terminateZone() { $this->get($this->getDomainUrl($this->domain), array(), 'DELETE'); } public function getZones() { $out = array(); $zoneResult = $this->get($this->getDomainUrl()); foreach ($zoneResult['domains'] as $zone) { $out[(string) $zone['name']] = ''; } try { $res = $this->get('droplets'); foreach ($res['droplets'] as $zone) { if (isset($out[(string) $zone['name']])) { $out[(string) $zone['name']] = (string) $zone['networks']['v4'][0]['ip_address']; } } } catch (exceptions\DNSSubmoduleException $exc) { } return $out; } protected function setGETParams($params) { return array('GET' => $params); } protected function setPOSTparams($params) { return array('POST' => $params); } protected function getDomainUrl($domain = "", $additional = array()) { if (!empty($additional)) { $addurl = ''; foreach ($additional as $value) { $addurl .= '/' . $value; } } return 'domains/' . $domain . $addurl; } public function processURL($url, $get = array()) { if (isset($url['fullurl'])) { return $url['fullurl']; } if (!empty($get)) { $additional = '?' . http_build_query($get); } return $this->hostname . $url . $additional; } private function get($function, $params = array(), $type = 'GET') { $url = $this->processURL($function, $params['GET']); $this->checkData(); $ch = curl_init(); $chOptions = array( CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_TIMEOUT => 30, CURLOPT_HTTPHEADER => array( 'Content-Type: application/json' ) ); if (is_array($params['POST']) && !empty($params['POST'])) { $post = json_encode($params['POST']); $chOptions[CURLOPT_POSTFIELDS] = $post; $chOptions[CURLOPT_HTTPHEADER][] = 'Content-Length: ' . strlen($post); } $header = 'Authorization: Bearer ' . $this->config['token']; $chOptions[CURLOPT_HTTPHEADER][] = $header; if (isset($params['POST']) && $type == 'GET') { $type = 'POST'; } if ($type !== false) { $chOptions[CURLOPT_CUSTOMREQUEST] = $type; } curl_setopt_array($ch, $chOptions); $out = curl_exec($ch); $out_info = curl_getinfo($ch); if ($type === 'DELETE') { if (is_string($out) && strlen($out) == 0) { return $out; } } if ($out_info['http_code'] != 200 && ( $out_info['http_code'] == 301 || $out_info['http_code'] == 302 )) { throw new exceptions\DNSSubmoduleException('SSL is required', dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM); } if ($out === false || $out == '') { throw new exceptions\DNSSubmoduleException("cURL Error: " . curl_errno($ch) . " - " . curl_error($ch), dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM); } $decodeInfo = json_decode($out, TRUE); if (isset($decodeInfo['id'])) { $this->error = $decodeInfo['id']; if (isset($decodeInfo['message'])) { throw new exceptions\DNSSubmoduleException($decodeInfo['message'], dns\SubmoduleExceptionCodes::INVALID_PARAMETERS); } } curl_close($ch); return $decodeInfo; } private function checkData() { if ($this->config['token'] == '' || empty($this->config['token'])) { throw new exceptions\DNSSubmoduleException('Api key is required', dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM); } } }