From 19eb9f5109128d7727791932d0ff3d09c3986e04 Mon Sep 17 00:00:00 2001 From: Vinicius Cubas Brand Date: Mon, 11 Sep 2017 15:06:49 -0300 Subject: [PATCH 1/8] change OC_Hooks to EventDispatcher Signed-off-by: Vinicius Cubas Brand --- lib/Service/CirclesService.php | 2 ++ lib/Service/EventsService.php | 59 +++++++++++++++++++++------------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/lib/Service/CirclesService.php b/lib/Service/CirclesService.php index b6fdcb27e..530d3d977 100644 --- a/lib/Service/CirclesService.php +++ b/lib/Service/CirclesService.php @@ -262,6 +262,8 @@ public function settingsCircle($circleUniqueId, $settings) { } $this->circlesRequest->updateCircle($circle); + + $this->eventsService->onSettingsChange($circle); } catch (\Exception $e) { throw $e; } diff --git a/lib/Service/EventsService.php b/lib/Service/EventsService.php index 57459c212..007a8490c 100644 --- a/lib/Service/EventsService.php +++ b/lib/Service/EventsService.php @@ -35,6 +35,7 @@ use OCP\Activity\IManager; use OCP\IUser; use OCP\IUserManager; +use Symfony\Component\EventDispatcher\GenericEvent; class EventsService { @@ -106,7 +107,7 @@ function($user) use ($event) { $this->publishEvent($event, [$user]); } ); - \OC_Hook::emit('\OCA\Circles', 'onCircleCreation', [$circle]); + $this->dispatch('\OCA\Circles::onCircleCreation', ['circle' => $circle]); } @@ -132,7 +133,7 @@ public function onCircleDestruction(Circle $circle) { $circle->getUniqueId(), Member::LEVEL_MEMBER, true ) ); - \OC_Hook::emit('\OCA\Circles', 'onCircleDestruction', [$circle]); + $this->dispatch('\OCA\Circles::onCircleDestruction', ['circle' => $circle]); } @@ -176,7 +177,7 @@ public function onMemberNew(Circle $circle, Member $member) { ) ) ); - \OC_Hook::emit('\OCA\Circles', 'onMemberNew', [$circle, $member]); + $this->dispatch('\OCA\Circles::onMemberNew', ['circle' => $circle, 'member' => $member]); } @@ -232,7 +233,7 @@ private function onMemberInvited(Circle $circle, Member $member) { ) ) ); - \OC_Hook::emit('\OCA\Circles', 'onMemberInvited', [$circle, $member]); + $this->dispatch('\OCA\Circles::onMemberInvited', ['circle' => $circle, 'member' => $member]); } @@ -264,7 +265,7 @@ private function onMemberRequesting(Circle $circle, Member $member) { ) ) ); - \OC_Hook::emit('\OCA\Circles', 'onMemberRequesting', [$circle, $member]); + $this->dispatch('\OCA\Circles::onMemberRequesting', ['circle' => $circle, 'member' => $member]); } @@ -297,7 +298,7 @@ public function onMemberLeaving(Circle $circle, Member $member) { ) ) ); - \OC_Hook::emit('\OCA\Circles', 'onMemberLeaving', [$circle, $member]); + $this->dispatch('\OCA\Circles::onMemberLeaving', ['circle' => $circle, 'member' => $member]); } @@ -330,7 +331,7 @@ public function onMemberLevel(Circle $circle, Member $member) { $this->membersRequest->avoidDuplicateMembers($mods, [$member]); $this->publishEvent($event, $mods); - \OC_Hook::emit('\OCA\Circles', 'onMemberLevel', [$circle, $member]); + $this->dispatch('\OCA\Circles::onMemberLevel', ['circle' => $circle, 'member' => $member]); } @@ -355,7 +356,7 @@ private function onMemberOwner(Circle $circle, Member $member) { $circle->getUniqueId(), Member::LEVEL_MEMBER, true ) ); - \OC_Hook::emit('\OCA\Circles', 'onMemberOwner', [$circle, $member]); + $this->dispatch('\OCA\Circles::onMemberOwner', ['circle' => $circle, 'member' => $member]); } @@ -388,7 +389,7 @@ public function onGroupLink(Circle $circle, Member $group) { ); $this->publishEvent($event, $mods); - \OC_Hook::emit('\OCA\Circles', 'onGroupLink', [$circle, $group]); + $this->dispatch('\OCA\Circles::onGroupLink', ['circle' => $circle, 'group' => $group]); } @@ -421,7 +422,7 @@ public function onGroupUnlink(Circle $circle, Member $group) { ); $this->publishEvent($event, $mods); - \OC_Hook::emit('\OCA\Circles', 'onGroupUnlink', [$circle, $group]); + $this->dispatch('\OCA\Circles::onGroupUnlink', ['circle' => $circle, 'group' => $group]); } @@ -454,7 +455,7 @@ public function onGroupLevel(Circle $circle, Member $group) { ); $this->publishEvent($event, $mods); - \OC_Hook::emit('\OCA\Circles', 'onGroupLevel', [$circle, $group]); + $this->dispatch('\OCA\Circles::onGroupLevel', ['circle' => $circle, 'group' => $group]); } @@ -479,7 +480,7 @@ public function onLinkRequestSent(Circle $circle, FederatedLink $link) { $link->getCircleId(), Member::LEVEL_MODERATOR, true ) ); - \OC_Hook::emit('\OCA\Circles', 'onLinkRequestSent', [$circle, $link]); + $this->dispatch('\OCA\Circles::onLinkRequestSent', ['circle' => $circle, 'link' => $link]); } @@ -504,7 +505,7 @@ public function onLinkRequestReceived(Circle $circle, FederatedLink $link) { $link->getCircleId(), Member::LEVEL_MODERATOR, true ) ); - \OC_Hook::emit('\OCA\Circles', 'onLinkRequestReceived', [$circle, $link]); + $this->dispatch('\OCA\Circles::onLinkRequestReceived', ['circle' => $circle, 'link' => $link]); } @@ -529,7 +530,7 @@ public function onLinkRequestRejected(Circle $circle, FederatedLink $link) { $link->getCircleId(), Member::LEVEL_MODERATOR, true ) ); - \OC_Hook::emit('\OCA\Circles', 'onLinkRequestRejected', [$circle, $link]); + $this->dispatch('\OCA\Circles::onLinkRequestRejected', ['circle' => $circle, 'link' => $link]); } @@ -554,7 +555,7 @@ public function onLinkRequestCanceled(Circle $circle, FederatedLink $link) { $link->getCircleId(), Member::LEVEL_MODERATOR, true ) ); - \OC_Hook::emit('\OCA\Circles', 'onLinkRequestCanceled', [$circle, $link]); + $this->dispatch('\OCA\Circles::onLinkRequestCanceled', ['circle' => $circle, 'link' => $link]); } @@ -579,7 +580,7 @@ public function onLinkRequestAccepted(Circle $circle, FederatedLink $link) { $link->getCircleId(), Member::LEVEL_MODERATOR, true ) ); - \OC_Hook::emit('\OCA\Circles', 'onLinkRequestAccepted', [$circle, $link]); + $this->dispatch('\OCA\Circles::onLinkRequestAccepted', ['circle' => $circle, 'link' => $link]); } @@ -604,7 +605,7 @@ public function onLinkRequestAccepting(Circle $circle, FederatedLink $link) { $link->getCircleId(), Member::LEVEL_MODERATOR, true ) ); - \OC_Hook::emit('\OCA\Circles', 'onLinkRequestAccepting', [$circle, $link]); + $this->dispatch('\OCA\Circles::onLinkRequestAccepting', ['circle' => $circle, 'link' => $link]); } @@ -629,7 +630,7 @@ public function onLinkUp(Circle $circle, FederatedLink $link) { $link->getCircleId(), Member::LEVEL_MODERATOR, true ) ); - \OC_Hook::emit('\OCA\Circles', 'onLinkUp', [$circle, $link]); + $this->dispatch('\OCA\Circles::onLinkUp', ['circle' => $circle, 'link' => $link]); } @@ -654,7 +655,7 @@ public function onLinkDown(Circle $circle, FederatedLink $link) { $link->getCircleId(), Member::LEVEL_MODERATOR, true ) ); - \OC_Hook::emit('\OCA\Circles', 'onLinkDown', [$circle, $link]); + $this->dispatch('\OCA\Circles::onLinkDown', ['circle' => $circle, 'link' => $link]); } @@ -685,13 +686,24 @@ public function onLinkRemove(Circle $circle, FederatedLink $link) { $event->setSubject( $subject, ['circle' => $circle->getJson(false, true), 'link' => $link->getJson()] ); - + $this->publishEvent( $event, $this->membersRequest->forceGetMembers( $link->getCircleId(), Member::LEVEL_MODERATOR, true ) ); - \OC_Hook::emit('\OCA\Circles', 'onLinkRemove', [$circle, $link]); + $this->dispatch('\OCA\Circles::onLinkRemove', ['circle' => $circle, 'link' => $link]); + } + + /** + * onSettingsChange() + * + * Called when the circle's settings are changed + * + * @param Circle $circle + */ + public function onSettingsChange(Circle $circle) { + $this->dispatch('\OCA\Circles::onSettingsChange', ['circle' => $circle]); } @@ -733,6 +745,9 @@ private function publishEvent(IEvent $event, array $users) { $this->activityManager->publish($event); } } - + + private function dispatch($context, $arguments) { + \OC::$server->getEventDispatcher()->dispatch($context, new GenericEvent(null,$arguments)); + } } \ No newline at end of file From 6f9e03f950f080d3c1994d6337365ef020896825 Mon Sep 17 00:00:00 2001 From: Maxence Lange Date: Mon, 11 Sep 2017 17:33:32 -0100 Subject: [PATCH 2/8] eventDispatcher in automatic DI Signed-off-by: Maxence Lange --- lib/Service/EventsService.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/Service/EventsService.php b/lib/Service/EventsService.php index 007a8490c..d59100ddf 100644 --- a/lib/Service/EventsService.php +++ b/lib/Service/EventsService.php @@ -35,7 +35,7 @@ use OCP\Activity\IManager; use OCP\IUser; use OCP\IUserManager; -use Symfony\Component\EventDispatcher\GenericEvent; +use Symfony\Component\EventDispatcher\EventDispatcher; class EventsService { @@ -49,6 +49,9 @@ class EventsService { /** @var IUserManager */ private $userManager; + /** @var EventDispatcher */ + private $eventDispatcher; + /** @var CirclesRequest */ private $circlesRequest; @@ -65,17 +68,19 @@ class EventsService { * @param string $userId * @param IManager $activityManager * @param IUserManager $userManager + * @param EventDispatcher $eventDispatcher * @param CirclesRequest $circlesRequest * @param MembersRequest $membersRequest * @param MiscService $miscService */ public function __construct( $userId, IManager $activityManager, IUserManager $userManager, - CirclesRequest $circlesRequest, MembersRequest $membersRequest, MiscService $miscService + EventDispatcher $eventDispatcher, CirclesRequest $circlesRequest, MembersRequest $membersRequest, MiscService $miscService ) { $this->userId = $userId; $this->activityManager = $activityManager; $this->userManager = $userManager; + $this->eventDispatcher = $eventDispatcher; $this->circlesRequest = $circlesRequest; $this->membersRequest = $membersRequest; $this->miscService = $miscService; @@ -747,7 +752,7 @@ private function publishEvent(IEvent $event, array $users) { } private function dispatch($context, $arguments) { - \OC::$server->getEventDispatcher()->dispatch($context, new GenericEvent(null,$arguments)); + $this->eventDispatcher->dispatch($context, new GenericEvent(null,$arguments)); } } \ No newline at end of file From e04b7e0837926efba145f075ffbcd6275dae6354 Mon Sep 17 00:00:00 2001 From: Vinicius Cubas Brand Date: Fri, 29 Sep 2017 18:30:29 -0300 Subject: [PATCH 3/8] Creation of panel to see circles' shared files This commit inserts a panel in files visualization to allow filtering files that were shared to one or more circles. Depends on some other modifications in nextcloud core, that will be referenced in the PR. Signed-off-by: Vinicius Cubas Brand --- appinfo/app.php | 5 + css/circles.filelist.css | 39 ++++ js/circles.files.app.js | 113 ++++++++++ js/circles.files.list.js | 281 ++++++++++++++++++++++++ lib/Api/v1/Circles.php | 27 +++ lib/AppInfo/Application.php | 39 +++- lib/Db/CircleProviderRequestBuilder.php | 24 +- lib/Service/CirclesService.php | 21 +- lib/ShareByCircleProvider.php | 34 +++ list.php | 26 +++ templates/list.php | 38 ++++ 11 files changed, 638 insertions(+), 9 deletions(-) create mode 100644 css/circles.filelist.css create mode 100644 js/circles.files.app.js create mode 100644 js/circles.files.list.js create mode 100644 list.php create mode 100644 templates/list.php diff --git a/appinfo/app.php b/appinfo/app.php index 2c7abea37..e5ecc4421 100644 --- a/appinfo/app.php +++ b/appinfo/app.php @@ -6,6 +6,8 @@ * later. See the COPYING file. * * @author Maxence Lange + * @author Vinicius Cubas Brand + * * @copyright 2017 * @license GNU AGPL version 3 or any later version * @@ -28,3 +30,6 @@ $app->registerNavigation(); $app->registerSettingsAdmin(); +$app->registerFilesPlugin(); + + diff --git a/css/circles.filelist.css b/css/circles.filelist.css new file mode 100644 index 000000000..468482ca6 --- /dev/null +++ b/css/circles.filelist.css @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017 + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ +#app-content-circlesfilter .select2-container { + width: 30%; + margin-left: 10px; +} + +#app-content-circlesfilter .select2-choices { + white-space: nowrap; + text-overflow: ellipsis; + background: #fff; + color: #555; + box-sizing: content-box; + border-radius: 3px; + border: 1px solid #ddd; + padding: 0; + min-height: auto; +} + +.nav-icon-circlesfilter { + background-image: url('../img/black_circle.svg'); +} + +#app-sidebar .mainFileInfoView .tag-label { + cursor: pointer; + padding: 13px; +} + +#app-sidebar .mainFileInfoView .icon-tag { + opacity: .5; + vertical-align: middle; +} diff --git a/js/circles.files.app.js b/js/circles.files.app.js new file mode 100644 index 000000000..431b7868d --- /dev/null +++ b/js/circles.files.app.js @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017 Cooperativa EITA (eita.org.br) + * + * @author Vinicius Cubas Brand + * @author Daniel Tygel + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ + +var api = OCA.Circles.api; + +(function() { + if (!OCA.Circles) { + /** + * @namespace + */ + OCA.Circles = {}; + } + + OCA.Circles.App = { + + initFileList: function($el) { + if (this._fileList) { + return this._fileList; + } + + this._fileList = new OCA.Circles.FileList( + $el, + { + id: 'circles', + scrollContainer: $('#app-content'), + fileActions: this._createFileActions(), + config: OCA.Files.App.getFilesConfig() + } + ); + + this._fileList.appName = t('circles', 'Circles'); + return this._fileList; + }, + + removeFileList: function() { + if (this._fileList) { + this._fileList.$fileList.empty(); + } + }, + + _createFileActions: function() { + // inherit file actions from the files app + var fileActions = new OCA.Files.FileActions(); + // note: not merging the legacy actions because legacy apps are not + // compatible with the sharing overview and need to be adapted first + fileActions.registerDefaultActions(); + fileActions.merge(OCA.Files.fileActions); + + if (!this._globalActionsInitialized) { + // in case actions are registered later + this._onActionsUpdated = _.bind(this._onActionsUpdated, this); + OCA.Files.fileActions.on('setDefault.app-circles', this._onActionsUpdated); + OCA.Files.fileActions.on('registerAction.app-circles', this._onActionsUpdated); + this._globalActionsInitialized = true; + } + + // when the user clicks on a folder, redirect to the corresponding + // folder in the files app instead of opening it directly + fileActions.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename, context) { + OCA.Files.App.setActiveView('files', {silent: true}); + OCA.Files.App.fileList.changeDirectory(OC.joinPaths(context.$file.attr('data-path'), filename), true, true); + }); + fileActions.setDefault('dir', 'Open'); + return fileActions; + }, + + _onActionsUpdated: function(ev) { + if (!this._fileList) { + return; + } + + if (ev.action) { + this._fileList.fileActions.registerAction(ev.action); + } else if (ev.defaultAction) { + this._fileList.fileActions.setDefault( + ev.defaultAction.mime, + ev.defaultAction.name + ); + } + }, + + /** + * Destroy the app + */ + destroy: function() { + OCA.Files.fileActions.off('setDefault.app-circles', this._onActionsUpdated); + OCA.Files.fileActions.off('registerAction.app-circles', this._onActionsUpdated); + this.removeFileList(); + this._fileList = null; + delete this._globalActionsInitialized; + } + }; + +})(); + +$(document).ready(function() { + $('#app-content-circlesfilter').on('show', function(e) { + OCA.Circles.App.initFileList($(e.target)); + }); + $('#app-content-circlesfilter').on('hide', function() { + OCA.Circles.App.removeFileList(); + }); +}); diff --git a/js/circles.files.list.js b/js/circles.files.list.js new file mode 100644 index 000000000..f6984471f --- /dev/null +++ b/js/circles.files.list.js @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2017 EITA Cooperative + * + * @author Vinicius Brand + * @author Daniel Tygel + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ +(function() { + /** + * @class OCA.Circles.FileList + * @augments OCA.Files.FileList + * + * @classdesc Circles file list. + * Contains a list of files filtered by circles + * + * @param $el container element with existing markup for the #controls + * and a table + * @param [options] map of options, see other parameters + * @param {Array.} [options.circlesIds] array of system tag ids to + * filter by + */ + var FileList = function($el, options) { + this.initialize($el, options); + }; + FileList.prototype = _.extend({}, OCA.Files.FileList.prototype, + /** @lends OCA.Circles.FileList.prototype */ { + id: 'circlesfilter', + appName: t('circles', 'Circles\' files'), + + /** + * Array of system tag ids to filter by + * + * @type Array. + */ + _circlesIds: [], + _lastUsedTags: [], + + _clientSideSort: true, + _allowSelection: false, + + _filterField: null, + + /** + * @private + */ + initialize: function($el, options) { + OCA.Files.FileList.prototype.initialize.apply(this, arguments); + if (this.initialized) { + return; + } + + if (options && options.circlesIds) { + this._circlesIds = options.circlesIds; + } + + OC.Plugins.attach('OCA.Circles.FileList', this); + + var $controls = this.$el.find('#controls').empty(); + + this._initFilterField($controls); + }, + + destroy: function() { + this.$filterField.remove(); + + OCA.Files.FileList.prototype.destroy.apply(this, arguments); + }, + + _initFilterField: function($container) { + var self = this; + this.$filterField = $(''); + $container.append(this.$filterField); + this.$filterField.select2({ + placeholder: t('circles', 'Select circles to filter by'), + allowClear: false, + multiple: true, + toggleSelect: true, + separator: ',', + query: _.bind(this._queryCirclesAutocomplete, this), + + id: function(circle) { + return circle.unique_id; + }, + + initSelection: function(element, callback) { + var val = $(element).val().trim(); + if (val) { + var circleIds = val.split(','), + circles = []; + + OCA.Circles.api.listCircles("all", '', 0, function(result) { + _.each(circleIds, function(circleId) { + var circle = _.find(result.data,function(circleData) { + return circleData.unique_id == circleId; + }); + if (!_.isUndefined(circle)) { + circles.push(circle); + } + }); + + callback(circles); + }); + + } else { + callback([]); + } + }, + + formatResult: function (circle) { + return circle.name; + }, + + formatSelection: function (circle) { + return circle.name; + //return OC.SystemTags.getDescriptiveTag(tag)[0].outerHTML; + }, + + sortResults: function(results) { + results.sort(function(a, b) { + var aLastUsed = self._lastUsedTags.indexOf(a.id); + var bLastUsed = self._lastUsedTags.indexOf(b.id); + + if (aLastUsed !== bLastUsed) { + if (bLastUsed === -1) { + return -1; + } + if (aLastUsed === -1) { + return 1; + } + return aLastUsed < bLastUsed ? -1 : 1; + } + + // Both not found + return OC.Util.naturalSortCompare(a.name, b.name); + }); + return results; + }, + + escapeMarkup: function(m) { + // prevent double markup escape + return m; + }, + formatNoMatches: function() { + return t('systemtags', 'No tags found'); + } + }); + this.$filterField.on('change', _.bind(this._onTagsChanged, this)); + return this.$filterField; + }, + + /** + * Autocomplete function for dropdown results + * + * @param {Object} query select2 query object + */ + _queryCirclesAutocomplete: function(query) { + + OCA.Circles.api.listCircles("all", query.term, 0, function(result) { + query.callback({ + results: result.data + }); + }); + /* + OC.SystemTags.collection.fetch({ + success: function() { + var results = OC.SystemTags.collection.filterByName(query.term); + + query.callback({ + results: _.invoke(results, 'toJSON') + }); + } + }); + */ + }, + + /** + * Event handler for when the URL changed + */ + _onUrlChanged: function(e) { + if (e.dir) { + var circles = _.filter(e.dir.split('/'), function(val) { return val.trim() !== ''; }); + this.$filterField.select2('val', circles || []); + this._circlesIds = circles; + this.reload(); + } + }, + + _onTagsChanged: function(ev) { + var val = $(ev.target).val().trim(); + if (val !== '') { + this._circlesIds = val.split(','); + } else { + this._circlesIds = []; + } + + this.$el.trigger(jQuery.Event('changeDirectory', { + dir: this._circlesIds.join('/') + })); + this.reload(); + }, + + updateEmptyContent: function() { + var dir = this.getCurrentDirectory(); + if (dir === '/') { + // root has special permissions + if (!this._circlesIds.length) { + // no tags selected + this.$el.find('#emptycontent').html('
' + + '

' + t('systemtags', 'Please select tags to filter by') + '

'); + } else { + // tags selected but no results + this.$el.find('#emptycontent').html('
' + + '

' + t('systemtags', 'No files found for the selected tags') + '

'); + } + this.$el.find('#emptycontent').toggleClass('hidden', !this.isEmpty); + this.$el.find('#filestable thead th').toggleClass('hidden', this.isEmpty); + } + else { + OCA.Files.FileList.prototype.updateEmptyContent.apply(this, arguments); + } + }, + + getDirectoryPermissions: function() { + return OC.PERMISSION_READ | OC.PERMISSION_DELETE; + }, + + updateStorageStatistics: function() { + // no op because it doesn't have + // storage info like free space / used space + }, + + reload: function() { + if (!this._circlesIds.length) { + // don't reload + this.updateEmptyContent(); + this.setFiles([]); + return $.Deferred().resolve(); + } + + this._selectedFiles = {}; + this._selectionSummary.clear(); + if (this._currentFileModel) { + this._currentFileModel.off(); + } + this._currentFileModel = null; + this.$el.find('.select-all').prop('checked', false); + this.showMask(); + this._reloadCall = this.filesClient.getFilteredFiles( + { + circlesIds: this._circlesIds + }, + { + properties: this._getWebdavProperties() + } + ); + if (this._detailsView) { + // close sidebar + this._updateDetailsView(null); + } + var callBack = this.reloadCallback.bind(this); + return this._reloadCall.then(callBack, callBack); + }, + + reloadCallback: function(status, result) { + if (result) { + // prepend empty dir info because original handler + result.unshift({}); + } + + return OCA.Files.FileList.prototype.reloadCallback.call(this, status, result); + } + }); + + OCA.Circles.FileList = FileList; +})(); + diff --git a/lib/Api/v1/Circles.php b/lib/Api/v1/Circles.php index d43c068ec..dced9d7f2 100644 --- a/lib/Api/v1/Circles.php +++ b/lib/Api/v1/Circles.php @@ -6,6 +6,9 @@ * later. See the COPYING file. * * @author Maxence Lange + * @author Vinicius Cubas Brand + * @author Daniel Tygel + * * @copyright 2017 * @license GNU AGPL version 3 or any later version * @@ -445,4 +448,28 @@ public static function generateCircleParameter(SharingFrame $frame) { ) ]; } + + /** + * Get a list of objects which are shred with $circleUniqueId. + * + * @param string|array $tagIds Tag id or array of tag ids. + * @param string $objectType object type + * @param int $limit Count of object ids you want to get + * @param string $offset The last object id you already received + * + * @return string[] array of object ids or empty array if none found + * + * @throws \OCP\SystemTag\TagNotFoundException if at least one of the + * given tags does not exist + * @throws \InvalidArgumentException When a limit is specified together with + * multiple tag ids + * + * @since 9.0.0 + */ + public static function getObjectIdsForCircles($circleUniqueIds) { + $c = self::getContainer(); + + return $c->query(CirclesService::class) + ->getObjectIdsForCircles($circleUniqueIds); + } } \ No newline at end of file diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index dad796b9e..27b2c0012 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -6,6 +6,9 @@ * later. See the COPYING file. * * @author Maxence Lange + * @author Vinicius Cubas Brand + * @author Daniel Tygel + * * @copyright 2017 * @license GNU AGPL version 3 or any later version * @@ -106,10 +109,10 @@ public function registerEvents(IAppContainer $container) { /** - * Register Navigation Tab + * Register Navigation elements */ public function registerNavigation() { - + // Register Navigation Tab $this->getContainer() ->getServer() ->getNavigationManager() @@ -128,10 +131,42 @@ function() { ]; } ); + + // Register Navigation in FileList + \OCA\Files\App::getNavigationManager()->add(function () { + $l = \OC::$server->getL10N('circles'); + return [ + 'id' => 'circlesfilter', + 'appname' => 'circles', + 'script' => 'list.php', + 'order' => 25, + 'name' => $l->t('Circles'), + ]; + }); } public function registerSettingsAdmin() { \OCP\App::registerAdmin(self::APP_NAME, 'lib/admin'); } + + public function registerFilesPlugin() { + $eventDispatcher = \OC::$server->getEventDispatcher(); + $eventDispatcher->addListener( + 'OCA\Files::loadAdditionalScripts', + function() { + // FIXME: no public API for these ? + \OCP\Util::addScript('circles', 'circles.v1.circles'); + \OCP\Util::addScript('circles', 'circles.v1.links'); + \OCP\Util::addScript('circles', 'circles.v1.members'); + \OCP\Util::addScript('circles', 'circles.v1'); + + \OCP\Util::addScript('circles', 'circles.files.app'); + \OCP\Util::addScript('circles', 'circles.files.list'); + + \OCP\Util::addStyle('circles'); + \OCP\Util::addStyle('circles', 'circles.filelist'); + } + ); + } } diff --git a/lib/Db/CircleProviderRequestBuilder.php b/lib/Db/CircleProviderRequestBuilder.php index 7b250bc12..d37c65fd4 100644 --- a/lib/Db/CircleProviderRequestBuilder.php +++ b/lib/Db/CircleProviderRequestBuilder.php @@ -7,6 +7,9 @@ * later. See the COPYING file. * * @author Maxence Lange + * @author Vinicius Cubas Brand + * @author Daniel Tygel + * * @copyright 2017 * @license GNU AGPL version 3 or any later version * @@ -55,7 +58,7 @@ protected function findShareParentSql($fileId, $circleId) { $qb = $this->getBaseSelectSql(); $this->limitToShareParent($qb); - $this->limitToCircle($qb, $circleId); + $this->limitToCircles($qb, [$circleId]); $this->limitToFiles($qb, $fileId); return $qb; @@ -63,16 +66,25 @@ protected function findShareParentSql($fileId, $circleId) { /** - * Limit the request to a Circle. + * Limit the request to the given Circles. * * @param IQueryBuilder $qb - * @param int $circleId + * @param array $circleUniqueIds */ - protected function limitToCircle(IQueryBuilder &$qb, $circleId) { + protected function limitToCircles(IQueryBuilder &$qb, $circleUniqueIds) { + + if (!is_array($circleUniqueIds)) { + $circleUniqueIds = array($circleUniqueIds); + } + $expr = $qb->expr(); $pf = ($qb->getType() === QueryBuilder::SELECT) ? 's.' : ''; - - $qb->andWhere($expr->eq($pf . 'share_with', $qb->createNamedParameter($circleId))); + $qb->andWhere( + $expr->in( + $pf . 'share_with', + $qb->createNamedParameter($circleUniqueIds, IQueryBuilder::PARAM_STR_ARRAY) + ) + ); } diff --git a/lib/Service/CirclesService.php b/lib/Service/CirclesService.php index fb807da25..2836f4fa9 100644 --- a/lib/Service/CirclesService.php +++ b/lib/Service/CirclesService.php @@ -6,6 +6,9 @@ * later. See the COPYING file. * * @author Maxence Lange + * @author Vinicius Cubas Brand + * @author Daniel Tygel + * * @copyright 2017 * @license GNU AGPL version 3 or any later version * @@ -38,6 +41,7 @@ use OCA\Circles\Exceptions\MemberIsNotOwnerException; use OCA\Circles\Model\Circle; use OCA\Circles\Model\Member; +use OCA\Circles\ShareByCircleProvider; use OCP\IL10N; class CirclesService { @@ -66,6 +70,9 @@ class CirclesService { /** @var MiscService */ private $miscService; + /** @var ShareByCircleProvider */ + private $shareProvider; + /** * CirclesService constructor. @@ -87,7 +94,8 @@ public function __construct( MembersRequest $membersRequest, FederatedLinksRequest $federatedLinksRequest, EventsService $eventsService, - MiscService $miscService + MiscService $miscService, + ShareByCircleProvider $shareProvider ) { $this->userId = $userId; $this->l10n = $l10n; @@ -97,6 +105,7 @@ public function __construct( $this->federatedLinksRequest = $federatedLinksRequest; $this->eventsService = $eventsService; $this->miscService = $miscService; + $this->shareProvider = $shareProvider; } @@ -435,4 +444,14 @@ public static function getCircleIcon($type, $png = false) { return $urlGen->getAbsoluteURL($urlGen->imagePath(Application::APP_NAME, 'black_circle' . $ext)); } + public function getObjectIdsForCircles($circleUniqueIds, $limit = -1, $offset = 0) { + if (!is_array($circleUniqueIds)) { + $circleUniqueIds = [$circleUniqueIds]; + } + + $objectIds = $this->shareProvider->getObjectIdsForCircles($this->userId, $circleUniqueIds, $limit, $offset); + + return $objectIds; + } + } \ No newline at end of file diff --git a/lib/ShareByCircleProvider.php b/lib/ShareByCircleProvider.php index 4bc3b71c8..82ef21cb7 100644 --- a/lib/ShareByCircleProvider.php +++ b/lib/ShareByCircleProvider.php @@ -6,6 +6,9 @@ * later. See the COPYING file. * * @author Maxence Lange + * @author Vinicius Cubas Brand + * @author Daniel Tygel + * * @copyright 2017 * @license GNU AGPL version 3 or any later version * @@ -535,6 +538,37 @@ public function getShareByToken($token) { return $share; } + public function getObjectIdsForCircles($userId, $circleUniqueIds, $limit, $offset) { + + $qb = $this->getCompleteSelectSql(); + $this->linkToFileCache($qb, $userId); + $this->limitToPage($qb, $limit, $offset); + $this->limitToCircles($qb, $circleUniqueIds); + + $this->linkToMember($qb, $userId, $this->configService->isLinkedGroupsAllowed()); + + $this->leftJoinShareInitiator($qb); + $cursor = $qb->execute(); + + $object_ids = []; + while ($data = $cursor->fetch()) { + + if ($data['initiator_circle_level'] < Member::LEVEL_MEMBER + && ($data['initiator_group_level'] < Member::LEVEL_MEMBER + || !$this->configService->isLinkedGroupsAllowed()) + ) { + continue; + } + + self::editShareFromParentEntry($data); + if (self::isAccessibleResult($data)) { + $object_ids[] = $data['file_source']; + } + } + $cursor->closeCursor(); + + return $object_ids; + } /** * We don't return a thing about children. diff --git a/list.php b/list.php new file mode 100644 index 000000000..928751f9c --- /dev/null +++ b/list.php @@ -0,0 +1,26 @@ + + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program 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, version 3, + * along with this program. If not, see + * + */ +// Check if we are a user +OCP\User::checkLoggedIn(); + +$tmpl = new OCP\Template('circles', 'list', ''); +$tmpl->printPage(); diff --git a/templates/list.php b/templates/list.php new file mode 100644 index 000000000..841ce7b5b --- /dev/null +++ b/templates/list.php @@ -0,0 +1,38 @@ +
+
+ + + + + + + + + + + + + + + + + +
+ + From b39762fd12d3a155390a299326671e89fd656266 Mon Sep 17 00:00:00 2001 From: Vinicius Cubas Brand Date: Wed, 4 Oct 2017 15:23:18 -0300 Subject: [PATCH 4/8] Hide circles that the user is not member Files-circles-panel: in javascript interface, just show the circles that the current user is member of. Signed-off-by: Vinicius Cubas Brand --- js/circles.files.list.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/circles.files.list.js b/js/circles.files.list.js index f6984471f..71be1d519 100644 --- a/js/circles.files.list.js +++ b/js/circles.files.list.js @@ -93,7 +93,7 @@ var circleIds = val.split(','), circles = []; - OCA.Circles.api.listCircles("all", '', 0, function(result) { + OCA.Circles.api.listCircles("all", '', 1, function(result) { _.each(circleIds, function(circleId) { var circle = _.find(result.data,function(circleData) { return circleData.unique_id == circleId; @@ -160,7 +160,7 @@ */ _queryCirclesAutocomplete: function(query) { - OCA.Circles.api.listCircles("all", query.term, 0, function(result) { + OCA.Circles.api.listCircles("all", query.term, 1, function(result) { query.callback({ results: result.data }); From 2397af8a413f30685c27d81fbcbcea469112efc4 Mon Sep 17 00:00:00 2001 From: Maxence Lange Date: Fri, 20 Oct 2017 15:34:36 -0100 Subject: [PATCH 5/8] moving files/methods around Signed-off-by: Maxence Lange --- appinfo/app.php | 3 +- css/circles.filelist.css | 39 ------- css/files/circles.filelist.css | 54 ++++++++++ files/list.php | 6 ++ js/{ => files}/circles.files.app.js | 0 js/{ => files}/circles.files.list.js | 30 ++++-- lib/Api/v1/Circles.php | 18 +--- lib/AppInfo/Application.php | 138 ++++++++++-------------- lib/Db/CircleProviderRequest.php | 106 ++++++++++++++++++ lib/Db/CircleProviderRequestBuilder.php | 7 +- lib/Service/CirclesService.php | 33 ++++-- lib/ShareByCircleProvider.php | 95 ++++------------ list.php | 26 ----- templates/{ => files}/list.php | 0 14 files changed, 294 insertions(+), 261 deletions(-) delete mode 100644 css/circles.filelist.css create mode 100644 css/files/circles.filelist.css create mode 100644 files/list.php rename js/{ => files}/circles.files.app.js (100%) rename js/{ => files}/circles.files.list.js (86%) create mode 100644 lib/Db/CircleProviderRequest.php delete mode 100644 list.php rename templates/{ => files}/list.php (100%) diff --git a/appinfo/app.php b/appinfo/app.php index e5ecc4421..f4bb8455f 100644 --- a/appinfo/app.php +++ b/appinfo/app.php @@ -28,8 +28,9 @@ $app = new \OCA\Circles\AppInfo\Application(); -$app->registerNavigation(); $app->registerSettingsAdmin(); +$app->registerNavigation(); +$app->registerFilesNavigation(); $app->registerFilesPlugin(); diff --git a/css/circles.filelist.css b/css/circles.filelist.css deleted file mode 100644 index 468482ca6..000000000 --- a/css/circles.filelist.css +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2017 - * - * This file is licensed under the Affero General Public License version 3 - * or later. - * - * See the COPYING-README file. - * - */ -#app-content-circlesfilter .select2-container { - width: 30%; - margin-left: 10px; -} - -#app-content-circlesfilter .select2-choices { - white-space: nowrap; - text-overflow: ellipsis; - background: #fff; - color: #555; - box-sizing: content-box; - border-radius: 3px; - border: 1px solid #ddd; - padding: 0; - min-height: auto; -} - -.nav-icon-circlesfilter { - background-image: url('../img/black_circle.svg'); -} - -#app-sidebar .mainFileInfoView .tag-label { - cursor: pointer; - padding: 13px; -} - -#app-sidebar .mainFileInfoView .icon-tag { - opacity: .5; - vertical-align: middle; -} diff --git a/css/files/circles.filelist.css b/css/files/circles.filelist.css new file mode 100644 index 000000000..c2f42cb31 --- /dev/null +++ b/css/files/circles.filelist.css @@ -0,0 +1,54 @@ +/* + * Circles - Bring cloud-users closer together. + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange + * @copyright 2017 + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 program. If not, see . + * + */ +#app-content-circlesfilter .select2-container { + width: 30%; + margin-left: 10px; +} + +#app-content-circlesfilter .select2-choices { + white-space: nowrap; + text-overflow: ellipsis; + background: #fff; + color: #555; + box-sizing: content-box; + border-radius: 3px; + border: 1px solid #ddd; + padding: 0; + min-height: auto; +} + +.nav-icon-circlesfilter { + background-image: url('../../img/black_circle.svg'); +} + +#app-sidebar .mainFileInfoView .tag-label { + cursor: pointer; + padding: 13px; +} + +#app-sidebar .mainFileInfoView .icon-tag { + opacity: .5; + vertical-align: middle; +} diff --git a/files/list.php b/files/list.php new file mode 100644 index 000000000..70e82b1f4 --- /dev/null +++ b/files/list.php @@ -0,0 +1,6 @@ +printPage(); diff --git a/js/circles.files.app.js b/js/files/circles.files.app.js similarity index 100% rename from js/circles.files.app.js rename to js/files/circles.files.app.js diff --git a/js/circles.files.list.js b/js/files/circles.files.list.js similarity index 86% rename from js/circles.files.list.js rename to js/files/circles.files.list.js index 71be1d519..89bc2e95d 100644 --- a/js/circles.files.list.js +++ b/js/files/circles.files.list.js @@ -1,13 +1,25 @@ /* - * Copyright (c) 2017 EITA Cooperative + * Circles - Bring cloud-users closer together. * - * @author Vinicius Brand - * @author Daniel Tygel + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. * - * This file is licensed under the Affero General Public License version 3 - * or later. + * @author Maxence Lange + * @copyright 2017 + * @license GNU AGPL version 3 or any later version * - * See the COPYING-README file. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 program. If not, see . * */ (function() { @@ -146,7 +158,7 @@ return m; }, formatNoMatches: function() { - return t('systemtags', 'No tags found'); + return t('systemtags', 'No circles found'); } }); this.$filterField.on('change', _.bind(this._onTagsChanged, this)); @@ -211,11 +223,11 @@ if (!this._circlesIds.length) { // no tags selected this.$el.find('#emptycontent').html('
' + - '

' + t('systemtags', 'Please select tags to filter by') + '

'); + '

' + t('systemtags', 'Please select circles to filter by') + '

'); } else { // tags selected but no results this.$el.find('#emptycontent').html('
' + - '

' + t('systemtags', 'No files found for the selected tags') + '

'); + '

' + t('systemtags', 'No files found for the selected circles') + '

'); } this.$el.find('#emptycontent').toggleClass('hidden', !this.isEmpty); this.$el.find('#filestable thead th').toggleClass('hidden', this.isEmpty); diff --git a/lib/Api/v1/Circles.php b/lib/Api/v1/Circles.php index dced9d7f2..bbb08d9e8 100644 --- a/lib/Api/v1/Circles.php +++ b/lib/Api/v1/Circles.php @@ -452,24 +452,16 @@ public static function generateCircleParameter(SharingFrame $frame) { /** * Get a list of objects which are shred with $circleUniqueId. * - * @param string|array $tagIds Tag id or array of tag ids. - * @param string $objectType object type - * @param int $limit Count of object ids you want to get - * @param string $offset The last object id you already received + * @since 0.14.0 * - * @return string[] array of object ids or empty array if none found - * - * @throws \OCP\SystemTag\TagNotFoundException if at least one of the - * given tags does not exist - * @throws \InvalidArgumentException When a limit is specified together with - * multiple tag ids + * @param array $circleUniqueIds * - * @since 9.0.0 + * @return string[] array of object ids or empty array if none found */ - public static function getObjectIdsForCircles($circleUniqueIds) { + public static function getFilesForCircles($circleUniqueIds) { $c = self::getContainer(); return $c->query(CirclesService::class) - ->getObjectIdsForCircles($circleUniqueIds); + ->getFilesForCircles($circleUniqueIds); } } \ No newline at end of file diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 27b2c0012..a0c958215 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -29,33 +29,13 @@ namespace OCA\Circles\AppInfo; -use OCA\Circles\Controller\FederatedController; -use OCA\Circles\Controller\GroupsController; -use OCA\Circles\Controller\NavigationController; -use OCA\Circles\Controller\CirclesController; -use OCA\Circles\Controller\MembersController; - - -use OCA\Circles\Controller\SettingsController; -use OCA\Circles\Controller\SharesController; -use OCA\Circles\Db\CirclesRequest; -use OCA\Circles\Db\FederatedLinksRequest; -use OCA\Circles\Db\MembersRequest; -use OCA\Circles\Events\UserEvents; -use OCA\Circles\Service\BroadcastService; -use OCA\Circles\Service\CirclesService; -use OCA\Circles\Service\EventsService; -use OCA\Circles\Service\FederatedLinkService; -use OCA\Circles\Service\GroupsService; -use OCA\Circles\Service\MembersService; -use OCA\Circles\Service\ConfigService; -use OCA\Circles\Service\MiscService; -use OCA\Circles\Service\SearchService; -use OCA\Circles\Service\SharingFrameService; +use OCA\Circles\Api\v1\Circles; +use OCA\Files\App as FilesApp; use OCP\AppFramework\App; use OCP\AppFramework\IAppContainer; use OCP\Util; + class Application extends App { const APP_NAME = 'circles'; @@ -65,17 +45,18 @@ class Application extends App { const CLIENT_TIMEOUT = 3; + /** @var IAppContainer */ + private $container; + /** * @param array $params */ public function __construct(array $params = array()) { parent::__construct(self::APP_NAME, $params); - $container = $this->getContainer(); + $this->container = $this->getContainer(); - // TODO: POURQUOI SELF:: ??!?? - self::registerEvents($container); - self::registerHooks(); + $this->registerHooks(); } @@ -92,59 +73,32 @@ public function registerHooks() { } - /** - * Register Events - * - * @param IAppContainer $container - */ - public function registerEvents(IAppContainer $container) { -// $container->registerService( -// 'UserEvents', function(IAppContainer $c) { -// return new UserEvents( -// $c->query('MembersService'), $c->query('GroupsService'), $c->query('MiscService') -// ); -// } -// ); - } - - /** * Register Navigation elements */ public function registerNavigation() { - // Register Navigation Tab - $this->getContainer() - ->getServer() - ->getNavigationManager() - ->add( - function() { - $urlGen = \OC::$server->getURLGenerator(); - $navName = \OC::$server->getL10N(self::APP_NAME) - ->t('Circles'); - - return [ - 'id' => self::APP_NAME, - 'order' => 5, - 'href' => $urlGen->linkToRoute('circles.Navigation.navigate'), - 'icon' => $urlGen->imagePath(self::APP_NAME, 'circles.svg'), - 'name' => $navName - ]; - } - ); - - // Register Navigation in FileList - \OCA\Files\App::getNavigationManager()->add(function () { - $l = \OC::$server->getL10N('circles'); - return [ - 'id' => 'circlesfilter', - 'appname' => 'circles', - 'script' => 'list.php', - 'order' => 25, - 'name' => $l->t('Circles'), - ]; - }); + + $appManager = $this->container->getServer() + ->getNavigationManager(); + $appManager->add( + function() { + $urlGen = \OC::$server->getURLGenerator(); + $navName = \OC::$server->getL10N(self::APP_NAME) + ->t('Circles'); + + return [ + 'id' => self::APP_NAME, + 'order' => 5, + 'href' => $urlGen->linkToRoute('circles.Navigation.navigate'), + 'icon' => $urlGen->imagePath(self::APP_NAME, 'circles.svg'), + 'name' => $navName + ]; + } + ); + } + public function registerSettingsAdmin() { \OCP\App::registerAdmin(self::APP_NAME, 'lib/admin'); } @@ -154,19 +108,37 @@ public function registerFilesPlugin() { $eventDispatcher->addListener( 'OCA\Files::loadAdditionalScripts', function() { - // FIXME: no public API for these ? - \OCP\Util::addScript('circles', 'circles.v1.circles'); - \OCP\Util::addScript('circles', 'circles.v1.links'); - \OCP\Util::addScript('circles', 'circles.v1.members'); - \OCP\Util::addScript('circles', 'circles.v1'); + Circles::addJavascriptAPI(); + + Util::addScript('circles', 'files/circles.files.app'); + Util::addScript('circles', 'files/circles.files.list'); + + Util::addStyle('circles', 'files/circles.filelist'); + } + ); + } - \OCP\Util::addScript('circles', 'circles.files.app'); - \OCP\Util::addScript('circles', 'circles.files.list'); - \OCP\Util::addStyle('circles'); - \OCP\Util::addStyle('circles', 'circles.filelist'); + /** + * + */ + public function registerFilesNavigation() { + + $appManager = FilesApp::getNavigationManager(); + $appManager->add( + function() { + $l = \OC::$server->getL10N('circles'); + + return [ + 'id' => 'circlesfilter', + 'appname' => 'circles', + 'script' => 'files/list.php', + 'order' => 25, + 'name' => $l->t('Shared to Circles'), + ]; } ); } + } diff --git a/lib/Db/CircleProviderRequest.php b/lib/Db/CircleProviderRequest.php new file mode 100644 index 000000000..5b5af1b2e --- /dev/null +++ b/lib/Db/CircleProviderRequest.php @@ -0,0 +1,106 @@ + + * @copyright 2017 + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 program. If not, see . + * + */ + + +namespace OCA\Circles\Db; + + +use OCA\Circles\Model\Member; + +class CircleProviderRequest extends CircleProviderRequestBuilder { + + + /** + * @param $userId + * @param $circleUniqueIds + * @param $limit + * @param $offset + * + * @return array + */ + public function getFilesForCircles($userId, $circleUniqueIds, $limit, $offset) { + + $qb = $this->getCompleteSelectSql(); + $this->linkToFileCache($qb, $userId); + $this->limitToPage($qb, $limit, $offset); + $this->limitToCircles($qb, $circleUniqueIds); + + $this->linkToMember($qb, $userId, $this->configService->isLinkedGroupsAllowed()); + + $this->leftJoinShareInitiator($qb); + $cursor = $qb->execute(); + + $object_ids = []; + while ($data = $cursor->fetch()) { + + if ($data['initiator_circle_level'] < Member::LEVEL_MEMBER + && ($data['initiator_group_level'] < Member::LEVEL_MEMBER + || !$this->configService->isLinkedGroupsAllowed()) + ) { + continue; + } + + self::editShareFromParentEntry($data); + if (self::isAccessibleResult($data)) { + $object_ids[] = $data['file_source']; + } + } + $cursor->closeCursor(); + + return $object_ids; + } + + + /** + * Returns whether the given database result can be interpreted as + * a share with accessible file (not trashed, not deleted) + * + * @param $data + *F + * + * @return bool + */ + protected static function isAccessibleResult($data) { + if ($data['fileid'] === null) { + return false; + } + + return (!(explode('/', $data['path'], 2)[0] !== 'files' + && explode(':', $data['storage_string_id'], 2)[0] === 'home')); + } + + + /** + * @param $data + */ + protected static function editShareFromParentEntry(&$data) { + if ($data['parent_id'] > 0) { + $data['permissions'] = $data['parent_perms']; + $data['file_target'] = $data['parent_target']; + } + } + +} \ No newline at end of file diff --git a/lib/Db/CircleProviderRequestBuilder.php b/lib/Db/CircleProviderRequestBuilder.php index d37c65fd4..2fb98ad93 100644 --- a/lib/Db/CircleProviderRequestBuilder.php +++ b/lib/Db/CircleProviderRequestBuilder.php @@ -35,15 +35,10 @@ use OCA\Circles\Model\Circle; use OCA\Circles\Model\Member; use OCP\DB\QueryBuilder\IQueryBuilder; -use OCP\IDBConnection; use OCP\Share; use OCP\Share\IShare; -class CircleProviderRequestBuilder { - - - /** @var IDBConnection */ - protected $dbConnection; +class CircleProviderRequestBuilder extends CoreRequestBuilder { /** diff --git a/lib/Service/CirclesService.php b/lib/Service/CirclesService.php index 2836f4fa9..ecf0097d4 100644 --- a/lib/Service/CirclesService.php +++ b/lib/Service/CirclesService.php @@ -31,13 +31,13 @@ use OCA\Circles\AppInfo\Application; +use OCA\Circles\Db\CircleProviderRequest; use OCA\Circles\Db\CirclesRequest; use OCA\Circles\Db\FederatedLinksRequest; use OCA\Circles\Db\MembersRequest; use OCA\Circles\Exceptions\CircleAlreadyExistsException; use OCA\Circles\Exceptions\CircleTypeDisabledException; use OCA\Circles\Exceptions\FederatedCircleNotAllowedException; -use OCA\Circles\Exceptions\MemberDoesNotExistException; use OCA\Circles\Exceptions\MemberIsNotOwnerException; use OCA\Circles\Model\Circle; use OCA\Circles\Model\Member; @@ -67,12 +67,12 @@ class CirclesService { /** @var EventsService */ private $eventsService; + /** @var CircleProviderRequest */ + private $circleProviderRequest; + /** @var MiscService */ private $miscService; - /** @var ShareByCircleProvider */ - private $shareProvider; - /** * CirclesService constructor. @@ -84,6 +84,7 @@ class CirclesService { * @param MembersRequest $membersRequest * @param FederatedLinksRequest $federatedLinksRequest * @param EventsService $eventsService + * @param CircleProviderRequest $circleProviderRequest * @param MiscService $miscService */ public function __construct( @@ -94,8 +95,8 @@ public function __construct( MembersRequest $membersRequest, FederatedLinksRequest $federatedLinksRequest, EventsService $eventsService, - MiscService $miscService, - ShareByCircleProvider $shareProvider + CircleProviderRequest $circleProviderRequest, + MiscService $miscService ) { $this->userId = $userId; $this->l10n = $l10n; @@ -104,8 +105,8 @@ public function __construct( $this->membersRequest = $membersRequest; $this->federatedLinksRequest = $federatedLinksRequest; $this->eventsService = $eventsService; + $this->circleProviderRequest = $circleProviderRequest; $this->miscService = $miscService; - $this->shareProvider = $shareProvider; } @@ -302,7 +303,9 @@ public function joinCircle($circleUniqueId) { try { $circle = $this->circlesRequest->getCircle($circleUniqueId, $this->userId); - $member = $this->membersRequest->getFreshNewMember($circleUniqueId, $this->userId, Member::TYPE_USER); + $member = $this->membersRequest->getFreshNewMember( + $circleUniqueId, $this->userId, Member::TYPE_USER + ); $member->hasToBeAbleToJoinTheCircle(); $member->joinCircle($circle->getType()); $this->membersRequest->updateMember($member); @@ -444,12 +447,22 @@ public static function getCircleIcon($type, $png = false) { return $urlGen->getAbsoluteURL($urlGen->imagePath(Application::APP_NAME, 'black_circle' . $ext)); } - public function getObjectIdsForCircles($circleUniqueIds, $limit = -1, $offset = 0) { + + /** + * @param string $circleUniqueIds + * @param int $limit + * @param int $offset + * + * @return array + */ + public function getFilesForCircles($circleUniqueIds, $limit = -1, $offset = 0) { if (!is_array($circleUniqueIds)) { $circleUniqueIds = [$circleUniqueIds]; } - $objectIds = $this->shareProvider->getObjectIdsForCircles($this->userId, $circleUniqueIds, $limit, $offset); + $objectIds = $this->circleProviderRequest->getFilesForCircles( + $this->userId, $circleUniqueIds, $limit, $offset + ); return $objectIds; } diff --git a/lib/ShareByCircleProvider.php b/lib/ShareByCircleProvider.php index 82ef21cb7..06ddae479 100644 --- a/lib/ShareByCircleProvider.php +++ b/lib/ShareByCircleProvider.php @@ -36,7 +36,7 @@ use OC\Share20\Share; use OCA\Circles\Api\v1\Circles; use OCA\Circles\AppInfo\Application; -use OCA\Circles\Db\CircleProviderRequestBuilder; +use OCA\Circles\Db\CircleProviderRequest; use OCA\Circles\Db\CirclesRequest; use OCA\Circles\Db\MembersRequest; use OCA\Circles\Model\Circle; @@ -58,7 +58,8 @@ use OCP\Share\IShare; use OCP\Share\IShareProvider; -class ShareByCircleProvider extends CircleProviderRequestBuilder implements IShareProvider { + +class ShareByCircleProvider extends CircleProviderRequest implements IShareProvider { /** @var IDBConnection */ protected $dbConnection; @@ -109,23 +110,20 @@ public function __construct( IDBConnection $connection, ISecureRandom $secureRandom, IUserManager $userManager, IRootFolder $rootFolder, IL10N $l10n, ILogger $logger, IURLGenerator $urlGenerator ) { - $this->dbConnection = $connection; + $app = new Application(); + $container = $app->getContainer(); + $configService = $container->query(ConfigService::class); + $miscService = $container->query(MiscService::class); + + parent::__construct($l10n, $connection, $configService, $miscService); + $this->secureRandom = $secureRandom; $this->userManager = $userManager; $this->rootFolder = $rootFolder; - $this->l10n = $l10n; $this->logger = $logger; $this->urlGenerator = $urlGenerator; - - $app = new Application(); - $this->circlesRequest = $app->getContainer() - ->query(CirclesRequest::class); - $this->membersRequest = $app->getContainer() - ->query(MembersRequest::class); - $this->configService = $app->getContainer() - ->query(ConfigService::class); - $this->miscService = $app->getContainer() - ->query(MiscService::class); + $this->circlesRequest = $container->query(CirclesRequest::class); + $this->membersRequest = $container->query(MembersRequest::class); } @@ -450,6 +448,15 @@ public function getSharedWith($userId, $shareType, $node, $limit, $offset) { } + /** + * @param string $userId + * @param $shareType + * @param Node $node + * @param int $limit + * @param int $offset + * + * @return array + */ private function getSharedWithCircleMembers($userId, $shareType, $node, $limit, $offset) { $qb = $this->getCompleteSelectSql(); @@ -485,16 +492,6 @@ private function getSharedWithCircleMembers($userId, $shareType, $node, $limit, return $shares; } - /** - * @param $data - */ - private static function editShareFromParentEntry(&$data) { - if ($data['parent_id'] > 0) { - $data['permissions'] = $data['parent_perms']; - $data['file_target'] = $data['parent_target']; - } - } - /** * Get a share by token @@ -538,37 +535,6 @@ public function getShareByToken($token) { return $share; } - public function getObjectIdsForCircles($userId, $circleUniqueIds, $limit, $offset) { - - $qb = $this->getCompleteSelectSql(); - $this->linkToFileCache($qb, $userId); - $this->limitToPage($qb, $limit, $offset); - $this->limitToCircles($qb, $circleUniqueIds); - - $this->linkToMember($qb, $userId, $this->configService->isLinkedGroupsAllowed()); - - $this->leftJoinShareInitiator($qb); - $cursor = $qb->execute(); - - $object_ids = []; - while ($data = $cursor->fetch()) { - - if ($data['initiator_circle_level'] < Member::LEVEL_MEMBER - && ($data['initiator_group_level'] < Member::LEVEL_MEMBER - || !$this->configService->isLinkedGroupsAllowed()) - ) { - continue; - } - - self::editShareFromParentEntry($data); - if (self::isAccessibleResult($data)) { - $object_ids[] = $data['file_source']; - } - } - $cursor->closeCursor(); - - return $object_ids; - } /** * We don't return a thing about children. @@ -691,25 +657,6 @@ private function assignShareObjectSharesProperties(IShare &$share, $data) { } - /** - * Returns whether the given database result can be interpreted as - * a share with accessible file (not trashed, not deleted) - * - * @param $data - *F - * - * @return bool - */ - private static function isAccessibleResult($data) { - if ($data['fileid'] === null) { - return false; - } - - return (!(explode('/', $data['path'], 2)[0] !== 'files' - && explode(':', $data['storage_string_id'], 2)[0] === 'home')); - } - - /** * @param IShare $share * diff --git a/list.php b/list.php deleted file mode 100644 index 928751f9c..000000000 --- a/list.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program 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, version 3, - * along with this program. If not, see - * - */ -// Check if we are a user -OCP\User::checkLoggedIn(); - -$tmpl = new OCP\Template('circles', 'list', ''); -$tmpl->printPage(); diff --git a/templates/list.php b/templates/files/list.php similarity index 100% rename from templates/list.php rename to templates/files/list.php From d9a1994c14024c6f96c2a7f45685403b2eb33ce9 Mon Sep 17 00:00:00 2001 From: Maxence Lange Date: Fri, 20 Oct 2017 15:40:55 -0100 Subject: [PATCH 6/8] fix access Signed-off-by: Maxence Lange --- lib/ShareByCircleProvider.php | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/lib/ShareByCircleProvider.php b/lib/ShareByCircleProvider.php index 06ddae479..4a4e710b2 100644 --- a/lib/ShareByCircleProvider.php +++ b/lib/ShareByCircleProvider.php @@ -61,9 +61,6 @@ class ShareByCircleProvider extends CircleProviderRequest implements IShareProvider { - /** @var IDBConnection */ - protected $dbConnection; - /** @var ILogger */ private $logger; @@ -76,9 +73,6 @@ class ShareByCircleProvider extends CircleProviderRequest implements IShareProvi /** @var IRootFolder */ private $rootFolder; - /** @var IL10N */ - private $l10n; - /** @var IURLGenerator */ private $urlGenerator; @@ -88,12 +82,6 @@ class ShareByCircleProvider extends CircleProviderRequest implements IShareProvi /** @var MembersRequest */ private $membersRequest; - /** @var ConfigService */ - private $configService; - - /** @var MiscService */ - private $miscService; - /** * DefaultShareProvider constructor. From cfffcd60d9a489879d42e37957a6581e081840a8 Mon Sep 17 00:00:00 2001 From: Maxence Lange Date: Mon, 30 Oct 2017 11:40:44 -0100 Subject: [PATCH 7/8] Fixes #144 Signed-off-by: Maxence Lange --- lib/Db/CircleProviderRequestBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Db/CircleProviderRequestBuilder.php b/lib/Db/CircleProviderRequestBuilder.php index c12e0e9e0..9b3e99da9 100644 --- a/lib/Db/CircleProviderRequestBuilder.php +++ b/lib/Db/CircleProviderRequestBuilder.php @@ -534,7 +534,7 @@ private function joinShare(IQueryBuilder &$qb) { $qb->addSelect('s.file_source', 's.file_target'); /** @noinspection PhpMethodParametersCountMismatchInspection */ $qb->from('share', 's') - ->where($expr->eq('s.share_type', $qb->createNamedParameter(Share::SHARE_TYPE_CIRCLE))) + ->andWhere($expr->eq('s.share_type', $qb->createNamedParameter(Share::SHARE_TYPE_CIRCLE))) ->andWhere( $expr->orX( $expr->eq('s.item_type', $qb->createNamedParameter('file')), From bdc99cc0d927decebb7a19c13129675d910d5c89 Mon Sep 17 00:00:00 2001 From: Maxence Lange Date: Mon, 30 Oct 2017 11:40:44 -0100 Subject: [PATCH 8/8] Revert "Fixes #144" This reverts commit cfffcd60d9a489879d42e37957a6581e081840a8. Signed-off-by: Maxence Lange --- lib/Db/CircleProviderRequestBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Db/CircleProviderRequestBuilder.php b/lib/Db/CircleProviderRequestBuilder.php index 9b3e99da9..c12e0e9e0 100644 --- a/lib/Db/CircleProviderRequestBuilder.php +++ b/lib/Db/CircleProviderRequestBuilder.php @@ -534,7 +534,7 @@ private function joinShare(IQueryBuilder &$qb) { $qb->addSelect('s.file_source', 's.file_target'); /** @noinspection PhpMethodParametersCountMismatchInspection */ $qb->from('share', 's') - ->andWhere($expr->eq('s.share_type', $qb->createNamedParameter(Share::SHARE_TYPE_CIRCLE))) + ->where($expr->eq('s.share_type', $qb->createNamedParameter(Share::SHARE_TYPE_CIRCLE))) ->andWhere( $expr->orX( $expr->eq('s.item_type', $qb->createNamedParameter('file')),