2012-02-18 06:56:20 +04:00
< ? php
/**
2013-07-13 19:02:07 +04:00
* ownCloud
*
* @ author Michael Gapczynski
* @ copyright 2012 Michael Gapczynski mtgap @ owncloud . com
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation ; either
* version 3 of the License , or any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details .
*
* You should have received a copy of the GNU Affero General Public
* License along with this library . If not , see < http :// www . gnu . org / licenses />.
*/
2012-02-18 06:56:20 +04:00
2012-09-07 20:30:48 +04:00
namespace OC\Files\Storage ;
2013-05-17 22:33:37 +04:00
set_include_path ( get_include_path () . PATH_SEPARATOR .
\OC_App :: getAppPath ( 'files_external' ) . '/3rdparty/google-api-php-client/src' );
require_once 'Google_Client.php' ;
require_once 'contrib/Google_DriveService.php' ;
2012-02-29 04:15:49 +04:00
2012-09-07 20:30:48 +04:00
class Google extends \OC\Files\Storage\Common {
2012-02-27 23:59:41 +04:00
2012-10-12 01:06:57 +04:00
private $id ;
2013-05-17 04:09:32 +04:00
private $service ;
private $driveFiles ;
2012-02-27 23:59:41 +04:00
2012-05-02 22:38:22 +04:00
private static $tempFiles = array ();
2013-05-17 04:09:32 +04:00
// Google Doc mimetypes
const FOLDER = 'application/vnd.google-apps.folder' ;
const DOCUMENT = 'application/vnd.google-apps.document' ;
const SPREADSHEET = 'application/vnd.google-apps.spreadsheet' ;
const DRAWING = 'application/vnd.google-apps.drawing' ;
const PRESENTATION = 'application/vnd.google-apps.presentation' ;
2013-05-25 19:10:20 +04:00
/**
* check if curl is installed
*/
public static function checkDependencies () {
if ( function_exists ( 'curl_init' )) {
return true ;
} else {
$l = new \OC_L10N ( 'files_external' );
2013-05-30 19:37:47 +04:00
return $l -> t ( '<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of Google Drive is not possible. Please ask your system administrator to install it.' );
2013-05-25 19:10:20 +04:00
}
}
2012-08-14 01:07:56 +04:00
public function __construct ( $params ) {
2013-05-17 04:09:32 +04:00
if ( isset ( $params [ 'configured' ]) && $params [ 'configured' ] === 'true'
&& isset ( $params [ 'client_id' ]) && isset ( $params [ 'client_secret' ])
2012-11-30 19:27:11 +04:00
&& isset ( $params [ 'token' ])
) {
2013-05-17 04:09:32 +04:00
$client = new \Google_Client ();
$client -> setClientId ( $params [ 'client_id' ]);
$client -> setClientSecret ( $params [ 'client_secret' ]);
$client -> setScopes ( array ( 'https://www.googleapis.com/auth/drive' ));
$client -> setUseObjects ( true );
$client -> setAccessToken ( $params [ 'token' ]);
$this -> service = new \Google_DriveService ( $client );
$token = json_decode ( $params [ 'token' ], true );
2013-06-05 02:07:14 +04:00
$this -> id = 'google::' . substr ( $params [ 'client_id' ], 0 , 30 ) . $token [ 'created' ];
2012-08-14 01:07:56 +04:00
} else {
2012-09-07 20:30:48 +04:00
throw new \Exception ( 'Creating \OC\Files\Storage\Google storage failed' );
2012-08-14 01:07:56 +04:00
}
2012-02-27 23:59:41 +04:00
}
2013-05-17 04:09:32 +04:00
public function getId () {
return $this -> id ;
2012-02-27 23:59:41 +04:00
}
2012-11-30 19:27:11 +04:00
/**
2013-05-17 04:09:32 +04:00
* Get the Google_DriveFile object for the specified path
* @ param string $path
2014-02-19 12:31:54 +04:00
* @ return string
2012-11-30 19:27:11 +04:00
*/
2013-05-17 04:09:32 +04:00
private function getDriveFile ( $path ) {
// Remove leading and trailing slashes
2013-07-23 18:50:14 +04:00
$path = trim ( $path , '/' );
2013-05-17 04:09:32 +04:00
if ( isset ( $this -> driveFiles [ $path ])) {
return $this -> driveFiles [ $path ];
} else if ( $path === '' ) {
$root = $this -> service -> files -> get ( 'root' );
$this -> driveFiles [ $path ] = $root ;
return $root ;
2012-02-29 04:15:49 +04:00
} else {
2013-05-17 04:09:32 +04:00
// Google Drive SDK does not have methods for retrieving files by path
// Instead we must find the id of the parent folder of the file
$parentId = $this -> getDriveFile ( '' ) -> getId ();
$folderNames = explode ( '/' , $path );
$path = '' ;
// Loop through each folder of this path to get to the file
foreach ( $folderNames as $name ) {
// Reconstruct path from beginning
if ( $path === '' ) {
$path .= $name ;
} else {
$path .= '/' . $name ;
}
if ( isset ( $this -> driveFiles [ $path ])) {
$parentId = $this -> driveFiles [ $path ] -> getId ();
} else {
2013-07-13 19:02:07 +04:00
$q = " title=' " . $name . " ' and ' " . $parentId . " ' in parents and trashed = false " ;
2013-05-17 04:09:32 +04:00
$result = $this -> service -> files -> listFiles ( array ( 'q' => $q )) -> getItems ();
if ( ! empty ( $result )) {
// Google Drive allows files with the same name, ownCloud doesn't
if ( count ( $result ) > 1 ) {
$this -> onDuplicateFileDetected ( $path );
return false ;
} else {
$file = current ( $result );
$this -> driveFiles [ $path ] = $file ;
$parentId = $file -> getId ();
}
} else {
// Google Docs have no extension in their title, so try without extension
$pos = strrpos ( $path , '.' );
if ( $pos !== false ) {
$pathWithoutExt = substr ( $path , 0 , $pos );
$file = $this -> getDriveFile ( $pathWithoutExt );
if ( $file ) {
// Switch cached Google_DriveFile to the correct index
unset ( $this -> driveFiles [ $pathWithoutExt ]);
$this -> driveFiles [ $path ] = $file ;
$parentId = $file -> getId ();
} else {
return false ;
}
} else {
return false ;
}
}
2012-03-24 22:49:44 +04:00
}
}
2013-05-17 04:09:32 +04:00
return $this -> driveFiles [ $path ];
2012-02-29 04:15:49 +04:00
}
2012-02-27 23:59:41 +04:00
}
2013-07-13 19:02:07 +04:00
/**
* Set the Google_DriveFile object in the cache
* @ param string $path
* @ param Google_DriveFile | false $file
*/
private function setDriveFile ( $path , $file ) {
2013-07-23 18:50:14 +04:00
$path = trim ( $path , '/' );
2013-07-13 19:02:07 +04:00
$this -> driveFiles [ $path ] = $file ;
if ( $file === false ) {
// Set all child paths as false
$len = strlen ( $path );
foreach ( $this -> driveFiles as $key => $file ) {
if ( substr ( $key , 0 , $len ) === $path ) {
$this -> driveFiles [ $key ] = false ;
}
}
}
}
2013-05-17 04:09:32 +04:00
/**
* Write a log message to inform about duplicate file names
* @ param string $path
*/
private function onDuplicateFileDetected ( $path ) {
$about = $this -> service -> about -> get ();
$user = $about -> getName ();
\OCP\Util :: writeLog ( 'files_external' ,
'Ignoring duplicate file name: ' . $path . ' on Google Drive for Google user: ' . $user ,
2013-07-13 19:02:07 +04:00
\OCP\Util :: INFO
);
2012-02-29 04:15:49 +04:00
}
2012-08-29 10:42:49 +04:00
2013-05-17 04:09:32 +04:00
/**
* Generate file extension for a Google Doc , choosing Open Document formats for download
* @ param string $mimetype
* @ return string
*/
private function getGoogleDocExtension ( $mimetype ) {
if ( $mimetype === self :: DOCUMENT ) {
return 'odt' ;
} else if ( $mimetype === self :: SPREADSHEET ) {
return 'ods' ;
} else if ( $mimetype === self :: DRAWING ) {
return 'jpg' ;
} else if ( $mimetype === self :: PRESENTATION ) {
// Download as .odp is not available
return 'pdf' ;
} else {
return '' ;
}
2012-10-12 01:06:57 +04:00
}
2012-02-29 04:15:49 +04:00
2012-02-27 23:59:41 +04:00
public function mkdir ( $path ) {
2013-07-13 19:02:07 +04:00
if ( ! $this -> is_dir ( $path )) {
$parentFolder = $this -> getDriveFile ( dirname ( $path ));
if ( $parentFolder ) {
$folder = new \Google_DriveFile ();
$folder -> setTitle ( basename ( $path ));
$folder -> setMimeType ( self :: FOLDER );
$parent = new \Google_ParentReference ();
$parent -> setId ( $parentFolder -> getId ());
$folder -> setParents ( array ( $parent ));
$result = $this -> service -> files -> insert ( $folder );
if ( $result ) {
$this -> setDriveFile ( $path , $result );
}
return ( bool ) $result ;
}
2012-02-27 23:59:41 +04:00
}
2013-07-13 19:02:07 +04:00
return false ;
2012-02-27 23:59:41 +04:00
}
2012-02-18 06:56:20 +04:00
2012-02-27 23:59:41 +04:00
public function rmdir ( $path ) {
2013-07-23 18:50:14 +04:00
if ( trim ( $path , '/' ) === '' ) {
2013-07-13 19:02:07 +04:00
$dir = $this -> opendir ( $path );
2013-09-04 15:06:04 +04:00
if ( is_resource ( $dir )) {
while (( $file = readdir ( $dir )) !== false ) {
if ( ! \OC\Files\Filesystem :: isIgnoredDir ( $file )) {
if ( ! $this -> unlink ( $path . '/' . $file )) {
return false ;
}
2013-07-13 19:02:07 +04:00
}
}
2013-09-04 15:06:04 +04:00
closedir ( $dir );
2013-07-13 19:02:07 +04:00
}
$this -> driveFiles = array ();
return true ;
} else {
return $this -> unlink ( $path );
}
2012-02-27 23:59:41 +04:00
}
public function opendir ( $path ) {
2013-05-17 04:09:32 +04:00
// Remove leading and trailing slashes
$path = trim ( $path , '/' );
$folder = $this -> getDriveFile ( $path );
if ( $folder ) {
$files = array ();
$duplicates = array ();
$pageToken = true ;
while ( $pageToken ) {
$params = array ();
if ( $pageToken !== true ) {
$params [ 'pageToken' ] = $pageToken ;
2012-02-29 04:15:49 +04:00
}
2013-07-13 19:02:07 +04:00
$params [ 'q' ] = " ' " . $folder -> getId () . " ' in parents and trashed = false " ;
2013-05-17 04:09:32 +04:00
$children = $this -> service -> files -> listFiles ( $params );
foreach ( $children -> getItems () as $child ) {
$name = $child -> getTitle ();
// Check if this is a Google Doc i.e. no extension in name
2013-07-13 19:02:07 +04:00
if ( $child -> getFileExtension () === ''
2013-05-17 04:09:32 +04:00
&& $child -> getMimeType () !== self :: FOLDER
) {
$name .= '.' . $this -> getGoogleDocExtension ( $child -> getMimeType ());
}
if ( $path === '' ) {
$filepath = $name ;
} else {
$filepath = $path . '/' . $name ;
}
// Google Drive allows files with the same name, ownCloud doesn't
// Prevent opendir() from returning any duplicate files
2013-07-13 19:02:07 +04:00
$key = array_search ( $name , $files );
if ( $key !== false || isset ( $duplicates [ $filepath ])) {
if ( ! isset ( $duplicates [ $filepath ])) {
$duplicates [ $filepath ] = true ;
$this -> setDriveFile ( $filepath , false );
unset ( $files [ $key ]);
$this -> onDuplicateFileDetected ( $filepath );
}
2013-05-17 04:09:32 +04:00
} else {
// Cache the Google_DriveFile for future use
2013-07-13 19:02:07 +04:00
$this -> setDriveFile ( $filepath , $child );
2013-05-17 04:09:32 +04:00
$files [] = $name ;
2012-03-24 22:49:44 +04:00
}
2012-02-27 23:59:41 +04:00
}
2013-05-17 04:09:32 +04:00
$pageToken = $children -> getNextPageToken ();
}
\OC\Files\Stream\Dir :: register ( 'google' . $path , $files );
return opendir ( 'fakedir://google' . $path );
} else {
return false ;
2012-02-29 04:15:49 +04:00
}
2012-02-27 23:59:41 +04:00
}
2012-02-29 04:15:49 +04:00
public function stat ( $path ) {
2013-05-17 04:09:32 +04:00
$file = $this -> getDriveFile ( $path );
if ( $file ) {
$stat = array ();
if ( $this -> filetype ( $path ) === 'dir' ) {
$stat [ 'size' ] = 0 ;
} else {
2013-05-17 19:42:14 +04:00
// Check if this is a Google Doc
if ( $this -> getMimeType ( $path ) !== $file -> getMimeType ()) {
// Return unknown file size
2013-07-25 18:14:46 +04:00
$stat [ 'size' ] = \OC\Files\SPACE_UNKNOWN ;
2013-05-17 19:42:14 +04:00
} else {
$stat [ 'size' ] = $file -> getFileSize ();
}
2012-11-30 19:27:11 +04:00
}
2013-05-17 04:09:32 +04:00
$stat [ 'atime' ] = strtotime ( $file -> getLastViewedByMeDate ());
$stat [ 'mtime' ] = strtotime ( $file -> getModifiedDate ());
$stat [ 'ctime' ] = strtotime ( $file -> getCreatedDate ());
2012-03-24 22:49:44 +04:00
return $stat ;
2013-05-17 04:09:32 +04:00
} else {
return false ;
2012-03-24 22:49:44 +04:00
}
2012-02-29 04:15:49 +04:00
}
public function filetype ( $path ) {
2013-05-17 04:09:32 +04:00
if ( $path === '' ) {
2012-02-29 04:15:49 +04:00
return 'dir' ;
2012-11-30 19:27:11 +04:00
} else {
2013-05-17 04:09:32 +04:00
$file = $this -> getDriveFile ( $path );
if ( $file ) {
if ( $file -> getMimeType () === self :: FOLDER ) {
return 'dir' ;
} else {
return 'file' ;
2012-02-27 23:59:41 +04:00
}
2013-05-17 04:09:32 +04:00
} else {
return false ;
2012-02-27 23:59:41 +04:00
}
}
}
2012-07-25 01:42:07 +04:00
public function isUpdatable ( $path ) {
2013-05-17 04:09:32 +04:00
$file = $this -> getDriveFile ( $path );
if ( $file ) {
return $file -> getEditable ();
2012-11-30 19:27:11 +04:00
} else {
2013-05-17 04:09:32 +04:00
return false ;
2012-02-27 23:59:41 +04:00
}
}
2012-08-29 10:42:49 +04:00
2012-02-27 23:59:41 +04:00
public function file_exists ( $path ) {
2013-05-17 04:09:32 +04:00
return ( bool ) $this -> getDriveFile ( $path );
2012-02-27 23:59:41 +04:00
}
2012-08-29 10:42:49 +04:00
2012-02-27 23:59:41 +04:00
public function unlink ( $path ) {
2013-05-17 04:09:32 +04:00
$file = $this -> getDriveFile ( $path );
if ( $file ) {
2013-07-13 19:02:07 +04:00
$result = $this -> service -> files -> trash ( $file -> getId ());
if ( $result ) {
$this -> setDriveFile ( $path , false );
}
return ( bool ) $result ;
2013-05-17 04:09:32 +04:00
} else {
return false ;
2012-02-27 23:59:41 +04:00
}
}
2012-02-29 04:15:49 +04:00
public function rename ( $path1 , $path2 ) {
2013-05-17 04:09:32 +04:00
$file = $this -> getDriveFile ( $path1 );
if ( $file ) {
if ( dirname ( $path1 ) === dirname ( $path2 )) {
$file -> setTitle ( basename (( $path2 )));
2012-05-02 22:38:22 +04:00
} else {
2013-05-17 04:09:32 +04:00
// Change file parent
$parentFolder2 = $this -> getDriveFile ( dirname ( $path2 ));
if ( $parentFolder2 ) {
$parent = new \Google_ParentReference ();
$parent -> setId ( $parentFolder2 -> getId ());
$file -> setParents ( array ( $parent ));
2013-07-13 19:02:07 +04:00
} else {
return false ;
2012-02-29 04:15:49 +04:00
}
}
2013-07-13 19:02:07 +04:00
$result = $this -> service -> files -> patch ( $file -> getId (), $file );
if ( $result ) {
$this -> setDriveFile ( $path1 , false );
$this -> setDriveFile ( $path2 , $result );
}
return ( bool ) $result ;
2013-05-17 04:09:32 +04:00
} else {
return false ;
2012-02-29 04:15:49 +04:00
}
2012-02-27 23:59:41 +04:00
}
2012-02-29 04:15:49 +04:00
public function fopen ( $path , $mode ) {
2013-05-17 04:09:32 +04:00
$pos = strrpos ( $path , '.' );
if ( $pos !== false ) {
$ext = substr ( $path , $pos );
} else {
$ext = '' ;
}
2012-05-02 22:38:22 +04:00
switch ( $mode ) {
case 'r' :
case 'rb' :
2013-05-17 04:09:32 +04:00
$file = $this -> getDriveFile ( $path );
if ( $file ) {
$exportLinks = $file -> getExportLinks ();
$mimetype = $this -> getMimeType ( $path );
$downloadUrl = null ;
if ( $exportLinks && isset ( $exportLinks [ $mimetype ])) {
$downloadUrl = $exportLinks [ $mimetype ];
} else {
$downloadUrl = $file -> getDownloadUrl ();
}
if ( isset ( $downloadUrl )) {
$request = new \Google_HttpRequest ( $downloadUrl , 'GET' , null , null );
$httpRequest = \Google_Client :: $io -> authenticatedRequest ( $request );
if ( $httpRequest -> getResponseHttpCode () == 200 ) {
$tmpFile = \OC_Helper :: tmpFile ( $ext );
$data = $httpRequest -> getResponseBody ();
file_put_contents ( $tmpFile , $data );
return fopen ( $tmpFile , $mode );
}
}
2012-05-02 22:38:22 +04:00
}
2013-07-13 19:02:07 +04:00
return false ;
2012-05-02 22:38:22 +04:00
case 'w' :
case 'wb' :
case 'a' :
case 'ab' :
case 'r+' :
case 'w+' :
case 'wb+' :
case 'a+' :
case 'x' :
case 'x+' :
case 'c' :
case 'c+' :
2012-09-07 20:30:48 +04:00
$tmpFile = \OC_Helper :: tmpFile ( $ext );
2013-01-28 18:34:15 +04:00
\OC\Files\Stream\Close :: registerCallback ( $tmpFile , array ( $this , 'writeBack' ));
2012-05-02 22:38:22 +04:00
if ( $this -> file_exists ( $path )) {
2013-05-17 04:09:32 +04:00
$source = $this -> fopen ( $path , 'rb' );
2012-05-02 22:38:22 +04:00
file_put_contents ( $tmpFile , $source );
}
self :: $tempFiles [ $tmpFile ] = $path ;
return fopen ( 'close://' . $tmpFile , $mode );
2012-02-29 04:15:49 +04:00
}
2012-02-27 23:59:41 +04:00
}
2012-05-02 22:38:22 +04:00
public function writeBack ( $tmpFile ) {
if ( isset ( self :: $tempFiles [ $tmpFile ])) {
2013-05-17 04:09:32 +04:00
$path = self :: $tempFiles [ $tmpFile ];
$parentFolder = $this -> getDriveFile ( dirname ( $path ));
if ( $parentFolder ) {
// TODO Research resumable upload
2013-07-13 19:02:07 +04:00
$mimetype = \OC_Helper :: getMimeType ( $tmpFile );
2013-05-17 04:09:32 +04:00
$data = file_get_contents ( $tmpFile );
$params = array (
'data' => $data ,
'mimeType' => $mimetype ,
);
2013-07-13 19:02:07 +04:00
$result = false ;
2013-05-17 04:09:32 +04:00
if ( $this -> file_exists ( $path )) {
2013-07-13 19:02:07 +04:00
$file = $this -> getDriveFile ( $path );
$result = $this -> service -> files -> update ( $file -> getId (), $file , $params );
2012-05-02 22:38:22 +04:00
} else {
2013-07-13 19:02:07 +04:00
$file = new \Google_DriveFile ();
$file -> setTitle ( basename ( $path ));
$file -> setMimeType ( $mimetype );
$parent = new \Google_ParentReference ();
$parent -> setId ( $parentFolder -> getId ());
$file -> setParents ( array ( $parent ));
$result = $this -> service -> files -> insert ( $file , $params );
}
if ( $result ) {
$this -> setDriveFile ( $path , $result );
2012-05-02 22:38:22 +04:00
}
}
2013-05-17 04:09:32 +04:00
unlink ( $tmpFile );
2012-05-02 22:38:22 +04:00
}
}
2012-08-29 10:42:49 +04:00
2013-05-17 04:09:32 +04:00
public function getMimeType ( $path ) {
$file = $this -> getDriveFile ( $path );
if ( $file ) {
$mimetype = $file -> getMimeType ();
// Convert Google Doc mimetypes, choosing Open Document formats for download
if ( $mimetype === self :: FOLDER ) {
2012-02-29 04:15:49 +04:00
return 'httpd/unix-directory' ;
2013-05-17 04:09:32 +04:00
} else if ( $mimetype === self :: DOCUMENT ) {
return 'application/vnd.oasis.opendocument.text' ;
} else if ( $mimetype === self :: SPREADSHEET ) {
return 'application/x-vnd.oasis.opendocument.spreadsheet' ;
} else if ( $mimetype === self :: DRAWING ) {
return 'image/jpeg' ;
} else if ( $mimetype === self :: PRESENTATION ) {
// Download as .odp is not available
return 'application/pdf' ;
2012-02-29 04:15:49 +04:00
} else {
2013-05-17 04:09:32 +04:00
return $mimetype ;
2012-02-29 04:15:49 +04:00
}
2013-05-17 04:09:32 +04:00
} else {
return false ;
2012-02-29 04:15:49 +04:00
}
}
2012-08-29 10:42:49 +04:00
2012-02-27 23:59:41 +04:00
public function free_space ( $path ) {
2013-05-17 04:09:32 +04:00
$about = $this -> service -> about -> get ();
return $about -> getQuotaBytesTotal () - $about -> getQuotaBytesUsed ();
2012-02-27 23:59:41 +04:00
}
2012-08-29 10:42:49 +04:00
2012-03-24 22:49:44 +04:00
public function touch ( $path , $mtime = null ) {
2013-05-17 04:09:32 +04:00
$file = $this -> getDriveFile ( $path );
2013-07-13 19:02:07 +04:00
$result = false ;
2013-05-17 04:09:32 +04:00
if ( $file ) {
if ( isset ( $mtime )) {
$file -> setModifiedDate ( $mtime );
2013-07-13 19:02:07 +04:00
$result = $this -> service -> files -> patch ( $file -> getId (), $file , array (
2013-05-17 04:09:32 +04:00
'setModifiedDate' => true ,
));
} else {
2013-07-13 19:02:07 +04:00
$result = $this -> service -> files -> touch ( $file -> getId ());
2013-05-17 04:09:32 +04:00
}
} else {
2013-07-13 19:02:07 +04:00
$parentFolder = $this -> getDriveFile ( dirname ( $path ));
if ( $parentFolder ) {
$file = new \Google_DriveFile ();
$file -> setTitle ( basename ( $path ));
$parent = new \Google_ParentReference ();
$parent -> setId ( $parentFolder -> getId ());
$file -> setParents ( array ( $parent ));
$result = $this -> service -> files -> insert ( $file );
}
}
if ( $result ) {
$this -> setDriveFile ( $path , $result );
2013-05-17 04:09:32 +04:00
}
2013-07-13 19:02:07 +04:00
return ( bool ) $result ;
2012-02-27 23:59:41 +04:00
}
2012-02-29 04:15:49 +04:00
2012-12-28 21:00:48 +04:00
public function test () {
if ( $this -> free_space ( '' )) {
return true ;
}
return false ;
}
2013-05-31 05:45:16 +04:00
public function hasUpdated ( $path , $time ) {
2014-02-13 19:28:49 +04:00
$appConfig = \OC :: $server -> getAppConfig ();
2013-05-31 05:45:16 +04:00
if ( $this -> is_file ( $path )) {
return parent :: hasUpdated ( $path , $time );
} else {
// Google Drive doesn't change modified times of folders when files inside are updated
// Instead we use the Changes API to see if folders have been updated, and it's a pain
$folder = $this -> getDriveFile ( $path );
if ( $folder ) {
$result = false ;
$folderId = $folder -> getId ();
2014-02-13 19:28:49 +04:00
$startChangeId = $appConfig -> getValue ( 'files_external' , $this -> getId () . 'cId' );
2013-05-31 05:45:16 +04:00
$params = array (
'includeDeleted' => true ,
'includeSubscribed' => true ,
);
if ( isset ( $startChangeId )) {
$startChangeId = ( int ) $startChangeId ;
$largestChangeId = $startChangeId ;
$params [ 'startChangeId' ] = $startChangeId + 1 ;
} else {
$largestChangeId = 0 ;
}
$pageToken = true ;
while ( $pageToken ) {
if ( $pageToken !== true ) {
$params [ 'pageToken' ] = $pageToken ;
}
$changes = $this -> service -> changes -> listChanges ( $params );
if ( $largestChangeId === 0 || $largestChangeId === $startChangeId ) {
$largestChangeId = $changes -> getLargestChangeId ();
}
if ( isset ( $startChangeId )) {
// Check if a file in this folder has been updated
// There is no way to filter by folder at the API level...
foreach ( $changes -> getItems () as $change ) {
2013-07-13 19:02:07 +04:00
$file = $change -> getFile ();
if ( $file ) {
foreach ( $file -> getParents () as $parent ) {
if ( $parent -> getId () === $folderId ) {
$result = true ;
// Check if there are changes in different folders
} else if ( $change -> getId () <= $largestChangeId ) {
// Decrement id so this change is fetched when called again
$largestChangeId = $change -> getId ();
$largestChangeId -- ;
}
2013-05-31 05:45:16 +04:00
}
}
}
$pageToken = $changes -> getNextPageToken ();
} else {
// Assuming the initial scan just occurred and changes are negligible
break ;
}
}
2014-02-13 19:28:49 +04:00
$appConfig -> setValue ( 'files_external' , $this -> getId () . 'cId' , $largestChangeId );
2013-05-31 05:45:16 +04:00
return $result ;
}
}
return false ;
}
2013-08-18 13:02:08 +04:00
}