<?php

use Vn\Lib;

/**
 * Adds a document to the Document Management System.
 */
class Add extends Vn\Web\JsonRequest
{
	function run ($db)
	{
		// XXX: Uncomment only to test the script
		//$_REQUEST['description'] = 'description';
		
		$description = empty ($_REQUEST['description']) ?
			NULL : $_REQUEST['description']; 
		
		$baseDir = _DATA_DIR .'/'. $this->app->getName ();
		$docsDir = "$baseDir/dms";
		$tempDir = "$baseDir/.dms";

		$digXDir = 3;
		$zerosDir = '';
		
		for ($i = 0; $i < $digXDir; $i++)
			$zerosDir .= '0';
		
		// Checks document restrictions
		
		if (empty ($_FILES['doc']['name']))
			throw new Lib\UserException ('File not choosed');

		$maxSize = $db->getValue ('SELECT max_size FROM dms_config');

		if ($_FILES['doc']['size'] > $maxSize * 1048576)
			throw new Lib\UserException (sprintf ('File size exceeds size: %d MB', $maxSize)));

		try {
			// Registers the document in the database

			$db->query ('START TRANSACTION');

			$db->query ('INSERT INTO dms_document SET description = #', [$description]);	
			$docId = (string) $db->getValue ('SELECT LAST_INSERT_ID()');
		
			$len = strlen ($docId);
			$neededLevels = ceil ($len / $digXDir) - 1;

			$dirLevels = $db->getValue (
				'SELECT dir_levels FROM dms_config LOCK IN SHARE MODE');

			if ($dirLevels > $neededLevels)
				$neededLevels = $dirLevels;

			// Reorganizes the file repository if necessary

			if ($dirLevels < $neededLevels)
				$dirLevels = $db->getValue (
					'SELECT dir_levels FROM dms_config FOR UPDATE');

			if ($dirLevels < $neededLevels)
			{
				if (is_dir ($docsDir))
				{
					$dif = ($neededLevels - $dirLevels) - 1;
					$newDir = $docsDir;
				
					for ($i = 0; $i < $dif; $i++)
						$newDir .= "/$zerosDir";
		
					$success = rename ($docsDir, $tempDir)
						&& mkdir ($newDir, 0770, TRUE)
						&& rename ($tempDir, "$newDir/$zerosDir");

					if (!$success)
						throw new Exception ('Error while reorganizing directory tree');
				}

				$curLevels = $db->query ('UPDATE dms_config SET dir_levels = #',
					[$neededLevels]);
			}

			// Saves the document to the repository

			$padLen = ($neededLevels + 1) * $digXDir;
			$paddedId = str_pad ($docId, $padLen, '0', STR_PAD_LEFT);
		
			$saveDir = $docsDir;
		
			for ($i = 0; $i < $neededLevels; $i++)
				$saveDir .= '/'. substr ($paddedId, $i * $digXDir, $digXDir);

			if (!file_exists ($saveDir))
				mkdir ($saveDir, 0770, TRUE);
			
			$savePath = "$saveDir/". substr ($paddedId, -$digXDir);
	
			move_uploaded_file ($_FILES['doc']['tmp_name'], $savePath);

			$db->query ('COMMIT');

			return $docId;
		}
		catch (Exception $e)
		{
			$db->query ('ROLLBACK');
			throw $e;
		}
	}
}

