all atb changes
68
app/plugins/bookmarks/controllers/api/bookmark_folders.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/bookmarks/controllers/api/bookmark_folders.php
|
||||
*
|
||||
* This is the api bookmark folders controller.
|
||||
*
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Controllers\Api;
|
||||
|
||||
use TheTempusProject\Models\User;
|
||||
use TheTempusProject\Classes\ApiController;
|
||||
use TheTempusProject\Houdini\Classes\Views;
|
||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
use TheTempusProject\Models\Folders;
|
||||
|
||||
class BookmarkFolders extends ApiController {
|
||||
protected static $folders;
|
||||
|
||||
public function __construct() {
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
parent::__construct();
|
||||
self::$folders = new Folders;
|
||||
}
|
||||
|
||||
public function create() {
|
||||
$user = self::$authToken->createdBy;
|
||||
|
||||
$payload = @file_get_contents('php://input');
|
||||
$payload = json_decode( $payload, true );
|
||||
|
||||
$result = self::$folders->create(
|
||||
$payload['name'],
|
||||
$payload['folder'] ?? 0,
|
||||
$payload['notes'] ?? '',
|
||||
$payload['color'] ?? 'default',
|
||||
$payload['privacy'] ?? 'private',
|
||||
$user
|
||||
);
|
||||
|
||||
if ( ! $result ) {
|
||||
$responseType = 'error';
|
||||
$response = 'There was an error creating your folder.';
|
||||
} else {
|
||||
$responseType = 'id';
|
||||
$response = $result;
|
||||
}
|
||||
Views::view( 'api.response', ['response' => json_encode( [ $responseType => $response ], true )]);
|
||||
}
|
||||
|
||||
public function list( $id = '' ) {
|
||||
$user = self::$authToken->createdBy;
|
||||
$folders = self::$folders->bySpecificUser( $user );
|
||||
|
||||
if ( ! $folders ) {
|
||||
$responseType = 'error';
|
||||
$response = 'There was an error creating your folder.';
|
||||
} else {
|
||||
$responseType = 'folders';
|
||||
$response = $folders;
|
||||
}
|
||||
Views::view( 'api.response', ['response' => json_encode( [ $responseType => $response ], true )]);
|
||||
}
|
||||
}
|
56
app/plugins/bookmarks/controllers/api/bookmarks.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/bookmarks/controllers/api/bookmarks.php
|
||||
*
|
||||
* This is the api bookmarks controller.
|
||||
*
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Controllers\Api;
|
||||
|
||||
use TheTempusProject\Models\User;
|
||||
use TheTempusProject\Classes\ApiController;
|
||||
use TheTempusProject\Houdini\Classes\Views;
|
||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
use TheTempusProject\Models\Bookmarks as Bookmark;
|
||||
|
||||
class Bookmarks extends ApiController {
|
||||
protected static $bookmarks;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
self::$bookmarks = new Bookmark;
|
||||
}
|
||||
|
||||
public function create() {
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
|
||||
$user = self::$authToken->createdBy;
|
||||
|
||||
$payload = @file_get_contents('php://input');
|
||||
$payload = json_decode( $payload, true );
|
||||
|
||||
$result = self::$bookmarks->create(
|
||||
$payload['name'],
|
||||
$payload['url'],
|
||||
$payload['folder'] ?? 0,
|
||||
$payload['notes'] ?? '',
|
||||
$payload['color'] ?? 'default',
|
||||
$payload['privacy'] ?? 'private',
|
||||
'external',
|
||||
$user
|
||||
);
|
||||
if ( ! $result ) {
|
||||
$responseType = 'error';
|
||||
$response = 'There was an error creating your folder.';
|
||||
} else {
|
||||
$responseType = 'data';
|
||||
$response = $result;
|
||||
}
|
||||
Views::view( 'api.response', ['response' => json_encode( [ $responseType => $response ], true )]);
|
||||
}
|
||||
}
|
992
app/plugins/bookmarks/controllers/bookmarks.php
Normal file
@ -0,0 +1,992 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/bookmarks/controllers/bookmarks.php
|
||||
*
|
||||
* This is the bookmarks controller.
|
||||
*
|
||||
* @package TP Bookmarks
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Controllers;
|
||||
|
||||
use TheTempusProject\Hermes\Functions\Redirect;
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
use TheTempusProject\Bedrock\Functions\Session;
|
||||
use TheTempusProject\Houdini\Classes\Issues;
|
||||
use TheTempusProject\Houdini\Classes\Views;
|
||||
use TheTempusProject\Classes\Controller;
|
||||
use TheTempusProject\Classes\Forms;
|
||||
use TheTempusProject\Models\Bookmarks as Bookmark;
|
||||
use TheTempusProject\Models\Folders;
|
||||
use TheTempusProject\Models\BookmarkDashboards as Dashboards;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Houdini\Classes\Components;
|
||||
use TheTempusProject\Houdini\Classes\Forms as HoudiniForms;
|
||||
use TheTempusProject\Houdini\Classes\Navigation;
|
||||
use TheTempusProject\Houdini\Classes\Template;
|
||||
use TheTempusProject\Hermes\Functions\Route as Routes;
|
||||
use TheTempusProject\Models\User;
|
||||
use TheTempusProject\Classes\Preferences;
|
||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||
|
||||
class Bookmarks extends Controller {
|
||||
protected static $bookmarks;
|
||||
protected static $folders;
|
||||
protected static $dashboards;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
if ( ! App::$isLoggedIn ) {
|
||||
Session::flash( 'notice', 'You must be logged in to create or manage bookmarks.' );
|
||||
return Redirect::home();
|
||||
}
|
||||
self::$bookmarks = new Bookmark;
|
||||
self::$folders = new Folders;
|
||||
self::$dashboards = new Dashboards;
|
||||
self::$title = 'Bookmarks - {SITENAME}';
|
||||
self::$pageDescription = 'Add and save url bookmarks here.';
|
||||
|
||||
$folderTabs = Views::simpleView( 'bookmarks.nav.folderTabs' );
|
||||
if ( stripos( Input::get('url'), 'bookmarks/bookmarks' ) !== false ) {
|
||||
$tabsView = Navigation::activePageSelect( $folderTabs, '/bookmarks/folders/', false, true );
|
||||
$userFolderTabs = Views::simpleView('bookmarks.nav.userFolderTabs', self::$folders->simpleObjectByUser(true) );
|
||||
$userFolderTabsView = Navigation::activePageSelect( $userFolderTabs, Input::get( 'url' ), false, true );
|
||||
} else {
|
||||
$tabsView = Navigation::activePageSelect( $folderTabs, Input::get( 'url' ), false, true );
|
||||
$userFolderTabsView = '';
|
||||
}
|
||||
Components::set( 'userFolderTabs', $userFolderTabsView );
|
||||
Components::set( 'SITE_URL', Routes::getAddress() );
|
||||
Views::raw( $tabsView );
|
||||
Components::append( 'TEMPLATE_JS_INCLUDES', Template::parse('<script language="JavaScript" crossorigin="anonymous" type="text/javascript" src="{ROOT_URL}app/plugins/bookmarks/js/bookmarks.js"></script>' ) );
|
||||
$viewOptions = Views::simpleView( 'bookmarks.nav.viewOptions' );
|
||||
Components::set( 'VIEW_OPTIONS', $viewOptions );
|
||||
$dashOptions = Views::simpleView( 'bookmarks.dashboards.dashOptions' );
|
||||
Components::set( 'DASH_OPTIONS', $dashOptions );
|
||||
$this->setPrefToggles();
|
||||
}
|
||||
|
||||
public function index() {
|
||||
self::$title = 'Manage Bookmarks - {SITENAME}';
|
||||
if ( Input::exists('submit') ) {
|
||||
$prefs = new Preferences;
|
||||
$user = new User;
|
||||
$fields = $prefs->convertFormToArray( true );
|
||||
$out = $user->updatePrefs( $fields, App::$activeUser->ID );
|
||||
$this->setPrefToggles();
|
||||
}
|
||||
|
||||
$folders = self::$folders->byUser();
|
||||
$panelArray = [];
|
||||
if ( !empty( $folders ) ) {
|
||||
foreach ( $folders as $folder ) {
|
||||
$panel = new \stdClass();
|
||||
$folderObject = new \stdClass();
|
||||
$folderObject->bookmarks = self::$bookmarks->byFolder( $folder->ID );
|
||||
$folderObject->ID = $folder->ID;
|
||||
$folderObject->title = $folder->title;
|
||||
$folderObject->color = $folder->color;
|
||||
$folderObject->uuid = $folder->uuid;
|
||||
$folderObject->bookmarkListRows = Views::simpleView( 'bookmarks.components.bookmarkListRows', $folderObject->bookmarks );
|
||||
$panelArray[] = $folderObject;
|
||||
}
|
||||
}
|
||||
if ( ! empty( $folders ) ) {
|
||||
Components::set( 'folderPanels', Views::simpleView( 'bookmarks.components.bookmarkListPanel', $panelArray ) );
|
||||
return Views::view( 'bookmarks.dash' );
|
||||
}
|
||||
return Views::view( 'bookmarks.indexExplainer' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Bookmarks
|
||||
*/
|
||||
public function bookmark( $id = 0 ) {
|
||||
$bookmark = self::$bookmarks->findById( $id );
|
||||
if ( $bookmark == false ) {
|
||||
Session::flash( 'error', 'Bookmark not found.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||
Session::flash( 'error', 'You do not have permission to modify this bookmark.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
Navigation::setCrumbComponent( 'BookmarkBreadCrumbs', 'bookmarks/bookmark/' . $id );
|
||||
return Views::view( 'bookmarks.bookmarks.view', $bookmark );
|
||||
}
|
||||
|
||||
public function unsorted() {
|
||||
self::$title = 'Unsorted Bookmarks - {SITENAME}';
|
||||
$bookmarks = self::$bookmarks->noFolder();
|
||||
Views::view( 'bookmarks.bookmarks.unsorted', $bookmarks );
|
||||
}
|
||||
|
||||
public function bookmarks( $id = null ) {
|
||||
$folder = self::$folders->findById( $id );
|
||||
if ( $folder == false ) {
|
||||
Session::flash( 'error', 'Folder not found.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
if ( $folder->createdBy != App::$activeUser->ID ) {
|
||||
Session::flash( 'error', 'You do not have permission to view this folder.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
Navigation::setCrumbComponent( 'BookmarkBreadCrumbs', 'bookmarks/bookmarks/' . $id );
|
||||
|
||||
$panelArray = [];
|
||||
$panel = new \stdClass();
|
||||
$folderObject = new \stdClass();
|
||||
$folderObject->bookmarks = self::$bookmarks->byFolder( $folder->ID );
|
||||
$folderObject->ID = $folder->ID;
|
||||
$folderObject->title = $folder->title;
|
||||
$folderObject->color = $folder->color;
|
||||
$folderObject->bookmarkListRows = Views::simpleView( 'bookmarks.components.bookmarkListRows', $folderObject->bookmarks );
|
||||
$panel->panel = Views::simpleView( 'bookmarks.components.bookmarkListPanel', [$folderObject] );
|
||||
$panelArray[] = $panel;
|
||||
|
||||
return Views::view( 'bookmarks.bookmarks.listPage', $panelArray );
|
||||
}
|
||||
|
||||
public function createBookmark( $id = null ) {
|
||||
self::$title = 'Add Bookmark - {SITENAME}';
|
||||
$folderID = Input::get('folder_id') ? Input::get('folder_id') : $id;
|
||||
$folderID = Input::post('folder_id') ? Input::post('folder_id') : $id;
|
||||
$this->setFolderSelect( $folderID );
|
||||
|
||||
if ( ! Input::exists() ) {
|
||||
return Views::view( 'bookmarks.bookmarks.create' );
|
||||
}
|
||||
if ( ! Forms::check( 'createBookmark' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error with your form.' => Check::userErrors() ] );
|
||||
return Views::view( 'bookmarks.bookmarks.create' );
|
||||
}
|
||||
|
||||
$result = self::$bookmarks->create(
|
||||
Input::post('title'),
|
||||
Input::post('url'),
|
||||
$folderID,
|
||||
Input::post('description'),
|
||||
Input::post('color'),
|
||||
Input::post('privacy'),
|
||||
);
|
||||
|
||||
if ( ! $result ) {
|
||||
Issues::add( 'error', [ 'There was an error creating your bookmark.' => Check::userErrors() ] );
|
||||
return Views::view( 'bookmarks.bookmarks.create' );
|
||||
}
|
||||
// self::$bookmarks->refreshInfo( $result );
|
||||
Session::flash( 'success', 'Your Bookmark has been created.' );
|
||||
if ( ! empty( $folderID ) ) {
|
||||
Redirect::to( 'bookmarks/bookmarks/'. $folderID );
|
||||
} else {
|
||||
Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
}
|
||||
|
||||
public function editBookmark( $id = null ) {
|
||||
self::$title = 'Edit Bookmark - {SITENAME}';
|
||||
$folderID = Input::exists('folder_id') ? Input::post('folder_id') : '';
|
||||
|
||||
$bookmark = self::$bookmarks->findById( $id );
|
||||
if ( $bookmark == false ) {
|
||||
Issues::add( 'error', 'Bookmark not found.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||
Issues::add( 'error', 'You do not have permission to modify this bookmark.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
if ( empty( $folderID ) ) {
|
||||
$folderID = $bookmark->folderID;
|
||||
}
|
||||
|
||||
$this->setFolderSelect( $folderID );
|
||||
Components::set( 'color', $bookmark->color );
|
||||
|
||||
if ( ! Input::exists( 'submit' ) ) {
|
||||
return Views::view( 'bookmarks.bookmarks.edit', $bookmark );
|
||||
}
|
||||
if ( ! Forms::check( 'editBookmark' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error updating your bookmark.' => Check::userErrors() ] );
|
||||
return Views::view( 'bookmarks.bookmarks.edit', $bookmark );
|
||||
}
|
||||
|
||||
$result = self::$bookmarks->update(
|
||||
$id,
|
||||
Input::post('title'),
|
||||
Input::post('url'),
|
||||
$folderID,
|
||||
Input::post('description'),
|
||||
Input::post('color'),
|
||||
Input::post('privacy'),
|
||||
);
|
||||
if ( ! $result ) {
|
||||
Issues::add( 'error', [ 'There was an error updating your bookmark.' => Check::userErrors() ] );
|
||||
return Views::view( 'bookmarks.bookmarks.edit', $bookmark );
|
||||
}
|
||||
Session::flash( 'success', 'Your Bookmark has been updated.' );
|
||||
Redirect::to( 'bookmarks/folders/'. $bookmark->folderID );
|
||||
}
|
||||
|
||||
public function deleteBookmark( $id = null ) {
|
||||
$bookmark = self::$bookmarks->findById( $id );
|
||||
if ( $bookmark == false ) {
|
||||
Issues::add( 'error', 'Bookmark not found.' );
|
||||
return $this->index();
|
||||
}
|
||||
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||
Issues::add( 'error', 'You do not have permission to modify this bookmark.' );
|
||||
return $this->index();
|
||||
}
|
||||
$result = self::$bookmarks->delete( $id );
|
||||
if ( !$result ) {
|
||||
Session::flash( 'error', 'There was an error deleting the bookmark(s)' );
|
||||
} else {
|
||||
Session::flash( 'success', 'Bookmark deleted' );
|
||||
}
|
||||
Redirect::to( 'bookmarks/folders/'. $bookmark->folderID );
|
||||
}
|
||||
|
||||
/**
|
||||
* Folders
|
||||
*/
|
||||
public function folders( $id = null) {
|
||||
$folder = self::$folders->findById( $id );
|
||||
if ( $folder == false ) {
|
||||
$folders = self::$folders->byUser();
|
||||
Components::set( 'foldersList', Views::simpleView( 'bookmarks.folders.list', $folders ) );
|
||||
return Views::view( 'bookmarks.folders.listPage' );
|
||||
}
|
||||
if ( $folder->createdBy != App::$activeUser->ID ) {
|
||||
Session::flash( 'error', 'You do not have permission to view this folder.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
Navigation::setCrumbComponent( 'BookmarkBreadCrumbs', 'bookmarks/folders/' . $id );
|
||||
return Views::view( 'bookmarks.folders.view', $folder );
|
||||
}
|
||||
|
||||
public function createFolder( $id = 0 ) {
|
||||
self::$title = 'Create Folder - {SITENAME}';
|
||||
$folderID = Input::exists('folder_id') ? Input::post('folder_id') : $id;
|
||||
$folders = self::$folders->simpleByUser();
|
||||
if ( ! empty( $folders ) ) {
|
||||
$this->setFolderSelect( $folderID );
|
||||
} else {
|
||||
$folderSelect = '';
|
||||
Components::set( 'folderSelect', $folderSelect );
|
||||
}
|
||||
if ( ! Input::exists() ) {
|
||||
return Views::view( 'bookmarks.folders.create' );
|
||||
}
|
||||
if ( ! Forms::check( 'createFolder' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error creating your folder.' => Check::userErrors() ] );
|
||||
return Views::view( 'bookmarks.folders.create' );
|
||||
}
|
||||
$folder = self::$folders->create( Input::post('title'), $folderID, Input::post('description'), Input::post('color'), Input::post('privacy') );
|
||||
if ( ! $folder ) {
|
||||
return Views::view( 'bookmarks.folders.create' );
|
||||
}
|
||||
Session::flash( 'success', 'Your Folder has been created.' );
|
||||
Redirect::to( 'bookmarks/folders' );
|
||||
}
|
||||
|
||||
public function editFolder( $id = null ) {
|
||||
self::$title = 'Edit Folder - {SITENAME}';
|
||||
$folder = self::$folders->findById( $id );
|
||||
|
||||
if ( $folder == false ) {
|
||||
Issues::add( 'error', 'Folder not found.' );
|
||||
return $this->index();
|
||||
}
|
||||
|
||||
if ( $folder->createdBy != App::$activeUser->ID ) {
|
||||
Issues::add( 'error', 'You do not have permission to modify this folder.' );
|
||||
return $this->index();
|
||||
}
|
||||
$folderID = ( false === Input::exists('folder_id') ) ? $folder->ID : Input::post('folder_id');
|
||||
|
||||
$this->setFolderSelect( $folderID );
|
||||
Components::set( 'color', $folder->color );
|
||||
|
||||
if ( ! Input::exists( 'submit' ) ) {
|
||||
return Views::view( 'bookmarks.folders.edit', $folder );
|
||||
}
|
||||
|
||||
if ( !Forms::check( 'editFolder' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error editing your folder.' => Check::userErrors() ] );
|
||||
return Views::view( 'bookmarks.folders.edit', $folder );
|
||||
}
|
||||
|
||||
$result = self::$folders->update( $id, Input::post('title'), $folderID, Input::post('description'), Input::post('color'), Input::post('privacy') );
|
||||
if ( !$result ) {
|
||||
Issues::add( 'error', [ 'There was an error updating your folder.' => Check::userErrors() ] );
|
||||
return Views::view( 'bookmarks.folders.edit', $folder );
|
||||
}
|
||||
Session::flash( 'success', 'Your Folder has been updated.' );
|
||||
Redirect::to( 'bookmarks/folders/'. $folder->ID );
|
||||
}
|
||||
|
||||
public function deleteFolder( $id = null ) {
|
||||
$folder = self::$folders->findById( $id );
|
||||
if ( $folder == false ) {
|
||||
Issues::add( 'error', 'Folder not found.' );
|
||||
return $this->index();
|
||||
}
|
||||
if ( $folder->createdBy != App::$activeUser->ID ) {
|
||||
Issues::add( 'error', 'You do not have permission to modify this folder.' );
|
||||
return $this->index();
|
||||
}
|
||||
$results = self::$bookmarks->deleteByFolder( $id );
|
||||
$result = self::$folders->delete( $id );
|
||||
if ( !$result ) {
|
||||
Session::flash( 'error', 'There was an error deleting the folder(s)' );
|
||||
} else {
|
||||
Session::flash( 'success', 'Folder deleted' );
|
||||
}
|
||||
Redirect::to( 'bookmarks/folders' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Dashboards
|
||||
*/
|
||||
public function addDash() {
|
||||
self::$title = 'Add Dashboard - {SITENAME}';
|
||||
if ( !App::$isMember ) {
|
||||
Issues::add( 'notice', 'You must have an active membership to add dashboards.' );
|
||||
return $this->index();
|
||||
}
|
||||
$folders = self::$folders->byUser() ?? [];
|
||||
|
||||
if ( !empty( $folders ) ) {
|
||||
foreach ( $folders as &$folder ) {
|
||||
$folder->selected = '';
|
||||
}
|
||||
}
|
||||
|
||||
$linkSelect = Views::simpleView( 'bookmarks.components.linkSelect', $folders );
|
||||
Components::set( 'LINK_SELECT', $linkSelect );
|
||||
|
||||
if ( ! Input::exists( 'submit' ) ) {
|
||||
return Views::view( 'bookmarks.dashboards.create' );
|
||||
}
|
||||
|
||||
if ( !Forms::check( 'createDashboard' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error creating your dashboard.' => Check::userErrors() ] );
|
||||
return Views::view( 'bookmarks.dashboards.create' );
|
||||
}
|
||||
|
||||
if ( is_array( Input::post('link_filter') ) && ! empty( Input::post('link_filter') ) ) {
|
||||
$filters = implode( ',', Input::post('link_filter') );
|
||||
} else {
|
||||
$filters = '';
|
||||
}
|
||||
if ( is_array( Input::post('link_order') ) && ! empty( Input::post('link_order') ) ) {
|
||||
$folders = implode( ',', Input::post('link_order') );
|
||||
} else {
|
||||
$folders = '';
|
||||
}
|
||||
$result = self::$dashboards->create( Input::post('title'), $filters, $folders, Input::post('description') );
|
||||
|
||||
if ( !$result ) {
|
||||
Issues::add( 'error', [ 'There was an error creating your dashboard.' => Check::userErrors() ] );
|
||||
return Views::view( 'bookmarks.dashboards.create' );
|
||||
}
|
||||
|
||||
Issues::add( 'success', 'Your dashboard has been created.' );
|
||||
return $this->dashboards();
|
||||
}
|
||||
|
||||
public function editDash( $id = null ) {
|
||||
self::$title = 'Edit Dashboard - {SITENAME}';
|
||||
if ( !App::$isMember ) {
|
||||
Issues::add( 'notice', 'You must have an active membership to edit dashboards.' );
|
||||
return $this->index();
|
||||
}
|
||||
$dash = self::$dashboards->findById( $id );
|
||||
|
||||
if ( $dash == false ) {
|
||||
Issues::add( 'error', 'Unknown Dashboard' );
|
||||
return $this->dashboards();
|
||||
}
|
||||
|
||||
if ( $dash->createdBy != App::$activeUser->ID ) {
|
||||
Issues::add( 'error', 'You do not have permission to view this dashboard.' );
|
||||
return $this->dashboards();
|
||||
}
|
||||
|
||||
$this->setDashToggles( explode( ',', $dash->saved_prefs ) );
|
||||
|
||||
$folders = self::$folders->byUser() ?? [];
|
||||
$selectedFolders = explode( ',', $dash->link_order );
|
||||
if ( !empty( $folders ) ) {
|
||||
foreach ( $folders as &$folder ) {
|
||||
if ( in_array( $folder->ID, $selectedFolders ) ) {
|
||||
$folder->selected = ' checked';
|
||||
} else {
|
||||
$folder->selected = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$linkSelect = Views::simpleView( 'bookmarks.components.linkSelect', $folders );
|
||||
Components::set( 'LINK_SELECT', $linkSelect );
|
||||
|
||||
if ( ! Input::exists( 'submit' ) ) {
|
||||
return Views::view( 'bookmarks.dashboards.edit', $dash );
|
||||
}
|
||||
|
||||
if ( ! Forms::check( 'editDashboard' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error editing your dashboard.' => Check::userErrors() ] );
|
||||
return Views::view( 'bookmarks.dashboards.edit', $dash );
|
||||
}
|
||||
|
||||
if ( is_array( Input::post('link_filter') ) && ! empty( Input::post('link_filter') ) ) {
|
||||
$filters = implode( ',', Input::post('link_filter') );
|
||||
} else {
|
||||
$filters = '';
|
||||
}
|
||||
|
||||
if ( is_array( Input::post('link_order') ) && ! empty( Input::post('link_order') ) ) {
|
||||
$folders = implode( ',', Input::post('link_order') );
|
||||
} else {
|
||||
$folders = '';
|
||||
}
|
||||
|
||||
$result = self::$dashboards->update( $id, Input::post('title'), $filters, $folders, Input::post('description') );
|
||||
|
||||
if ( !$result ) {
|
||||
Issues::add( 'error', [ 'There was an error updating your dashboard.' => Check::userErrors() ] );
|
||||
return Views::view( 'bookmarks.dashboards.edit', $dash );
|
||||
}
|
||||
|
||||
Issues::add( 'success', 'Your dashboard has been updated.' );
|
||||
return $this->dashboards();
|
||||
}
|
||||
|
||||
public function deleteDash( $id = null ) {
|
||||
if ( !App::$isMember ) {
|
||||
Issues::add( 'notice', 'You must have an active membership to delete dashboards.' );
|
||||
return $this->index();
|
||||
}
|
||||
$dash = self::$dashboards->findById( $id );
|
||||
if ( $dash == false ) {
|
||||
Issues::add( 'error', 'Unknown Dashboard' );
|
||||
return $this->dashboards();
|
||||
}
|
||||
if ( $dash->createdBy != App::$activeUser->ID ) {
|
||||
Issues::add( 'error', 'You do not have permission to delete this dash.' );
|
||||
return $this->dashboards();
|
||||
}
|
||||
$result = self::$dashboards->delete( $id );
|
||||
if ( !$result ) {
|
||||
Issues::add( 'error', 'There was an error deleting the dashboard(s)' );
|
||||
} else {
|
||||
Issues::add( 'success', 'Dashboard deleted' );
|
||||
}
|
||||
return $this->dashboards();
|
||||
}
|
||||
|
||||
public function dashboard( $uuid = null ) {
|
||||
self::$title = 'Bookmark Dashboard - {SITENAME}';
|
||||
if ( !App::$isMember ) {
|
||||
Issues::add( 'notice', 'You must have an active membership to view dashboards.' );
|
||||
return $this->index();
|
||||
}
|
||||
$dash = self::$dashboards->findByUuid( $uuid );
|
||||
if ( $dash == false ) {
|
||||
return $this->dashboards();
|
||||
}
|
||||
if ( $dash->createdBy != App::$activeUser->ID ) {
|
||||
Issues::add( 'error', 'You do not have permission to view this dash.' );
|
||||
return $this->dashboards();
|
||||
}
|
||||
if ( Input::exists( 'submit' ) ) {
|
||||
if ( Forms::check( 'updateDashboard' ) ) {
|
||||
$filters = '';
|
||||
$folders = '';
|
||||
|
||||
if ( is_array( Input::post('link_filter') ) && ! empty( Input::post('link_filter') ) ) {
|
||||
$filters = implode( ',', Input::post('link_filter') );
|
||||
}
|
||||
|
||||
if ( ! empty( Input::post('link_order') ) ) {
|
||||
$folders = Input::post('link_order');
|
||||
}
|
||||
|
||||
$result = self::$dashboards->updateDash( $dash->ID, $filters, $folders );
|
||||
|
||||
if ( !$result ) {
|
||||
Issues::add( 'error', [ 'There was an error saving your dashboard.' => Check::userErrors() ] );
|
||||
} else {
|
||||
Issues::add( 'success', 'Your dashboard has been saved.' );
|
||||
}
|
||||
} else {
|
||||
Issues::add( 'error', [ 'There was an error saving your dashboard.' => Check::userErrors() ] );
|
||||
}
|
||||
unset( $_POST );
|
||||
}
|
||||
$dash = self::$dashboards->findByUuid( $uuid );
|
||||
|
||||
$foldersArray = [];
|
||||
if ( ! empty( $dash->link_order ) ) {
|
||||
$folders = explode( ',', $dash->link_order );
|
||||
foreach ( $folders as $key => $id ) {
|
||||
$folder = self::$folders->findById( $id );
|
||||
if ( empty( $folder ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$bookmarks = self::$bookmarks->byFolder( $folder->ID );
|
||||
if ( empty( $bookmarks ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$folderObject = new \stdClass();
|
||||
$folderObject->ID = $folder->ID;
|
||||
$folderObject->title = $folder->title;
|
||||
$folderObject->color = $folder->color;
|
||||
$folderObject->uuid = $folder->uuid;
|
||||
$folderObject->bookmarkRows = Views::simpleView( 'bookmarks.dashboards.bookmarkRows', $bookmarks );
|
||||
$foldersArray[] = $folderObject;
|
||||
}
|
||||
}
|
||||
Components::set( 'folderPanels', Views::simpleView( 'bookmarks.dashboards.folderPanels', $foldersArray ) );
|
||||
|
||||
if ( ! empty( $dash->saved_prefs ) ) {
|
||||
$this->setDashToggles( explode( ',', $dash->saved_prefs ) );
|
||||
} else {
|
||||
$this->setDashToggles( [] );
|
||||
}
|
||||
|
||||
return Views::view( 'bookmarks.dashboards.view', $dash );
|
||||
}
|
||||
|
||||
public function dashboards() {
|
||||
self::$title = 'Bookmark Dashboards - {SITENAME}';
|
||||
|
||||
if ( !App::$isMember ) {
|
||||
Issues::add( 'notice', 'You will need an active subscription to start creating dashboards. You can check our <a href="/member/join" class="text-decoration-none">Pricing</a> page for more details.' );
|
||||
return Views::view( 'bookmarks.dashboardExplainer' );
|
||||
}
|
||||
$dashboards = self::$dashboards->byUser();
|
||||
return Views::view( 'bookmarks.dashboards.list', $dashboards );
|
||||
}
|
||||
|
||||
/**
|
||||
* Functionality
|
||||
*/
|
||||
public function publish( $id = null ) {
|
||||
$bookmark = self::$bookmarks->findById( $id );
|
||||
if ( $bookmark == false ) {
|
||||
Session::flash( 'error', 'Bookmark not found.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||
Session::flash( 'error', 'You do not have permission to modify this bookmark.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
self::$bookmarks->publish( $id );
|
||||
Session::flash( 'success', 'Bookmark mad Public.' );
|
||||
return Redirect::to( 'bookmarks/share' );
|
||||
}
|
||||
|
||||
public function retract( $id = null ) {
|
||||
$bookmark = self::$bookmarks->findById( $id );
|
||||
if ( $bookmark == false ) {
|
||||
Session::flash( 'error', 'Bookmark not found.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||
Session::flash( 'error', 'You do not have permission to modify this bookmark.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
self::$bookmarks->retract( $id );
|
||||
Session::flash( 'success', 'Bookmark made Private.' );
|
||||
return Redirect::to( 'bookmarks/share' );
|
||||
}
|
||||
|
||||
public function hideBookmark( $id = null ) {
|
||||
$bookmark = self::$bookmarks->findById( $id );
|
||||
if ( $bookmark == false ) {
|
||||
Session::flash( 'error', 'Bookmark not found.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||
Session::flash( 'error', 'You do not have permission to modify this bookmark.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
self::$bookmarks->hide( $id );
|
||||
Session::flash( 'success', 'Bookmark hidden.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
|
||||
public function archiveBookmark( $id = null ) {
|
||||
$bookmark = self::$bookmarks->findById( $id );
|
||||
if ( $bookmark == false ) {
|
||||
Session::flash( 'error', 'Bookmark not found.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||
Session::flash( 'error', 'You do not have permission to modify this bookmark.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
self::$bookmarks->archive( $id );
|
||||
Session::flash( 'success', 'Bookmark archived.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
|
||||
public function showBookmark( $id = null ) {
|
||||
$bookmark = self::$bookmarks->findById( $id );
|
||||
if ( $bookmark == false ) {
|
||||
Session::flash( 'error', 'Bookmark not found.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||
Session::flash( 'error', 'You do not have permission to modify this bookmark.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
self::$bookmarks->show( $id );
|
||||
Session::flash( 'success', 'Bookmark shown.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
|
||||
public function unarchiveBookmark( $id = null ) {
|
||||
$bookmark = self::$bookmarks->findById( $id );
|
||||
if ( $bookmark == false ) {
|
||||
Session::flash( 'error', 'Bookmark not found.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||
Session::flash( 'error', 'You do not have permission to modify this bookmark.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
self::$bookmarks->unarchive( $id );
|
||||
Session::flash( 'success', 'Bookmark un-archived.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
|
||||
public function refreshBookmark( $id = null ) {
|
||||
$bookmark = self::$bookmarks->findById( $id );
|
||||
if ( $bookmark == false ) {
|
||||
Session::flash( 'error', 'Bookmark not found.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||
Session::flash( 'error', 'You do not have permission to modify this bookmark.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
$info = self::$bookmarks->refreshInfo( $id );
|
||||
if ( false == $info ) {
|
||||
Session::flash( 'error', 'Issue refreshing your bookmark.' );
|
||||
return Redirect::to( 'bookmarks/bookmark/' . $bookmark->ID );
|
||||
}
|
||||
Session::flash( 'success', 'Bookmark data refreshed.' );
|
||||
return Redirect::to( 'bookmarks/bookmark/' . $bookmark->ID );
|
||||
}
|
||||
|
||||
public function import() {
|
||||
self::$title = 'Bookmark Import - {SITENAME}';
|
||||
if ( !App::$isMember ) {
|
||||
Issues::add( 'notice', 'You will need an active subscription to start importing bookmarks. You can check our <a href="/member/join" class="text-decoration-none">Pricing</a> page for more details.' );
|
||||
return Views::view( 'bookmarks.importExplainer' );
|
||||
}
|
||||
|
||||
if ( ! Input::exists('submit') ) {
|
||||
return Views::view( 'bookmarks.import' );
|
||||
}
|
||||
|
||||
if ( ! Forms::check( 'importBookmarks' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error importing your bookmarks.' => Check::userErrors() ] );
|
||||
return Views::view( 'bookmarks.import' );
|
||||
}
|
||||
|
||||
if ( isset( $_FILES['bookmark_file'] ) ) {
|
||||
$file = $_FILES['bookmark_file'];
|
||||
|
||||
if ($file['size'] > 1024 * 1024) { // 1024 KB = 1 MB
|
||||
Issues::add( 'error', 'There is a 1 meg limit on bookmark imports at this time.' );
|
||||
return Views::view( 'bookmarks.import' );
|
||||
}
|
||||
|
||||
$fileExtension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
|
||||
if ($fileExtension !== 'html') {
|
||||
Issues::add( 'error', 'Invalid file type. Only .html files are allowed.' );
|
||||
return Views::view( 'bookmarks.import' );
|
||||
}
|
||||
|
||||
$fileContent = file_get_contents($file['tmp_name']);
|
||||
} else {
|
||||
Issues::add( 'error', 'No Import detected' );
|
||||
return Views::view( 'bookmarks.import' );
|
||||
}
|
||||
|
||||
$out = $this->parseBookmarks($fileContent);
|
||||
$date = date('F j, Y');
|
||||
$description = 'Imported on ' . $date . ' from file: ' . $file['name'];
|
||||
|
||||
$importFolder = self::$folders->create( 'New Import', 0, $description );
|
||||
foreach ($out as $folder => $bookmarks) {
|
||||
$currentFolder = self::$folders->create( $folder, $importFolder, $description );
|
||||
foreach ($bookmarks as $index => $bookmark) {
|
||||
self::$bookmarks->create( $bookmark['name'], $bookmark['url'], $currentFolder);
|
||||
}
|
||||
}
|
||||
|
||||
Session::flash( 'success', 'Your Bookmark has been created.' );
|
||||
Redirect::to( 'bookmarks/bookmarks/'. $importFolder );
|
||||
}
|
||||
|
||||
public function export() {
|
||||
self::$title = 'Bookmark Export - {SITENAME}';
|
||||
if ( !App::$isMember ) {
|
||||
Issues::add( 'notice', 'You will need an active subscription to start exporting bookmarks. You can check our <a href="/member/join" class="text-decoration-none">Pricing</a> page for more details.' );
|
||||
return Views::view( 'bookmarks.exportExplainer' );
|
||||
}
|
||||
|
||||
$folders = self::$folders->byUser();
|
||||
|
||||
if ( ! Input::exists('submit') ) {
|
||||
return Views::view( 'bookmarks.export', $folders );
|
||||
}
|
||||
|
||||
if ( ! Forms::check( 'exportBookmarks' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error exporting your bookmarks.' => Check::userErrors() ] );
|
||||
return Views::view( 'bookmarks.export', $folders );
|
||||
}
|
||||
|
||||
$htmlDoc = '';
|
||||
$htmlDoc .= '<!DOCTYPE NETSCAPE-Bookmark-file-1>' . PHP_EOL;
|
||||
$htmlDoc .= '<!-- This is an automatically generated file.' . PHP_EOL;
|
||||
$htmlDoc .= ' It will be read and overwritten.' . PHP_EOL;
|
||||
$htmlDoc .= ' DO NOT EDIT! -->' . PHP_EOL;
|
||||
$htmlDoc .= '<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">' . PHP_EOL;
|
||||
$htmlDoc .= '<TITLE>Bookmarks</TITLE>' . PHP_EOL;
|
||||
$htmlDoc .= '<H1>Bookmarks</H1>' . PHP_EOL;
|
||||
$htmlDoc .= '<DL><p>' . PHP_EOL;
|
||||
foreach ( Input::post('BF_') as $key => $id ) {
|
||||
if ( $id == 'unsorted' ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$folder = self::$folders->findById( $id );
|
||||
if ( $folder == false ) {
|
||||
Session::flash( 'error', 'Folder not found.' );
|
||||
return Redirect::to( 'bookmarks/index' );
|
||||
}
|
||||
|
||||
$hiddenExcluded = ! ( Input::post('hiddenIncluded') ?? false );
|
||||
$archivedExcluded = ! ( Input::post('archivedIncluded') ?? false );
|
||||
|
||||
$links = self::$bookmarks->byFolder( $folder->ID, $hiddenExcluded, $archivedExcluded );
|
||||
$htmlDoc .= $this->exportFolder( $folder->title, $folder->createdAt, $folder->createdAt, $links );
|
||||
}
|
||||
$htmlDoc .= '</DL><p>' . PHP_EOL;
|
||||
|
||||
$folder = UPLOAD_DIRECTORY . App::$activeUser->username;
|
||||
if ( !file_exists( $folder ) ) {
|
||||
mkdir( $folder, 0777, true );
|
||||
}
|
||||
$file = $folder . DIRECTORY_SEPARATOR . 'export.html';
|
||||
|
||||
$result = file_put_contents( $file, $htmlDoc );
|
||||
|
||||
if ($result !== false) {
|
||||
$filename = basename($file);
|
||||
$downloadUrl = '/uploads/' . App::$activeUser->username . '/export.html';
|
||||
|
||||
Session::flash( 'success', 'Your Export is available for download <a target="_blank" href="' . $downloadUrl . '">here</a>.' );
|
||||
Redirect::to( 'bookmarks/export' );
|
||||
} else {
|
||||
Session::flash( 'error', 'There was an issue exporting your bookmarks, please try again.' );
|
||||
return Redirect::to( 'bookmarks/export' );
|
||||
}
|
||||
}
|
||||
|
||||
public function share() {
|
||||
$panelArray = [];
|
||||
$folders = self::$folders->byUser();
|
||||
if ( empty( $folders ) ) {
|
||||
return Views::view( 'bookmarks.shareExplainer' );
|
||||
}
|
||||
foreach ( $folders as $key => $folder ) {
|
||||
$panel = new \stdClass();
|
||||
$folderObject = new \stdClass();
|
||||
if ( $folder->privacy == 'private' ) {
|
||||
$links = self::$bookmarks->publicByFolder( $folder->ID );
|
||||
} else {
|
||||
$links = self::$bookmarks->byFolder( $folder->ID );
|
||||
}
|
||||
$folderObject->bookmarks = $links;
|
||||
|
||||
$folderObject->ID = $folder->ID;
|
||||
$folderObject->uuid = $folder->uuid;
|
||||
$folderObject->title = $folder->title;
|
||||
$folderObject->color = $folder->color;
|
||||
$folderObject->privacyBadge = $folder->privacyBadge;
|
||||
|
||||
$folderObject->bookmarkListRows = Views::simpleView( 'bookmarks.components.shareListRows', $folderObject->bookmarks );
|
||||
$panel->panel = Views::simpleView( 'bookmarks.components.shareListPanel', [$folderObject] );
|
||||
$panelArray[] = $panel;
|
||||
}
|
||||
return Views::view( 'bookmarks.share', $panelArray );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Private
|
||||
*/
|
||||
private function exportFolder( $title, $editedAt, $createdAt, $links ) {
|
||||
$htmlDoc = '<DT><H3 ADD_DATE="'.$createdAt.'" LAST_MODIFIED="'.$editedAt.'">'.$title.'</H3>' . PHP_EOL;
|
||||
$htmlDoc .= '<DL><p>' . PHP_EOL;
|
||||
if ( ! empty( $links ) ) {
|
||||
foreach ( $links as $key => $link ) {
|
||||
$htmlDoc .= $this->exportLink( $link->url, $link->icon, $link->createdAt, $link->title );
|
||||
}
|
||||
}
|
||||
$htmlDoc .= '</DL><p>' . PHP_EOL;
|
||||
return $htmlDoc;
|
||||
}
|
||||
|
||||
private function exportLink( $url, $icon, $createdAt, $title ) {
|
||||
$htmlDoc = '<DT><A HREF="'.$url.'" ADD_DATE="'.$createdAt.'" ICON="'.$icon.'">'.$title.'</A>' . PHP_EOL;
|
||||
return $htmlDoc;
|
||||
}
|
||||
|
||||
private function parseBookmarks($htmlContent) {
|
||||
$started = false;
|
||||
$out = [];
|
||||
$currentFolder = [];
|
||||
$folderName = ['unknown'];
|
||||
$lines = explode("\n", $htmlContent);
|
||||
foreach ($lines as $line) {
|
||||
if ( $started == false ) {
|
||||
if (preg_match("/<h1>(.*?)<\/h1>/i", $line, $matches)) {
|
||||
$started = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (preg_match('/<DL><p>/i', $line, $matches)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (preg_match('/<H3(.*)>(.*?)<\/h3>/i', $line, $matches)) {
|
||||
$newFolder = $matches[2];
|
||||
$out[$newFolder] = [];
|
||||
array_unshift($folderName, $newFolder );
|
||||
continue;
|
||||
}
|
||||
|
||||
if (preg_match('/<\/DL><p>/i', $line, $matches)) {
|
||||
array_shift($folderName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (preg_match('/<A HREF="(.*?)"(.*)>(.*?)<\/A>/i', $line, $matches)) {
|
||||
$href = $matches[1];
|
||||
$guts = $matches[2];
|
||||
$text = $matches[3];
|
||||
$added = '';
|
||||
$icon = '';
|
||||
|
||||
if (preg_match('/ADD_DATE="(.*?)"/i', $guts, $addMatches)) {
|
||||
$added = $addMatches[1];
|
||||
}
|
||||
if (preg_match('/ICON="(.*?)"/i', $guts, $iconMatches)) {
|
||||
$icon = $iconMatches[1];
|
||||
}
|
||||
|
||||
$currentFolder = $folderName[0];
|
||||
$out[$currentFolder][] = [
|
||||
'name' => $text,
|
||||
'url' => $href,
|
||||
'addDate' => $added,
|
||||
'icon' => $icon,
|
||||
'folderName' => $folderName[0],
|
||||
];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
private function setFolderSelect( $folderID ) {
|
||||
$options = self::$folders->simpleByUser();
|
||||
$out = '';
|
||||
$out .= '<div class="mb-3 row">';
|
||||
$out .= '<label for="folder_id" class="col-lg-5 col-form-label text-end">Folder</label>';
|
||||
$out .= '<div class="col-lg-3">';
|
||||
$out .= '<select name="folder_id" id="folder_id" class="form-control">';
|
||||
if ( isset( $options[0] ) ) {
|
||||
$assocOptions = [];
|
||||
foreach ( $options as $key => $value ) {
|
||||
$assocOptions[$value] = $value;
|
||||
}
|
||||
$options = $assocOptions;
|
||||
}
|
||||
if ( ! empty( $options ) ) {
|
||||
foreach ( $options as $fieldname => $value ) {
|
||||
if ( $folderID == $value ) {
|
||||
$selected = ' selected';
|
||||
} else {
|
||||
$selected = '';
|
||||
}
|
||||
$out .= '<option value="' . $value . '"' . $selected . '>' . $fieldname . '</option>';
|
||||
}
|
||||
} else {
|
||||
$out .= '<option value="0" selected>No Folder</option>';
|
||||
}
|
||||
$out .= '</select>';
|
||||
$out .= '</div>';
|
||||
$out .= '</div>';
|
||||
$folderSelect = Template::parse( $out );
|
||||
Components::set( 'folderSelect', $folderSelect );
|
||||
}
|
||||
|
||||
private function setPrefToggles() {
|
||||
$prefsArray = [
|
||||
'editModeSwitch',
|
||||
'showArchivedSwitch',
|
||||
'showHiddenSwitch',
|
||||
'archiveButtonSwitch',
|
||||
'visibilityButtonSwitch',
|
||||
'privacyButtonSwitch',
|
||||
'shareButtonSwitch',
|
||||
'addButtonSwitch'
|
||||
];
|
||||
foreach ($prefsArray as $key => $name) {
|
||||
if ( empty( App::$activeUser->prefs[$name] ) ) {
|
||||
Components::set( $name . '_IS_CHECKED', '' );
|
||||
} else {
|
||||
Components::set( $name . '_IS_CHECKED', ' checked' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function setDashToggles( $current = [] ) {
|
||||
$prefsArray = [
|
||||
'editModeSwitch',
|
||||
'showArchivedSwitch',
|
||||
'showHiddenSwitch',
|
||||
'archiveButtonSwitch',
|
||||
'visibilityButtonSwitch',
|
||||
'privacyButtonSwitch',
|
||||
'shareButtonSwitch',
|
||||
'addButtonSwitch'
|
||||
];
|
||||
foreach ( $prefsArray as $key => $name ) {
|
||||
Debug::error( $name );
|
||||
Debug::error( $current );
|
||||
if ( ! in_array( $name, $current ) ) {
|
||||
Components::set( $name . '_IS_CHECKED', '' );
|
||||
} else {
|
||||
Debug::error( '_IS_CHECKED' );
|
||||
Components::set( $name . '_IS_CHECKED', ' checked' );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
148
app/plugins/bookmarks/controllers/extensions.php
Normal file
@ -0,0 +1,148 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/bookmarks/controllers/extensions.php
|
||||
*
|
||||
* This is the extensions controller.
|
||||
*
|
||||
* @package TP Bookmarks
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Controllers;
|
||||
|
||||
use TheTempusProject\Classes\Controller;
|
||||
use TheTempusProject\Houdini\Classes\Views;
|
||||
use TheTempusProject\Houdini\Classes\Issues;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Hermes\Functions\Route as Routes;
|
||||
use TheTempusProject\Models\Token;
|
||||
use TheTempusProject\Houdini\Classes\Components;
|
||||
use TheTempusProject\Models\Folders;
|
||||
use TheTempusProject\Houdini\Classes\Template;
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
|
||||
class Extensions extends Controller {
|
||||
public function index() {
|
||||
self::$title = 'Browser Extensions';
|
||||
self::$pageDescription = 'Our extensions cover all major browsers with the notable exception of Safari. Chrome, Opera, Brave, Firefox, and Edge are all represented; giving users a simple way to add bookmarks and folders from any page.';
|
||||
if ( App::$isLoggedIn ) {
|
||||
Issues::add( 'success', 'We also have a simple solution to using the app from your mobile devices <a href="/extensions/mobile">here</a>.' );
|
||||
}
|
||||
Views::view( 'bookmarks.extensions.index' );
|
||||
}
|
||||
|
||||
public function mobile() {
|
||||
self::$title = 'Mobile Bookmarklet';
|
||||
self::$pageDescription = 'When you find yourself on the go, sometimes an extension isn\'t an option. For those times, we have the mobile bookmarklet to allow you to add bookmarks from your mobile devices.';
|
||||
|
||||
if ( ! App::$isLoggedIn ) {
|
||||
Issues::add( 'notice', 'Since the bookmarklet is tied directly to your account, you will need to <a href="/home/login">log in</a> to generate the code for your account.' );
|
||||
return Views::view( 'bookmarks.extensions.bookmarkletExplainer' );
|
||||
}
|
||||
|
||||
if ( Input::exists('privacy') ) {
|
||||
$privacy = 'const privacy = "' . Input::post('privacy') . '";';
|
||||
} else {
|
||||
$privacy = 'const privacy = prompt("Enter privacy level (e.g., public/private):");';
|
||||
}
|
||||
Components::set( 'BK_JS_PRIVACY', $privacy );
|
||||
|
||||
if ( Input::exists('includeDescription') ) {
|
||||
$description = 'const notes = prompt("Enter a description (optional):");';
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
Components::set( 'BK_JS_NOTES', $description );
|
||||
|
||||
if ( Input::exists('includeColor') ) {
|
||||
$color = 'const color = "'.Input::post('color').'";';
|
||||
} else {
|
||||
$color = '';
|
||||
}
|
||||
Components::set( 'BK_JS_COLOR', $color );
|
||||
|
||||
if ( Input::exists('includeFolder') ) {
|
||||
$folder = 'const folder = "'.Input::post('folder_id').'";';
|
||||
} else {
|
||||
$folder = '';
|
||||
}
|
||||
Components::set( 'BK_JS_FOLDER', $folder );
|
||||
|
||||
$this->setFolderSelect(Input::post('folder'));
|
||||
|
||||
$tokens = new Token;
|
||||
$apiKey = $tokens->findOrCreateUserToken( App::$activeUser->ID, true );
|
||||
$apiUrl = Routes::getAddress() . 'api/bookmarks/create';
|
||||
Components::set( 'BK_API_KEY', $apiKey );
|
||||
Components::set( 'BK_API_URL', $apiUrl );
|
||||
|
||||
Views::view( 'bookmarks.extensions.bookmarklet' );
|
||||
}
|
||||
|
||||
public function chrome() {
|
||||
self::$title = 'Chrome Extension';
|
||||
self::$pageDescription = 'Our Chrome extension allows you to quickly add new bookmarks or folders right from your browser\'s toolbar.';
|
||||
Views::view( 'bookmarks.extensions.chrome' );
|
||||
}
|
||||
|
||||
public function firefox() {
|
||||
self::$title = 'Firefox Extension';
|
||||
self::$pageDescription = 'Our Firefox extension allows you to quickly add new bookmarks or folders right from your browser\'s toolbar.';
|
||||
Views::view( 'bookmarks.extensions.firefox' );
|
||||
}
|
||||
|
||||
public function opera() {
|
||||
self::$title = 'Opera Extension';
|
||||
self::$pageDescription = 'Our Opera extension allows you to quickly add new bookmarks or folders right from your browser\'s toolbar.';
|
||||
Views::view( 'bookmarks.extensions.opera' );
|
||||
}
|
||||
|
||||
public function edge() {
|
||||
self::$title = 'Edge Extension';
|
||||
self::$pageDescription = 'Our Edge extension allows you to quickly add new bookmarks or folders right from your browser\'s toolbar.';
|
||||
Views::view( 'bookmarks.extensions.edge' );
|
||||
}
|
||||
|
||||
public function brave() {
|
||||
self::$title = 'Brave Extension';
|
||||
self::$pageDescription = 'Our Brave extension allows you to quickly add new bookmarks or folders right from your browser\'s toolbar.';
|
||||
Views::view( 'bookmarks.extensions.brave' );
|
||||
}
|
||||
|
||||
public function safari() {
|
||||
self::$title = 'Safari Extension';
|
||||
self::$pageDescription = 'Our Safari extension allows you to quickly add new bookmarks or folders right from your browser\'s toolbar.';
|
||||
Views::view( 'bookmarks.extensions.safari' );
|
||||
}
|
||||
|
||||
private function setFolderSelect( $folderID = null ) {
|
||||
$folders = new Folders;
|
||||
$options = $folders->simpleByUser();
|
||||
$out = '';
|
||||
$out .= '<select name="folder_id" id="folder_id" class="form-control">';
|
||||
if ( isset( $options[0] ) ) {
|
||||
$assocOptions = [];
|
||||
foreach ( $options as $key => $value ) {
|
||||
$assocOptions[$value] = $value;
|
||||
}
|
||||
$options = $assocOptions;
|
||||
}
|
||||
if ( ! empty( $options ) ) {
|
||||
foreach ( $options as $fieldname => $value ) {
|
||||
if ( $value == $folderID ) {
|
||||
$selected = ' selected';
|
||||
} else {
|
||||
$selected = '';
|
||||
}
|
||||
$out .= '<option value="' . $value . '"' . $selected . '>' . $fieldname . '</option>';
|
||||
}
|
||||
} else {
|
||||
$out .= '<option value="0" selected>No Folder</option>';
|
||||
}
|
||||
$out .= '</select>';
|
||||
$folderSelect = Template::parse( $out );
|
||||
Components::set( 'folderSelect', $folderSelect );
|
||||
}
|
||||
}
|
107
app/plugins/bookmarks/controllers/shared.php
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/bookmarks/controllers/shared.php
|
||||
*
|
||||
* This is the bug reports controller.
|
||||
*
|
||||
* @package TP Bookmarks
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Controllers;
|
||||
|
||||
use TheTempusProject\Hermes\Functions\Redirect;
|
||||
use TheTempusProject\Bedrock\Functions\Session;
|
||||
use TheTempusProject\Houdini\Classes\Views;
|
||||
use TheTempusProject\Classes\Controller;
|
||||
use TheTempusProject\Models\Bookmarks as Bookmark;
|
||||
use TheTempusProject\Models\Folders;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Houdini\Classes\Components;
|
||||
use TheTempusProject\Hermes\Functions\Route as Routes;
|
||||
|
||||
class Shared extends Controller {
|
||||
protected static $bookmarks;
|
||||
protected static $folders;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
self::$bookmarks = new Bookmark;
|
||||
self::$folders = new Folders;
|
||||
self::$title = 'Bookmarks - {SITENAME}';
|
||||
self::$pageDescription = 'Add and save url bookmarks here.';
|
||||
Components::set( 'SITE_URL', Routes::getAddress() );
|
||||
}
|
||||
|
||||
public function shared( $type = '', $id = '' ) {
|
||||
if ( empty( $type ) ) {
|
||||
Session::flash( 'error', 'Unknown share' );
|
||||
return Redirect::to( 'home/index' );
|
||||
}
|
||||
|
||||
if ( empty( $id ) ) {
|
||||
Session::flash( 'error', 'Unknown share' );
|
||||
return Redirect::to( 'home/index' );
|
||||
}
|
||||
|
||||
$type = strtolower( $type );
|
||||
if ( ! in_array( $type, ['link','folder'] ) ) {
|
||||
Session::flash( 'error', 'Unknown share' );
|
||||
return Redirect::to( 'home/index' );
|
||||
}
|
||||
|
||||
$this->$type( $id );
|
||||
}
|
||||
|
||||
public function link( $id = '' ) {
|
||||
if ( empty( $id ) ) {
|
||||
Session::flash( 'error', 'Unknown share' );
|
||||
return Redirect::to( 'home/index' );
|
||||
}
|
||||
$bookmark = self::$bookmarks->findByUuid( $id );
|
||||
if ( $bookmark == false ) {
|
||||
Session::flash( 'error', 'Unknown share' );
|
||||
return Redirect::to( 'home/index' );
|
||||
}
|
||||
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||
if ( $bookmark->privacy == 'private' ) {
|
||||
if ( empty( $bookmark->folderID ) ) {
|
||||
Session::flash( 'error', 'Unknown share' );
|
||||
return Redirect::to( 'home/index' );
|
||||
}
|
||||
$folder = self::$folders->findByUuid( $bookmark->folderID );
|
||||
if ( $folder == false ) {
|
||||
Session::flash( 'error', 'Unknown share' );
|
||||
return Redirect::to( 'home/index' );
|
||||
}
|
||||
if ( $folder->privacy == 'private' ) {
|
||||
Session::flash( 'error', 'Unknown share' );
|
||||
return Redirect::to( 'home/index' );
|
||||
}
|
||||
}
|
||||
}
|
||||
return Views::view( 'bookmarks.public.bookmark', $bookmark );
|
||||
}
|
||||
|
||||
public function folder( $id = '' ) {
|
||||
if ( empty( $id ) ) {
|
||||
Session::flash( 'error', 'Unknown share' );
|
||||
return Redirect::to( 'home/index' );
|
||||
}
|
||||
$folder = self::$folders->findByUuid( $id );
|
||||
if ( $folder == false ) {
|
||||
Session::flash( 'error', 'Unknown share' );
|
||||
return Redirect::to( 'home/index' );
|
||||
}
|
||||
if ( $folder->privacy == 'private' ) {
|
||||
Session::flash( 'error', 'Unknown share' );
|
||||
return Redirect::to( 'home/index' );
|
||||
}
|
||||
$folder->bookmarks = self::$bookmarks->unsafeByFolder( $folder->ID );
|
||||
$folder->bookmarkListRows = Views::simpleView( 'bookmarks.components.publicListRows', $folder->bookmarks );
|
||||
$folder->panel = Views::simpleView( 'bookmarks.components.publicList', [$folder] );
|
||||
return Views::view( 'bookmarks.public.folder', $folder );
|
||||
}
|
||||
}
|
114
app/plugins/bookmarks/controllers/tutorials.php
Normal file
@ -0,0 +1,114 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/bookmarks/controllers/tutorials.php
|
||||
*
|
||||
* This is the tutorials controller.
|
||||
*
|
||||
* @package TP Bookmarks
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Controllers;
|
||||
|
||||
use TheTempusProject\Houdini\Classes\Issues;
|
||||
use TheTempusProject\Houdini\Classes\Views;
|
||||
use TheTempusProject\Classes\Controller;
|
||||
use TheTempusProject\Houdini\Classes\Navigation;
|
||||
use TheTempusProject\Houdini\Classes\Components;
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
|
||||
class Tutorials extends Controller {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
self::$title = 'Tutorials - {SITENAME}';
|
||||
self::$pageDescription = 'We have detailed walkthroughs on how to perform a number of tasks for every major browser.';
|
||||
}
|
||||
|
||||
public function index( $browser = '', $tutorial = '' ) {
|
||||
return Views::view( 'bookmarks.tutorials.list' );
|
||||
}
|
||||
|
||||
public function brave( $tutorial = '' ) {
|
||||
Navigation::setCrumbComponent( 'tutorialCrumbs', Input::get( 'url' ) );
|
||||
|
||||
if ( ! in_array( $tutorial, ['pin','settings','import','export'] ) ) {
|
||||
$test = new \stdClass();
|
||||
$test->pretty = 'Brave';
|
||||
$test->printed = 'brave';
|
||||
return Views::view( 'bookmarks.tutorials.card', [ $test ] );
|
||||
}
|
||||
return Views::view( 'bookmarks.tutorials.brave.' . $tutorial );
|
||||
}
|
||||
|
||||
public function chrome( $tutorial = '' ) {
|
||||
Navigation::setCrumbComponent( 'tutorialCrumbs', Input::get( 'url' ) );
|
||||
|
||||
if ( ! in_array( $tutorial, ['pin','settings','import','export'] ) ) {
|
||||
$test = new \stdClass();
|
||||
$test->pretty = 'Chrome';
|
||||
$test->printed = 'chrome';
|
||||
return Views::view( 'bookmarks.tutorials.card', [ $test ] );
|
||||
}
|
||||
|
||||
return Views::view( 'bookmarks.tutorials.chrome.' . $tutorial );
|
||||
}
|
||||
|
||||
public function edge( $tutorial = '' ) {
|
||||
Navigation::setCrumbComponent( 'tutorialCrumbs', Input::get( 'url' ) );
|
||||
|
||||
if ( ! in_array( $tutorial, ['pin','settings','import','export'] ) ) {
|
||||
$test = new \stdClass();
|
||||
$test->pretty = 'Edge';
|
||||
$test->printed = 'edge';
|
||||
return Views::view( 'bookmarks.tutorials.card', [ $test ] );
|
||||
}
|
||||
return Views::view( 'bookmarks.tutorials.edge.' . $tutorial );
|
||||
}
|
||||
|
||||
public function opera( $tutorial = '' ) {
|
||||
Navigation::setCrumbComponent( 'tutorialCrumbs', Input::get( 'url' ) );
|
||||
|
||||
if ( ! in_array( $tutorial, ['pin','settings','import','export'] ) ) {
|
||||
$test = new \stdClass();
|
||||
$test->pretty = 'Opera';
|
||||
$test->printed = 'opera';
|
||||
return Views::view( 'bookmarks.tutorials.card', [ $test ] );
|
||||
}
|
||||
return Views::view( 'bookmarks.tutorials.opera.' . $tutorial );
|
||||
}
|
||||
|
||||
public function firefox( $tutorial = '' ) {
|
||||
Navigation::setCrumbComponent( 'tutorialCrumbs', Input::get( 'url' ) );
|
||||
|
||||
if ( ! in_array( $tutorial, ['pin','settings','import','export'] ) ) {
|
||||
$test = new \stdClass();
|
||||
$test->pretty = 'Firefox';
|
||||
$test->printed = 'firefox';
|
||||
return Views::view( 'bookmarks.tutorials.card', [ $test ] );
|
||||
}
|
||||
return Views::view( 'bookmarks.tutorials.firefox.' . $tutorial );
|
||||
}
|
||||
|
||||
public function safari( $tutorial = '' ) {
|
||||
Issues::add( 'notice', 'Safari is not supported at this time.' );
|
||||
return;
|
||||
if ( ! in_array( $tutorial, ['pin','settings','import','export'] ) ) {
|
||||
Issues::add( 'notice', 'Unknown tutorial' );
|
||||
return Views::view( 'bookmarks.tutorials.list' );
|
||||
}
|
||||
return Views::view( 'bookmarks.tutorials.safari.' . $tutorial );
|
||||
}
|
||||
|
||||
public function mobile( $tutorial = '' ) {
|
||||
Navigation::setCrumbComponent( 'tutorialCrumbs', Input::get( 'url' ) );
|
||||
if ( ! in_array( $tutorial, ['iphone','android'] ) ) {
|
||||
$test = new \stdClass();
|
||||
$test->pretty = 'Mobile';
|
||||
$test->printed = 'mobile';
|
||||
return Views::view( 'bookmarks.tutorials.mobileCard', [ $test ] );
|
||||
}
|
||||
return Views::view( 'bookmarks.tutorials.mobile.' . $tutorial );
|
||||
}
|
||||
}
|
225
app/plugins/bookmarks/forms.php
Normal file
@ -0,0 +1,225 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/bookmarks/forms.php
|
||||
*
|
||||
* This houses all of the form checking functions for this plugin.
|
||||
*
|
||||
* @package TP Bookmarks
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Plugins\Bookmarks;
|
||||
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Classes\Forms;
|
||||
|
||||
class BookmarksForms extends Forms {
|
||||
/**
|
||||
* Adds these functions to the form list.
|
||||
*/
|
||||
public function __construct() {
|
||||
self::addHandler( 'createBookmark', __CLASS__, 'createBookmark' );
|
||||
self::addHandler( 'createFolder', __CLASS__, 'createFolder' );
|
||||
self::addHandler( 'editBookmark', __CLASS__, 'editBookmark' );
|
||||
self::addHandler( 'editFolder', __CLASS__, 'editFolder' );
|
||||
self::addHandler( 'importBookmarks', __CLASS__, 'importBookmarks' );
|
||||
self::addHandler( 'exportBookmarks', __CLASS__, 'exportBookmarks' );
|
||||
self::addHandler( 'createDashboard', __CLASS__, 'createDashboard' );
|
||||
self::addHandler( 'editDashboard', __CLASS__, 'editDashboard' );
|
||||
self::addHandler( 'updateDashboard', __CLASS__, 'updateDashboard' );
|
||||
}
|
||||
|
||||
public static function createBookmark() {
|
||||
// if ( ! Input::exists( 'title' ) ) {
|
||||
// Check::addUserError( 'You must include a title.' );
|
||||
// return false;
|
||||
// }
|
||||
if ( ! Input::exists( 'url' ) ) {
|
||||
Check::addUserError( 'You must include a url.' );
|
||||
return false;
|
||||
}
|
||||
// if ( ! Input::exists( 'color' ) ) {
|
||||
// Check::addUserError( 'You must include a color.' );
|
||||
// return false;
|
||||
// }
|
||||
// if ( ! Input::exists( 'privacy' ) ) {
|
||||
// Check::addUserError( 'You must include a privacy.' );
|
||||
// return false;
|
||||
// }
|
||||
// if ( !self::token() ) {
|
||||
// Check::addUserError( 'token - comment out later.' );
|
||||
// return false;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function createFolder() {
|
||||
if ( ! Input::exists( 'title' ) ) {
|
||||
Check::addUserError( 'You must include a title.' );
|
||||
return false;
|
||||
}
|
||||
// if ( ! Input::exists( 'color' ) ) {
|
||||
// Check::addUserError( 'You must include a color.' );
|
||||
// return false;
|
||||
// }
|
||||
// if ( ! Input::exists( 'privacy' ) ) {
|
||||
// Check::addUserError( 'You must include a privacy.' );
|
||||
// return false;
|
||||
// }
|
||||
// if ( ! self::token() ) {
|
||||
// Check::addUserError( 'token - comment out later.' );
|
||||
// return false;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function editBookmark() {
|
||||
// if ( ! Input::exists( 'title' ) ) {
|
||||
// Check::addUserError( 'You must include a title.' );
|
||||
// return false;
|
||||
// }
|
||||
if ( ! Input::exists( 'url' ) ) {
|
||||
Check::addUserError( 'You must include a url.' );
|
||||
return false;
|
||||
}
|
||||
// if ( ! Input::exists( 'color' ) ) {
|
||||
// Check::addUserError( 'You must include a color.' );
|
||||
// return false;
|
||||
// }
|
||||
// if ( ! Input::exists( 'privacy' ) ) {
|
||||
// Check::addUserError( 'You must include a privacy.' );
|
||||
// return false;
|
||||
// }
|
||||
// if ( !self::token() ) {
|
||||
// Check::addUserError( 'token - comment out later.' );
|
||||
// return false;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function editFolder() {
|
||||
if ( ! Input::exists( 'submit' ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( ! Input::exists( 'title' ) ) {
|
||||
Check::addUserError( 'You must include a title.' );
|
||||
return false;
|
||||
}
|
||||
// if ( ! Input::exists( 'color' ) ) {
|
||||
// Check::addUserError( 'You must include a color.' );
|
||||
// return false;
|
||||
// }
|
||||
// if ( ! Input::exists( 'privacy' ) ) {
|
||||
// Check::addUserError( 'You must include a privacy.' );
|
||||
// return false;
|
||||
// }
|
||||
// if ( !self::token() ) {
|
||||
// Check::addUserError( 'token - comment out later.' );
|
||||
// return false;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function importBookmarks() {
|
||||
if ( ! Input::exists( 'submit' ) ) {
|
||||
return false;
|
||||
}
|
||||
// if ( ! Input::exists( 'title' ) ) {
|
||||
// Check::addUserError( 'You must include a title.' );
|
||||
// return false;
|
||||
// }
|
||||
// if ( ! Input::exists( 'color' ) ) {
|
||||
// Check::addUserError( 'You must include a color.' );
|
||||
// return false;
|
||||
// }
|
||||
// if ( ! Input::exists( 'privacy' ) ) {
|
||||
// Check::addUserError( 'You must include a privacy.' );
|
||||
// return false;
|
||||
// }
|
||||
// if ( !self::token() ) {
|
||||
// Check::addUserError( 'token - comment out later.' );
|
||||
// return false;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function exportBookmarks() {
|
||||
if ( ! Input::exists( 'submit' ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( ! Input::exists( 'BF_' ) ) {
|
||||
return false;
|
||||
}
|
||||
// if ( ! Input::exists( 'title' ) ) {
|
||||
// Check::addUserError( 'You must include a title.' );
|
||||
// return false;
|
||||
// }
|
||||
// if ( ! Input::exists( 'color' ) ) {
|
||||
// Check::addUserError( 'You must include a color.' );
|
||||
// return false;
|
||||
// }
|
||||
// if ( ! Input::exists( 'privacy' ) ) {
|
||||
// Check::addUserError( 'You must include a privacy.' );
|
||||
// return false;
|
||||
// }
|
||||
// if ( !self::token() ) {
|
||||
// Check::addUserError( 'token - comment out later.' );
|
||||
// return false;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function createDashboard() {
|
||||
if ( ! Input::exists( 'submit' ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( ! Input::exists( 'title' ) ) {
|
||||
Check::addUserError( 'You must include a title.' );
|
||||
return false;
|
||||
}
|
||||
if ( ! Input::exists( 'link_order' ) ) {
|
||||
Check::addUserError( 'You must include at least 1 link or folder.' );
|
||||
return false;
|
||||
}
|
||||
if ( !self::token() ) {
|
||||
Check::addUserError( 'There was an issue with your request.' );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function updateDashboard() {
|
||||
if ( ! Input::exists( 'submit' ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( !self::token() ) {
|
||||
Check::addUserError( 'There was an issue with your request.' );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function editDashboard() {
|
||||
if ( ! Input::exists( 'submit' ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( ! Input::exists( 'title' ) ) {
|
||||
Check::addUserError( 'You must include a title.' );
|
||||
return false;
|
||||
}
|
||||
if ( ! Input::exists( 'link_order' ) ) {
|
||||
Check::addUserError( 'You must include at least 1 link or folder.' );
|
||||
return false;
|
||||
}
|
||||
if ( !self::token() ) {
|
||||
Check::addUserError( 'There was an issue with your request.' );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
new BookmarksForms;
|
BIN
app/plugins/bookmarks/images/android/add.png
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
app/plugins/bookmarks/images/android/add2.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
app/plugins/bookmarks/images/android/add3.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
app/plugins/bookmarks/images/android/added.png
Normal file
After Width: | Height: | Size: 152 KiB |
BIN
app/plugins/bookmarks/images/brave/bookmark-manager.png
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
app/plugins/bookmarks/images/brave/bookmark-menu.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
BIN
app/plugins/bookmarks/images/brave/bookmarks.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
app/plugins/bookmarks/images/brave/export.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
app/plugins/bookmarks/images/brave/extensions-icon.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
app/plugins/bookmarks/images/brave/import.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
app/plugins/bookmarks/images/brave/options.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
app/plugins/bookmarks/images/brave/pin.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
app/plugins/bookmarks/images/brave/pinned.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
app/plugins/bookmarks/images/brave/settings-page.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
app/plugins/bookmarks/images/brave/settings.png
Normal file
After Width: | Height: | Size: 7.0 KiB |
BIN
app/plugins/bookmarks/images/chrome/bookmark-manager.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
app/plugins/bookmarks/images/chrome/bookmark-menu.png
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
app/plugins/bookmarks/images/chrome/bookmarks.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
app/plugins/bookmarks/images/chrome/chrome-add.jpg
Normal file
After Width: | Height: | Size: 45 KiB |
BIN
app/plugins/bookmarks/images/chrome/chrome-login.jpg
Normal file
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 96 KiB |
BIN
app/plugins/bookmarks/images/chrome/chrome-settings.jpg
Normal file
After Width: | Height: | Size: 81 KiB |
BIN
app/plugins/bookmarks/images/chrome/chrome-small-promo-tile.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
app/plugins/bookmarks/images/chrome/export.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
app/plugins/bookmarks/images/chrome/extensions-icon.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
app/plugins/bookmarks/images/chrome/import.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
app/plugins/bookmarks/images/chrome/options.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
app/plugins/bookmarks/images/chrome/pin.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
app/plugins/bookmarks/images/chrome/pinned.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
app/plugins/bookmarks/images/chrome/settings-page.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
app/plugins/bookmarks/images/chrome/settings.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
app/plugins/bookmarks/images/edge/bookmark-options.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
app/plugins/bookmarks/images/edge/edge-add.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
app/plugins/bookmarks/images/edge/edge-login.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
app/plugins/bookmarks/images/edge/edge-settings.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
app/plugins/bookmarks/images/edge/edge-small-promo-tile.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
app/plugins/bookmarks/images/edge/export.png
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
app/plugins/bookmarks/images/edge/extensions-icon.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
app/plugins/bookmarks/images/edge/favorites.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
app/plugins/bookmarks/images/edge/import-complete.png
Normal file
After Width: | Height: | Size: 8.5 KiB |
BIN
app/plugins/bookmarks/images/edge/import-menu.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
app/plugins/bookmarks/images/edge/import-select.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
app/plugins/bookmarks/images/edge/import-start.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
app/plugins/bookmarks/images/edge/import.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
app/plugins/bookmarks/images/edge/options.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
app/plugins/bookmarks/images/edge/pin.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
app/plugins/bookmarks/images/edge/pinned.png
Normal file
After Width: | Height: | Size: 6.0 KiB |
BIN
app/plugins/bookmarks/images/edge/settings-page.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
app/plugins/bookmarks/images/edge/settings.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
app/plugins/bookmarks/images/firefox/added.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
app/plugins/bookmarks/images/firefox/bookmarks.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
app/plugins/bookmarks/images/firefox/enable.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
app/plugins/bookmarks/images/firefox/export.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
app/plugins/bookmarks/images/firefox/extensions-icon.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
app/plugins/bookmarks/images/firefox/firefox-login.jpg
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
app/plugins/bookmarks/images/firefox/firefox-save.jpg
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
app/plugins/bookmarks/images/firefox/firefox-settings.jpg
Normal file
After Width: | Height: | Size: 74 KiB |
BIN
app/plugins/bookmarks/images/firefox/icon.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
app/plugins/bookmarks/images/firefox/import-export.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
app/plugins/bookmarks/images/firefox/import.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
app/plugins/bookmarks/images/firefox/manage-bookmarks.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
app/plugins/bookmarks/images/firefox/manage-page.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
app/plugins/bookmarks/images/firefox/manage-select.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
app/plugins/bookmarks/images/firefox/manage.png
Normal file
After Width: | Height: | Size: 9.6 KiB |
BIN
app/plugins/bookmarks/images/firefox/options.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
app/plugins/bookmarks/images/firefox/pin.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
app/plugins/bookmarks/images/firefox/pinned.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
app/plugins/bookmarks/images/firefox/settings-page.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
app/plugins/bookmarks/images/firefox/settings.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
app/plugins/bookmarks/images/firefox/version.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
app/plugins/bookmarks/images/opera/bookmarks.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
app/plugins/bookmarks/images/opera/export.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
app/plugins/bookmarks/images/opera/extensions.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
app/plugins/bookmarks/images/opera/import-select.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
app/plugins/bookmarks/images/opera/import-start.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
app/plugins/bookmarks/images/opera/import-success.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
app/plugins/bookmarks/images/opera/import.png
Normal file
After Width: | Height: | Size: 9.0 KiB |
BIN
app/plugins/bookmarks/images/opera/opera-login.jpg
Normal file
After Width: | Height: | Size: 69 KiB |
BIN
app/plugins/bookmarks/images/opera/opera-promo-image.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
app/plugins/bookmarks/images/opera/opera-save.jpg
Normal file
After Width: | Height: | Size: 107 KiB |
BIN
app/plugins/bookmarks/images/opera/opera-settiings.jpg
Normal file
After Width: | Height: | Size: 190 KiB |
BIN
app/plugins/bookmarks/images/opera/optiions.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
app/plugins/bookmarks/images/opera/options.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
app/plugins/bookmarks/images/opera/pin.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
app/plugins/bookmarks/images/opera/pinned.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
app/plugins/bookmarks/images/opera/settings-page.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
app/plugins/bookmarks/images/opera/sidebar.png
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
app/plugins/bookmarks/images/opera/toolbar.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
35
app/plugins/bookmarks/js/bookmarklet.js
Normal file
@ -0,0 +1,35 @@
|
||||
javascript:(function() {
|
||||
const apiKey = localStorage.getItem('notAnAuthToken');
|
||||
const apiUrl = localStorage.getItem('api_url');
|
||||
const name = prompt("Enter a name for the bookmark:");
|
||||
const notes = prompt("Enter any notes (optional):");
|
||||
const color = prompt("Enter a color (optional):");
|
||||
const privacy = prompt("Enter privacy level (e.g., public/private):");
|
||||
const folder = prompt("Enter a folder (optional):");
|
||||
const url = window.location.href;
|
||||
|
||||
if (!name) {
|
||||
alert("Name is required.");
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(apiUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${apiKey}`
|
||||
},
|
||||
body: JSON.stringify({ name, url, notes, color, privacy, folder })
|
||||
})
|
||||
.then(response => {
|
||||
if (response.ok) {
|
||||
alert("Bookmark saved successfully!");
|
||||
} else {
|
||||
alert("Failed to save bookmark. Please check your API key.");
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
alert("An unknown error occurred while saving the bookmark.");
|
||||
});
|
||||
})();
|
234
app/plugins/bookmarks/js/bookmarks.js
Normal file
@ -0,0 +1,234 @@
|
||||
let masonryInstance;
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Handle all bootstrap popover inits
|
||||
const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]')
|
||||
const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))
|
||||
|
||||
// Initialize all toggle functions
|
||||
toggleVisibility('editModeSwitch', 'edit-mode');
|
||||
toggleVisibility('showArchivedSwitch', 'link-archived');
|
||||
toggleVisibility('showHiddenSwitch', 'link-hidden');
|
||||
toggleVisibility('archiveButtonSwitch', 'btn-archive');
|
||||
toggleVisibility('visibilityButtonSwitch', 'btn-hideshow');
|
||||
toggleVisibility('privacyButtonSwitch', 'btn-publish');
|
||||
toggleVisibility('addButtonSwitch', 'btn-addlink');
|
||||
toggleVisibility('shareButtonSwitch', 'btn-share');
|
||||
|
||||
toggleVisibility('dashShowArchivedSwitch', 'link-archived');
|
||||
toggleVisibility('dashShowHiddenSwitch', 'link-hidden');
|
||||
toggleVisibility('dashAddButtonSwitch', 'btn-addlink');
|
||||
toggleVisibility('dashShareButtonSwitch', 'btn-share');
|
||||
|
||||
// Retrieve the list of collapsed folderCard IDs from local storage
|
||||
|
||||
const onDashboard = document.getElementById("dash_id");
|
||||
let collapsedFolders;
|
||||
if ( onDashboard ) {
|
||||
collapsedFolders = JSON.parse(localStorage.getItem( 'collapsedDashFolders' + onDashboard.value )) || [];
|
||||
} else {
|
||||
collapsedFolders = JSON.parse(localStorage.getItem( 'collapsedFolders' )) || [];
|
||||
}
|
||||
|
||||
// Collapse the elements stored in local storage when the page loads
|
||||
collapsedFolders.forEach((folderId) => {
|
||||
const collapseElement = document.querySelector(`#Collapse${folderId}`);
|
||||
if ( collapseElement ) {
|
||||
collapseElement.classList.remove('show');
|
||||
}
|
||||
});
|
||||
|
||||
// Add event listeners to track expand and collapse actions
|
||||
document.querySelectorAll('.accordion-item').forEach((item) => {
|
||||
const folderCardId = item.closest('.bookmark-card')?.id?.replace('folderCard', '');
|
||||
|
||||
if ( ! folderCardId ) return;
|
||||
|
||||
const collapseElement = item.querySelector('.collapse');
|
||||
|
||||
// Listen for collapse and expand events
|
||||
collapseElement.addEventListener('hidden.bs.collapse', () => {
|
||||
let storageName;
|
||||
// Add the folderCard ID to local storage when collapsed
|
||||
if (!collapsedFolders.includes(folderCardId)) {
|
||||
collapsedFolders.push(folderCardId);
|
||||
if ( onDashboard ) {
|
||||
storageName = 'collapsedDashFolders' + onDashboard.value;
|
||||
} else {
|
||||
storageName = 'collapsedFolders';
|
||||
}
|
||||
localStorage.setItem( storageName , JSON.stringify(collapsedFolders));
|
||||
}
|
||||
});
|
||||
|
||||
collapseElement.addEventListener('shown.bs.collapse', () => {
|
||||
let storageName;
|
||||
// Remove the folderCard ID from local storage when expanded
|
||||
const index = collapsedFolders.indexOf(folderCardId);
|
||||
if (index > -1) {
|
||||
collapsedFolders.splice(index, 1);
|
||||
if ( onDashboard ) {
|
||||
storageName = 'collapsedDashFolders' + onDashboard.value;
|
||||
} else {
|
||||
storageName = 'collapsedFolders';
|
||||
}
|
||||
localStorage.setItem( storageName , JSON.stringify(collapsedFolders));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const masonryContainer = document.getElementById("bookmarkSort");
|
||||
|
||||
if ( ! masonryContainer ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( localStorage.getItem('manageFolderOrder') ) {
|
||||
loadDashLinkOrder();
|
||||
}
|
||||
|
||||
masonryInstance = new Masonry(masonryContainer, {
|
||||
columnHeight: '.accordion',
|
||||
itemSelector: ".bookmark-card",
|
||||
percentPosition: false
|
||||
});
|
||||
|
||||
const test = () => masonryInstance.layout();
|
||||
|
||||
masonryContainer.addEventListener('hidden.bs.collapse', test );
|
||||
masonryContainer.addEventListener('shown.bs.collapse', test );
|
||||
|
||||
// Select all folder-raise and folder-lower buttons
|
||||
|
||||
const raiseButtons = document.querySelectorAll(".folder-raise");
|
||||
const lowerButtons = document.querySelectorAll(".folder-lower");
|
||||
|
||||
// Function to move the folderCard up
|
||||
function moveUp(event) {
|
||||
const folderCard = event.target.closest(".bookmark-card");
|
||||
const bookmarkSort = document.getElementById("bookmarkSort");
|
||||
const orderId = document.getElementById("dashLinkOrder");
|
||||
|
||||
if (folderCard) {
|
||||
const previousSibling = folderCard.previousElementSibling;
|
||||
if (previousSibling) {
|
||||
// Remove and reinsert the element before the previous sibling
|
||||
bookmarkSort.removeChild(folderCard);
|
||||
bookmarkSort.insertBefore(folderCard, previousSibling);
|
||||
masonryInstance.reloadItems();
|
||||
masonryInstance.layout();
|
||||
updateDashLinkOrder();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function to move the folderCard down
|
||||
function moveDown(event) {
|
||||
const folderCard = event.target.closest(".bookmark-card");
|
||||
const bookmarkSort = document.getElementById("bookmarkSort");
|
||||
|
||||
if (folderCard) {
|
||||
const nextSibling = folderCard.nextElementSibling;
|
||||
if (nextSibling) {
|
||||
// Remove and reinsert the element after the next sibling
|
||||
bookmarkSort.removeChild(folderCard);
|
||||
bookmarkSort.insertBefore(folderCard, nextSibling.nextSibling);
|
||||
masonryInstance.reloadItems();
|
||||
masonryInstance.layout();
|
||||
updateDashLinkOrder();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add event listeners to the raise buttons
|
||||
raiseButtons.forEach(button => {
|
||||
button.addEventListener("click", moveUp);
|
||||
});
|
||||
|
||||
// Add event listeners to the lower buttons
|
||||
lowerButtons.forEach(button => {
|
||||
button.addEventListener("click", moveDown);
|
||||
});
|
||||
// after hiding/showing elements
|
||||
masonryInstance.layout();
|
||||
});
|
||||
|
||||
// Function to handle showing or hiding elements based on the checkbox state
|
||||
function toggleVisibility(switchId, className) {
|
||||
const switchElement = document.getElementById(switchId);
|
||||
const elementsToToggle = document.querySelectorAll(`.${className}`);
|
||||
|
||||
if ( ! switchElement ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Listen for changes to the checkbox
|
||||
switchElement.addEventListener('change', () => {
|
||||
if (switchElement.checked) {
|
||||
elementsToToggle.forEach(element => {
|
||||
element.style.display = '';
|
||||
});
|
||||
} else {
|
||||
elementsToToggle.forEach(element => {
|
||||
element.style.display = 'none';
|
||||
});
|
||||
}
|
||||
if (typeof masonryInstance !== 'undefined') {
|
||||
masonryInstance.reloadItems();
|
||||
masonryInstance.layout()
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
// Trigger the toggle initially to set the correct visibility on page load
|
||||
switchElement.dispatchEvent(new Event('change'));
|
||||
}
|
||||
|
||||
function updateDashLinkOrder() {
|
||||
const bookmarkCards = document.querySelectorAll("#bookmarkSort .bookmark-card");
|
||||
const ids = Array.from( bookmarkCards ).map( card => {
|
||||
const match = card.id.match(/folderCard(\d+)/);
|
||||
return match ? match[1] : null;
|
||||
}).filter( id => id !== null );
|
||||
|
||||
const dashLinkOrder = document.getElementById("dashLinkOrder");
|
||||
if (dashLinkOrder) {
|
||||
dashLinkOrder.value = ids.join(",");
|
||||
} else {
|
||||
localStorage.setItem('manageFolderOrder', ids.join(","));
|
||||
}
|
||||
}
|
||||
|
||||
function loadDashLinkOrder() {
|
||||
const onDashboard = document.getElementById("dash_id");
|
||||
const storedOrder = localStorage.getItem("manageFolderOrder"); // Get the saved order
|
||||
const bookmarkSort = document.getElementById("bookmarkSort");
|
||||
|
||||
if ( onDashboard || !storedOrder || !bookmarkSort ) return; // Exit if no saved order or no container
|
||||
|
||||
const orderArray = storedOrder.split(","); // Convert the saved order into an array
|
||||
const bookmarkCards = Array.from(document.querySelectorAll("#bookmarkSort .bookmark-card"));
|
||||
|
||||
// Create a map for quick lookup of cards by their ID
|
||||
const cardMap = new Map();
|
||||
bookmarkCards.forEach(card => {
|
||||
const match = card.id.match(/folderCard(\d+)/);
|
||||
if (match) cardMap.set(match[1], card);
|
||||
});
|
||||
|
||||
// Reorder elements based on the saved order
|
||||
const orderedElements = [];
|
||||
orderArray.forEach(id => {
|
||||
if (cardMap.has(id)) {
|
||||
orderedElements.push(cardMap.get(id)); // Add elements in the specified order
|
||||
cardMap.delete(id); // Remove from the map once processed
|
||||
}
|
||||
});
|
||||
|
||||
// Add any remaining (unspecified) elements to the end of the list
|
||||
const remainingElements = Array.from(cardMap.values());
|
||||
orderedElements.push(...remainingElements);
|
||||
|
||||
// Clear the container and append the elements in the new order
|
||||
bookmarkSort.innerHTML = ""; // Remove all children
|
||||
orderedElements.forEach(element => bookmarkSort.appendChild(element)); // Append in order
|
||||
}
|
176
app/plugins/bookmarks/models/bookmark_dashboards.php
Normal file
@ -0,0 +1,176 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/bookmarks/models/bookmark_dashboards.php
|
||||
*
|
||||
* This class is used for the manipulation of the bookmark_dashboards database table.
|
||||
*
|
||||
* @package TP Bookmarks
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Models;
|
||||
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||
use TheTempusProject\Classes\DatabaseModel;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Houdini\Classes\Filters;
|
||||
use TheTempusProject\Canary\Classes\CustomException;
|
||||
|
||||
class BookmarkDashboards extends DatabaseModel {
|
||||
public $tableName = 'bookmark_dashboards';
|
||||
public $databaseMatrix = [
|
||||
[ 'title', 'varchar', '256' ],
|
||||
[ 'saved_prefs', 'text', '' ],
|
||||
[ 'link_order', 'text', '' ],
|
||||
[ 'description', 'text', '' ],
|
||||
[ 'createdBy', 'int', '11' ],
|
||||
[ 'createdAt', 'int', '11' ],
|
||||
[ 'updatedAt', 'int', '11' ],
|
||||
[ 'uuid', 'char', '36' ],
|
||||
];
|
||||
|
||||
/**
|
||||
* The model constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function create( $title, $saved_prefs, $link_order, $description = '' ) {
|
||||
if ( ! Check::dataTitle( $title ) ) {
|
||||
Debug::info( 'Dash: illegal title.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'title' => $title,
|
||||
'description' => $description,
|
||||
'saved_prefs' => $saved_prefs,
|
||||
'link_order' => $link_order,
|
||||
'uuid' => generateUuidV4(),
|
||||
'createdBy' => App::$activeUser->ID,
|
||||
'createdAt' => time(),
|
||||
];
|
||||
if ( ! self::$db->insert( $this->tableName, $fields ) ) {
|
||||
new CustomException( 'dashCreate' );
|
||||
Debug::error( "Dash: not created " . var_export($fields,true) );
|
||||
return false;
|
||||
}
|
||||
return self::$db->lastId();
|
||||
}
|
||||
|
||||
public function update( $id, $title, $saved_prefs, $link_order, $description = '' ) {
|
||||
if ( !Check::id( $id ) ) {
|
||||
Debug::info( 'Dash: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
if ( !Check::dataTitle( $title ) ) {
|
||||
Debug::info( 'Dash: illegal title.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'title' => $title,
|
||||
'description' => $description,
|
||||
'saved_prefs' => $saved_prefs,
|
||||
'link_order' => $link_order,
|
||||
];
|
||||
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||
new CustomException( 'dashUpdate' );
|
||||
Debug::error( "Dash: $id not updated" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function updateDash( $id, $saved_prefs = '', $link_order = '' ) {
|
||||
if ( !Check::id( $id ) ) {
|
||||
Debug::info( 'Dash: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [];
|
||||
$fields['saved_prefs'] = $saved_prefs;
|
||||
if ( ! empty( $link_order ) ) {
|
||||
$fields['link_order'] = $link_order;
|
||||
}
|
||||
if ( empty( $fields ) ) {
|
||||
return true;
|
||||
}
|
||||
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||
new CustomException( 'dashUpdate' );
|
||||
Debug::error( "Dash: $id not updated" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function byUser( $limit = null ) {
|
||||
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||
if ( empty( $limit ) ) {
|
||||
$views = self::$db->get( $this->tableName, $whereClause );
|
||||
} else {
|
||||
$views = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [0, $limit] );
|
||||
}
|
||||
if ( !$views->count() ) {
|
||||
Debug::info( 'No Views found.' );
|
||||
return false;
|
||||
}
|
||||
return $this->filter( $views->results() );
|
||||
}
|
||||
|
||||
public function getName( $id ) {
|
||||
$views = self::findById( $id );
|
||||
if (false == $views) {
|
||||
return 'unknown';
|
||||
}
|
||||
return $views->title;
|
||||
}
|
||||
|
||||
public function simpleByUser() {
|
||||
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||
$views = self::$db->get( $this->tableName, $whereClause );
|
||||
if ( !$views->count() ) {
|
||||
Debug::warn( 'Could not find any Views' );
|
||||
return false;
|
||||
}
|
||||
|
||||
$views = $views->results();
|
||||
$out = [];
|
||||
foreach ( $views as $view ) {
|
||||
$out[ $view->title ] = $view->ID;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
public function simpleObjectByUser() {
|
||||
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||
$views = self::$db->get( $this->tableName, $whereClause );
|
||||
if ( !$views->count() ) {
|
||||
Debug::warn( 'Could not find any Views' );
|
||||
return false;
|
||||
}
|
||||
|
||||
$views = $views->results();
|
||||
$out = [];
|
||||
foreach ( $views as $view ) {
|
||||
$obj = new \stdClass();
|
||||
$obj->title = $view->title;
|
||||
$obj->ID = $view->ID;
|
||||
$out[] = $obj;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
public function findByUuid( $id ) {
|
||||
$whereClause = ['uuid', '=', $id];
|
||||
|
||||
$dashboards = self::$db->get( $this->tableName, $whereClause );
|
||||
|
||||
if ( !$dashboards->count() ) {
|
||||
Debug::info( 'No Dashboards found.' );
|
||||
return false;
|
||||
}
|
||||
return $this->filter( $dashboards->first() );
|
||||
}
|
||||
}
|
800
app/plugins/bookmarks/models/bookmarks.php
Normal file
@ -0,0 +1,800 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/bookmarks/models/bookmarks.php
|
||||
*
|
||||
* This class is used for the manipulation of the bookmarks database table.
|
||||
*
|
||||
* @package TP Bookmarks
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Models;
|
||||
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||
use TheTempusProject\Classes\DatabaseModel;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Houdini\Classes\Filters;
|
||||
use TheTempusProject\Canary\Classes\CustomException;
|
||||
|
||||
class Bookmarks extends DatabaseModel {
|
||||
public $tableName = 'bookmarks';
|
||||
public $linkTypes = [
|
||||
'Open in New Tab' => 'external',
|
||||
'Open in Same Tab' => 'internal',
|
||||
];
|
||||
|
||||
public $databaseMatrix = [
|
||||
[ 'title', 'varchar', '256' ],
|
||||
[ 'url', 'text', '' ],
|
||||
[ 'color', 'varchar', '48' ],
|
||||
[ 'privacy', 'varchar', '48' ],
|
||||
[ 'folderID', 'int', '11' ],
|
||||
[ 'description', 'text', '' ],
|
||||
[ 'createdBy', 'int', '11' ],
|
||||
[ 'createdAt', 'int', '11' ],
|
||||
[ 'meta', 'text', '' ],
|
||||
[ 'icon', 'text', '' ],
|
||||
[ 'archivedAt', 'int', '11' ],
|
||||
[ 'refreshedAt', 'int', '11' ],
|
||||
[ 'hiddenAt', 'int', '11' ],
|
||||
[ 'order', 'int', '11' ],
|
||||
[ 'linkType', 'varchar', '32' ],
|
||||
[ 'uuid', 'char', '36' ],
|
||||
];
|
||||
|
||||
/**
|
||||
* The model constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function create( $title, $url, $folderID = 0, $description = '', $color = 'default', $privacy = 'private', $type = 'external', $user = null ) {
|
||||
if ( empty( $user ) ) {
|
||||
$user = App::$activeUser->ID;
|
||||
}
|
||||
$fields = [
|
||||
'title' => $title,
|
||||
'url' => $url,
|
||||
'description' => $description,
|
||||
'color' => $color,
|
||||
'privacy' => $privacy,
|
||||
'createdBy' => $user,
|
||||
'uuid' => generateUuidV4(),
|
||||
'createdAt' => time(),
|
||||
];
|
||||
if ( !empty( $folderID ) ) {
|
||||
$fields['folderID'] = $folderID;
|
||||
} else {
|
||||
$fields['folderID'] = null;
|
||||
}
|
||||
if ( ! self::$db->insert( $this->tableName, $fields ) ) {
|
||||
new CustomException( 'bookmarkCreate' );
|
||||
Debug::error( "Bookmarks: not created " . var_export($fields,true) );
|
||||
return false;
|
||||
}
|
||||
return self::$db->lastId();
|
||||
}
|
||||
|
||||
public function update( $id, $title, $url, $folderID = 0, $description = '', $color = 'default', $privacy = 'private', $type = 'external', $order = 0 ) {
|
||||
if ( !Check::id( $id ) ) {
|
||||
Debug::info( 'Bookmarks: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'title' => $title,
|
||||
'url' => $url,
|
||||
'description' => $description,
|
||||
'color' => $color,
|
||||
'privacy' => $privacy,
|
||||
// 'linkType' => $type,
|
||||
// 'order' => $order,
|
||||
];
|
||||
if ( !empty( $folderID ) ) {
|
||||
$fields['folderID'] = $folderID;
|
||||
}
|
||||
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||
new CustomException( 'bookmarkUpdate' );
|
||||
Debug::error( "Bookmarks: $id not updated" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function findByUuid( $id ) {
|
||||
$whereClause = ['uuid', '=', $id];
|
||||
if ( empty( $limit ) ) {
|
||||
$bookmarks = self::$db->get( $this->tableName, $whereClause );
|
||||
} else {
|
||||
$bookmarks = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [0, $limit] );
|
||||
}
|
||||
if ( !$bookmarks->count() ) {
|
||||
Debug::info( 'No Bookmarks found.' );
|
||||
return false;
|
||||
}
|
||||
return $this->filter( $bookmarks->first() );
|
||||
}
|
||||
|
||||
public function byUser( $limit = null ) {
|
||||
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||
if ( empty( $limit ) ) {
|
||||
$bookmarks = self::$db->get( $this->tableName, $whereClause );
|
||||
} else {
|
||||
$bookmarks = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [0, $limit] );
|
||||
}
|
||||
if ( !$bookmarks->count() ) {
|
||||
Debug::info( 'No Bookmarks found.' );
|
||||
return false;
|
||||
}
|
||||
return $this->filter( $bookmarks->results() );
|
||||
}
|
||||
|
||||
public function unsafeByFolder( $id, $limit = null ) {
|
||||
$whereClause = [ 'folderID', '=', $id ];
|
||||
if ( empty( $limit ) ) {
|
||||
$bookmarks = self::$db->get( $this->tableName, $whereClause );
|
||||
} else {
|
||||
$bookmarks = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [0, $limit] );
|
||||
}
|
||||
if ( !$bookmarks->count() ) {
|
||||
Debug::info( 'No Bookmarks found.' );
|
||||
return false;
|
||||
}
|
||||
return $this->filter( $bookmarks->results() );
|
||||
}
|
||||
|
||||
public function byFolder( $id, $hiddenExcluded = false, $archivedExcluded = false ) {
|
||||
$whereClause = ['createdBy', '=', App::$activeUser->ID ];
|
||||
$whereClause = array_merge( $whereClause, [ 'AND', 'folderID', '=', $id ] );
|
||||
if ( ! empty( $hiddenExcluded ) ) {
|
||||
$whereClause = array_merge( $whereClause, [ 'AND', 'hiddenAt', 'is', 'NULL'] );
|
||||
}
|
||||
if ( ! empty( $archivedExcluded ) ) {
|
||||
$whereClause = array_merge( $whereClause, [ 'AND', 'archivedAt', 'is', 'NULL'] );
|
||||
}
|
||||
$bookmarks = self::$db->get( $this->tableName, $whereClause );
|
||||
if ( ! $bookmarks->count() ) {
|
||||
Debug::info( 'No Bookmarks found.' );
|
||||
return false;
|
||||
}
|
||||
return $this->filter( $bookmarks->results() );
|
||||
}
|
||||
|
||||
public function publicByFolder( $id, $limit = null ) {
|
||||
$whereClause = ['createdBy', '=', App::$activeUser->ID, 'AND'];
|
||||
$whereClause = array_merge( $whereClause, [ 'folderID', '=', $id, 'AND', 'privacy', '=', 'public' ] );
|
||||
if ( empty( $limit ) ) {
|
||||
$bookmarks = self::$db->get( $this->tableName, $whereClause );
|
||||
} else {
|
||||
$bookmarks = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [0, $limit] );
|
||||
}
|
||||
if ( !$bookmarks->count() ) {
|
||||
Debug::info( 'No Bookmarks found.' );
|
||||
return false;
|
||||
}
|
||||
return $this->filter( $bookmarks->results() );
|
||||
}
|
||||
|
||||
public function noFolder( $id = 0, $limit = 10 ) {
|
||||
$whereClause = ['createdBy', '=', App::$activeUser->ID, 'AND'];
|
||||
if ( !empty( $id ) ) {
|
||||
$whereClause = array_merge( $whereClause, ['folderID', '!=', $id] );
|
||||
} else {
|
||||
$whereClause = array_merge( $whereClause, [ 'folderID', 'IS', null] );
|
||||
}
|
||||
if ( empty( $limit ) ) {
|
||||
$bookmarks = self::$db->get( $this->tableName, $whereClause );
|
||||
} else {
|
||||
$bookmarks = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [ 0, $limit ] );
|
||||
}
|
||||
if ( !$bookmarks->count() ) {
|
||||
Debug::info( 'No Bookmarks found.' );
|
||||
return false;
|
||||
}
|
||||
return $this->filter( $bookmarks->results() );
|
||||
}
|
||||
|
||||
public function getName( $id ) {
|
||||
$bookmarks = self::findById( $id );
|
||||
if (false == $bookmarks) {
|
||||
return 'unknown';
|
||||
}
|
||||
return $bookmarks->title;
|
||||
}
|
||||
|
||||
public function getColor( $id ) {
|
||||
$bookmarks = self::findById( $id );
|
||||
if (false == $bookmarks) {
|
||||
return 'default';
|
||||
}
|
||||
return $bookmarks->color;
|
||||
}
|
||||
|
||||
public function simpleByUser() {
|
||||
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||
$bookmarks = self::$db->get( $this->tableName, $whereClause );
|
||||
if ( !$bookmarks->count() ) {
|
||||
Debug::warn( 'Could not find any bookmarks' );
|
||||
return false;
|
||||
}
|
||||
|
||||
$bookmarks = $bookmarks->results();
|
||||
$out = [];
|
||||
foreach ( $bookmarks as $bookmarks ) {
|
||||
$out[ $bookmarks->title ] = $bookmarks->ID;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
public function simpleObjectByUser() {
|
||||
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||
$bookmarks = self::$db->get( $this->tableName, $whereClause );
|
||||
if ( !$bookmarks->count() ) {
|
||||
Debug::warn( 'Could not find any bookmarks' );
|
||||
return false;
|
||||
}
|
||||
|
||||
$bookmarks = $bookmarks->results();
|
||||
$out = [];
|
||||
foreach ( $bookmarks as $bookmarks ) {
|
||||
$obj = new \stdClass();
|
||||
$obj->title = $bookmarks->title;
|
||||
$obj->ID = $bookmarks->ID;
|
||||
$out[] = $obj;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
public function deleteByFolder( $folderID ) {
|
||||
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND' ];
|
||||
$whereClause = array_merge( $whereClause, [ 'folderID', '=', $folderID ] );
|
||||
$bookmarks = self::$db->get( $this->tableName, $whereClause );
|
||||
if ( ! $bookmarks->count() ) {
|
||||
Debug::info( 'No ' . $this->tableName . ' data found.' );
|
||||
return [];
|
||||
}
|
||||
foreach( $bookmarks->results() as $bookmark ) {
|
||||
$this->delete( $bookmark->ID );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function resolveShortenedUrl( $url ) {
|
||||
$ch = curl_init($url);
|
||||
|
||||
// Set curl options
|
||||
curl_setopt($ch, CURLOPT_NOBODY, true); // We don't need the body
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // Follow redirects
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return the response
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 30); // Set a timeout
|
||||
// curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); // Maybe sketchy?
|
||||
// Maybe sketchy?
|
||||
// curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // Disable SSL host verification
|
||||
// curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Disable SSL peer verification
|
||||
// curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
|
||||
|
||||
// added to support the regex site
|
||||
// curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
||||
|
||||
// =
|
||||
// curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'AES256+EECDH:AES256+EDH' );
|
||||
|
||||
|
||||
|
||||
|
||||
// Execute curl
|
||||
$response = curl_exec( $ch );
|
||||
|
||||
// Check if there was an error
|
||||
if ( curl_errno( $ch ) ) {
|
||||
|
||||
|
||||
// Get error details
|
||||
$errorCode = curl_errno($ch);
|
||||
$errorMessage = curl_error($ch);
|
||||
// Log or display the error details
|
||||
dv('cURL Error: ' . $errorMessage . ' (Error Code: ' . $errorCode . ')');
|
||||
|
||||
curl_close($ch);
|
||||
// return $url; // Return the original URL if there was an error
|
||||
|
||||
|
||||
$url = rtrim( $url, '/' );
|
||||
$ch2 = curl_init($url);
|
||||
curl_setopt($ch2, CURLOPT_NOBODY, true); // We don't need the body
|
||||
curl_setopt($ch2, CURLOPT_FOLLOWLOCATION, true); // Follow redirects
|
||||
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true); // Return the response
|
||||
curl_setopt($ch2, CURLOPT_TIMEOUT, 5); // Set a timeout
|
||||
curl_exec($ch2);
|
||||
|
||||
if ( curl_errno( $ch2 ) ) {
|
||||
|
||||
}
|
||||
curl_close( $ch );
|
||||
return $url;
|
||||
}
|
||||
|
||||
// Get the effective URL (the final destination after redirects)
|
||||
$finalUrl = curl_getinfo( $ch, CURLINFO_EFFECTIVE_URL );
|
||||
curl_close( $ch );
|
||||
|
||||
return $finalUrl;
|
||||
|
||||
// $headers = get_headers( $url, 1 );
|
||||
$headers = @get_headers($url, 1);
|
||||
if ( $headers === false ) {
|
||||
}
|
||||
if ( isset( $headers['Location'] ) ) {
|
||||
if (is_array($headers['Location'])) {
|
||||
return end($headers['Location']);
|
||||
} else {
|
||||
return $headers['Location'];
|
||||
}
|
||||
} else {
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
|
||||
public function filter( $data, $params = [] ) {
|
||||
foreach ( $data as $instance ) {
|
||||
if ( !is_object( $instance ) ) {
|
||||
$instance = $data;
|
||||
$end = true;
|
||||
}
|
||||
|
||||
$instance->iconHtml = '<i class="fa fa-fw fa-link"></i>';
|
||||
if ( ! empty( $instance->icon ) ) {
|
||||
if ( strpos($instance->icon, 'http') !== false) {
|
||||
$instance->iconHtml = '<img src="' . $instance->icon .'">';
|
||||
} else {
|
||||
if ( ! empty( $instance->url ) ) {
|
||||
$base_url = $this->getBaseUrl( $instance->url );
|
||||
$instance->iconHtml = '<img src="' . $base_url . ltrim( $instance->icon, '/' ) .'">';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $instance->privacy == 'private' ) {
|
||||
$instance->privacyBadge = '<span class="mx-2 translate-center badge bg-success rounded-pill">Private</span>';
|
||||
$instance->publish = '
|
||||
<a href="{ROOT_URL}bookmarks/publish/'.$instance->ID.'" class="btn btn-sm btn-outline-danger">
|
||||
<i class="fa fa-fw fa-lock"></i>
|
||||
</a>';
|
||||
} else {
|
||||
$instance->privacyBadge = '<span class="mx-2 translate-center badge bg-danger rounded-pill">Public</span>';
|
||||
$instance->publish = '
|
||||
<a href="{ROOT_URL}bookmarks/retract/'.$instance->ID.'" class="btn btn-sm btn-outline-secondary">
|
||||
<i class="fa fa-fw fa-lock"></i>
|
||||
</a>';
|
||||
}
|
||||
if ( empty( $instance->hiddenAt ) ) {
|
||||
$instance->hidden_class = '';
|
||||
$instance->hideBtn = '
|
||||
<a href="{ROOT_URL}bookmarks/hideBookmark/'.$instance->ID.'" class="btn btn-sm btn-outline-warning">
|
||||
<i class="fa fa-fw fa-eye"></i>
|
||||
</a>';
|
||||
} else {
|
||||
$instance->hidden_class = 'link-hidden';
|
||||
$instance->hideBtn = '
|
||||
<a href="{ROOT_URL}bookmarks/showBookmark/'.$instance->ID.'" class="btn btn-sm btn-outline-secondary">
|
||||
<i class="fa fa-fw fa-eye"></i>
|
||||
</a>';
|
||||
}
|
||||
|
||||
if ( empty( $instance->archivedAt ) ) {
|
||||
$instance->archived_class = '';
|
||||
$instance->archiveBtn = '
|
||||
<a href="{ROOT_URL}bookmarks/archiveBookmark/'.$instance->ID.'" class="btn btn-sm btn-outline-info">
|
||||
<i class="fa fa-fw fa-briefcase"></i>
|
||||
</a>';
|
||||
} else {
|
||||
$instance->archived_class = 'link-archived';
|
||||
$instance->archiveBtn = '
|
||||
<a href="{ROOT_URL}bookmarks/unarchiveBookmark/'.$instance->ID.'" class="btn btn-sm btn-outline-secondary">
|
||||
<i class="fa fa-fw fa-briefcase"></i>
|
||||
</a>';
|
||||
}
|
||||
|
||||
if ( ! empty( $instance->refreshedAt ) && time() < ( $instance->refreshedAt + ( 60 * 10 ) ) ) {
|
||||
$instance->refreshBtn = '
|
||||
<a href="{ROOT_URL}bookmarks/refreshBookmark/'.$instance->ID.'" class="btn btn-sm btn-danger">
|
||||
<i class="fa fa-fw fa-refresh"></i>
|
||||
</a>';
|
||||
} else {
|
||||
$instance->refreshBtn = '
|
||||
<a href="{ROOT_URL}bookmarks/refreshBookmark/'.$instance->ID.'" class="btn btn-sm btn-success">
|
||||
<i class="fa fa-fw fa-refresh"></i>
|
||||
</a>';
|
||||
}
|
||||
|
||||
$out[] = $instance;
|
||||
if ( !empty( $end ) ) {
|
||||
$out = $out[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
public function hide( $id ) {
|
||||
if ( !Check::id( $id ) ) {
|
||||
Debug::info( 'Bookmarks: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'hiddenAt' => time(),
|
||||
];
|
||||
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||
new CustomException( 'bookmarkUpdate' );
|
||||
Debug::error( "Bookmarks: $id not updated" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function show( $id ) {
|
||||
if ( !Check::id( $id ) ) {
|
||||
Debug::info( 'Bookmarks: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'hiddenAt' => NULL,
|
||||
];
|
||||
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||
new CustomException( 'bookmarkUpdate' );
|
||||
Debug::error( "Bookmarks: $id not updated" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function publish( $id ) {
|
||||
if ( !Check::id( $id ) ) {
|
||||
Debug::info( 'Bookmarks: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'privacy' => 'public',
|
||||
];
|
||||
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||
new CustomException( 'bookmarkUpdate' );
|
||||
Debug::error( "Bookmarks: $id not updated" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function retract( $id ) {
|
||||
if ( !Check::id( $id ) ) {
|
||||
Debug::info( 'Bookmarks: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'privacy' => 'private',
|
||||
];
|
||||
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||
new CustomException( 'bookmarkUpdate' );
|
||||
Debug::error( "Bookmarks: $id not updated" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function archive( $id ) {
|
||||
if ( !Check::id( $id ) ) {
|
||||
Debug::info( 'Bookmarks: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'archivedAt' => time(),
|
||||
];
|
||||
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||
new CustomException( 'bookmarkUpdate' );
|
||||
Debug::error( "Bookmarks: $id not updated" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function unarchive( $id ) {
|
||||
if ( !Check::id( $id ) ) {
|
||||
Debug::info( 'Bookmarks: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'archivedAt' => NULL,
|
||||
];
|
||||
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||
new CustomException( 'bookmarkUpdate' );
|
||||
Debug::error( "Bookmarks: $id not updated" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function extractMetaTags($htmlContent) {
|
||||
$doc = new \DOMDocument();
|
||||
@$doc->loadHTML($htmlContent);
|
||||
$metaTags = [];
|
||||
foreach ($doc->getElementsByTagName('meta') as $meta) {
|
||||
$name = $meta->getAttribute('name') ?: $meta->getAttribute('property');
|
||||
$content = $meta->getAttribute('content');
|
||||
if ($name && $content) {
|
||||
$metaTags[$name] = $content;
|
||||
}
|
||||
}
|
||||
return $metaTags;
|
||||
}
|
||||
|
||||
public function fetchUrlData($url) {
|
||||
$ch = curl_init();
|
||||
|
||||
// Set cURL options
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_HEADER, true); // Include headers in the output
|
||||
curl_setopt($ch, CURLOPT_NOBODY, false); // Include the body in the output
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // Follow redirects
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 30); // Set a timeout
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // Disable SSL host verification for testing
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Disable SSL peer verification for testing
|
||||
|
||||
// Execute cURL request
|
||||
$response = curl_exec($ch);
|
||||
|
||||
// Check if there was an error
|
||||
if (curl_errno($ch)) {
|
||||
$errorMessage = curl_error($ch);
|
||||
curl_close($ch);
|
||||
throw new \Exception('cURL Error: ' . $errorMessage);
|
||||
}
|
||||
|
||||
// Get HTTP status code
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
// Separate headers and body
|
||||
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
||||
$headers = substr($response, 0, $headerSize);
|
||||
$body = substr($response, $headerSize);
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
// Parse headers into an associative array
|
||||
$headerLines = explode("\r\n", trim($headers));
|
||||
$headerArray = [];
|
||||
foreach ($headerLines as $line) {
|
||||
$parts = explode(': ', $line, 2);
|
||||
if (count($parts) == 2) {
|
||||
$headerArray[$parts[0]] = $parts[1];
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'http_code' => $httpCode,
|
||||
'headers' => $headerArray,
|
||||
'body' => $body,
|
||||
];
|
||||
}
|
||||
|
||||
private function getMetaTagsAndFavicon( $url ) {
|
||||
try {
|
||||
// $url = 'https://runescape.wiki';
|
||||
$data = $this->fetchUrlData($url);
|
||||
|
||||
// iv($data);
|
||||
|
||||
// Get headers
|
||||
$headers = $data['headers'];
|
||||
iv($headers);
|
||||
|
||||
// Get meta tags
|
||||
$metaTags = $this->extractMetaTags($data['body']);
|
||||
} catch (Exception $e) {
|
||||
dv( 'Error: ' . $e->getMessage());
|
||||
|
||||
}
|
||||
$metaInfo = [
|
||||
'url' => $url,
|
||||
'title' => null,
|
||||
'description' => null,
|
||||
'image' => null,
|
||||
'favicon' => null
|
||||
];
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$html = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($html === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$meta = @get_meta_tags( $url );
|
||||
|
||||
$dom = new \DOMDocument('1.0', 'utf-8');
|
||||
$dom->strictErrorChecking = false;
|
||||
$dom->loadHTML($html, LIBXML_NOERROR);
|
||||
$xml = simplexml_import_dom($dom);
|
||||
$arr = $xml->xpath('//link[@rel="shortcut icon"]');
|
||||
|
||||
// Get the title of the page
|
||||
$titles = $dom->getElementsByTagName('title');
|
||||
if ($titles->length > 0) {
|
||||
$metaInfo['title'] = $titles->item(0)->nodeValue;
|
||||
}
|
||||
|
||||
// Get the meta tags
|
||||
$metaTags = $dom->getElementsByTagName('meta');
|
||||
$metadata = [];
|
||||
foreach ($metaTags as $meta) {
|
||||
$metadata[] = [
|
||||
'name' => $meta->getAttribute('name'),
|
||||
'property' => $meta->getAttribute('property'),
|
||||
'content' => $meta->getAttribute('content')
|
||||
];
|
||||
if ($meta->getAttribute('name') === 'description') {
|
||||
$metaInfo['description'] = $meta->getAttribute('content');
|
||||
}
|
||||
if ($meta->getAttribute('itemprop') === 'image') {
|
||||
$metaInfo['google_image'] = $meta->getAttribute('content');
|
||||
}
|
||||
if ($meta->getAttribute('property') === 'og:image') {
|
||||
$metaInfo['image'] = $meta->getAttribute('content');
|
||||
}
|
||||
}
|
||||
|
||||
// Get the link tags to find the favicon
|
||||
$linkTags = $dom->getElementsByTagName('link');
|
||||
$metadata['links'] = [];
|
||||
foreach ($linkTags as $link) {
|
||||
$metadata['links'][] = [ $link->getAttribute('rel') => $link->getAttribute('href') ];
|
||||
if ( $link->getAttribute('rel') === 'icon' || $link->getAttribute('rel') === 'shortcut icon') {
|
||||
$metaInfo['favicon'] = $link->getAttribute('href');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$metaInfo['metadata'] = $metadata;
|
||||
|
||||
return $metaInfo;
|
||||
}
|
||||
|
||||
public function retrieveInfo( $url ) {
|
||||
$finalDestination = $this->resolveShortenedUrl( $url );
|
||||
$info = $this->getMetaTagsAndFavicon( $finalDestination );
|
||||
$base_url = $this->getBaseUrl( $finalDestination );
|
||||
|
||||
if ( ! empty( $info['favicon'] ) ) {
|
||||
echo 'favicon exists' . PHP_EOL;
|
||||
if ( stripos( $info['favicon'], 'http' ) !== false) {
|
||||
echo 'favicon is full url' . PHP_EOL;
|
||||
$imageUrl = $info['favicon'];
|
||||
} else {
|
||||
echo 'favicon is not full url' . PHP_EOL;
|
||||
$imageUrl = trim( $base_url, '/' ) . '/' . ltrim( $info['favicon'], '/' );
|
||||
}
|
||||
if ( $this->isValidImageUrl( $imageUrl ) ) {
|
||||
echo 'image is valid' . PHP_EOL;
|
||||
$info['favicon'] = $imageUrl;
|
||||
} else {
|
||||
echo 'image is not valid' . PHP_EOL;
|
||||
$base_info = $this->getMetaTagsAndFavicon( $base_url );
|
||||
if ( ! empty( $base_info['favicon'] ) ) {
|
||||
echo 'parent favicon exists!';
|
||||
if ( stripos( $base_info['favicon'], 'http' ) !== false) {
|
||||
echo 'parent favicon is full url' . PHP_EOL;
|
||||
$imageUrl = $base_info['favicon'];
|
||||
} else {
|
||||
echo 'parent favicon is not full url' . PHP_EOL;
|
||||
$imageUrl = trim( $base_url, '/' ) . '/' . ltrim( $base_info['favicon'], '/' );
|
||||
}
|
||||
if ( $this->isValidImageUrl( $imageUrl ) ) {
|
||||
echo 'parent favicon image is valid' . PHP_EOL;
|
||||
$info['favicon'] = $imageUrl;
|
||||
} else {
|
||||
echo 'parent favicon image is not valid' . PHP_EOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo 'favicon does not exist' . PHP_EOL;
|
||||
$base_info = $this->getMetaTagsAndFavicon( $base_url );
|
||||
if ( ! empty( $base_info['favicon'] ) ) {
|
||||
echo 'parent favicon exists!' . PHP_EOL;
|
||||
if ( stripos( $base_info['favicon'], 'http' ) !== false) {
|
||||
echo 'parent favicon is full url' . PHP_EOL;
|
||||
$imageUrl = $base_info['favicon'];
|
||||
} else {
|
||||
echo 'parent favicon is not full url' . PHP_EOL;
|
||||
$imageUrl = trim( $base_url, '/' ) . '/' . ltrim( $base_info['favicon'], '/' );
|
||||
}
|
||||
if ( $this->isValidImageUrl( $imageUrl ) ) {
|
||||
echo 'parent favicon image is valid' . PHP_EOL;
|
||||
$info['favicon'] = $imageUrl;
|
||||
} else {
|
||||
echo 'parent favicon image is not valid' . PHP_EOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
public function refreshInfo( $id ) {
|
||||
if ( !Check::id( $id ) ) {
|
||||
Debug::info( 'Bookmarks: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$bookmark = self::findById( $id );
|
||||
if ( $bookmark == false ) {
|
||||
Debug::info( 'Bookmarks not found.' );
|
||||
return false;
|
||||
}
|
||||
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||
Debug::info( 'You do not have permission to modify this bookmark.' );
|
||||
return false;
|
||||
}
|
||||
if ( time() < ( $bookmark->refreshedAt + ( 60 * 10 ) ) ) {
|
||||
Debug::info( 'You may only fetch bookmarks once every 10 minutes.' );
|
||||
return false;
|
||||
}
|
||||
|
||||
$info = $this->retrieveInfo( $bookmark->url );
|
||||
|
||||
$fields = [
|
||||
// 'refreshedAt' => time(),
|
||||
];
|
||||
|
||||
if ( empty( $bookmark->title ) && ! empty( $info['title'] ) ) {
|
||||
$fields['title'] = $info['title'];
|
||||
}
|
||||
if ( empty( $bookmark->description ) && ! empty( $info['description'] ) ) {
|
||||
$fields['description'] = $info['description'];
|
||||
}
|
||||
|
||||
if ( ( empty( $bookmark->icon ) || ! $this->isValidImageUrl( $bookmark->icon ) ) && ! empty( $info['favicon'] ) ) {
|
||||
$fields['icon'] = $info['favicon'];
|
||||
}
|
||||
$fields['meta'] = json_encode( $info['metadata'] );
|
||||
|
||||
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||
new CustomException( 'bookmarkUpdate' );
|
||||
Debug::error( "Bookmarks: $id not updated" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getBaseUrl ( $url ) {
|
||||
if ( empty($url) ) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
$parsedUrl = parse_url($url);
|
||||
if (isset($parsedUrl['scheme']) && isset($parsedUrl['host'])) {
|
||||
return $parsedUrl['scheme'] . '://' . $parsedUrl['host'] . '/';
|
||||
} else {
|
||||
return null; // URL is not valid or cannot be parsed
|
||||
}
|
||||
}
|
||||
|
||||
public function isValidImageUrl($url) {
|
||||
$headers = @get_headers($url);
|
||||
if ($headers && strpos($headers[0], '200') !== false) {
|
||||
|
||||
return true;
|
||||
// Further check to ensure it's an image
|
||||
foreach ($headers as $header) {
|
||||
if (strpos(strtolower($header), 'content-type:') !== false) {
|
||||
if (strpos(strtolower($header), 'image/') !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
216
app/plugins/bookmarks/models/folders.php
Normal file
@ -0,0 +1,216 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/bookmarks/models/folders.php
|
||||
*
|
||||
* This class is used for the manipulation of the folders database table.
|
||||
*
|
||||
* @package TP Bookmarks
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Models;
|
||||
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||
use TheTempusProject\Classes\DatabaseModel;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Houdini\Classes\Filters;
|
||||
use TheTempusProject\Canary\Classes\CustomException;
|
||||
|
||||
class Folders extends DatabaseModel {
|
||||
public $tableName = 'folders';
|
||||
public $databaseMatrix = [
|
||||
[ 'title', 'varchar', '256' ],
|
||||
[ 'color', 'varchar', '48' ],
|
||||
[ 'privacy', 'varchar', '48' ],
|
||||
[ 'description', 'text', '' ],
|
||||
[ 'folderID', 'int', '11' ],
|
||||
[ 'createdBy', 'int', '11' ],
|
||||
[ 'createdAt', 'int', '11' ],
|
||||
[ 'uuid', 'char', '36' ],
|
||||
];
|
||||
|
||||
/**
|
||||
* The model constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function findByUuid( $id ) {
|
||||
$whereClause = ['uuid', '=', $id];
|
||||
if ( empty( $limit ) ) {
|
||||
$folders = self::$db->get( $this->tableName, $whereClause );
|
||||
} else {
|
||||
$folders = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [0, $limit] );
|
||||
}
|
||||
if ( !$folders->count() ) {
|
||||
Debug::info( 'No Folders found.' );
|
||||
return false;
|
||||
}
|
||||
return $this->filter( $folders->first() );
|
||||
}
|
||||
|
||||
public function create( $title, $folderID = 0, $description = '', $color = 'default', $privacy = 'private', $user = null ) {
|
||||
if ( empty( $user ) ) {
|
||||
$user = App::$activeUser->ID;
|
||||
}
|
||||
if ( ! Check::dataTitle( $title ) ) {
|
||||
Debug::info( 'Folders: illegal title.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'title' => $title,
|
||||
'description' => $description,
|
||||
'color' => $color,
|
||||
'privacy' => $privacy,
|
||||
'uuid' => generateUuidV4(),
|
||||
'createdBy' => $user,
|
||||
'createdAt' => time(),
|
||||
];
|
||||
|
||||
if ( !empty( $folderID ) ) {
|
||||
$fields['folderID'] = $folderID;
|
||||
}
|
||||
if ( ! self::$db->insert( $this->tableName, $fields ) ) {
|
||||
new CustomException( 'folderCreate' );
|
||||
Debug::error( "Folders: not created " . var_export($fields,true) );
|
||||
return false;
|
||||
}
|
||||
return self::$db->lastId();
|
||||
}
|
||||
|
||||
public function update( $id, $title, $folderID = 0, $description = '', $color = 'default', $privacy = 'private' ) {
|
||||
if ( !Check::id( $id ) ) {
|
||||
Debug::info( 'Folders: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
if ( !Check::dataTitle( $title ) ) {
|
||||
Debug::info( 'Folders: illegal title.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'title' => $title,
|
||||
'description' => $description,
|
||||
'color' => $color,
|
||||
'privacy' => $privacy,
|
||||
];
|
||||
if ( !empty( $folderID ) ) {
|
||||
$fields['folderID'] = $folderID;
|
||||
}
|
||||
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||
new CustomException( 'folderUpdate' );
|
||||
Debug::error( "Folders: $id not updated: $fields" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function byUser( $limit = null ) {
|
||||
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||
if ( empty( $limit ) ) {
|
||||
$folders = self::$db->get( $this->tableName, $whereClause );
|
||||
} else {
|
||||
$folders = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [0, $limit] );
|
||||
}
|
||||
if ( !$folders->count() ) {
|
||||
Debug::info( 'No Folders found.' );
|
||||
return false;
|
||||
}
|
||||
return $this->filter( $folders->results() );
|
||||
}
|
||||
|
||||
public function bySpecificUser( $userID, $limit = null ) {
|
||||
$whereClause = ['createdBy', '=', $userID];
|
||||
if ( empty( $limit ) ) {
|
||||
$folders = self::$db->get( $this->tableName, $whereClause );
|
||||
} else {
|
||||
$folders = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [0, $limit] );
|
||||
}
|
||||
if ( !$folders->count() ) {
|
||||
Debug::info( 'No Folders found.' );
|
||||
return false;
|
||||
}
|
||||
return $this->filter( $folders->results() );
|
||||
}
|
||||
|
||||
public function getName( $id ) {
|
||||
$folder = self::findById( $id );
|
||||
if (false == $folder) {
|
||||
return 'unknown';
|
||||
}
|
||||
return $folder->title;
|
||||
}
|
||||
|
||||
public function getColor( $id ) {
|
||||
$folder = self::findById( $id );
|
||||
if (false == $folder) {
|
||||
return 'default';
|
||||
}
|
||||
return $folder->color;
|
||||
}
|
||||
|
||||
public function simpleByUser() {
|
||||
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||
$folders = self::$db->get( $this->tableName, $whereClause );
|
||||
if ( !$folders->count() ) {
|
||||
Debug::warn( 'Could not find any folders' );
|
||||
return false;
|
||||
}
|
||||
|
||||
$folders = $folders->results();
|
||||
$out = [];
|
||||
$out[ 'No Folder' ] = 0;
|
||||
foreach ( $folders as $folder ) {
|
||||
$out[ $folder->title ] = $folder->ID;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
public function simpleObjectByUser() {
|
||||
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||
$folders = self::$db->get( $this->tableName, $whereClause );
|
||||
if ( !$folders->count() ) {
|
||||
Debug::warn( 'Could not find any folders' );
|
||||
return false;
|
||||
}
|
||||
|
||||
$folders = $folders->results();
|
||||
$out = [];
|
||||
foreach ( $folders as $folder ) {
|
||||
$obj = new \stdClass();
|
||||
$obj->title = $folder->title;
|
||||
$obj->ID = $folder->ID;
|
||||
$out[] = $obj;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
public function filter( $data, $params = [] ) {
|
||||
foreach ( $data as $instance ) {
|
||||
if ( !is_object( $instance ) ) {
|
||||
$instance = $data;
|
||||
$end = true;
|
||||
}
|
||||
// Real Work Starts Here
|
||||
$instance->prettyPrivacy = ucfirst( $instance->privacy );
|
||||
$instance->prettyTitle = ucfirst( $instance->title );
|
||||
|
||||
if ( $instance->privacy == 'private' ) {
|
||||
$instance->privacyBadge = '<span class="mx-2 translate-center badge bg-success rounded-pill">Private</span>';
|
||||
} else {
|
||||
$instance->privacyBadge = '<span class="mx-2 translate-center badge rounded-pill bg-danger">Public</span>';
|
||||
}
|
||||
|
||||
// Real Work Ends Here
|
||||
$out[] = $instance;
|
||||
if ( !empty( $end ) ) {
|
||||
$out = $out[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
}
|