diff --git a/repository/s3/lib.php b/repository/s3/lib.php index 0d7fae98154..eb972d15e17 100644 --- a/repository/s3/lib.php +++ b/repository/s3/lib.php @@ -43,6 +43,23 @@ class repository_s3 extends repository { $this->s = new S3($this->access_key, $this->secret_key); } + /** + * Extracts the Bucket and URI from the path + * + * @param string $path path in this format 'bucket/path/to/folder/and/file' + * @return array including bucket and uri + */ + protected function explode_path($path) { + $parts = explode('/', $path, 2); + if (isset($parts[1]) && $parts[1] !== '') { + list($bucket, $uri) = $parts; + } else { + $bucket = $parts[0]; + $uri = ''; + } + return array($bucket, $uri); + } + /** * Get S3 file list * @@ -54,8 +71,13 @@ class repository_s3 extends repository { if (empty($this->access_key)) { die(json_encode(array('e'=>get_string('needaccesskey', 'repository_s3')))); } + $list = array(); $list['list'] = array(); + $list['path'] = array( + array('name' => get_string('pluginname', 'repository_s3'), 'path' => '') + ); + // the management interface url $list['manage'] = false; // dynamically loading @@ -65,29 +87,79 @@ class repository_s3 extends repository { $list['nologin'] = true; // set to true, the search button will be removed $list['nosearch'] = true; + $tree = array(); + if (empty($path)) { $buckets = $this->s->listBuckets(); foreach ($buckets as $bucket) { $folder = array( 'title' => $bucket, 'children' => array(), - 'thumbnail'=>$OUTPUT->pix_url('f/folder-32')->out(false), - 'path'=>$bucket - ); + 'thumbnail' => $OUTPUT->pix_url('f/folder-32')->out(false), + 'path' => $bucket + ); $tree[] = $folder; } } else { - $contents = $this->s->getBucket($path); - foreach ($contents as $file) { - $info = $this->s->getObjectInfo($path, baseName($file['name'])); - $tree[] = array( - 'title'=>$file['name'], - 'size'=>$file['size'], - 'date'=>userdate($file['time']), - 'source'=>$path.'/'.$file['name'], - 'thumbnail' => $OUTPUT->pix_url(file_extension_icon($file['name'], 32))->out(false) + + $files = array(); + $folders = array(); + list($bucket, $uri) = $this->explode_path($path); + + $contents = $this->s->getBucket($bucket, $uri, null, null, '/', true); + foreach ($contents as $object) { + + // If object has a prefix, it is a 'CommonPrefix', which we consider a folder + if (isset($object['prefix'])) { + $title = rtrim($object['prefix'], '/'); + } else { + $title = $object['name']; + } + + // Removes the prefix (folder path) from the title + if (strlen($uri) > 0) { + $title = substr($title, strlen($uri)); + // Check if title is empty and not zero + if (empty($title) && !is_numeric($title)) { + // Amazon returns the prefix itself, we skip it + continue; + } + } + + // This is a so-called CommonPrefix, we consider it as a folder + if (isset($object['prefix'])) { + $folders[] = array( + 'title' => $title, + 'children' => array(), + 'thumbnail' => $OUTPUT->pix_url('f/folder-32')->out(false), + 'path' => $bucket . '/' . $object['prefix'] ); + } else { + $files[] = array( + 'title' => $title, + 'size' => $object['size'], + 'datemodified' => $object['time'], + 'source' => $bucket . '/' . $object['name'], + 'thumbnail' => $OUTPUT->pix_url(file_extension_icon($title, 32))->out(false) + ); + } + } + $tree = array_merge($folders, $files); + } + + $trail = ''; + if (!empty($path)) { + $parts = explode('/', $path); + if (count($parts) > 1) { + foreach ($parts as $part) { + if (!empty($part)) { + $trail .= $part . '/'; + $list['path'][] = array('name' => $part, 'path' => $trail); + } + } + } else { + $list['path'][] = array('name' => $path, 'path' => $path); } } @@ -103,14 +175,11 @@ class repository_s3 extends repository { * @param string $file The file path in moodle * @return array The local stored path */ - public function get_file($filepath, $file) { - global $CFG; - $arr = explode('/', $filepath); - $bucket = $arr[0]; - $filename = $arr[1]; + public function get_file($filepath, $file = '') { + list($bucket, $uri) = $this->explode_path($filepath); $path = $this->prepare_file($file); - $this->s->getObject($bucket, $filename, $path); - return array('path'=>$path); + $this->s->getObject($bucket, $uri, $path); + return array('path' => $path); } /**