nextcloud/lib/filecache/update.php

210 lines
5.6 KiB
PHP

<?php
/**
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
/**
* handles updating the filecache according to outside changes
*/
class OC_FileCache_Update{
/**
* check if a file or folder is updated outside owncloud
* @param string path
* @param string root (optional)
* @return bool
*/
public static function hasUpdated($path,$root=false){
if($root===false){
$view=OC_Filesystem::getView();
}else{
$view=new OC_FilesystemView($root);
}
if(!$view->file_exists($path)){
return false;
}
$cachedData=OC_FileCache_Cached::get($path,$root);
if(isset($cachedData['mtime'])){
$cachedMTime=$cachedData['mtime'];
return $view->hasUpdated($path,$cachedMTime);
}else{//file not in cache, so it has to be updated
if(($path=='/' or $path=='') and $root===false){//dont auto update the home folder, it will be scanned
return false;
}
return true;
}
}
/**
* delete non existing files from the cache
*/
public static function cleanFolder($path,$root=false){
if($root===false){
$view=OC_Filesystem::getView();
}else{
$view=new OC_FilesystemView($root);
}
$cachedContent=OC_FileCache_Cached::getFolderContent($path,$root);
foreach($cachedContent as $fileData){
$path=$fileData['path'];
$file=$view->getRelativePath($path);
if(!$view->file_exists($file)){
if($root===false){//filesystem hooks are only valid for the default root
OC_Hook::emit('OC_Filesystem','post_delete',array('path'=>$file));
}else{
self::delete($file,$root);
}
}
}
}
/**
* update the cache according to changes in the folder
* @param string path
* @param string root (optional)
*/
public static function updateFolder($path,$root=false){
if($root===false){
$view=OC_Filesystem::getView();
}else{
$view=new OC_FilesystemView($root);
}
$dh=$view->opendir($path.'/');
if($dh){//check for changed/new files
while (($filename = readdir($dh)) !== false) {
if($filename != '.' and $filename != '..'){
$file=$path.'/'.$filename;
if(self::hasUpdated($file,$root)){
if($root===false){//filesystem hooks are only valid for the default root
OC_Hook::emit('OC_Filesystem','post_write',array('path'=>$file));
}else{
self::update($file,$root);
}
}
}
}
}
self::cleanFolder($path,$root);
//update the folder last, so we can calculate the size correctly
if($root===false){//filesystem hooks are only valid for the default root
OC_Hook::emit('OC_Filesystem','post_write',array('path'=>$path));
}else{
self::update($path,$root);
}
}
/**
* called when changes are made to files
* @param array $params
* @param string root (optional)
*/
public static function fileSystemWatcherWrite($params){
$path=$params['path'];
self::update($path);
}
/**
* called when files are deleted
* @param array $params
* @param string root (optional)
*/
public static function fileSystemWatcherDelete($params){
$path=$params['path'];
self::delete($path);
}
/**
* called when files are deleted
* @param array $params
* @param string root (optional)
*/
public static function fileSystemWatcherRename($params){
$oldPath=$params['oldpath'];
$newPath=$params['newpath'];
self::rename($oldPath,$newPath);
}
/**
* update the filecache according to changes to the fileysystem
* @param string path
* @param string root (optional)
*/
public static function update($path,$root=false){
if($root===false){
$view=OC_Filesystem::getView();
}else{
$view=new OC_FilesystemView($root);
}
$mimetype=$view->getMimeType($path);
$size=0;
$cached=OC_FileCache_Cached::get($path,$root);
$cachedSize=isset($cached['size'])?$cached['size']:0;
if($mimetype=='httpd/unix-directory'){
if(OC_FileCache::inCache($path,$root)){
$cachedContent=OC_FileCache_Cached::getFolderContent($path,$root);
foreach($cachedContent as $file){
$size+=$file['size'];
}
$mtime=$view->filemtime($path);
$ctime=$view->filectime($path);
$writable=$view->is_writable($path);
OC_FileCache::put($path,array('size'=>$size,'mtime'=>$mtime,'ctime'=>$ctime,'mimetype'=>$mimetype,'writable'=>$writable));
}else{
$count=0;
OC_FileCache::scan($path,null,$count,$root);
return; //increaseSize is already called inside scan
}
}else{
$size=OC_FileCache::scanFile($path,$root);
}
OC_FileCache::increaseSize(dirname($path),$size-$cachedSize,$root);
}
/**
* update the filesystem after a delete has been detected
* @param string path
* @param string root (optional)
*/
public static function delete($path,$root=false){
$cached=OC_FileCache_Cached::get($path,$root);
if(!isset($cached['size'])){
return;
}
$size=$cached['size'];
OC_FileCache::increaseSize(dirname($path),-$size,$root);
OC_FileCache::delete($path,$root);
}
/**
* update the filesystem after a rename has been detected
* @param string oldPath
* @param string newPath
* @param string root (optional)
*/
public static function rename($oldPath,$newPath,$root=false){
if(!OC_FileCache::inCache($oldPath,$root)){
return;
}
if($root===false){
$view=OC_Filesystem::getView();
}else{
$view=new OC_FilesystemView($root);
}
$cached=OC_FileCache_Cached::get($oldPath,$root);
$oldSize=$cached['size'];
$size=$view->filesize($newPath);
OC_FileCache::increaseSize(dirname($oldPath),-$oldSize,$root);
OC_FileCache::increaseSize(dirname($newPath),$oldSize,$root);
OC_FileCache::move($oldPath,$newPath);
}
}