From 318d024cc1c7c5d8f32e828f2fc9b9f1db65a27c Mon Sep 17 00:00:00 2001
From: Robin Appelman <icewind1991@gmail.com>
Date: Sat, 16 Apr 2011 17:07:44 +0200
Subject: [PATCH] show size of folders in filebrowser

---
 files/templates/index.php |  2 +-
 lib/files.php             |  1 +
 lib/filestorage.php       | 70 ++++++++++++++++++++++++++++++++++++++-
 3 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/files/templates/index.php b/files/templates/index.php
index 695a3c45a9..f1fdafc27c 100644
--- a/files/templates/index.php
+++ b/files/templates/index.php
@@ -33,7 +33,7 @@
 			<tr>
 				<td class="selection"><input type="checkbox" /></td>
 				<td class="filename"><a style="background-image:url(<?php if($file["type"] == "dir") echo mimetype_icon("dir"); else echo mimetype_icon($file["mime"]); ?>)" href="<?php if($file["type"] == "dir") echo link_to("files", "index.php?dir=".$file["directory"]."/".$file["name"]); else echo link_to("files", "download.php?file=".$file["directory"]."/".$file["name"]); ?>" title=""><?php echo $file["name"]; ?></a></td>
-				<td class="filesize"><?php if($file["type"] != "dir" ) echo human_file_size($file["size"]); ?></td>
+				<td class="filesize"><?php echo human_file_size($file["size"]); ?></td>
 				<td class="date"><?php if($file["type"] != "dir") echo $file["date"]; ?></td>
 				<td class="fileaction"><a href="" title=""><img src="images/drop-arrow.png" alt="+" /></a></td>
 			</tr>
diff --git a/lib/files.php b/lib/files.php
index a1f983b6b2..642a7e7204 100644
--- a/lib/files.php
+++ b/lib/files.php
@@ -64,6 +64,7 @@ class OC_FILES {
 					$file['directory']=$directory;
 					$stat=OC_FILESYSTEM::stat($directory.'/'.$filename);
 					$file=array_merge($file,$stat);
+					$file['size']=OC_FILESYSTEM::filesize($directory.'/'.$filename);
 					$file['mime']=OC_FILES::getMimeType($directory .'/'. $filename);
 					$file['readable']=OC_FILESYSTEM::is_readable($directory .'/'. $filename);
 					$file['writeable']=OC_FILESYSTEM::is_writeable($directory .'/'. $filename);
diff --git a/lib/filestorage.php b/lib/filestorage.php
index 68f232d3a6..e7fb9e9d27 100644
--- a/lib/filestorage.php
+++ b/lib/filestorage.php
@@ -124,7 +124,11 @@ class OC_FILESTORAGE_LOCAL extends OC_FILESTORAGE{
 		return $filetype;
 	}
 	public function filesize($path){
-		return filesize($this->datadir.$path);
+		if($this->is_dir($path)){
+			return $this->getFolderSize($path);
+		}else{
+			return filesize($this->datadir.$path);
+		}
 	}
 	public function is_readable($path){
 		return is_readable($this->datadir.$path);
@@ -159,6 +163,7 @@ class OC_FILESTORAGE_LOCAL extends OC_FILESTORAGE{
 	public function file_put_contents($path,$data){
 		if($return=file_put_contents($this->datadir.$path,$data)){
 			$this->notifyObservers($path,OC_FILEACTION_WRITE);
+			$this->clearFolderSizeCache($path);
 		}
 	}
 	public function unlink($path){
@@ -197,11 +202,13 @@ class OC_FILESTORAGE_LOCAL extends OC_FILESTORAGE{
 				case 'x+':
 				case 'a+':
 					$this->notifyObservers($path,OC_FILEACTION_READ | OC_FILEACTION_WRITE);
+					$this->clearFolderSizeCache($path);
 					break;
 				case 'w':
 				case 'x':
 				case 'a':
 					$this->notifyObservers($path,OC_FILEACTION_WRITE);
+					$this->clearFolderSizeCache($path);
 					break;
 			}
 		}
@@ -440,5 +447,66 @@ class OC_FILESTORAGE_LOCAL extends OC_FILESTORAGE{
 		}
 		return $return;
 	}
+	
+	/**
+	 * @brief get the size of folder and it's content
+	 * @param string $path file path
+	 * @return int size of folder and it's content
+	 */
+	public function getFolderSize($path){
+		$query=OC_DB::prepare("SELECT size FROM *PREFIX*foldersize WHERE path=?");
+		$size=$query->execute(array($path))->fetchAll();
+		if(count($size)>0){// we already the size, just return it
+			return $size[0]['size'];
+		}else{//the size of the folder isn't know, calulate it
+			return $this->calculateFolderSize($path);
+		}
+	}
+	
+	/**
+	 * @brief calulate the size of folder and it's content and cache it
+	 * @param string $path file path
+	 * @return int size of folder and it's content
+	 */
+	public function calculateFolderSize($path){
+		$size=0;
+		if ($dh = $this->opendir($path)) {
+			while (($filename = readdir($dh)) !== false) {
+				if($filename!='.' and $filename!='..'){
+					$subFile=$path.'/'.$filename;
+					if($this->is_file($subFile)){
+						$size+=$this->filesize($subFile);
+					}else{
+						$size+=$this->calculateFolderSize($subFile);
+					}
+				}
+			}
+			$query=OC_DB::prepare("SELECT size FROM *PREFIX*foldersize WHERE path=?");
+			$hasSize=$query->execute(array($path))->fetchAll();
+			if(count($hasSize)>0){// yes, update it
+				$query=OC_DB::prepare("UPDATE *PREFIX*foldersize SET size=? WHERE path=?");
+				$result=$query->execute(array($size,$path));
+			}else{// no insert it
+				$query=OC_DB::prepare("INSERT INTO *PREFIX*foldersize VALUES(?,?)");
+				$result=$query->execute(array($path,$size));
+			}
+		}
+		return $size;
+	}
+	
+	/**
+	 * @brief clear the folder size cache of folders containing a file
+	 * @param string $path
+	 */
+	public function clearFolderSizeCache($path){
+		$path=dirname($path);
+		$query=OC_DB::prepare("DELETE FROM *PREFIX*foldersize WHERE path = ?");
+		$result=$query->execute(array($path));
+		if($path!='/'){
+			$parts=explode('/');
+			array_pop($parts);
+			$parent=implode('/',$parts);
+		}
+	}
 }
 ?>
\ No newline at end of file
-- 
GitLab