Browse Source
Allow to search by comments
Allow to search by comments
Signed-off-by: Joas Schilling <coding@schilljs.com>pull/9222/head
committed by
Daniel Calviño Sánchez
10 changed files with 403 additions and 1 deletions
-
2apps/comments/composer/composer/autoload_classmap.php
-
2apps/comments/composer/composer/autoload_static.php
-
1apps/comments/js/merged.json
-
132apps/comments/js/search.js
-
7apps/comments/lib/AppInfo/Application.php
-
93apps/comments/lib/Search/Provider.php
-
109apps/comments/lib/Search/Result.php
-
42lib/private/Comments/Manager.php
-
12lib/public/Comments/ICommentsManager.php
-
4tests/lib/Comments/FakeManager.php
@ -0,0 +1,132 @@ |
|||
/* |
|||
* Copyright (c) 2014 |
|||
* |
|||
* This file is licensed under the Affero General Public License version 3 |
|||
* or later. |
|||
* |
|||
* See the COPYING-README file. |
|||
* |
|||
*/ |
|||
(function(OC, OCA, $) { |
|||
"use strict"; |
|||
|
|||
/** |
|||
* Construct a new FileActions instance |
|||
* @constructs Files |
|||
*/ |
|||
var Comment = function() { |
|||
this.initialize(); |
|||
}; |
|||
|
|||
Comment.prototype = { |
|||
|
|||
fileList: null, |
|||
|
|||
/** |
|||
* Initialize the file search |
|||
*/ |
|||
initialize: function() { |
|||
|
|||
var self = this; |
|||
|
|||
this.fileAppLoaded = function() { |
|||
return !!OCA.Files && !!OCA.Files.App; |
|||
}; |
|||
function inFileList($row, result) { |
|||
return false; |
|||
|
|||
if (! self.fileAppLoaded()) { |
|||
return false; |
|||
} |
|||
var dir = self.fileList.getCurrentDirectory().replace(/\/+$/,''); |
|||
var resultDir = OC.dirname(result.path); |
|||
return dir === resultDir && self.fileList.inList(result.name); |
|||
} |
|||
function hideNoFilterResults() { |
|||
var $nofilterresults = $('.nofilterresults'); |
|||
if ( ! $nofilterresults.hasClass('hidden') ) { |
|||
$nofilterresults.addClass('hidden'); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* |
|||
* @param {jQuery} $row |
|||
* @param {Object} result |
|||
* @param {int} result.id |
|||
* @param {string} result.comment |
|||
* @param {string} result.authorId |
|||
* @param {string} result.authorName |
|||
* @param {string} result.link |
|||
* @param {string} result.fileName |
|||
* @param {string} result.path |
|||
* @returns {*} |
|||
*/ |
|||
this.renderCommentResult = function($row, result) { |
|||
if (inFileList($row, result)) { |
|||
return null; |
|||
} |
|||
hideNoFilterResults(); |
|||
/*render preview icon, show path beneath filename, |
|||
show size and last modified date on the right */ |
|||
this.updateLegacyMimetype(result); |
|||
|
|||
var $pathDiv = $('<div>').addClass('path').text(result.path); |
|||
|
|||
var $avatar = $('<div>'); |
|||
$avatar.addClass('avatar') |
|||
.css('display', 'inline-block') |
|||
.css('vertical-align', 'middle') |
|||
.css('margin', '0 5px 2px 3px'); |
|||
|
|||
if (result.authorName) { |
|||
$avatar.avatar(result.authorId, 21, undefined, false, undefined, result.authorName); |
|||
} else { |
|||
$avatar.avatar(result.authorId, 21); |
|||
} |
|||
|
|||
$row.find('td.info div.name').after($pathDiv).text(result.comment).prepend($('<span>').addClass('path').css('margin-right', '5px').text(result.authorName)).prepend($avatar); |
|||
$row.find('td.result a').attr('href', result.link); |
|||
|
|||
$row.find('td.icon').css('background-image', 'url(' + OC.imagePath('core', 'actions/comment') + ')'); |
|||
var dir = OC.dirname(result.path); |
|||
if (dir === '') { |
|||
dir = '/'; |
|||
} |
|||
$row.find('td.info a').attr('href', |
|||
OC.generateUrl('/apps/files/?dir={dir}&scrollto={scrollto}', {dir: dir, scrollto: result.fileName}) |
|||
); |
|||
|
|||
return $row; |
|||
}; |
|||
|
|||
this.handleCommentClick = function($row, result, event) { |
|||
if (self.fileAppLoaded() && self.fileList.id === 'files') { |
|||
self.fileList.changeDirectory(OC.dirname(result.path)); |
|||
self.fileList.scrollTo(result.name); |
|||
return false; |
|||
} else { |
|||
return true; |
|||
} |
|||
}; |
|||
|
|||
this.updateLegacyMimetype = function (result) { |
|||
// backward compatibility:
|
|||
if (!result.mime && result.mime_type) { |
|||
result.mime = result.mime_type; |
|||
} |
|||
}; |
|||
this.setFileList = function (fileList) { |
|||
this.fileList = fileList; |
|||
}; |
|||
|
|||
OC.Plugins.register('OCA.Search.Core', this); |
|||
}, |
|||
attach: function(search) { |
|||
search.setRenderer('comment', this.renderCommentResult.bind(this)); |
|||
search.setHandler('comment', this.handleCommentClick.bind(this)); |
|||
} |
|||
}; |
|||
|
|||
OCA.Search.comment = new Comment(); |
|||
})(OC, OCA, $); |
@ -0,0 +1,93 @@ |
|||
<?php |
|||
/** |
|||
* @copyright Copyright (c) 2018 Joas Schilling <coding@schilljs.com> |
|||
* |
|||
* @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 <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCA\Comments\Search; |
|||
|
|||
use OCP\Comments\IComment; |
|||
use OCP\Files\Folder; |
|||
use OCP\Files\Node; |
|||
use OCP\Files\NotFoundException; |
|||
use OCP\IUser; |
|||
|
|||
class Provider extends \OCP\Search\Provider { |
|||
|
|||
/** |
|||
* Search for $query |
|||
* |
|||
* @param string $query |
|||
* @return array An array of OCP\Search\Result's |
|||
* @since 7.0.0 |
|||
*/ |
|||
public function search($query): array { |
|||
$cm = \OC::$server->getCommentsManager(); |
|||
$us = \OC::$server->getUserSession(); |
|||
|
|||
$user = $us->getUser(); |
|||
if (!$user instanceof IUser) { |
|||
return []; |
|||
} |
|||
$uf = \OC::$server->getUserFolder($user->getUID()); |
|||
|
|||
if ($uf === null) { |
|||
return []; |
|||
} |
|||
|
|||
/** @var IComment[] $comments */ |
|||
$comments = $cm->search($query, 'files', '', 'comment'); |
|||
|
|||
$result = []; |
|||
foreach ($comments as $comment) { |
|||
if ($comment->getActorType() !== 'users') { |
|||
continue; |
|||
} |
|||
|
|||
$displayName = $cm->resolveDisplayName('user', $comment->getActorId()); |
|||
|
|||
try { |
|||
$file = $this->getFileForComment($uf, $comment); |
|||
$result[] = new Result($query, |
|||
$comment, |
|||
$displayName, |
|||
$file->getPath() |
|||
); |
|||
} catch (NotFoundException $e) { |
|||
continue; |
|||
} |
|||
} |
|||
|
|||
return $result; |
|||
} |
|||
|
|||
/** |
|||
* @param Folder $userFolder |
|||
* @param IComment $comment |
|||
* @return Node |
|||
* @throws NotFoundException |
|||
*/ |
|||
protected function getFileForComment(Folder $userFolder, IComment $comment): Node { |
|||
$nodes = $userFolder->getById((int) $comment->getObjectId()); |
|||
if (empty($nodes)) { |
|||
throw new NotFoundException('File not found'); |
|||
} |
|||
|
|||
return array_shift($nodes); |
|||
} |
|||
} |
@ -0,0 +1,109 @@ |
|||
<?php |
|||
/** |
|||
* @copyright Copyright (c) 2018 Joas Schilling <coding@schilljs.com> |
|||
* |
|||
* @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 <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCA\Comments\Search; |
|||
|
|||
use OCP\Comments\IComment; |
|||
use OCP\Files\NotFoundException; |
|||
use OCP\Search\Result as BaseResult; |
|||
|
|||
class Result extends BaseResult { |
|||
|
|||
public $type = 'comment'; |
|||
public $comment; |
|||
public $authorId; |
|||
public $authorName; |
|||
public $path; |
|||
public $fileName; |
|||
|
|||
/** |
|||
* @param string $search |
|||
* @param IComment $comment |
|||
* @param string $authorName |
|||
* @param string $path |
|||
* @throws NotFoundException |
|||
*/ |
|||
public function __construct(string $search, |
|||
IComment $comment, |
|||
string $authorName, |
|||
string $path) { |
|||
parent::__construct( |
|||
(int) $comment->getId(), |
|||
$comment->getMessage() |
|||
/* @todo , [link to file] */ |
|||
); |
|||
|
|||
$this->comment = $this->getRelevantMessagePart($comment->getMessage(), $search); |
|||
$this->authorId = $comment->getActorId(); |
|||
$this->authorName = $authorName; |
|||
$this->fileName = basename($path); |
|||
$this->path = $this->getVisiblePath($path); |
|||
} |
|||
|
|||
/** |
|||
* @param string $path |
|||
* @return string |
|||
* @throws NotFoundException |
|||
*/ |
|||
protected function getVisiblePath(string $path): string { |
|||
$segments = explode('/', trim($path, '/'), 3); |
|||
|
|||
if (!isset($segments[2])) { |
|||
throw new NotFoundException('Path not inside visible section'); |
|||
} |
|||
|
|||
return $segments[2]; |
|||
} |
|||
|
|||
/** |
|||
* @param string $message |
|||
* @param string $search |
|||
* @return string |
|||
* @throws NotFoundException |
|||
*/ |
|||
protected function getRelevantMessagePart(string $message, string $search): string { |
|||
$start = stripos($message, $search); |
|||
if ($start === false) { |
|||
throw new NotFoundException('Comment section not found'); |
|||
} |
|||
|
|||
$end = $start + strlen($search); |
|||
|
|||
if ($start <= 25) { |
|||
$start = 0; |
|||
$prefix = ''; |
|||
} else { |
|||
$start -= 25; |
|||
$prefix = '…'; |
|||
} |
|||
|
|||
if ((strlen($message) - $end) <= 25) { |
|||
$end = strlen($message); |
|||
$suffix = ''; |
|||
} else { |
|||
$end += 25; |
|||
$suffix = '…'; |
|||
} |
|||
|
|||
return $prefix . substr($message, $start, $end - $start) . $suffix; |
|||
} |
|||
|
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue