Refresh
This commit is contained in:
170
app/Services/Exporter.php
Executable file
170
app/Services/Exporter.php
Executable file
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Folder;
|
||||
use App\Models\User;
|
||||
|
||||
/**
|
||||
* Exports data from Cyca.
|
||||
*/
|
||||
class Exporter
|
||||
{
|
||||
/**
|
||||
* Should we include highlights in the export ?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $withHighlights = true;
|
||||
|
||||
/**
|
||||
* Should we include bookmarks in the export ?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $withBookmarks = true;
|
||||
|
||||
/**
|
||||
* User to import data for.
|
||||
*
|
||||
* @var \App\Models\User
|
||||
*/
|
||||
protected $forUser;
|
||||
|
||||
/**
|
||||
* Folder to export bookmarks and feeds from.
|
||||
*
|
||||
* @var \App\Models\Folder
|
||||
*/
|
||||
protected $fromFolder;
|
||||
|
||||
/**
|
||||
* Should we ignore highlights during export ? By default, highlights will
|
||||
* be exported as well.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function withoutHighlights()
|
||||
{
|
||||
$this->withHighlights = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we ignore bookmarks during export ? By default, bookmarks will
|
||||
* be exported as well.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function withoutBookmarks()
|
||||
{
|
||||
$this->withoutBookmarks = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines which user to export data for. If not defined, user will be
|
||||
* extracted from request.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function forUser(User $user)
|
||||
{
|
||||
$this->forUser = $user;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines from which folder data will be exported. If not defined, root
|
||||
* folder attached to specified user will be used.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function fromFolder(Folder $folder)
|
||||
{
|
||||
$this->fromFolder = $folder;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export specified user's data into a PHP array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function export()
|
||||
{
|
||||
if (empty($this->fromFolder)) {
|
||||
$this->fromFolder = $this->forUser->groups()->active()->first()->folders()->ofType('root')->first();
|
||||
}
|
||||
|
||||
$rootArray = [
|
||||
'documents' => [],
|
||||
'folders' => $this->exportTree($this->fromFolder->children()->get()),
|
||||
];
|
||||
|
||||
foreach ($this->fromFolder->documents()->get() as $document) {
|
||||
$documentArray = [
|
||||
'url' => $document->url,
|
||||
'feeds' => [],
|
||||
];
|
||||
|
||||
foreach ($document->feeds()->get() as $feed) {
|
||||
$documentArray['feeds'] = [
|
||||
'url' => $feed->url,
|
||||
'is_ignored' => $feed->is_ignored,
|
||||
];
|
||||
}
|
||||
|
||||
$rootArray['documents'][] = $documentArray;
|
||||
}
|
||||
|
||||
return [
|
||||
'highlights' => $this->forUser->highlights()->select(['expression', 'color'])->get(),
|
||||
'bookmarks' => $rootArray,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a single tree branch.
|
||||
*
|
||||
* @param mixed $folders
|
||||
*/
|
||||
protected function exportTree($folders)
|
||||
{
|
||||
$array = [];
|
||||
|
||||
foreach ($folders as $folder) {
|
||||
$folderArray = [
|
||||
'title' => $folder->title,
|
||||
'documents' => [],
|
||||
'folders' => [],
|
||||
];
|
||||
|
||||
foreach ($folder->documents()->get() as $document) {
|
||||
$documentArray = [
|
||||
'url' => $document->url,
|
||||
'feeds' => [],
|
||||
];
|
||||
|
||||
foreach ($document->feeds()->get() as $feed) {
|
||||
$documentArray['feeds'][] = [
|
||||
'url' => $feed->url,
|
||||
'is_ignored' => $feed->is_ignored,
|
||||
];
|
||||
}
|
||||
|
||||
$folderArray['documents'][] = $documentArray;
|
||||
}
|
||||
|
||||
$folderArray['folders'] = $this->exportTree(($folder->children()->get()));
|
||||
|
||||
$array[] = $folderArray;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
}
|
||||
321
app/Services/Importer.php
Executable file
321
app/Services/Importer.php
Executable file
@@ -0,0 +1,321 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Document;
|
||||
use App\Models\Feed;
|
||||
use App\Models\Folder;
|
||||
use App\Models\Group;
|
||||
use App\Models\Highlight;
|
||||
use App\Models\IgnoredFeed;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* Imports data in Cyca.
|
||||
*/
|
||||
class Importer
|
||||
{
|
||||
/**
|
||||
* Adapter used to import data.
|
||||
*
|
||||
* @var \App\Contracts\ImportAdapter
|
||||
*/
|
||||
protected $importAdapter;
|
||||
|
||||
/**
|
||||
* User to import data for.
|
||||
*
|
||||
* @var \App\Models\User
|
||||
*/
|
||||
protected $forUser;
|
||||
|
||||
/**
|
||||
* Folder to import bookmarks and feeds to.
|
||||
*
|
||||
* @var \App\Models\Folder
|
||||
*/
|
||||
protected $inFolder;
|
||||
|
||||
/**
|
||||
* Should we import highlights as well ?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $withHighlights = true;
|
||||
|
||||
/**
|
||||
* Data to be imported as an array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dataArray = [];
|
||||
|
||||
/**
|
||||
* Group to import data to.
|
||||
*
|
||||
* @var \App\Models\Group
|
||||
*/
|
||||
protected $inGroup;
|
||||
|
||||
/**
|
||||
* Indicates which adapter to use for importation.
|
||||
*
|
||||
* @param string $adapterName
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function using($adapterName)
|
||||
{
|
||||
$className = config(sprintf('importers.adapters.%s.adapter', $adapterName));
|
||||
|
||||
if (empty($className)) {
|
||||
abort(422, sprintf('Unknown import adapter %s', $className));
|
||||
}
|
||||
|
||||
$this->importAdapter = new $className();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines which user to import data for. If not defined, user will be
|
||||
* extracted from request.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function forUser(User $user)
|
||||
{
|
||||
$this->forUser = $user;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the group to import data to.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function inGroup(Group $group)
|
||||
{
|
||||
$this->inGroup = $group;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines in which folder data will be imported to. If not defined, root
|
||||
* folder attached to specified user will be used.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function inFolder(Folder $folder)
|
||||
{
|
||||
$this->inFolder = $folder;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we ignore highlights during import ? By default, highlights will
|
||||
* be imported as well.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function withoutHighlights()
|
||||
{
|
||||
$this->withHighlights = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import data from specified file. Must be a valid json file, valid from
|
||||
* Cyca's architecture point of view.
|
||||
*
|
||||
* @param string $path Full path to file to import
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function fromFile($path)
|
||||
{
|
||||
if (empty($this->forUser)) {
|
||||
abort(422, 'Target user not specified');
|
||||
}
|
||||
|
||||
$contents = file_get_contents($path);
|
||||
|
||||
if (empty($contents)) {
|
||||
abort(422, 'File does not exists');
|
||||
}
|
||||
|
||||
$this->dataArray = json_decode($contents, true);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import data using current request informations.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function fromRequest(Request $request)
|
||||
{
|
||||
if (empty($this->importAdapter)) {
|
||||
$this->using($request->input('importer'));
|
||||
}
|
||||
|
||||
if (empty($this->importAdapter)) {
|
||||
abort(422, 'An import adapter must be specified');
|
||||
}
|
||||
|
||||
if (empty($this->forUser)) {
|
||||
$this->forUser = $request->user();
|
||||
}
|
||||
|
||||
$this->dataArray = $this->importAdapter->importFromRequest($request);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the import.
|
||||
*/
|
||||
public function import()
|
||||
{
|
||||
if (empty($this->inGroup)) {
|
||||
$this->inGroup = $this->forUser->groups()->wherePivot('status', '=', 'own')->first();
|
||||
}
|
||||
|
||||
if (empty($this->inFolder)) {
|
||||
$this->inFolder = $this->inGroup->folders()->ofType('root')->first();
|
||||
}
|
||||
|
||||
if ($this->withHighlights && !empty($this->dataArray['highlights'])) {
|
||||
$this->importHighlights($this->dataArray['highlights']);
|
||||
}
|
||||
|
||||
if (!empty($this->dataArray['bookmarks'])) {
|
||||
$this->importBookmarks($this->dataArray['bookmarks']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import highlights from specified array.
|
||||
*
|
||||
* @param array $highlights
|
||||
*/
|
||||
protected function importHighlights($highlights)
|
||||
{
|
||||
foreach ($highlights as $highlightData) {
|
||||
$highlight = Highlight::where('user_id', $this->forUser->id)->where('expression', $highlightData['expression'])->first();
|
||||
|
||||
if (!$highlight) {
|
||||
$highlight = new Highlight();
|
||||
|
||||
$highlight->user_id = $this->forUser->id;
|
||||
$highlight->expression = $highlightData['expression'];
|
||||
$highlight->color = $highlightData['color'];
|
||||
|
||||
$highlight->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import bookmarks from specified array.
|
||||
*
|
||||
* @param array $bookmarks
|
||||
*/
|
||||
protected function importBookmarks($bookmarks)
|
||||
{
|
||||
$this->importDocuments($this->inFolder, $bookmarks['documents'] ?: []);
|
||||
$this->importFolders($this->inFolder, $bookmarks['folders'] ?: []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import folders.
|
||||
*
|
||||
* @param \App\Models\Folder Destination folder
|
||||
* @param array $foldersData Array of sub-folders definitions
|
||||
* @param mixed $folder
|
||||
*/
|
||||
protected function importFolders($folder, $foldersData)
|
||||
{
|
||||
foreach ($foldersData as $folderData) {
|
||||
$children = $this->inGroup->folders()->save(new Folder([
|
||||
'title' => $folderData['title'],
|
||||
'parent_id' => $folder->id,
|
||||
'user_id' => $this->forUser->id,
|
||||
]));
|
||||
|
||||
$this->importDocuments($children, $folderData['documents']);
|
||||
$this->importFolders($children, $folderData['folders']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import documents.
|
||||
*
|
||||
* @param \App\Models\Folder Destination folder
|
||||
* @param array $documentsData Array of documents definitions
|
||||
* @param mixed $folder
|
||||
*/
|
||||
protected function importDocuments($folder, $documentsData)
|
||||
{
|
||||
foreach ($documentsData as $docData) {
|
||||
if (empty($docData['url'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$url = urldecode($docData['url']);
|
||||
$document = Document::firstOrCreate(['url' => $url]);
|
||||
|
||||
if (array_key_exists('feeds', $docData)) {
|
||||
$this->importFeeds($document, $docData['feeds']);
|
||||
}
|
||||
|
||||
$folder->documents()->save($document, [
|
||||
'initial_url' => $url,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import feeds.
|
||||
*
|
||||
* @param \App\Models\Document $document Destination document
|
||||
* @param array $feedsData Array of feeds definitions
|
||||
*/
|
||||
protected function importFeeds($document, $feedsData)
|
||||
{
|
||||
$feedsToAttach = $document->feeds()->get()->pluck('id')->all();
|
||||
|
||||
foreach ($feedsData as $feedData) {
|
||||
if (empty($feedData['url'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$feedUrl = urldecode($feedData['url']);
|
||||
|
||||
$feed = Feed::firstOrCreate(['url' => $feedUrl]);
|
||||
|
||||
$feedsToAttach[] = $feed->id;
|
||||
|
||||
if ($feedData['is_ignored']) {
|
||||
$ignoredFeed = IgnoredFeed::where('user_id', $this->forUser->id)->where('feed_id', $feed->id)->first();
|
||||
|
||||
if (!$ignoredFeed) {
|
||||
$ignoredFeed = new IgnoredFeed();
|
||||
|
||||
$ignoredFeed->user()->associate($this->forUser);
|
||||
$ignoredFeed->feed()->associate($feed);
|
||||
|
||||
$ignoredFeed->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$document->feeds()->sync($feedsToAttach);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user