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

Allow duplicated documents #108

Merged
merged 46 commits into from
Jul 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
7dde2b0
Moved KlinkApiController tests to DocumentPreviewControllerTest
avvertix Jul 4, 2018
8f94a0d
Add macro to http request for checking if comes from a K-Search
avvertix Jul 5, 2018
2138c9f
Commenting the hash uniqueness check
avvertix Jul 5, 2018
1038e0e
Clean import of Carbon
avvertix Jul 5, 2018
22c30df
Document preview
avvertix Jul 5, 2018
9240372
Change K-Link API controller to redirect to new preview and download …
avvertix Jul 5, 2018
7a9fe81
Use the newly defined routes
avvertix Jul 5, 2018
ec92a42
Preliminary thumbnail and download controllers
avvertix Jul 5, 2018
fcc6e6a
Uniformed file download
avvertix Jul 5, 2018
f5a89b7
[ci skip[ Preliminary controllers for thumbnail and download action
avvertix Jul 5, 2018
f609bf7
Download and version tests
avvertix Jul 6, 2018
838663b
Thumbnail controller
avvertix Jul 6, 2018
07942c5
Code style
avvertix Jul 6, 2018
c274103
Fix side effect of a change
avvertix Jul 6, 2018
06dfc83
Make document and thumbnail url optional and generated on demand
avvertix Jul 6, 2018
1238fdc
Clean already exists check
avvertix Jul 6, 2018
e4fdef8
Rename /d/ and /t/ routes according to latest discussion
avvertix Jul 6, 2018
1e60139
Duplicate document and event
avvertix Jul 10, 2018
1356e6b
Base mail notification of the duplicates
avvertix Jul 10, 2018
06ffd7e
Code style
avvertix Jul 10, 2018
eb0a3f0
Presentation of the duplication details
avvertix Jul 10, 2018
a974159
Fix usage of wrong database trait
avvertix Jul 11, 2018
e1dada2
Duplicate document message
avvertix Jul 11, 2018
e596e65
Remove middleware only from upload test
avvertix Jul 11, 2018
7ef7172
Protect against null $errors
avvertix Jul 11, 2018
76ecca9
Fix edit page test
avvertix Jul 11, 2018
38ea3ce
Code style
avvertix Jul 11, 2018
eff94f8
Hide empty collection message on duplicate if no collections are atta…
avvertix Jul 11, 2018
fd1b74f
Clear database trait.
avvertix Jul 11, 2018
39ae285
Add group_closure table to ClearDatabase trait
avvertix Jul 11, 2018
8a26ade
Ensure clean database
avvertix Jul 11, 2018
06a4b5a
Duplicate resolution
avvertix Jul 11, 2018
2791bf1
Improve duplication notification mail content
avvertix Jul 12, 2018
35e2ecd
Some logging
avvertix Jul 12, 2018
0390b6a
Switching to a dev branch of the k-search client to see if indexing e…
avvertix Jul 12, 2018
b3ca206
trigger reindex method
avvertix Jul 12, 2018
f82e35a
changed the check for descriptor equality
avvertix Jul 12, 2018
7846864
added duplicates
salaidin Jul 13, 2018
f26967b
improved RUS text duplicates
salaidin Jul 13, 2018
6ff4b93
Fix duplicate in collection message
avvertix Jul 13, 2018
a30dd1e
Add documentation about documents and duplicates
avvertix Jul 13, 2018
090b7ea
fix js callback
avvertix Jul 16, 2018
6e2fad8
Protection over reindex trigger error
avvertix Jul 16, 2018
09d41e7
Code style
avvertix Jul 16, 2018
5fb322a
Use File hash for checking duplicates
avvertix Jul 17, 2018
d94c9ff
Using K-Search client php 3.0.2
avvertix Jul 17, 2018
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
27 changes: 26 additions & 1 deletion app/DocumentDescriptor.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,14 @@ public function owner()
return $this->belongsTo('KBox\User', 'owner_id', 'id');
}

/**
* All duplicates of the document in the system
*/
public function duplicates()
{
return $this->hasMany('KBox\DuplicateDocument', 'duplicate_document_id', 'id');
}

/**
* Get the Projects that contain this document descriptor
*
Expand Down Expand Up @@ -503,7 +511,24 @@ public function getCopyrightOwnerAttribute($value = null)
return $this->castAttribute('copyright_owner', $value);
}


public function getDocumentUriAttribute($value = null)
{
if (! $value) {
return route('documents.preview', ['uuid' => $this->uuid]);
}

return $value;
}

public function getThumbnailUriAttribute($value = null)
{
if (! $value) {
return route('documents.thumbnail', ['uuid' => $this->uuid]);
}

return $value;
}

// --- convert to/from KlinkDocumentDescriptor

/**
Expand Down
183 changes: 183 additions & 0 deletions app/DuplicateDocument.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
<?php

namespace KBox;

use Carbon\Carbon;
use Illuminate\Support\HtmlString;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Support\Htmlable;

class DuplicateDocument extends Model implements Htmlable
{
protected $table = 'duplicate_descriptors';

protected $dates = ['notification_sent_at', 'resolved_at'];

protected $fillable = ['user_id','duplicate_document_id', 'document_id', 'resolved_at'];

/**
* Set if the user has been notified
*
* @param bool $started
* @return void
*/
public function setSentAttribute($sent)
{
if ($sent && ! $this->notification_sent_at) {
$this->attributes['notification_sent_at'] = Carbon::now();
}

if (! $sent && $this->notification_sent_at) {
$this->attributes['notification_sent_at'] = null;
}
}

/**
* Get if user has been notified
*
* @param mixed $value not taken into account
* @return bool
*/
public function getSentAttribute($value = null)
{
return isset($this->attributes['notification_sent_at']) && ! is_null($this->attributes['notification_sent_at']);
}

/**
* Set if the user has resolved the duplication with an action
*
* @param bool $started
* @return void
*/
public function setResolvedAttribute($resolved)
{
if ($resolved && ! $this->resolved_at) {
$this->attributes['resolved_at'] = Carbon::now();
}

if (! $resolved && $this->resolved_at) {
$this->attributes['resolved_at'] = null;
}
}

/**
* Get if user has resolved the duplication
*
* @param mixed $value not taken into account
* @return bool
*/
public function getResolvedAttribute($value = null)
{
return isset($this->attributes['resolved_at']) && ! is_null($this->attributes['resolved_at']);
}

/**
* Get a message representing the duplicate.
*
* @param mixed $value not taken into account
* @return bool
*/
public function getMessageAttribute($value = null)
{
if (is_null($this->document) || is_null($this->duplicateOf)) {
return '';
}

$args = [
'duplicate_link' => RoutingHelpers::preview($this->document),
'duplicate_title' => e($this->document->title),
'existing_link' => RoutingHelpers::preview($this->duplicateOf),
'existing_title' => e($this->duplicateOf->title),
];

if ($this->document->owner_id === $this->user_id && $this->duplicateOf->owner_id === $this->user_id) {
return trans('documents.duplicates.message_me_owner', $args);
}

$service = app('Klink\DmsDocuments\DocumentsService');

$collections = $service->getDocumentCollections($this->duplicateOf, $this->user);

if (! $collections->isEmpty()) {
return trans('documents.duplicates.message_in_collection', array_merge($args, [
'owner' => e($this->duplicateOf->owner->name),
'collections' => $collections->map(function ($c) {
return '<a href="'.route('documents.groups.show', [ 'id' => $c->id, 'highlight' => $this->duplicateOf->id]).'">'.e($c->name).'</a>';
})->implode(', ')
]));
} else {
return trans('documents.duplicates.message_with_owner', array_merge($args, [
'owner' => e($this->duplicateOf->owner->name)
]));
}

return '';
}

/**
* Return the HTML short message representation of this duplicate
*/
public function toHtml()
{
return new HtmlString($this->message);
}

/**
* The user that uploaded, and therefore triggered, the duplicate document finding
*
* @return \KBox\User
*/
public function user()
{
return $this->belongsTo('KBox\User', 'user_id', 'id');
}

/**
* The document that caused the duplicate finding
*
* @return \Kbox\DocumentDescriptor
*/
public function document()
{
return $this->belongsTo('KBox\DocumentDescriptor', 'duplicate_document_id', 'id')->withTrashed();
}

/**
* The existing document in the system
*
* @return \Kbox\DocumentDescriptor
*/
public function duplicateOf()
{
return $this->belongsTo('KBox\DocumentDescriptor', 'document_id', 'id')->withTrashed();
}

/**
* Filter by user
* @param KBox\User|in $user
*/
public function scopeOf($query, $user)
{
$id = is_a($user, 'KBox\User') ? $user->id : $user;

return $query->where('user_id', $id);
}

/**
* Filter for not sent notifications
*
*/
public function scopeNotSent($query)
{
return $query->whereNull('notification_sent_at');
}

/**
* Filter for not sent notifications
*
*/
public function scopeNotResolved($query)
{
return $query->whereNull('resolved_at');
}
}
49 changes: 49 additions & 0 deletions app/Events/FileDuplicateFoundEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace KBox\Events;

