/src/TrafficManagement/Zone.php

https://gitlab.com/blueprintmrk/dyn-php · PHP · 676 lines · 348 code · 88 blank · 240 comment · 62 complexity · 0ebb5084122b8fe827e1f737f05003ee MD5 · raw file

  1. <?php
  2. namespace Dyn\TrafficManagement;
  3. use Dyn\TrafficManagement\Record\RecordInterface;
  4. use Dyn\TrafficManagement\Api\Client as ApiClient;
  5. use Dyn\TrafficManagement\Api\Response as ApiResponse;
  6. use Dyn\TrafficManagement\Service\ServiceInterface;
  7. use Dyn\TrafficManagement\Service\DynamicDNS;
  8. class Zone
  9. {
  10. /**
  11. * The zone name, e.g. example.com
  12. *
  13. * @var string
  14. */
  15. protected $name;
  16. /**
  17. * The zone type, either 'Primary' or 'Secondary'
  18. *
  19. * @var string
  20. */
  21. protected $type;
  22. /**
  23. * One of 'increment', 'epoch', 'day', 'minute'. Increment is the default.
  24. *
  25. * @var string
  26. */
  27. protected $serialStyle;
  28. /**
  29. * @var integer
  30. */
  31. protected $serial;
  32. /**
  33. * @var string
  34. */
  35. protected $rname;
  36. /**
  37. * Default TTL for the zone
  38. *
  39. * @var integer
  40. */
  41. protected $defaultTtl;
  42. /**
  43. * Dyn API client instance
  44. *
  45. * @var ApiClient
  46. */
  47. protected $apiClient;
  48. /**
  49. * Constructor
  50. *
  51. * @param ApiClient $apiClient
  52. */
  53. public function __construct(ApiClient $apiClient)
  54. {
  55. $this->apiClient = $apiClient;
  56. }
  57. /**
  58. * Setter for zone name
  59. *
  60. * @param string $name
  61. */
  62. public function setName($name)
  63. {
  64. $this->name = $name;
  65. return $this;
  66. }
  67. /**
  68. * Getter for zone name
  69. *
  70. * @return string
  71. */
  72. public function getName()
  73. {
  74. return $this->name;
  75. }
  76. /**
  77. * Setter for type
  78. *
  79. * @param string $type
  80. */
  81. public function setType($type)
  82. {
  83. $this->type = $type;
  84. return $this;
  85. }
  86. /**
  87. * Getter for type
  88. *
  89. * @return string
  90. */
  91. public function getType()
  92. {
  93. return $this->type;
  94. }
  95. /**
  96. * Setter for serial style. Valid values:
  97. * * increment - Serials are incremented by 1 on every change. Default setting.
  98. * * epoch - Serials will be the UNIX timestamp at the time of the publish.
  99. * * day - Serials will be in the form of YYYYMMDDxx where xx is incremented
  100. * by one for each change during that particular day.
  101. * * minute - Serials will be in the form of YYMMDDHHMM.
  102. *
  103. * @param string $serialStyle
  104. */
  105. public function setSerialStyle($serialStyle)
  106. {
  107. $validSerialStyles = array('increment', 'epoch', 'day', 'minute');
  108. if (!in_array($serialStyle, $validSerialStyles)) {
  109. throw new \InvalidArgumentException(
  110. 'Invalid serial style specified. Must be one of: ' .
  111. implode(', ', $validSerialStyles)
  112. );
  113. }
  114. $this->serialStyle = $serialStyle;
  115. return $this;
  116. }
  117. /**
  118. * Getter for serial style
  119. *
  120. * @return string
  121. */
  122. public function getSerialStyle()
  123. {
  124. return $this->serialStyle;
  125. }
  126. /**
  127. * Setter for serial
  128. *
  129. * @param integer $serial [description]
  130. */
  131. public function setSerial($serial)
  132. {
  133. $this->serial = $serial;
  134. return $this;
  135. }
  136. /**
  137. * Getter for serial
  138. *
  139. * @return integer
  140. */
  141. public function getSerial()
  142. {
  143. return $this->serial;
  144. }
  145. /**
  146. * Setter for rname
  147. *
  148. * @param string $rname
  149. */
  150. public function setRname($rname)
  151. {
  152. $this->rname = $rname;
  153. return $this;
  154. }
  155. /**
  156. * Getter for rname
  157. *
  158. * @return string
  159. */
  160. public function getRname()
  161. {
  162. return $this->rname;
  163. }
  164. /**
  165. * Setter for default TTL
  166. *
  167. * This is mainly used for object creation
  168. *
  169. * @param integer $defaultTtl
  170. */
  171. public function setDefaultTtl($defaultTtl)
  172. {
  173. $this->defaultTtl = $defaultTtl;
  174. return $this;
  175. }
  176. /**
  177. * Getter for default TTL
  178. *
  179. * @param integer $defaultTtl
  180. * @return integer
  181. */
  182. public function getDefaultTtl($defaultTtl)
  183. {
  184. return $this->defaultTtl;
  185. }
  186. /**
  187. * Create the supplied record
  188. *
  189. * @param RecordInterface $record
  190. * @param string $fqdn
  191. * @return boolean|ApiResponse
  192. */
  193. public function createRecord(RecordInterface $record, $fqdn = null)
  194. {
  195. if ($fqdn === null) {
  196. $fqdn = $record->getFqdn();
  197. }
  198. $params = array(
  199. 'rdata' => $record->getRData(),
  200. 'ttl' => $record->getTtl()
  201. );
  202. return $this->createRecordFromParams($record->getType(), $fqdn, $params);
  203. }
  204. /**
  205. * Create a record with the supplied values
  206. *
  207. * @param string $type Record type to create, A, CNAME etc.
  208. * @param string $fqdn FQDN of the record to create
  209. * @param array $params Array of record parameters
  210. * @return boolean|ApiResponse
  211. */
  212. public function createRecordFromParams($type, $fqdn, array $params)
  213. {
  214. $result = $this->apiClient->post('/'.$type.'Record/'.$this->getName().'/'.$fqdn.'/', $params);
  215. if ($result && $result->isOk()) {
  216. if ($result->isComplete()) {
  217. return true;
  218. } else {
  219. return $result;
  220. }
  221. }
  222. return false;
  223. }
  224. /**
  225. * Returns a specific record by ID
  226. *
  227. * @param string $type The record type, e.g. A, AAAA, CNAME
  228. * @param string $fqdn The FQDN of the record to be returned
  229. * @param integer $id The numeric ID of the record to be returned
  230. * @return RecordInterface
  231. */
  232. public function getRecord($type, $fqdn, $id)
  233. {
  234. $path = '/'.$type.'Record/'.$this->getName().'/'.$fqdn.'/'.$id.'/';
  235. $result = $this->apiClient->get($path, array('detail' => 'y'));
  236. if ($result && $result->isComplete()) {
  237. $className = 'Dyn\TrafficManagement\Record\\'.$type;
  238. $record = $className::build($result->data);
  239. return $record;
  240. }
  241. return $result;
  242. }
  243. /**
  244. * Returns the record(s) of the specified type with the specified FQDN, or false
  245. * if none exist.
  246. *
  247. * @param string $type The record type, e.g. A, AAAA, CNAME
  248. * @param string $fqdn The FQDN of the record(s) to be returned
  249. * @return array|false
  250. */
  251. public function getRecords($type, $fqdn)
  252. {
  253. $path = '/'.$type.'Record/'.$this->getName().'/'.$fqdn.'/';
  254. $result = $this->apiClient->get($path, array('detail' => 'y'));
  255. if ($result && $result->isComplete()) {
  256. $className = 'Dyn\TrafficManagement\Record\\'.$type;
  257. $records = array();
  258. foreach ($result->data as $recordData) {
  259. $record = $className::build($recordData);
  260. $records[] = $record;
  261. }
  262. return $records;
  263. }
  264. return $result;
  265. }
  266. /**
  267. * Updates the specified record
  268. *
  269. * @param RecordInterface $record
  270. * @return boolean|ApiResponse
  271. */
  272. public function updateRecord(RecordInterface $record)
  273. {
  274. $type = $record->getType();
  275. $fqdn = $record->getFqdn();
  276. $id = $record->getId();
  277. $params = array(
  278. 'rdata' => $record->getRData(),
  279. 'ttl' => $record->getTtl()
  280. );
  281. return $this->updateRecordFromParams($type, $fqdn, $id, $params);
  282. }
  283. /**
  284. * Updates a record with the specified values
  285. *
  286. * @param string $type
  287. * @param string $fqdn
  288. * @param integer $id
  289. * @param array $params
  290. * @return boolean|ApiResponse
  291. */
  292. public function updateRecordFromParams($type, $fqdn, $id, array $params)
  293. {
  294. $path = '/'.$type.'Record/'.$this->getName().'/'.$fqdn.'/'.$id.'/';
  295. $result = $this->apiClient->put($path, $params);
  296. if ($result && $result->isOk()) {
  297. if ($result->isComplete()) {
  298. return true;
  299. } else {
  300. return $result;
  301. }
  302. }
  303. return false;
  304. }
  305. /**
  306. * Delete the specified record
  307. *
  308. * @param RecordInterface $record
  309. * @return boolean|ApiResponse
  310. */
  311. public function deleteRecord(RecordInterface $record)
  312. {
  313. $type = $record->getType();
  314. $fqdn = $record->getFqdn();
  315. $id = $record->getId();
  316. return $this->deleteRecordFromParams($type, $fqdn, $id);
  317. }
  318. /**
  319. * Deletes a specific record
  320. *
  321. * @param string $type
  322. * @param string $fqdn
  323. * @param integer $id
  324. * @return boolean|ApiResponse
  325. */
  326. public function deleteRecordFromParams($type, $fqdn, $id)
  327. {
  328. $path = '/'.$type.'Record/'.$this->getName().'/'.$fqdn.'/'.$id.'/';
  329. $result = $this->apiClient->delete($path);
  330. if ($result && $result->isOk()) {
  331. if ($result->isComplete()) {
  332. return true;
  333. } else {
  334. return $result;
  335. }
  336. }
  337. return false;
  338. }
  339. /**
  340. * Deletes all records of a specified type at the specified FQDN
  341. *
  342. * @param string $type
  343. * @param string $fqdn
  344. * @return boolean|ApiResponse
  345. */
  346. public function deleteRecords($type, $fqdn)
  347. {
  348. $path = '/'.$type.'Record/'.$this->getName().'/'.$fqdn.'/';
  349. $result = $this->apiClient->delete($path);
  350. if ($result && $result->isOk()) {
  351. if ($result->isComplete()) {
  352. return true;
  353. } else {
  354. return $result;
  355. }
  356. }
  357. return false;
  358. }
  359. /**
  360. * Returns all records on this zone, grouped by type. If a FQDN is provided,
  361. * returns only records from that point in the zone heirarchy and below.
  362. *
  363. * @param string $fqdn
  364. * @return array
  365. */
  366. public function getAllRecords($fqdn = null)
  367. {
  368. $path = '/AllRecord/'.$this->name;
  369. if ($fqdn) {
  370. $path .= '/'.$fqdn;
  371. }
  372. $path .= '/';
  373. $result = $this->apiClient->get($path, array('detail' => 'y'));
  374. if ($result && $result->isComplete()) {
  375. // convert the result into objects of the correct type
  376. $records = array();
  377. foreach ($result->data as $key => $recordData) {
  378. // workout the class name (ns_records -> NS)
  379. $type = strtoupper(substr($key, 0, strpos($key, '_')));
  380. $className = 'Dyn\TrafficManagement\Record\\'.$type;
  381. $records[$type] = array();
  382. if (count($recordData) > 0) {
  383. foreach ($recordData as $recordRow) {
  384. $record = $className::build($recordRow);
  385. $records[$type][] = $record;
  386. }
  387. }
  388. }
  389. return $records;
  390. }
  391. return false;
  392. }
  393. /**
  394. * Returns the API resource path for the supplied service.
  395. *
  396. * @param ServiceInterface $service
  397. * @param string $fqdn
  398. * @return string
  399. */
  400. protected function buildServicePath(ServiceInterface $service, $fqdn)
  401. {
  402. $path = '/'.$service->getType().'/'.$this->getName().'/'.$fqdn;
  403. if ($service instanceof DynamicDNS) {
  404. // DDNS uses a slightly different path
  405. $path .= '/'.$service->getRecordType();
  406. }
  407. $path .= '/';
  408. return $path;
  409. }
  410. /**
  411. * Creates the supplied service at $fqdn
  412. *
  413. * @param ServiceInterface $service
  414. * @param string $fqdn
  415. * @return ServiceInterface|ApiResponse
  416. */
  417. public function createService(ServiceInterface $service, $fqdn = null)
  418. {
  419. if ($fqdn === null) {
  420. $fqdn = $service->getFqdn();
  421. }
  422. $path = $this->buildServicePath($service, $fqdn);
  423. $params = $service->getParams();
  424. $result = $this->apiClient->post($path, $params);
  425. if ($result && $result->isOk()) {
  426. if ($result->isComplete()) {
  427. return $service;
  428. } else {
  429. return $result;
  430. }
  431. }
  432. return false;
  433. }
  434. /**
  435. * Returns the service of the specified type at $fqdn
  436. *
  437. * @param string $type
  438. * @param string $fqdn
  439. * @param string $ddnsRecordType DDNS record type (required if $type is DDNS)
  440. * @return ServiceInterface|false
  441. */
  442. public function getService($type, $fqdn, $ddnsRecordType = null)
  443. {
  444. $path = '/'.$type.'/'.$this->getName().'/'.$fqdn.'/';
  445. if ($type == 'DDNS') {
  446. if ($ddnsRecordType) {
  447. if ($ddnsRecordType == 'A' || $ddnsRecordType == 'AAAA') {
  448. $path .= $ddnsRecordType.'/';
  449. } else {
  450. throw new \InvalidArgumentException(
  451. "DDNS record type must be either 'A' or 'AAAA'"
  452. );
  453. }
  454. } else {
  455. throw new \InvalidArgumentException(
  456. "DDNS record type ('A' or 'AAAA') must be specified " .
  457. "when loading a DDNS service"
  458. );
  459. }
  460. }
  461. $result = $this->apiClient->get($path);
  462. if ($result && $result->isComplete()) {
  463. if ($type == 'DDNS') {
  464. $className = 'Dyn\TrafficManagement\Service\DynamicDNS';
  465. } else {
  466. $className = 'Dyn\TrafficManagement\Service\\'.$type;
  467. }
  468. $service = $className::build($result->data);
  469. return $service;
  470. }
  471. return false;
  472. }
  473. /**
  474. * Updates the supplied service
  475. *
  476. * @param ServiceInterface $service
  477. * @return boolean|ApiResponse
  478. */
  479. public function updateService(ServiceInterface $service)
  480. {
  481. $path = $this->buildServicePath($service, $service->getFqdn());
  482. $params = $service->getParams();
  483. $result = $this->apiClient->put($path, $params);
  484. if ($result && $result->isOk()) {
  485. if ($result->isComplete()) {
  486. return true;
  487. } else {
  488. return $result;
  489. }
  490. }
  491. return false;
  492. }
  493. /**
  494. * Deletes the supplied service
  495. *
  496. * @param ServiceInterface $service
  497. * @return boolean|ApiResponse
  498. */
  499. public function deleteService(ServiceInterface $service)
  500. {
  501. $path = $this->buildServicePath($service, $service->getFqdn());
  502. $result = $this->apiClient->delete($path);
  503. if ($result && $result->isOk()) {
  504. if ($result->isComplete()) {
  505. return true;
  506. } else {
  507. return $result;
  508. }
  509. }
  510. return false;
  511. }
  512. /**
  513. * Publish changes made to the zone
  514. *
  515. * @return ApiResponse
  516. */
  517. public function publish()
  518. {
  519. return $this->apiClient->put(
  520. '/Zone/'.$this->getName(),
  521. array(
  522. 'publish' => true
  523. )
  524. );
  525. }
  526. /**
  527. * Freeze the zone, preventing changes to it until it is thawed.
  528. *
  529. * @return ApiResponse
  530. */
  531. public function freeze()
  532. {
  533. return $this->apiClient->put(
  534. '/Zone/'.$this->getName(),
  535. array(
  536. 'freeze' => true
  537. )
  538. );
  539. }
  540. /**
  541. * Thaw a frozen zone, allowing changes to be made again
  542. *
  543. * @return ApiResponse
  544. */
  545. public function thaw()
  546. {
  547. return $this->apiClient->put(
  548. '/Zone/'.$this->getName(),
  549. array(
  550. 'thaw' => true
  551. )
  552. );
  553. }
  554. /**
  555. * Returns any unpublished changes made within the current session
  556. *
  557. * @return array|false|ApiResponse
  558. */
  559. public function getChanges()
  560. {
  561. $result = $this->apiClient->get('/ZoneChanges/'.$this->getName());
  562. if ($result && $result->isOk()) {
  563. if ($result->isComplete()) {
  564. return $result->data;
  565. } else {
  566. return $result;
  567. }
  568. }
  569. return false;
  570. }
  571. /**
  572. * Discards any unpublished changes made within the current session
  573. *
  574. * @return boolean|ApiResponse
  575. */
  576. public function discardChanges()
  577. {
  578. $result = $this->apiClient->delete('/ZoneChanges/'.$this->getName());
  579. if ($result && $result->isOk()) {
  580. if ($result->isComplete()) {
  581. return true;
  582. } else {
  583. return $result;
  584. }
  585. }
  586. return false;
  587. }
  588. }