<commit_before><?php
/**
 * Copyright (c) 2012 <NAME> <<EMAIL>>
 * This file is licensed under the Affero General Public License version 3 or
 * later.
 * See the COPYING-README file.
 */

namespace OC\Files\Cache;

class Upgrade {
	/**
	 * @var Legacy $legacy
	 */
	private $legacy;

	private $numericIds = array();

	private $mimeTypeIds = array();

	/**
	 * @param Legacy $legacy
	 */
	public function __construct($legacy) {
		$this->legacy = $legacy;
	}

	/**
	 * Preform a upgrade a path and it's childs
	 *
	 * @param string $path
	 * @param bool $mode
	 */
	function upgradePath($path, $mode = Scanner::SCAN_RECURSIVE) {
		if (!$this->legacy->hasItems()) {
			return;
		}
		\OC_Hook::emit('\OC\Files\Cache\Upgrade', 'migrate_path', $path);
		if ($row = $this->legacy->get($path)) {
			$data = $this->getNewData($row);
			if ($data) {
				$this->insert($data);
				$this->upgradeChilds($data['id'], $mode);
			}
		}
	}

	/**
	 * upgrade all child elements of an item
	 *
	 * @param int $id
	 * @param bool $mode
	 */
	function upgradeChilds($id, $mode = Scanner::SCAN_RECURSIVE) {
		$children = $this->legacy->getChildren($id);
		foreach ($children as $child) {
			$childData = $this->getNewData($child);
			\OC_Hook::emit('\OC\Files\Cache\Upgrade', 'migrate_path', $child['path']);
			if ($childData) {
				$this->insert($childData);
				if ($mode == Scanner::SCAN_RECURSIVE) {
					$this->upgradeChilds($child['id']);
				}
			}
		}
	}

