Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add uploading support for registered users #520

Closed
wants to merge 4 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add uploading support for registered users
oparoz committed Mar 1, 2016
commit f2c246dd84cdbd423a222fa39adee343787b709b
5 changes: 4 additions & 1 deletion controller/pagecontroller.php
Original file line number Diff line number Diff line change
@@ -82,7 +82,10 @@ public function index() {
$appName = $this->appName;

// Parameters sent to the template
$params = ['appName' => $appName];
$params = [
'appName' => $appName,
'uploadUrl' => $this->urlGenerator->linkTo('files', 'ajax/upload.php')
];

// Will render the page using the template found in templates/index.php
$response = new TemplateResponse($appName, 'index', $params);
13 changes: 13 additions & 0 deletions css/styles.css
Original file line number Diff line number Diff line change
@@ -284,3 +284,16 @@ http://www.bypeople.com/author/comatosed/*/
.icon-gallery {
background-image: url('../img/gallery-dark.svg');
}

.oc-dialog .fileexists .icon {
background-position: center center;
background-size: cover !important;
}

#uploadprogressbar {
margin-top: 5px;
}

.stop.icon-close {
margin-top: 5px;
}
5 changes: 4 additions & 1 deletion js/gallery.js
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
"use strict";
var Gallery = {
currentAlbum: null,
currentEtag: null,
config: {},
/** Map of the whole gallery, built as we navigate through folders */
albumMap: {},
@@ -391,6 +392,7 @@
var mimeType = null;
var mTime = null;
var etag = null;
var size = null;
var albumInfo = data.albuminfo;
var currentLocation = albumInfo.path;
// This adds a new node to the map for each parent album
@@ -406,8 +408,9 @@
mimeType = files[i].mimetype;
mTime = files[i].mtime;
etag = files[i].etag;
size = files[i].size;

image = new GalleryImage(path, path, fileId, mimeType, mTime, etag);
image = new GalleryImage(path, path, fileId, mimeType, mTime, etag, size);

// Determines the folder name for the image
var dir = OC.dirname(path);
16 changes: 9 additions & 7 deletions js/galleryimage.js
Original file line number Diff line number Diff line change
@@ -14,21 +14,23 @@
/**
* Creates a new image object to store information about a media file
*
* @param src
* @param path
* @param fileId
* @param mimeType
* @param mTime modification time
* @param etag
* @param {string} src
* @param {string} path
* @param {number} fileId
* @param {string} mimeType
* @param {number} mTime modification time
* @param {string} etag
* @param {number} size
* @constructor
*/
var GalleryImage = function (src, path, fileId, mimeType, mTime, etag) {
var GalleryImage = function (src, path, fileId, mimeType, mTime, etag, size) {
this.src = src;
this.path = path;
this.fileId = fileId;
this.mimeType = mimeType;
this.mTime = mTime;
this.etag = etag;
this.size = size;
this.thumbnail = null;
this.domDef = null;
this.spinner = null;
27 changes: 26 additions & 1 deletion js/galleryview.js
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@
var View = function () {
this.element = $('#gallery');
this.loadVisibleRows.loading = false;
this._setupUploader();
this.breadcrumb = new Gallery.Breadcrumb();
};

@@ -81,9 +82,10 @@

this.clear();

if (albumPath !== Gallery.currentAlbum) {
if (Gallery.albumMap[albumPath].etag !== Gallery.currentEtag) {
this.loadVisibleRows.loading = false;
Gallery.currentAlbum = albumPath;
Gallery.currentEtag = Gallery.albumMap[albumPath].etag;
this._setupButtons(albumPath);
}

@@ -200,6 +202,29 @@
$('#sort-date-button').hide();
},

/**
* Sets up our custom handlers for folder uploading operations
*
* We only want it to be called for that specific case as all other file uploading
* operations will call Files.highlightFiles
*
* @see OC.Upload.init/file_upload_param.done()
*
* @private
*/
_setupUploader: function () {
$('#file_upload_start').on('fileuploaddone', function (e, data) {
if (data.files[0] === data.originalFiles[data.originalFiles.length - 1]
&& data.files[0].relativePath) {

//Ask for a refresh of the photowall
Gallery.getFiles(Gallery.currentAlbum).done(function () {
Gallery.view.init(Gallery.currentAlbum);
});
}
});
},

/**
* Adds all the click handlers to buttons the first time they appear in the interface
*
2 changes: 1 addition & 1 deletion js/thumbnail.js
Original file line number Diff line number Diff line change
@@ -90,7 +90,7 @@ function Thumbnail (fileId, square) {
*/
loadBatch: function (ids, square) {
var map = (square) ? Thumbnails.squareMap : Thumbnails.map;
// Purely here as a precaution
// Prevents re-loading thumbnails when resizing the window
ids = ids.filter(function (id) {
return !map[id];
});
164 changes: 164 additions & 0 deletions js/upload-helper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/* global Gallery, Thumbnails */
/**
* OCA.FileList methods needed for file uploading
*
* This hack makes it possible to use the Files scripts as is, without having to import and
* maintain them in Gallery
*
* Empty methods are for the "new" button, if we want to implement that one day
*
* @type {{inList: FileList.inList, lastAction: FileList.lastAction, getUniqueName:
* FileList.getUniqueName, getCurrentDirectory: FileList.getCurrentDirectory, add:
* FileList.add, checkName: FileList.checkName}}
*/
var FileList = {
/**
* Makes sure the filename does not exist
*
* Gives an early chance to the user to abort the action, before uploading everything to the
* server.
* Albums are not supported as we don't have a full list of images contained in a sub-album
*
* @param fileName
* @returns {*}
*/
findFile: function (fileName) {
"use strict";
var path = Gallery.currentAlbum + '/' + fileName;
var galleryImage = Gallery.imageMap[path];
if (galleryImage) {
var fileInfo = {
name: fileName,
directory: Gallery.currentAlbum,
path: path,
etag: galleryImage.etag,
mtime: galleryImage.mTime * 1000, // Javascript gives the Epoch time in milliseconds
size: galleryImage.size
};
return fileInfo;
} else {
return null;
}
},

/**
* Refreshes the photowall
*
* Called at the end of the uploading process when 1 or multiple files are sent
* Never called with folders on Chrome, unless files are uploaded at the same time as folders
*
* @param fileList
*/
highlightFiles: function (fileList) {
"use strict";
//Ask for a refresh of the photowall
Gallery.getFiles(Gallery.currentAlbum).done(function () {
var fileId, path;
// Removes the cached thumbnails of files which have been re-uploaded
_(fileList).each(function (fileName) {
path = Gallery.currentAlbum + '/' + fileName;
if (Gallery.imageMap[path]) {
fileId = Gallery.imageMap[path].fileId;
if (Thumbnails.map[fileId]) {
delete Thumbnails.map[fileId];
}
}
});

Gallery.view.init(Gallery.currentAlbum);
});
},

/**
* Retrieves the current album
*
* @returns {string}
*/
getCurrentDirectory: function () {
"use strict";

// In Files, dirs start with a /
return '/' + Gallery.currentAlbum;
},
inList: function (filename) {
"use strict";

},
lastAction: function () {
"use strict";

},
getUniqueName: function (newname) {
"use strict";

},
add: function (fileData, options) {
"use strict";

},
checkName: function (name, newname, bool) {
"use strict";

}
};

/**
* OCA.Files methods needed for file uploading
*
* This hack makes it possible to use the Files scripts as is, without having to import and
* maintain them in Gallery
*
* @type {{isFileNameValid: Files.isFileNameValid, generatePreviewUrl: Files.generatePreviewUrl}}
*/
var Files = {
App: {fileList: {}},

isFileNameValid: function (name) {
"use strict";
var trimmedName = name.trim();
if (trimmedName === '.' || trimmedName === '..') {
throw t('files', '"{name}" is an invalid file name.', {name: name});
} else if (trimmedName.length === 0) {
throw t('files', 'File name cannot be empty.');
}
return true;

},

/**
* Generates a preview for the conflict dialogue
*
* Since Gallery uses the fileId and Files uses the path, we have to use the preview endpoint
* of Files
*/
generatePreviewUrl: function (urlSpec) {
"use strict";
var previewUrl;
var path = urlSpec.file;

// In Files, root files start with //
if (path.indexOf('//') === 0) {
path = path.substring(2);
} else {
// Directories start with /
path = path.substring(1);
}

if (Gallery.imageMap[path]) {
var fileId = Gallery.imageMap[path].fileId;
var thumbnail = Thumbnails.map[fileId];
previewUrl = thumbnail.image.src;
} else {
var previewDimension = 96;
urlSpec.x = Math.ceil(previewDimension * window.devicePixelRatio);
urlSpec.y = Math.ceil(previewDimension * window.devicePixelRatio);
urlSpec.forceIcon = 0;
previewUrl = OC.generateUrl('/core/preview.png?') + $.param(urlSpec);
}

return previewUrl;
}
};

OCA.Files = Files;
OCA.Files.App.fileList = FileList;
4 changes: 3 additions & 1 deletion service/searchmediaservice.php
Original file line number Diff line number Diff line change
@@ -202,13 +202,15 @@ private function addFileToResults($file) {
$mimeType = $file->getMimetype();
$mTime = $file->getMTime();
$etag = $file->getEtag();
$size = $file->getSize();

$imageData = [
'path' => $imagePath,
'fileid' => $imageId,
'mimetype' => $mimeType,
'mtime' => $mTime,
'etag' => $etag
'etag' => $etag,
'size' => $size
];

$this->images[] = $imageData;
31 changes: 30 additions & 1 deletion templates/part.content.php
Original file line number Diff line number Diff line change
@@ -27,9 +27,20 @@
'vendor/bigshot/bigshot-compressed',
'slideshow',
'slideshowcontrols',
'slideshowzoomablepreview'
'slideshowzoomablepreview',
'upload-helper'
]
);
script(
'files',
[
'upload',
'file-upload',
'jquery.fileupload',
'jquery.iframe-transport'
]
);

style(
$_['appName'],
[
@@ -41,6 +52,12 @@
'gallerybutton'
]
);
style(
'files',
[
'upload'
]
);
?>
<div id="controls">
<div id='breadcrumbs'></div>
@@ -67,6 +84,14 @@
</div>
</div>
</div>
<div id="uploadprogresswrapper">
<div id="uploadprogressbar"></div>
<button class="stop icon-close" style="display:none">
<span class="hidden-visually">
<?php p($l->t('Cancel upload')) ?>
</span>
</button>
</div>
<span class="right">
<!-- sharing button -->
<div id="share-button" class="button">
@@ -100,3 +125,7 @@
<div id="gallery" class="hascontrols"></div>
<div id="emptycontent" class="hidden"></div>
<input type="hidden" name="allowShareWithLink" id="allowShareWithLink" value="yes"/>
<div class="hiddenuploadfield">
<input type="file" id="file_upload_start" class="hiddenuploadfield" name="files[]"
data-url="<?php print_unescaped($_['uploadUrl']); ?>"/>
</div>
15 changes: 12 additions & 3 deletions tests/unit/GalleryUnitTest.php
Original file line number Diff line number Diff line change
@@ -93,7 +93,9 @@ protected function mockGetResourceFromIdWithBadFile($mockedObject, $fileId, $exc
*
* @return \PHPUnit_Framework_MockObject_MockObject
*/
protected function mockFile($fileId, $storageId = 'home::user', $isReadable = true, $path = ''
protected function mockFile(
$fileId, $storageId = 'home::user', $isReadable = true, $path = '',
$etag = "8603c11cd6c5d739f2c156c38b8db8c4", $size = 1024
) {
$storage = $this->mockGetStorage($storageId);
$file = $this->getMockBuilder('OCP\Files\File')
@@ -109,12 +111,19 @@ protected function mockFile($fileId, $storageId = 'home::user', $isReadable = tr
->willReturn($isReadable);
$file->method('getPath')
->willReturn($path);
$file->method('getEtag')
->willReturn($etag);
$file->method('getSize')
->willReturn($size);

return $file;
}

protected function mockJpgFile($fileId) {
$file = $this->mockFile($fileId);
protected function mockJpgFile(
$fileId, $storageId = 'home::user', $isReadable = true, $path = '',
$etag = "8603c11cd6c5d739f2c156c38b8db8c4", $size = 1024
) {
$file = $this->mockFile($fileId, $storageId, $isReadable, $path, $etag, $size);
$this->mockJpgFileMethods($file);

return $file;
13 changes: 12 additions & 1 deletion tests/unit/controller/PageControllerTest.php
Original file line number Diff line number Diff line change
@@ -69,7 +69,12 @@ protected function setUp() {


public function testIndex() {
$params = ['appName' => $this->appName];
$url = 'http://owncloud/ajax/upload.php';
$this->mockUrlToUploadEndpoint($url);
$params = [
'appName' => $this->appName,
'uploadUrl' => $url
];
$template = new TemplateResponse($this->appName, 'index', $params);

$response = $this->controller->index();
@@ -239,4 +244,10 @@ private function mockCookieGet($key, $value) {
->willReturn($value);
}

private function mockUrlToUploadEndpoint($url) {
$this->urlGenerator->expects($this->once())
->method('linkTo')
->with('files', 'ajax/upload.php')
->willReturn($url);
}
}
62 changes: 62 additions & 0 deletions tests/unit/service/SearchMediaServiceTest.php
Original file line number Diff line number Diff line change
@@ -205,6 +205,68 @@ public function testGetMediaFiles($topFolder, $result) {
$this->assertSame($result, sizeof($response));
}

public function providesFolderWithFilesData() {
$isReadable = true;
$mounted = false;
$mount = null;
$query = '.nomedia';
$queryResult = false;

$file1 = [
'fileid' => 11111,
'storageId' => 'home::user',
'isReadable' => true,
'path' => null,
'etag' => "8603c11cd6c5d739f2c156c38b8db8c4",
'size' => 1024,
'mimetype' => 'image/jpeg'
];


$folder1 = $this->mockFolder(
'home::user', 545454, [
$this->mockJpgFile(
$file1['fileid'], $file1['storageId'], $file1['isReadable'], $file1['path'],
$file1['etag'], $file1['size']
)
], $isReadable, $mounted, $mount, $query, $queryResult
);

return [
[
$folder1, [
[
'path' => $file1['path'],
'fileid' => $file1['fileid'],
'mimetype' => $file1['mimetype'],
'mtime' => null,
'etag' => $file1['etag'],
'size' => $file1['size']
]
]
]
];
}

/**
* @dataProvider providesFolderWithFilesData
*
* @param array $topFolder
* @param int $result
*/
public function testPropertiesOfGetMediaFiles($topFolder, $result) {
$supportedMediaTypes = [
'image/png',
'image/jpeg',
'image/gif'
];
$features = [];

$response = $this->service->getMediaFiles($topFolder, $supportedMediaTypes, $features);

$this->assertSame($result, $response);
}

/**
* @expectedException \OCA\Gallery\Service\NotFoundServiceException
*/