[ 'data.gchange.fr' ], 'cesiumplus' => [ 'g1.data.le-sou.org', 'g1.data.duniter.fr' ], 'duniter' => [ 'duniter.g1.1000i100.fr', 'duniter-g1.p2p.legal', 'duniter.normandie-libre.fr', 'g1.mithril.re', 'g1.presles.fr', 'duniter.vincentux.fr', 'g1.le-sou.org', 'g1.donnadieu.fr', ] ]; private $nodeTimeout = [ 'duniter' => 2, 'cesiumplus' => 5, 'gchange' => 5, ]; private $nodeTimeoutIncrement = [ 'duniter' => 2, 'cesiumplus' => 10, 'gchange' => 10 ]; private $node = NULL; private $unit = 'quantitative'; /********************** * Methods **********************/ public function __construct () { } public static function getInstance () { if (!isset(DAO::$dao)) { DAO::$dao = new DAO(); } return DAO::$dao; } private function setUnit ($unit) { if (!empty($unit)) { if (!in_array($unit, $this->units)) { $out = []; $out[] = _('L\'unité renseignée n\'existe pas.'); $out[] = _('Vérifiez votre synthaxe.'); $this->decease($out); } else { $this->unit = $unit; } } } public function decease ($errorMsgs) { if (!is_array($errorMsgs)) { $errorMsgs = explode("\n", $errorMsgs); } if ($this->displayType == 'img') { $source = imagecreatetruecolor(500, 200); $bgColor = imagecolorallocate($source, 255, 255, 255); imagefill($source, 0, 0, $bgColor); $txtColor = imagecolorallocate($source, 0, 0, 0); $errorMsgFontSize = 3; $x = 5; $y = 5; foreach ($errorMsgs as $msg) { imagestring($source, $errorMsgFontSize, $x, $y, utf8_decode($msg), $txtColor); $y += $errorMsgFontSize + 20; } imagepng($source); imagedestroy($source); } else if ($this->displayType == 'svg') { echo ' '; $x = 25; $y = 25; foreach ($errorMsgs as $msg) { echo ' '. $msg . ' '; $y += 25; } echo ' '; } else { ob_get_clean(); // to prevent error message to display inside an HTML container (case of error generated by get method calls) echo ' '. _('Erreur critique') . '
'; foreach ($errorMsgs as $msg) { echo '

' . $msg . '

'; } echo '
'; } exit; } public function printUnit () { if ($this->unit == 'relative') { if ($this->displayType == 'img') { return _('DUĞ1'); } else { return _('DUĞ1'); } } else { return _('Ğ1'); } } public function convertIntoChosenUnit ($amountInQuantitative) { if ($this->unit == 'quantitative') { return $amountInQuantitative; } else { if (!isset($this->startDateUdAmount)) { $this->startDateUdAmount = $this->getUdAmount($this->startDate); } return round($amountInQuantitative / $this->startDateUdAmount, 2); } } public function addNode ($node) { $node = htmlspecialchars($node); $this->nodes = array_unique( array_merge( (array)$node, $this->nodes ) ); } public function addNodes ($nodes) { if (!is_array($nodes)) { $nodes = explode(' ', $nodes); } foreach ($nodes as $node) { $this->addNode($node); } } /** * @return $nodes array */ public function getNodesList ($nodeType = 'duniter') { switch ($nodeType) { case 'gchange': $nodesFilename = 'nodes-gchange'; break; case 'cesiumplus': $nodesFilename = 'nodes-cesiumplus'; break; default: $nodesFilename = 'nodes'; break; } $nodesFilename .= '.txt'; $nodesFullpath = $this->cacheDir . $nodesFilename; $nodes = $this->nodes[$nodeType]; if ($this->isActivatedCache) { if (!file_exists($nodesFullpath)) { shuffle($nodes); $this->cacheNodes($nodes, $nodeType); } else { $nodesStr = file_get_contents($nodesFullpath); $nodes = explode("\n", $nodesStr); } } else { shuffle($nodes); } return $nodes; } protected function cacheNodes ($nodes, $nodeType = 'duniter') { switch ($nodeType) { case 'gchange': $nodesFilename = 'nodes-gchange'; break; case 'cesiumplus': $nodesFilename = 'nodes-cesiumplus'; break; default: $nodesFilename = 'nodes'; break; } $nodesFilename .= '.txt'; if (!file_exists($this->cacheDir)) { mkdir($this->cacheDir, 0777, true); } file_put_contents($this->cacheDir . $nodesFilename, implode("\n", $nodes)); } protected function saveNodes ($nodes, $nodeType = 'duniter') { $this->nodes[$nodeType] = $nodes; } protected function fetchJson_aux ($nodes, $uri, $nodeType, $queryParams, $nodesNb, $nodeTimeout) { // $header = 'Content-Type: application/x-www-form-urlencoded'; // $header = "Content-Type: text/xml\r\n"; if (!empty($queryParams)) { $opts = [ 'http' => [ 'method' => 'POST', 'content' => json_encode($queryParams), // 'header' => $header, 'timeout' => $nodeTimeout ] ]; } else { $opts = [ 'http' => [ 'method' => 'GET', 'timeout' => $nodeTimeout ] ]; } $streamContext = stream_context_create($opts); $i = 0; do { $json = @file_get_contents("https://" . current($nodes) . $uri, false, $streamContext); if (empty($json)) { $nodes[] = array_shift($nodes); ++$i; } } while (empty($json) and ($i < $nodesNb)); if (!empty($json)) { // Let's save node order for other queries : $this->saveNodes($nodes, $nodeType); if ($this->isActivatedCache) { $this->cacheNodes($nodes, $nodeType); } } return $json; } public function fetchJson ($uri, $nodeType = 'duniter', $queryParams = NULL) { $json = NULL; $nodes = $this->getNodesList($nodeType); $nodesNb = count($nodes); $maxTries = 3; $nodeTimeout = $this->nodeTimeout[$nodeType]; $nodeTimeoutIncrement = $this->nodeTimeoutIncrement[$nodeType]; for ($i = 0; ($i < 3) and empty($json); ++$i) { $json = $this->fetchJson_aux($nodes, $uri, $nodeType, $queryParams, $nodesNb, $nodeTimeout); $nodeTimeout += $nodeTimeoutIncrement; } if (empty($json)) { $out = []; $out[] = _('Aucun noeud '. $nodeType .' n\'a été trouvé ou la requête n\'a pas abouti.'); $out[] = _('Noeud interrogés : '); $out = array_merge($out, $nodes); $out[] = _('URI: ' . $uri); if (isset($queryParams)) { $out[] = _('Paramètres de la requête : '); $out[] = print_r($queryParams, true); } $this->decease($out); } return $json; } protected function fetchUdAmount ($date) { // On récupère les numéros de chaque blocks de DU journalier $json = $this->fetchJson('/blockchain/with/ud'); $blocks = json_decode($json)->result->blocks; if ($date > $this->now) { // On récupère le dernier block $blockNum = end($blocks); } else { // On récupère le bloc de la date qui nous intéresse $blockNum = $blocks[count($blocks) - $this->today->diff($date)->format("%a") - 1]; } // Puis on récupère le montant du DU $json = $this->fetchJson('/blockchain/block/' . $blockNum); $block = json_decode($json); return ($block->dividend / 100); } public function getUdAmount ($date) { $udFilename = $this->getUdFilename($date); $udsCacheDir = $this->cacheDir . 'uds/'; $udFullPath = $udsCacheDir . $udFilename; if ($this->isActivatedCache) { if (file_exists($udFullPath)) { $udCachedAmount = file_get_contents($udFullPath); if (is_numeric($udCachedAmount) and $udCachedAmount != 0) { $udAmount = floatval($udCachedAmount); } } if (!isset($udAmount)) { $udAmount = $this->fetchUdAmount($date); // Cache UD amount if (!file_exists($udsCacheDir)) { mkdir($udsCacheDir, 0777, true); } file_put_contents($udFullPath, $udAmount); } } else { $udAmount = $this->fetchUdAmount($date); } return $udAmount; } protected function getUdFilename ($date) { $datePreviousAutumnEquinox = new DateTime($date->format('Y') . '-09-22'); $datePreviousSpringEquinox = new DateTime($date->format('Y') . '-03-20'); if ($date > $datePreviousAutumnEquinox) { $udFilename = $date->format('Y') . '-autumn'; } elseif ($date > $datePreviousSpringEquinox) { $udFilename = $date->format('Y') . '-spring'; } else { $udFilename = ($date->sub(new DateInterval('P1Y'))->format('Y')). '-autumn'; } return $udFilename . '.txt'; } }