use KBox\User;
use KBox\DuplicateDocument;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\InteractsWithQueue;

class FileDuplicateFoundEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels, InteractsWithQueue, Queueable;

/**
* @var \KBox\User;
*/
public $user;

/**
* @var \KBox\DuplicateDocument
*/
public $duplicateDocument;

/**
* Create a new event instance.
*
* @return void
*/
public function __construct(User $user, DuplicateDocument $duplicateDocument)
{
$this->user = $user;
$this->duplicateDocument = $duplicateDocument;
}

/**
* Get the channels the event should broadcast on.
*
* @return Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
12 changes: 0 additions & 12 deletions app/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
use Carbon\Carbon;
use Illuminate\Support\Facades\Storage;
use Dyrynda\Database\Support\GeneratesUuid;
use KBox\Exceptions\FileAlreadyExistsException;
use Klink\DmsAdapter\KlinkDocumentUtils;
use Illuminate\Support\Facades\Crypt;

Expand Down Expand Up @@ -608,7 +607,6 @@ public function videoResources()
* @param \KBox\User $uploader The user that perfomed the upload
* @param \KBox\File $revision_of The file that will be replaced with this new uploaded version
* @return \KBox\File
* @throws \KBox\Exceptions\FileAlreadyExistsException if a file with the same hash already exists in the system
*/
public static function createFromUploadedFile(UploadedFile $upload, User $uploader, File $revision_of = null)
{
Expand Down Expand Up @@ -643,16 +641,6 @@ public static function createFromUploadedFile(UploadedFile $upload, User $upload

$hash = KlinkDocumentUtils::generateDocumentHash($file_absolute_path);

if (static::existsByHash($hash)) {
$storage->deleteDirectory($destination_path);

$f = static::findByHash($hash);

$descr = $f->getLastVersion()->document;

throw new FileAlreadyExistsException($filename, $descr, $f);
}

$file_model->name = $filename;
$file_model->uuid = $uuid;
$file_model->hash = $hash;
Expand Down
4 changes: 4 additions & 0 deletions app/Http/Composers/DocumentsComposer.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ public function descriptor(View $view)
} else {
$view->with('badge_error', false);
}

$view->with('badge_duplicate', $document->duplicates()->of($auth_user)->exists());
}
}
}
Expand Down Expand Up @@ -196,6 +198,8 @@ public function descriptorPanel(View $view)
} else {
$view->with('show_versions', false);
}

$view->with('badge_duplicate', $document->duplicates()->of($auth_user)->exists());
}
}
}
Expand Down
52 changes: 52 additions & 0 deletions app/Http/Composers/DuplicateDocumentsComposer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace KBox\Http\Composers;

use KBox\DocumentDescriptor;
use Illuminate\Contracts\View\View;
use Klink\DmsDocuments\DocumentsService;

class DuplicateDocumentsComposer
{

/**
* @var \Klink\DmsDocuments\DocumentsService
*/
private $documents = null;



/**
* Create a new profile composer.
*
* @param UserRepository $users
* @return void
*/
public function __construct(DocumentsService $documentsService)
{
$this->documents = $documentsService;
}

public function duplicatePartial(View $view)
{
$document = isset($view['duplicate']) ? $view['duplicate']->duplicateOf : null;

$auth_check = \Auth::check();

if (! $auth_check) {
return;
}

if (! is_a($document, DocumentDescriptor::class)) {
return;
}

$auth_user = \Auth::user();

$collections = $this->documents->getDocumentCollections($document, $auth_user);

$view->with('is_in_collection', ! $collections->isEmpty());

$view->with('collections', $collections);
}
}
Loading