public static function export(Blueprint $blueprint, $type = "tar", $where = NULL, array $filters = NULL)
 {
     // NOTE: type=(tar, csv)
     $tag = "EntityExporter::export()";
     Log::notice("{$tag}");
     // create export path
     $path_tmp = BPConfig::$path_tmp;
     $path_unique = $path_tmp . uniqid("bp") . "/";
     $path_export = $path_unique . $blueprint->signature() . "/";
     Log::debug("{$tag}: path_export = {$path_export}");
     $fields = $blueprint->fields();
     // get data to export
     try {
         $results = EntityExporter::prepareData($blueprint, $where, $filters);
     } catch (Exception $e) {
         throw $e;
     }
     // create tmp directory for tar files
     if ($type == "tar") {
         if (is_writable($path_tmp)) {
             if (!mkdir($path_export, 0777, true)) {
                 throw new Exception("{$tag}: Failed to mkdir: {$path_export}");
             }
         } else {
             throw new Exception("{$tag}: Cannot write to " . $path_tmp);
         }
     }
     // start output buffer
     $csv = "";
     $csv .= "id,";
     // add header row
     foreach ($fields as $f) {
         $displayAs = $f->getKey();
         $csv .= "{$displayAs},";
         if ($f->isForeignKey()) {
             // Add column header for foreign value
             $csv .= $f->getForeignValue() . ",";
         }
     }
     $csv = substr($csv, 0, strlen($csv) - 1);
     // remove trailing comma ","
     $csv .= "\n";
     // add result rows
     for ($i = 0; $i < $results->get_num_rows(); $i++) {
         $row = $results->get_next_row();
         $csv .= $row->id . ",";
         foreach ($fields as $f) {
             $key = $f->getKey();
             // retrieve value
             if ($f->isForeignKey()) {
                 // Insert local value before foreign value
                 $value = $row->{$key};
                 $csv .= "{$value},";
                 // Retrieve foreign value and continue with formatting below...
                 $foreignValue = str_replace(".", "_", $f->getForeignValue());
                 $value = $row->{$foreignValue};
             } else {
                 $value = $row->{$key};
             }
             // format values
             if (!empty($value) || $value == 0) {
                 // format values based on dataType
                 switch ($f->getDataType()) {
                     case "int":
                         if ($f->isForeignKey()) {
                             $value = "\"{$value}\"";
                         }
                         break;
                     case "string":
                         // encrypted values
                         if ($f->getEncType() == "md5" || $f->getEncType() == "sha1") {
                             $value = "******";
                         } else {
                             $value = addslashes($value);
                             $value = "\"{$value}\"";
                         }
                         break;
                     case "text":
                         $value = "\"{$value}\"";
                         break;
                     case "binary":
                         // generate filename
                         $filename_bin = $blueprint->getKey() . "." . $key . "." . $row->id . "." . Binary::extension($f->getMimeType());
                         // write binary data to file
                         if ($type == "tar") {
                             $path_bin = $path_export . $filename_bin;
                             Log::debug("{$tag}: Creating binary file: {$path_bin}");
                             if (!file_put_contents($path_bin, $value)) {
                                 Log::warning("{$tag}: Failed to create binary file: {$path_bin}");
                             }
                         }
                         // replace raw data with filename
                         $value = $filename_bin;
                         break;
                     default:
                         $value = addslashes($value);
                 }
                 // TODO: format values based on ListBlueprint formatter
             }
             // END: if( (!empty($value)) || ($value==0) )
             $csv .= "{$value},";
         }
         $csv = substr($csv, 0, strlen($csv) - 1);
         // remove trailing comma ","
         $csv .= "\n";
     }
     // create tar
     if ($type == "tar") {
         // create blueprint xml file in export path
         $path_blueprint = $path_export . $blueprint->signature();
         $xmlStr = $blueprint->asXml();
         file_put_contents($path_blueprint, $xmlStr);
         // create csv file in export path
         $path_csv = $path_export . $blueprint->getKey() . ".csv";
         file_put_contents($path_csv, $csv);
         $path_tar = $path_unique . $blueprint->getKey() . ".tar";
         $cmd = "tar --create --directory={$path_unique} --file={$path_tar} --gzip " . $blueprint->signature();
         Log::debug("{$tag}: Executing: {$cmd}");
         exec($cmd);
         // retrieve contents of tar file
         $tar = file_get_contents($path_tar);
         // cleanup
         $glob = glob($path_export . "*");
         foreach ($glob as $path_clean) {
             if (!unlink($path_clean)) {
                 Log::warning("{$tag}: Failed to unlink: {$path_clean}");
             }
         }
         if (!rmdir($path_export)) {
             Log::warning("{$tag}: Failed to rmdir: {$path_export}");
         }
         if (!unlink($path_tar)) {
             Log::warning("{$tag}: Failed to unlink: {$path_tar}");
         }
         if (!rmdir($path_unique)) {
             Log::warning("{$tag}: Failed to rmdir: {$path_unique}");
         }
         return $tar;
     } else {
         if ($type == "csv") {
             return $csv;
         }
     }
 }