mirror of
https://github.com/Kovah/LinkAce.git
synced 2025-04-21 23:42:10 +02:00
Move html importer logic into action and improve imports via HTTP and console (refs #201)
This commit is contained in:
parent
20ce10106d
commit
271386c3c8
91
app/Actions/ImportHtmlBookmarks.php
Normal file
91
app/Actions/ImportHtmlBookmarks.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions;
|
||||
|
||||
use App\Helper\HtmlMeta;
|
||||
use App\Helper\LinkIconMapper;
|
||||
use App\Models\Link;
|
||||
use App\Models\Tag;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Shaarli\NetscapeBookmarkParser\NetscapeBookmarkParser;
|
||||
|
||||
class ImportHtmlBookmarks
|
||||
{
|
||||
protected $imported = 0;
|
||||
protected $skipped = 0;
|
||||
|
||||
public function run(string $data, string $userId, bool $generateMeta = true): bool
|
||||
{
|
||||
$parser = new NetscapeBookmarkParser(true, [], '0', storage_path('logs'));
|
||||
|
||||
try {
|
||||
$links = $parser->parseString($data);
|
||||
} catch (\Exception $e) {
|
||||
Log::error($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($links)) {
|
||||
// This will never be reached at the moment because the bookmark parser is not capable of handling
|
||||
// empty bookmarks exports. See https://github.com/shaarli/netscape-bookmark-parser/issues/50
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($links as $link) {
|
||||
if (Link::whereUrl($link['uri'])->first()) {
|
||||
$this->skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($generateMeta) {
|
||||
$linkMeta = HtmlMeta::getFromUrl($link['uri']);
|
||||
$title = $link['title'] ?: $linkMeta['title'];
|
||||
$description = $link['note'] ?: $linkMeta['description'];
|
||||
} else {
|
||||
$title = $link['title'];
|
||||
$description = $link['note'];
|
||||
}
|
||||
|
||||
$newLink = Link::create([
|
||||
'user_id' => $userId,
|
||||
'url' => $link['uri'],
|
||||
'title' => $title,
|
||||
'description' => $description,
|
||||
'icon' => LinkIconMapper::mapLink($link['uri']),
|
||||
'is_private' => $link['pub'],
|
||||
'created_at' => Carbon::createFromTimestamp($link['time']),
|
||||
'updated_at' => Carbon::now(),
|
||||
]);
|
||||
|
||||
if (!empty($link['tags'])) {
|
||||
$tags = explode(' ', $link['tags']);
|
||||
|
||||
$newTags = [];
|
||||
foreach ($tags as $tag) {
|
||||
$newTag = Tag::firstOrCreate([
|
||||
'user_id' => $userId,
|
||||
'name' => $tag,
|
||||
]);
|
||||
$newTags[] = $newTag->id;
|
||||
}
|
||||
|
||||
$newLink->tags()->sync($newTags);
|
||||
}
|
||||
|
||||
$this->imported++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getImportCount(): int
|
||||
{
|
||||
return $this->imported;
|
||||
}
|
||||
|
||||
public function getSkippedCount(): int
|
||||
{
|
||||
return $this->skipped;
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ trait AsksForUser
|
||||
/** @var User */
|
||||
protected $user;
|
||||
|
||||
protected function askForUserEmail(): void
|
||||
protected function askForUser(): void
|
||||
{
|
||||
do {
|
||||
$email = $this->ask('Please enter the user email address');
|
||||
|
@ -2,15 +2,10 @@
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Helper\HtmlMeta;
|
||||
use App\Helper\LinkIconMapper;
|
||||
use App\Models\Link;
|
||||
use App\Models\Tag;
|
||||
use Carbon\Carbon;
|
||||
use App\Actions\ImportHtmlBookmarks;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Shaarli\NetscapeBookmarkParser\NetscapeBookmarkParser;
|
||||
use Illuminate\Support\Facades\File;
|
||||
|
||||
/**
|
||||
* Class ImportCommand
|
||||
@ -19,132 +14,52 @@ use Shaarli\NetscapeBookmarkParser\NetscapeBookmarkParser;
|
||||
*/
|
||||
class ImportCommand extends Command
|
||||
{
|
||||
use AsksForUser;
|
||||
|
||||
protected $signature = 'links:import
|
||||
{filename : Bookmarks file to import}
|
||||
{--skip-lookup : Whether the lookup should be skipped.}
|
||||
{filepath : Bookmarks file to import}
|
||||
{--skip-meta-generation : Whether the automatic generation of titles should be skipped.}
|
||||
{--skip-check : Whether the links checking should be skipped afterwards}';
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
$lookup = true;
|
||||
$check = true;
|
||||
$lookupMeta = true;
|
||||
|
||||
if ($this->argument('filename')) {
|
||||
$filename = $this->argument('filename');
|
||||
} else {
|
||||
// Check if option "-skip-lookup" is present
|
||||
if ($this->option('skip-meta-generation')) {
|
||||
$this->info('Skipping automatic meta generation.');
|
||||
$lookupMeta = false;
|
||||
}
|
||||
|
||||
$this->info('You will be asked to select a user who will be the owner of the imported bookmarks now.');
|
||||
$this->askForUser();
|
||||
|
||||
$this->info('Reading file "' . $this->argument('filepath') . '"...');
|
||||
$data = File::get(storage_path($this->argument('filepath')));
|
||||
|
||||
if ($data === false || empty($data)) {
|
||||
$this->warn('The provided file is empty or could not be read!');
|
||||
return;
|
||||
}
|
||||
|
||||
$importer = new ImportHtmlBookmarks;
|
||||
$result = $importer->run($data, $this->user->id, $lookupMeta);
|
||||
|
||||
// Check if option "-skip-lookup" is present
|
||||
if ($this->option('skip-lookup')) {
|
||||
$this->info("Skipping lookup");
|
||||
$lookup = !$this->option('skip-lookup');
|
||||
if ($result === false) {
|
||||
$this->error('Error while importing bookmarks. Please check the application logs.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if option "-skip-check" is present
|
||||
if ($this->option('skip-check')) {
|
||||
$this->info("Skipping link check");
|
||||
$check = !$this->option('skip-check');
|
||||
}
|
||||
|
||||
|
||||
// Read file
|
||||
$this->info('Reading file "' . $filename . '"...');
|
||||
$data = file_get_contents($filename);
|
||||
|
||||
|
||||
$parser = new NetscapeBookmarkParser(true, [], '0', storage_path('logs'));
|
||||
|
||||
try {
|
||||
$links = $parser->parseString($data);
|
||||
} catch (Exception $e) {
|
||||
Log::error($e->getMessage());
|
||||
|
||||
$this->error(trans('import.import_error'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($links)) {
|
||||
// This will never be reached at the moment because the bookmark parser is not capable of handling
|
||||
// empty bookmarks exports. See https://github.com/shaarli/netscape-bookmark-parser/issues/50
|
||||
$this->error(trans('import.import_empty'));
|
||||
return;
|
||||
}
|
||||
|
||||
$userId = 1;
|
||||
$imported = 0;
|
||||
$skipped = 0;
|
||||
|
||||
$bar = $this->output->createProgressBar(count($links));
|
||||
|
||||
$bar->start();
|
||||
|
||||
|
||||
foreach ($links as $link) {
|
||||
if (Link::whereUrl($link['uri'])->first()) {
|
||||
$skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
$bar->advance();
|
||||
|
||||
if ($lookup) {
|
||||
$linkMeta = HtmlMeta::getFromUrl($link['uri']);
|
||||
|
||||
$title = $link['title'] ?: $linkMeta['title'];
|
||||
|
||||
$description = $link['note'] ?: $linkMeta['description'];
|
||||
} else {
|
||||
$title = $link['title'];
|
||||
|
||||
$description = $link['note'];
|
||||
}
|
||||
|
||||
$newLink = Link::create([
|
||||
'user_id' => $userId,
|
||||
'url' => $link['uri'],
|
||||
'title' => $title,
|
||||
'description' => $description,
|
||||
'icon' => LinkIconMapper::mapLink($link['uri']),
|
||||
'is_private' => $link['pub'],
|
||||
'created_at' => Carbon::createFromTimestamp($link['time']),
|
||||
'updated_at' => Carbon::now(),
|
||||
]);
|
||||
|
||||
// Get all tags
|
||||
if (!empty($link['tags'])) {
|
||||
$tags = explode(' ', $link['tags']);
|
||||
|
||||
$newTags = [];
|
||||
foreach ($tags as $tag) {
|
||||
$newTag = Tag::firstOrCreate([
|
||||
'user_id' => $userId,
|
||||
'name' => $tag,
|
||||
]);
|
||||
|
||||
$newTags[] = $newTag->id;
|
||||
}
|
||||
|
||||
$newLink->tags()->sync($newTags);
|
||||
}
|
||||
|
||||
$imported++;
|
||||
}
|
||||
|
||||
$bar->finish();
|
||||
|
||||
// Force new line
|
||||
$this->comment(PHP_EOL);
|
||||
|
||||
if ($check) {
|
||||
// Queue link check
|
||||
$this->info('Skipping link check.');
|
||||
} else {
|
||||
Artisan::queue('links:check');
|
||||
}
|
||||
|
||||
$this->info(trans('import.import_successfully', [
|
||||
'imported' => $imported,
|
||||
'skipped' => $skipped,
|
||||
'imported' => $importer->getImportCount(),
|
||||
'skipped' => $importer->getSkippedCount(),
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ class ResetPasswordCommand extends Command
|
||||
{
|
||||
$this->line('This tool allows you to reset the password for any user.');
|
||||
|
||||
$this->askForUserEmail();
|
||||
$this->askForUser();
|
||||
$this->resetUserPassword();
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ class ViewRecoveryCodesCommand extends Command
|
||||
{
|
||||
$this->line('This tool allows you to view the 2FA recovery codes for any user.');
|
||||
|
||||
$this->askForUserEmail();
|
||||
$this->askForUser();
|
||||
$this->viewBackupCodes();
|
||||
}
|
||||
|
||||
|
@ -2,19 +2,12 @@
|
||||
|
||||
namespace App\Http\Controllers\App;
|
||||
|
||||
use App\Helper\HtmlMeta;
|
||||
use App\Helper\LinkIconMapper;
|
||||
use App\Actions\ImportHtmlBookmarks;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\DoImportRequest;
|
||||
use App\Models\Link;
|
||||
use App\Models\Tag;
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Filesystem\FileNotFoundException;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Shaarli\NetscapeBookmarkParser\NetscapeBookmarkParser;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class ImportController extends Controller
|
||||
{
|
||||
@ -41,78 +34,21 @@ class ImportController extends Controller
|
||||
{
|
||||
$data = $request->file('import-file')->get();
|
||||
|
||||
$parser = new NetscapeBookmarkParser(true, [], '0', storage_path('logs'));
|
||||
$importer = new ImportHtmlBookmarks;
|
||||
$result = $importer->run($data, auth()->id());
|
||||
|
||||
try {
|
||||
$links = $parser->parseString($data);
|
||||
} catch (Exception $e) {
|
||||
Log::error($e->getMessage());
|
||||
|
||||
return response()->json([
|
||||
if ($result === false) {
|
||||
response()->json([
|
||||
'success' => false,
|
||||
'message' => trans('import.import_error'),
|
||||
]);
|
||||
}
|
||||
|
||||
if (empty($links)) {
|
||||
// This will never be reached at the moment because the bookmark parser is not capable of handling
|
||||
// empty bookmarks exports. See https://github.com/shaarli/netscape-bookmark-parser/issues/50
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => trans('import.import_empty'),
|
||||
]);
|
||||
}
|
||||
|
||||
$userId = auth()->id();
|
||||
$imported = 0;
|
||||
$skipped = 0;
|
||||
|
||||
foreach ($links as $link) {
|
||||
if (Link::whereUrl($link['uri'])->first()) {
|
||||
$skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
$linkMeta = HtmlMeta::getFromUrl($link['uri']);
|
||||
|
||||
$title = $link['title'] ?: $linkMeta['title'];
|
||||
|
||||
$newLink = Link::create([
|
||||
'user_id' => $userId,
|
||||
'url' => $link['uri'],
|
||||
'title' => $title,
|
||||
'description' => $link['note'] ?: $linkMeta['description'],
|
||||
'icon' => LinkIconMapper::mapLink($link['uri']),
|
||||
'is_private' => $link['pub'],
|
||||
'created_at' => Carbon::createFromTimestamp($link['time']),
|
||||
'updated_at' => Carbon::now(),
|
||||
]);
|
||||
|
||||
// Get all tags
|
||||
if (!empty($link['tags'])) {
|
||||
$tags = explode(' ', $link['tags']);
|
||||
|
||||
$newTags = [];
|
||||
foreach ($tags as $tag) {
|
||||
$newTag = Tag::firstOrCreate([
|
||||
'user_id' => $userId,
|
||||
'name' => $tag,
|
||||
]);
|
||||
|
||||
$newTags[] = $newTag->id;
|
||||
}
|
||||
|
||||
$newLink->tags()->sync($newTags);
|
||||
}
|
||||
|
||||
$imported++;
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => trans('import.import_successfully', [
|
||||
'imported' => $imported,
|
||||
'skipped' => $skipped,
|
||||
'imported' => $importer->getImportCount(),
|
||||
'skipped' => $importer->getSkippedCount(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user