$name($arguments[0]); } public function mainDescription() { return 'Record Synchronization'; } /** * @param $params */ public function syncAdd($params) { try { $zone = $this->getZone($params); $this->setStatus(TaskStatusEnum::IN_PROGRESS); $this->loopThroughServers($zone, $params['submodule'], true, function ($module, $masterRecords) { $this->syncRecords($module, $masterRecords); }); } catch (\Exception $e) { $this->setStatus(TaskStatusEnum::ERROR); $this->addResult(['error' => $e->getMessage()]); LogHelper::addFailLog($this->mainDescription() . "_" . __FUNCTION__, $e->getMessage()); return; } $this->setStatus(TaskStatusEnum::FINISHED); } /** * @param $params */ public function syncDelete($params) { try { $zone = $this->getZone($params); $this->setStatus(TaskStatusEnum::IN_PROGRESS); $this->loopThroughServers($zone, $params['submodule'], true, function ($module, $masterRecords) { $this->syncRecords($module, $masterRecords); }); } catch (\Exception $e) { $this->setStatus(TaskStatusEnum::ERROR); $this->addResult(['error' => $e->getMessage()]); LogHelper::addFailLog($this->mainDescription() . "_" . __FUNCTION__, $e->getMessage()); return; } $this->setStatus(TaskStatusEnum::FINISHED); } /** * @param $params */ public function syncEdit($params) { try { $zone = $this->getZone($params); $this->setStatus(TaskStatusEnum::IN_PROGRESS); $this->loopThroughServers($zone, $params['submodule'], true, function ($module, $masterRecords) { $this->syncRecords($module, $masterRecords); }); } catch (\Exception $e) { $this->setStatus(TaskStatusEnum::ERROR); $this->addResult(['error' => $e->getMessage()]); LogHelper::addFailLog($this->mainDescription() . "_" . __FUNCTION__, $e->getMessage()); return; } $this->setStatus(TaskStatusEnum::FINISHED); } /** * @param $params */ public function syncActivateZone($params) { try { $this->setStatus(TaskStatusEnum::IN_PROGRESS); $zone = $this->getZone($params); $this->loopThroughServers($zone, $params['submodule'], true, function ($module, $masterRecords) { $module->getSubmodule()->getModule()->activateZone(); $module->wipeRecords(); $this->syncRecords($module, $masterRecords); }); } catch (\Exception $e) { $this->setStatus(TaskStatusEnum::ERROR); $this->addResult(['error' => $e->getMessage()]); LogHelper::addFailLog($this->mainDescription() . "_" . __FUNCTION__, $e->getMessage()); return; } $this->setStatus(TaskStatusEnum::FINISHED); } /** * @param $params */ public function syncTerminateZone($params) { try { $this->setStatus(TaskStatusEnum::IN_PROGRESS); $this->loopThroughServers($params['zone'], $params['submodule'], false, function ($module, $masterRecords) { $module->getSubmodule()->getModule()->terminateZone(); }); } catch (\Exception $e) { $this->setStatus(TaskStatusEnum::ERROR); $this->addResult(['error' => $e->getMessage()]); LogHelper::addFailLog($this->mainDescription() . "_" . __FUNCTION__, $e->getMessage()); return; } $this->setStatus(TaskStatusEnum::FINISHED); } /** * @param $params */ public function syncUpdateRDNS($params) { try { $this->setStatus(TaskStatusEnum::IN_PROGRESS); $this->loopThroughServers($params['zone'], $params['submodule'], true, function ($module, $masterRecords) { $this->syncRecords($module, $masterRecords); }); } catch (\Exception $e) { $this->setStatus(TaskStatusEnum::ERROR); $this->addResult(['error' => $e->getMessage()]); LogHelper::addFailLog($this->mainDescription() . "_" . __FUNCTION__, $e->getMessage()); return; } $this->setStatus(TaskStatusEnum::FINISHED); } /** * @param $params */ public function syncRemoveRDNS($params) { try { $this->setStatus(TaskStatusEnum::IN_PROGRESS); $this->loopThroughServers($params['zone'], $params['submodule'], true, function ($module, $masterRecords) { $this->syncRecords($module, $masterRecords); }); } catch (\Exception $e) { $this->setStatus(TaskStatusEnum::ERROR); $this->addResult(['error' => $e->getMessage()]); LogHelper::addFailLog($this->mainDescription() . "_" . __FUNCTION__, $e->getMessage()); return; } $this->setStatus(TaskStatusEnum::FINISHED); } protected function getZone($params) { $submodule = $params['submodule']; if(!$submodule) { $domain = explode('_', $this->description(),2)[1]; throw new \Exception('Zone does not exists:' . ($domain ? ': ' . $domain : '')); } $zoneRepository = Repository::factory(); return $zoneRepository->byServerID($submodule->getServer()->id)->byName($submodule->getDomain())->get()[0]; } /** * @param $zone * @param $submodule * @param $withRecords * @param callable $callable */ private function loopThroughServers($zone, $submodule, $withRecords, callable $callable) { [$master, $slaves] = $this->getServers($zone); $masterRecords = []; if ($master == null) { return; } if ($withRecords) { $masterModule = $master->getServer()->getModule(); $masterModule->setDomain($submodule->getDomain()); $masterRecords = $masterModule->getRecords(); } foreach ($slaves as $slaveServer) { try { if(!$slaveServer->getServer()->isEnabled()) { continue; } $module = $slaveServer->getServer()->getModule(); $module->setDomain($submodule->getDomain()); $callable($module, $masterRecords); } catch (\Exception $e) { $this->setStatus(TaskStatusEnum::ERROR); $this->addResult(['error' => $e->getMessage()]); LogHelper::addFailLog($this->mainDescription() . "_" . __FUNCTION__, $e->getMessage()); } } } /** * @param $zone * @return array */ private function getServers($zone) { if ($zone == null) { return; } $package = $zone->getPackage(); if($package == false) return []; $master = null; $slaves = []; foreach ($package->getServers() as $server) { if ($server->isMaster()) { $master = $server; } else { $slaves[] = $server; } } return [ $master, $slaves ]; } /** * @param $module * @param array $masterRecords */ protected function syncRecords($module, $masterRecords = []) { $slaveRecords = $module->getRecords(); $domain = $module->getSubmodule()->getModule()->getDomain(); /** * Add record which does not exist in slave */ foreach ($masterRecords as $masterRecord) { if (in_array($masterRecord->type, ['SOA'])) { continue; } $found = false; foreach ($slaveRecords as $slaveRecord) { if ($masterRecord->compare($slaveRecord, $domain)) { $found = true; continue; } } if (!$found) { //this can cause CPanel records duplicate problem $masterRecord->ttl = $masterRecord->ttl ?: 3600; try { $module->getSubmodule()->getModule()->addRecord($masterRecord); } catch (\Exception $e) { $this->addResult(['error' => $e->getMessage()]); LogHelper::addFailLog($this->mainDescription() . "_" . __FUNCTION__, $e->getMessage()); } } } /** * Delete record from slave which does not exist in master */ $recordsToDelete = []; foreach ($slaveRecords as $slaveRecord) { if (in_array($slaveRecord->type, ['SOA'])) { continue; } $found = false; foreach ($masterRecords as $masterRecord) { if ($slaveRecord->compare($masterRecord, $domain)) { $found = true; continue; } } if (!$found) { $recordsToDelete[] = $slaveRecord; } } //sorting because CPanel as slave dynamically changes line during removal usort($recordsToDelete, function ($a, $b) { return $a == $b ? 0 : (int)$a->line < (int)$b->line; }); foreach ($recordsToDelete as $recordToDelete) { try { $module->getSubmodule()->getModule()->deleteRecord($recordToDelete); } catch (\Exception $e) { $this->addResult(['error' => $e->getMessage()]); LogHelper::addFailLog($this->mainDescription() . "_" . __FUNCTION__, $e->getMessage()); } } } }