public function restore()
 {
     // check db
     $url = "http://{$this->adminUrl}{$this->host}:{$this->port}/" . urlencode($this->database) . "/";
     fwrite(STDOUT, "Checking db '{$this->database}' at {$this->host}:{$this->port} ..." . PHP_EOL);
     $curl = getCommonCurl($url);
     $result = trim(curl_exec($curl));
     $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
     curl_close($curl);
     if (200 == $statusCode) {
         // $this->database exists
         $exists = true;
         $db_info = json_decode($result, true);
         $docCount = isset($db_info['doc_count']) ? $db_info['doc_count'] : 0;
         fwrite(STDOUT, "{$this->database} '{$this->database}' has {$docCount} documents." . PHP_EOL);
     } elseif (404 == $statusCode) {
         // $this->database not found
         $exists = false;
         $docCount = 0;
     } else {
         // unknown status
         fwrite(STDOUT, "ERROR: Unsupported response when checking db '{$this->database}' status (http status code = {$statusCode}) " . $result . PHP_EOL);
         return;
     }
     if ($this->drop && $exists) {
         // drop $this->database
         fwrite(STDOUT, "Deleting {$this->database} '{$this->database}'..." . PHP_EOL);
         $curl = getCommonCurl($url);
         curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
         $result = trim(curl_exec($curl));
         $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
         curl_close($curl);
         if (200 != $statusCode) {
             fwrite(STDOUT, "ERROR: Unsupported response when deleting db '{$this->database}' (http status code = {$statusCode}) " . $result . PHP_EOL);
             return;
         }
         $exists = false;
         $docCount = 0;
     }
     if ($docCount && !$this->forceRestore) {
         // has documents, but no force
         fwrite(STDOUT, "ERROR: {$this->database} '{$this->database}' has {$docCount} documents. Refusing to restore without -F force flag." . PHP_EOL);
         return;
     }
     if (!$exists) {
         // create db
         fwrite(STDOUT, "Creating {$this->database} '{$this->database}'..." . PHP_EOL);
         $curl = getCommonCurl($url);
         curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
         $result = trim(curl_exec($curl));
         $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
         curl_close($curl);
         if (201 != $statusCode) {
             fwrite(STDOUT, "ERROR: Unsupported response when creating db '{$this->database}' (http status code = {$statusCode}) " . $result . PHP_EOL);
             return;
         }
     }
     if ($this->separateFiles) {
         $files = array();
         foreach (glob("{$this->separateFiles}/*") as $file) {
             if ($file != '.' && $file != '..' && $file != 'dummy') {
                 $files[] = json_decode(file_get_contents($file), true);
             }
         }
         $decodedContent = new stdClass();
         $decodedContent->new_edits = false;
         $decodedContent->docs = $files;
     } else {
         // post dump
         $fileContent = file_get_contents($filename);
         $decodedContent = json_decode($fileContent);
     }
     fwrite(STDOUT, ">>>>>>>>>>>>>>>>> RESTORING STARTED <<<<<<<<<<<<<<<<<<<<<" . PHP_EOL);
     foreach ($decodedContent->docs as $documentTemp) {
         if (!is_array($documentTemp)) {
             $documentTemp = (array) $documentTemp;
         }
         //we need to fetch the latest revision of the document, because in order to upload a new version of document we MUST know latest rev ID
         $url = "http://{$this->adminUrl}{$this->host}:{$this->port}/" . urlencode($this->database) . "/" . urlencode($documentTemp["_id"]);
         $curl = getCommonCurl($url);
         $result = trim(curl_exec($curl));
         $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
         if ($statusCode == 200) {
             $result = json_decode($result, true);
             if (isset($result["_rev"]) && $result["_rev"]) {
                 $documentTemp["_rev"] = $result["_rev"];
             }
         }
         if (isset($documentTemp["_revisions"])) {
             unset($documentTemp["_revisions"]);
         }
         $url = "http://{$this->adminUrl}{$this->host}:{$this->port}/" . urlencode($this->database) . "/" . urlencode($documentTemp["_id"]);
         fwrite(STDOUT, "Restoring '{$documentTemp['_id']}|rev:{$documentTemp['_rev']}' into db '{$this->database}' at {$this->host}:{$this->port}.." . PHP_EOL);
         //If we don't wont to upload attachments then we need to remove content from the file used for upload
         if (!$this->inlineAttachment && isset($documentTemp["_attachments"]) && $documentTemp["_attachments"]) {
             unset($documentTemp["_attachments"]);
             unset($documentTemp["unnamed"]);
         }
         $documentTemp = clearEmptyKey($documentTemp);
         $curl = getCommonCurl($url);
         curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
         /* or PUT */
         curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($documentTemp));
         curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
         curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/json', 'Accept: */*'));
         // TODO: use next string when get ideas why it is not working and how to fix it.
         //curl_setopt($curl, CURLOPT_INFILE, $filehandle); // strange, but this does not work
         $result = trim(curl_exec($curl));
         //fclose($filehandle);
         $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
         curl_close($curl);
         /*
         if ($statusCode < 200 || 299 < $statusCode) {
             fwrite(STDOUT,  "ERROR: Unable to post data to \"{$url}\" (http status code = {$statusCode}) " . $result . PHP_EOL); 
         }
         */
         $messages = json_decode($result, true);
         $errors = 0;
         if (is_array($messages)) {
             if (isset($messages['error'])) {
                 $doc_id = isset($messages['id']) ? $messages['id'] : $documentTemp["_id"];
                 $reason = isset($messages['reason']) ? $messages['reason'] : $messages['error'];
                 fwrite(STDOUT, "ERROR: [{$doc_id}] = {$reason}" . PHP_EOL);
                 $errors++;
             } else {
                 if (isset($messages['ok'])) {
                     $doc_id = isset($messages['id']) ? $messages['id'] : '?';
                     fwrite(STDOUT, "SUCCESS: [{$doc_id}] restored!" . PHP_EOL);
                 }
             }
         }
     }
     fwrite(STDOUT, ">>>>>>>>>>>>>>>>> RESTORING FINISHED! <<<<<<<<<<<<<<<<<<<<<" . PHP_EOL);
 }
 public function download()
 {
     // get all docs IDs
     $url = "http://{$this->host}:{$this->port}/" . $this->database . "/_all_docs";
     fwrite(STDERR, "Fetching all documents info from db '{$this->database}' at {$this->host}:{$this->port} ..." . PHP_EOL);
     $curl = getCommonCurl($url);
     $result = trim(curl_exec($curl));
     $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
     curl_close($curl);
     if (200 == $statusCode) {
         $all_docs = json_decode($result, true);
     } else {
         // unknown status
         fwrite(STDERR, "ERROR: Unsupported response when fetching all documents info from db '{$this->database}' (http status code = {$this->statusCode}) " . PHP_EOL);
         return;
         //exit(2);
     }
     if (!isset($all_docs['rows']) || !count($all_docs['rows']) || !is_array($all_docs['rows'])) {
         //if we want to save each document in separate file
         if ($this->separateFiles) {
             if (!file_exists('./' . $this->databaseName)) {
                 mkdir('./' . $this->databaseName, 0777, true);
             }
             if (!count($all_docs['rows'])) {
                 $dummy = fopen('./' . $this->databaseName . '/' . 'dummy', "a+");
                 fwrite($dummy, "1", 1);
                 fclose($dummy);
             }
         }
         fwrite(STDERR, "ERROR: No documents found in db '{$this->database}'." . PHP_EOL);
     }
     if (!$this->separateFiles) {
         // first part of dump
         if (!$this->noHistory) {
             fwrite($this->fp, '{"new_edits":false,"docs":[' . PHP_EOL);
         } else {
             fwrite($this->fp, '{"docs":[' . PHP_EOL);
         }
     }
     $first = true;
     $count = count($all_docs['rows']);
     fwrite(STDERR, "Found {$count} documents..." . PHP_EOL);
     $i = 1;
     foreach ($all_docs['rows'] as $doc) {
         // foreach DOC get all revs
         if (!$this->noHistory) {
             $url = "http://{$this->host}:{$this->port}/{$this->database}/" . urlencode($doc['id']) . "?revs=true&revs_info=true" . ($this->inlineAttachment ? "&attachments=true" : "");
         } else {
             $url = "http://{$this->host}:{$this->port}/{$this->database}/" . urlencode($doc['id']) . ($this->inlineAttachment || $this->binaryAttachments ? "?attachments=true" : "");
         }
         //fwrite(STDERR, "[{$doc['id']}]");
         $percentage = round($i++ / sizeof($all_docs['rows']) * 100, 2);
         fwrite(STDERR, "Processing database \"{$this->database}\": {$percentage}%\n");
         $curl = getCommonCurl($url);
         curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/json', 'Accept: *\\/*'));
         $result = $wholeDocument = curl_exec($curl);
         $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
         curl_close($curl);
         if (200 == $statusCode) {
             $doc_revs = json_decode($result);
             $doc_revs = (array) $doc_revs;
         } else {
             // unknown status
             fwrite(STDERR, "ERROR: Unsupported response when fetching document [{$doc['id']}] from db '{$this->database}' (http status code = {$statusCode}) " . PHP_EOL);
             return;
             //exit(2);
         }
         //REVISIONS
         if (isset($doc_revs['_revs_info']) && count($doc_revs['_revs_info']) > 1) {
             $revs_info = toArray($doc_revs["_revs_info"]);
             $revs_info = clearEmptyKey($revs_info);
             fwrite(STDERR, "" . PHP_EOL);
             // we have more than one revision
             $revs_info = array_reverse($revs_info);
             $lastRev = end($revs_info);
             $lastRev = $lastRev['rev'];
             reset($revs_info);
             foreach ($revs_info as $rev) {
                 // foreach rev fetch DB/ID?rev=REV&revs=true
                 //fwrite(STDERR, "[{$doc['id']}] @ {$rev['rev']}");
                 if ('available' === $rev['status']) {
                     $url = "http://{$this->host}:{$this->port}/{$this->database}/" . urlencode($doc['id']) . "?revs=true&rev=" . urlencode($rev['rev']);
                     $curl = getCommonCurl($url);
                     $result = curl_exec($curl);
                     $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
                     curl_close($curl);
                     if (200 == $statusCode) {
                         $full_doc = trim($result);
                     } else {
                         // unknown status
                         fwrite(STDERR, "ERROR: Unsupported response when fetching document [{$doc['id']}] revision [{$rev['rev']}] from db '{$this->database}' (http status code = {$statusCode}) " . PHP_EOL);
                         return;
                         //exit(2);
                     }
                     if (is_callable($this->callbackFilter) && !call_user_func($this->callbackFilter, json_decode($full_doc, true), $lastRev)) {
                         fwrite(STDERR, " = skipped" . PHP_EOL);
                         continue;
                         // skip that doc version because callback returned false
                     } else {
                         //fwrite(STDERR, "" . PHP_EOL);
                     }
                 } elseif ('missing' === $rev['status']) {
                     //fwrite(STDERR, " = missing" . PHP_EOL);
                     continue;
                     // missing docs are not available anyhow
                 } elseif ('deleted' === $rev['status']) {
                     //fwrite(STDERR, " = deleted" . PHP_EOL);
                     continue;
                     // we will never get deleted docs as we do not have them in _all_docs list
                 } else {
                     //fwrite(STDERR, " = unsupported revision status" . PHP_EOL);
                     continue;
                     // who knows :)
                 }
                 if ($this->prettyJsonOutput) {
                     $full_doc = indent($full_doc);
                 }
                 //if we want to save each document in separate file
                 if ($this->separateFiles) {
                     if (!file_exists('./' . $this->databaseName)) {
                         mkdir('./' . $this->databaseName, 0777, true);
                     }
                     $myfile = fopen("./" . $this->databaseName . "/" . $doc['id'] . '_rev' . $rev['rev'] . ".json", "w");
                     fwrite($myfile, $full_doc);
                     fclose($myfile);
                     //Or if we want to join them together
                 } else {
                     // add document to dump
                     if (!$first) {
                         fwrite($this->fp, ', ' . PHP_EOL . $full_doc);
                     } else {
                         fwrite($this->fp, $full_doc);
                     }
                     $first = false;
                 }
             }
             //NO REVISIONS
         } else {
             // we have only one revision
             unset($doc_revs['_revs_info']);
             $lastRev = $doc_revs['_rev'];
             if (is_callable($this->callbackFilter) && !call_user_func($this->callbackFilter, $doc_revs, $lastRev)) {
                 fwrite(STDERR, " = skipped" . PHP_EOL);
                 continue;
                 // skip that doc version because callback returned false
             } else {
                 fwrite(STDERR, "" . PHP_EOL);
             }
             if ($this->noHistory) {
                 unset($doc_revs['_rev']);
             }
             if (!$this->inlineAttachment && !$this->binaryAttachments) {
                 unset($doc_revs["_attachments"]);
             }
             $doc_revs = clearEmptyKey($doc_revs);
             $full_doc = json_encode($doc_revs, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
             $doc_revs = toArray($doc_revs);
             if ($this->binaryAttachments && !$this->inlineAttachment && isset($doc_revs["_attachments"]) && $doc_revs["_attachments"]) {
                 foreach ($doc_revs["_attachments"] as $key => $value) {
                     $doc_revs["_attachments"][$key]["length"] = strlen($value["data"]);
                     $doc_revs["_attachments"][$key]["stub"] = true;
                     unset($doc_revs["_attachments"][$key]["data"]);
                 }
             }
             if ($this->prettyJsonOutput) {
                 $full_doc = indent($full_doc);
             }
             //IF we want to save each document in separate file
             if ($this->separateFiles) {
                 if (!file_exists('./' . $this->databaseName)) {
                     mkdir('./' . $this->databaseName, 0777, true);
                 }
                 $myfile = fopen("./" . $this->databaseName . "/" . $doc['id'] . ".json", "wb");
                 if ($myfile != false) {
                     fwrite($myfile, $full_doc);
                     fclose($myfile);
                 }
                 //Or if we want to join them together..
             } else {
                 if ($full_doc !== null && $full_doc !== false) {
                     if (!$first) {
                         fwrite($this->fp, ', ' . PHP_EOL . $full_doc);
                     } else {
                         fwrite($this->fp, $full_doc);
                     }
                     $first = false;
                 }
             }
             /* 
              *   Binary attachments 
              */
             if ($this->binaryAttachments && $doc_revs["_attachments"]) {
                 foreach ($doc_revs["_attachments"] as $attachment_id => $content) {
                     $tempUrl = "http://{$this->host}:{$this->port}/{$this->database}/" . urlencode($doc['id']) . "/" . urlencode($attachment_id);
                     $folder = $this->databaseName . '/' . $doc['id'];
                     if (!file_exists('./' . $folder)) {
                         mkdir('./' . $folder, 0777, true);
                     }
                     $ch = getCommonCurl($tempUrl);
                     $fp = fopen('./' . $folder . '/' . $attachment_id, 'wb');
                     //download attachment to current folder
                     curl_setopt($ch, CURLOPT_FILE, $fp);
                     curl_setopt($ch, CURLOPT_HEADER, 0);
                     curl_exec($ch);
                     curl_close($ch);
                     fclose($fp);
                 }
             }
         }
     }
     // end of dump
     if (!$this->separateFiles) {
         fwrite($this->fp, PHP_EOL . ']}' . PHP_EOL);
     }
     if ($this->fp) {
         fclose($this->fp);
     }
     return;
     //exit(0);
 }