	/**
	 * insert data into the new cache
	 *
	 * @param array $data the data for the new cache
	 */
	function insert($data) {
		static $insertQuery = null;
		if(is_null($insertQuery)) {
			$insertQuery = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache`
				( `fileid`, `storage`, `path`, `path_hash`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` )
				VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');
		}
		if (!$this->inCache($data['storage'], $data['path_hash'], $data['id'])) {
			$insertQuery->execute(array($data['id'], $data['storage'],
				$data['path'], $data['path_hash'], $data['parent'], $data['name'],
				$data['mimetype'], $data['mimepart'], $data['size'], $data['mtime'], $data['encrypted'], $data['etag']));
		}
	}

	/**
	 * check if an item is already in the new cache
	 *
	 * @param string $storage
	 * @param string $pathHash
	 * @param string $id
	 * @return bool
	 */
	function inCache($storage, $pathHash, $id) {
		static $query = null;
		if(is_null($query)) {
			$query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE (`storage` = ? AND `path_hash` = ?) OR `fileid` = ?');
		}
		$result = $query->execute(array($storage, $pathHash, $id));
		return (bool)$result->fetchRow();
	}

	/**
	 * get the new data array from the old one
	 *
	 * @param array $data the data from the old cache
	 * Example data array
	 * Array
	 *	(
	 *		[id] => 418
	 *		[path] => /tina/files/picture.jpg		//relative to datadir
	 *		[path_hash] => 66d4547e372888deed80b24fec9b192b
	 *		[parent] => 234
	 *		[name] => picture.jpg
	 *		[user] => tina
	 *		[size] => 1265283
	 *		[ctime] => 1363909709
	 *		[mtime] => 1363909709
	 *		[mimetype] => image/jpeg
	 *		[mimepart] => image
	 *		[encrypted] => 0
	 *		[versioned] => 0
	 *		[writable] => 1
	 *	)
	 *
	 * @return array
	 */
	function getNewData($data) {
		$newData = $data;
		/**
		 * @var \OC\Files\Storage\Storage $storage
		 * @var string $internalPath;
		 */
		list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($data['path']);
		if ($storage) {
			$newData['path_hash'] = md5($internalPath);
			$newData['path'] = $internalPath;
			$newData['storage'] = $this->getNumericId($storage);
			$newData['parent'] = ($internalPath === '') ? -1 : $data['parent'];
			$newData['permissions'] = ($data['writable']) ? \OCP\PERMISSION_ALL : \OCP\PERMISSION_READ;
			$newData['storage_object'] = $storage;
			$newData['mimetype'] = $this->getMimetypeId($newData['mimetype'], $storage);
			$newData['mimepart'] = $this->getMimetypeId($newData['mimepart'], $storage);
			$newData['etag'] = $this->getETag($data['path'], $data['user'], $internalPath, $storage);
			return $newData;
		} else {
			\OC_Log::write('core', 'Unable to migrate data from old cache for '.$data['path'].' because the storage was not found', \OC_Log::ERROR);
			return false;
		}
	}

	/**
	 * get a file`s E-Tag
	 *
	 * @param string $legacyPath in the form of a legacy path
	 * @param string $user the user ID the file referred to in path belongs to
	 * @param string $internalPath
	 * @param \OC\Files\Storage\Storage $storage
	 * @return string Etag
	 */
	function getETag($legacyPath, $user, $internalPath, $storage) {
		static $queryGetETag = null;
		static $queryCleanUp = null;

		//the path in the database is stored wo /$user/files
		//we need to strip it off, care is taken if user == files
		$offset = strpos($legacyPath,  '/files/', 2) + 6;
		$legacyPath = substr($legacyPath, $offset);

		//Look for the E-Tag in the old database
		if(is_null($queryGetETag)) {
			$queryGetETag = \OC_DB::prepare('
				SELECT `propertyvalue`
				FROM `*PREFIX*properties`
				WHERE `propertyname` = \'{DAV:}getetag\'
					AND `propertypath` = ?
					AND `userid` = ?
				LIMIT 1');
		}
		$result = $queryGetETag->execute(array($legacyPath, $user));
		$etag = $result->fetchOne();

		if($etag) {
			if(is_null($queryCleanUp)) {
				$queryCleanUp = \OC_DB::prepare('
					DELETE FROM `*PREFIX*properties`
					WHERE `propertyname` = \'{DAV:}getetag\'
						AND `propertypath` = ?
						AND `userid` = ?
					LIMIT 1
					');
			}

			//On success: remove the old DB entry and return the value
			$queryCleanUp->execute(array($legacyPath, $user));
			return $etag;
		}

		//No etag detected, determine it with new methods
		return $storage->getETag($internalPath);
	}

	/**
	 * get the numeric storage id
	 *
	 * @param \OC\Files\Storage\Storage $storage
	 * @return int<commit_msg>Change LIMIT in DB query respectively remove where not necessary<commit_after><?php
/**
 * Copyright (c) 2012 <NAME> <<EMAIL>>
 * This file is licensed under the Affero General Public License version 3 or
 * later.
 * See the COPYING-README file.
 */

namespace OC\Files\Cache;

class Upgrade {
	/**
	 * @var Legacy $legacy
	 */
	private $legacy;

	private $numericIds = array();

	private $mimeTypeIds = array();

	/**
	 * @param Legacy $legacy
	 */
	public function __construct($legacy) {
		$this->legacy = $legacy;
	}

	/**
	 * Preform a upgrade a path and it's childs
	 *
	 * @param string $path
	 * @param bool $mode
	 */
	function upgradePath($path, $mode = Scanner::SCAN_RECURSIVE) {
		if (!$this->legacy->hasItems()) {
			return;
		}
		\OC_Hook::emit('\OC\Files\Cache\Upgrade', 'migrate_path', $path);
		if ($row = $this->legacy->get($path)) {
			$data = $this->getNewData($row);
			if ($data) {
				$this->insert($data);
				$this->upgradeChilds($data['id'], $mode);
			}
		}
	}

	/**
	 * upgrade all child elements of an item
	 *
	 * @param int $id
	 * @param bool $mode
	 */
	function upgradeChilds($id, $mode = Scanner::SCAN_RECURSIVE) {
		$children = $this->legacy->getChildren($id);
		foreach ($children as $child) {
			$childData = $this->getNewData($child);
			\OC_Hook::emit('\OC\Files\Cache\Upgrade', 'migrate_path', $child['path']);
			if ($childData) {
				$this->insert($childData);
				if ($mode == Scanner::SCAN_RECURSIVE) {
					$this->upgradeChilds($child['id']);
				}
			}
		}
	}

	/**
	 * insert data into the new cache
	 *
	 * @param array $data the data for the new cache
	 */
	function insert($data) {
		static $insertQuery = null;
		if(is_null($insertQuery)) {
			$insertQuery = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache`
				( `fileid`, `storage`, `path`, `path_hash`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` )
				VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');
		}
		if (!$this->inCache($data['storage'], $data['path_hash'], $data['id'])) {
			$insertQuery->execute(array($data['id'], $data['storage'],
				$data['path'], $data['path_hash'], $data['parent'], $data['name'],
				$data['mimetype'], $data['mimepart'], $data['size'], $data['mtime'], $data['encrypted'], $data['etag']));
		}
	}

	/**
	 * check if an item is already in the new cache
	 *
	 * @param string $storage
	 * @param string $pathHash
	 * @param string $id
	 * @return bool
	 */
	function inCache($storage, $pathHash, $id) {
		static $query = null;
		if(is_null($query)) {
			$query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE (`storage` = ? AND `path_hash` = ?) OR `fileid` = ?');
		}
		$result = $query->execute(array($storage, $pathHash, $id));
		return (bool)$result->fetchRow();
	}

	/**
	 * get the new data array from the old one
	 *
	 * @param array $data the data from the old cache
	 * Example data array
	 * Array
	 *	(
	 *		[id] => 418
	 *		[path] => /tina/files/picture.jpg		//relative to datadir
	 *		[path_hash] => 66d4547e372888deed80b24fec9b192b
	 *		[parent] => 234
	 *		[name] => picture.jpg
	 *		[user] => tina
	 *		[size] => 1265283
	 *		[ctime] => 1363909709
	 *		[mtime] => 1363909709
	 *		[mimetype] => image/jpeg
	 *		[mimepart] => image
	 *		[encrypted] => 0
	 *		[versioned] => 0
	 *		[writable] => 1
	 *	)
	 *
	 * @return array
	 */
	function getNewData($data) {
		$newData = $data;
		/**
		 * @var \OC\Files\Storage\Storage $storage
		 * @var string $internalPath;
		 */
		list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($data['path']);
		if ($storage) {
			$newData['path_hash'] = md5($internalPath);
			$newData['path'] = $internalPath;
			$newData['storage'] = $this->getNumericId($storage);
			$newData['parent'] = ($internalPath === '') ? -1 : $data['parent'];
			$newData['permissions'] = ($data['writable']) ? \OCP\PERMISSION_ALL : \OCP\PERMISSION_READ;
			$newData['storage_object'] = $storage;
			$newData['mimetype'] = $this->getMimetypeId($newData['mimetype'], $storage);
			$newData['mimepart'] = $this->getMimetypeId($newData['mimepart'], $storage);
			$newData['etag'] = $this->getETag($data['path'], $data['user'], $internalPath, $storage);
			return $newData;
		} else {
			\OC_Log::write('core', 'Unable to migrate data from old cache for '.$data['path'].' because the storage was not found', \OC_Log::ERROR);
			return false;
		}
	}

	/**
	 * get a file`s E-Tag
	 *
	 * @param string $legacyPath in the form of a legacy path
	 * @param string $user the user ID the file referred to in path belongs to
	 * @param string $internalPath
	 * @param \OC\Files\Storage\Storage $storage
	 * @return string Etag
	 */
	function getETag($legacyPath, $user, $internalPath, $storage) {
		static $queryGetETag = null;
		static $queryCleanUp = null;

		//the path in the database is stored wo /$user/files
		//we need to strip it off, care is taken if user == files
		$offset = strpos($legacyPath,  '/files/', 2) + 6;
		$legacyPath = substr($legacyPath, $offset);

		//Look for the E-Tag in the old database
		if(is_null($queryGetETag)) {
			$queryGetETag = \OC_DB::prepare('
				SELECT `propertyvalue`
				FROM `*PREFIX*properties`
				WHERE `propertyname` = \'{DAV:}getetag\'
					AND `propertypath` = ?
					AND `userid` = ?
				', 1);
		}
		$result = $queryGetETag->execute(array($legacyPath, $user));
		$etag = $result->fetchOne();

		if($etag) {
			if(is_null($queryCleanUp)) {
				$queryCleanUp = \OC_DB::prepare('
					DELETE FROM `*PREFIX*properties`
					WHERE `propertyname` = \'{DAV:}getetag\'
						AND `propertypath` = ?
						AND `userid` = ?
					');
			}

			//On success: remove the old DB entry and return the value
			$queryCleanUp->execute(array($legacyPath, $user));
			return $etag;
		}

		//No etag detected, determine it with new methods
		return $storage->getETag($internalPath);
	}

	/**
	 * get the numeric storage id
	 *
	 * @param \OC\Files\Storage\Storage $storage
	 * @return int
{'fraction_non_alphanumeric': 0.18862022319918836, 'fraction_numerical': 0.011244504565437944, 'mean_word_length': 3.6009334889148192, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 87, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1433732', 'n_tokens_mistral': 4793, 'n_tokens_neox': 4164, 'n_words': 989}