<?php

error_reporting(-1);

class Archivator 
{
	public function createArchive($inputFolder, $outputFile)
	{	
		$data = $this->readFolder($inputFolder);
		
		$converted = json_encode($data);

		$outputStream = fopen($outputFile, 'x');
		fwrite($outputStream, $converted);
		fclose($outputStream);
	}

	public function extract($inputFile, $outputFolder)
	{
		$converted = file_get_contents($inputFile);
		$data = json_decode($converted, true);
		$this->writeData($data, $outputFolder);
	}

	private function writeData($arr, $outputFolder)
	{
		foreach ($arr as $key => $value){
			if (isset($value['name']) && $value['type']=='file'){
				file_put_contents($outputFolder."/".$value['name'], base64_decode($value['data']));
			} else {
				if($value['type']){
					$this->writeData($value, $outputFolder.$value['name'] );
				} else {
					echo "Something went wrong in writeData.\n";
				}
			}
		}
	}

	private function readFolder($path)
	{
		$result = array();
		if ($handler = opendir($path)){
			while (false !== ($file = readdir($handler))){
				if ($file != "." && $file != ".."){
					if (is_dir($path.$file)){
						$result[$file] = $this->readFolder($path.$file."\\");
					} else {
						$result[] = $this->readFile($path.$file);
					}
				}
			}

		return $result;
		} else {
			echo "Something went wrong in function readFolder. Sorry. \n";
		}
	}

	private function readFile($path)
	{
		$file = array();
		$inputStream = fopen($path, 'rb');
		if ($inputStream != false){
			$value = "";
			while ($byte = fread($inputStream, 1024*1024)){
				$value .= $byte;
			}
		$file['data'] = base64_encode($value);  // It's one of possible ways to do it but filesize will be biger(~33%), in some cases it's a problem.
		fclose($inputStream);
		$file['name'] = basename($path);
		$file['type'] = filetype($path);

		return $file;
		} else {
			echo "No such file or directory"."\n";
		}
	}
}
$arch = new Archivator();
$arch->createArchive('d:\\ok\\', 'dat');
$arch->extract('dat', 'd:\\');
$y = fgets(STDIN);