Initial commit
This commit is contained in:
402
app/plugins/bookmarks/controllers/bookmarks.php
Normal file
402
app/plugins/bookmarks/controllers/bookmarks.php
Normal file
@ -0,0 +1,402 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/bugreport/controllers/bugreport.php
|
||||
*
|
||||
* This is the bug reports controller.
|
||||
*
|
||||
* @package TP BugReports
|
||||
* @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\TheTempusProject as App;
|
||||
use TheTempusProject\Houdini\Classes\Components;
|
||||
use TheTempusProject\Houdini\Classes\Forms as HoudiniForms;
|
||||
use TheTempusProject\Houdini\Classes\Navigation;
|
||||
|
||||
class Bookmarks extends Controller {
|
||||
protected static $bookmarks;
|
||||
protected static $folders;
|
||||
|
||||
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::$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 );
|
||||
Views::raw( $tabsView );
|
||||
}
|
||||
|
||||
public function index() {
|
||||
$bookmarks = self::$bookmarks->noFolder();
|
||||
$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->bookmarkListRows = Views::simpleView( 'bookmarks.components.bookmarkListRows', $folderObject->bookmarks );
|
||||
$panel->panel = Views::simpleView( 'bookmarks.components.bookmarkListPanel', [$folderObject] );
|
||||
$panelArray[] = $panel;
|
||||
}
|
||||
}
|
||||
Components::set( 'foldersList', Views::simpleView( 'bookmarks.folders.list', $folders ) );
|
||||
Components::set( 'folderPanels', Views::simpleView( 'bookmarks.components.folderPanelList', $panelArray ) );
|
||||
Components::set( 'bookmarksList', Views::simpleView( 'bookmarks.bookmarks.list', $bookmarks ) );
|
||||
return Views::view( 'bookmarks.dash' );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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 );
|
||||
|
||||
|
||||
$bookmarks = self::$bookmarks->noFolder();
|
||||
|
||||
$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.components.folderPanelList', $panelArray );
|
||||
}
|
||||
|
||||
public function createBookmark( $id = null ) {
|
||||
$folderID = Input::get('folder_id') ? Input::get('folder_id') : $id;
|
||||
$folderID = Input::post('folder_id') ? Input::post('folder_id') : $id;
|
||||
$folderSelect = HoudiniForms::getFormFieldHtml( 'folder_id', 'Folder', 'select', $folderID, self::$folders->simpleByUser() );
|
||||
Components::set( 'folderSelect', $folderSelect );
|
||||
|
||||
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.' );
|
||||
Redirect::to( 'bookmarks/bookmarks/'. $folderID );
|
||||
}
|
||||
|
||||
public function editBookmark( $id = null ) {
|
||||
$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;
|
||||
}
|
||||
|
||||
$folderSelect = HoudiniForms::getFormFieldHtml( 'folder_id', 'Folder', 'select', $folderID, self::$folders->simpleByUser() );
|
||||
Components::set( 'folderSelect', $folderSelect );
|
||||
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();
|
||||
return Views::view( 'bookmarks.folders.list', $folders );
|
||||
}
|
||||
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 ) {
|
||||
$folderID = Input::exists('folder_id') ? Input::post('folder_id') : $id;
|
||||
$folders = self::$folders->simpleByUser();
|
||||
if ( ! empty( $folders ) ) {
|
||||
$folderSelect = HoudiniForms::getFormFieldHtml( 'folder_id', 'Folder', 'select', $folderID, $folders );
|
||||
} 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 ) {
|
||||
$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');
|
||||
|
||||
$folderSelect = HoudiniForms::getFormFieldHtml( 'folder_id', 'Folder', 'select', $folderID, self::$folders->simpleByUser() );
|
||||
Components::set( 'folderSelect', $folderSelect );
|
||||
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' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Functionality
|
||||
*/
|
||||
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 );
|
||||
}
|
||||
}
|
122
app/plugins/bookmarks/forms.php
Normal file
122
app/plugins/bookmarks/forms.php
Normal file
@ -0,0 +1,122 @@
|
||||
<?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' );
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
new BookmarksForms;
|
149
app/plugins/bookmarks/models/bookmarkViews.php
Normal file
149
app/plugins/bookmarks/models/bookmarkViews.php
Normal file
@ -0,0 +1,149 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/bookmarks/models/bookmarkViews.php
|
||||
*
|
||||
* This class is used for the manipulation of the bookmark_views 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\Classes\Config;
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Canary\Canary as Debug;
|
||||
use TheTempusProject\Classes\DatabaseModel;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Houdini\Classes\Filters;
|
||||
use TheTempusProject\Bedrock\Classes\CustomException;
|
||||
|
||||
class BookmarkViews extends DatabaseModel {
|
||||
public $tableName = 'bookmark_views';
|
||||
public $databaseMatrix = [
|
||||
[ 'title', 'varchar', '256' ],
|
||||
[ 'description', 'text', '' ],
|
||||
[ 'privacy', 'varchar', '48' ],
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[ 'createdBy', 'int', '11' ],
|
||||
[ 'createdAt', 'int', '11' ],
|
||||
[ 'updatedAt', 'int', '11' ],
|
||||
];
|
||||
|
||||
/**
|
||||
* The model constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function create( $title, $description = '', $privacy = 'private' ) {
|
||||
if ( ! Check::dataTitle( $title ) ) {
|
||||
Debug::info( 'Views: illegal title.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'title' => $title,
|
||||
'description' => $description,
|
||||
'privacy' => $privacy,
|
||||
'createdBy' => App::$activeUser->ID,
|
||||
'createdAt' => time(),
|
||||
];
|
||||
if ( ! self::$db->insert( $this->tableName, $fields ) ) {
|
||||
new CustomException( 'viewCreate' );
|
||||
Debug::error( "Views: not created " . var_export($fields,true) );
|
||||
return false;
|
||||
}
|
||||
return self::$db->lastId();
|
||||
}
|
||||
|
||||
public function update( $id, $title, $description = '', $privacy = 'private' ) {
|
||||
if ( !Check::id( $id ) ) {
|
||||
Debug::info( 'Views: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
if ( !Check::dataTitle( $title ) ) {
|
||||
Debug::info( 'Views: illegal title.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'title' => $title,
|
||||
'description' => $description,
|
||||
'privacy' => $privacy,
|
||||
];
|
||||
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||
new CustomException( 'viewUpdate' );
|
||||
Debug::error( "Views: $id not updated: $fields" );
|
||||
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;
|
||||
}
|
||||
}
|
705
app/plugins/bookmarks/models/bookmarks.php
Normal file
705
app/plugins/bookmarks/models/bookmarks.php
Normal file
@ -0,0 +1,705 @@
|
||||
<?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\Classes\Config;
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Canary\Canary as Debug;
|
||||
use TheTempusProject\Classes\DatabaseModel;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Houdini\Classes\Filters;
|
||||
use TheTempusProject\Bedrock\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' ],
|
||||
];
|
||||
|
||||
/**
|
||||
* The model constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function create( $title, $url, $folderID = 0, $description = '', $color = 'default', $privacy = 'private', $type = 'external' ) {
|
||||
$fields = [
|
||||
'title' => $title,
|
||||
'url' => $url,
|
||||
'description' => $description,
|
||||
'color' => $color,
|
||||
'privacy' => $privacy,
|
||||
'createdBy' => App::$activeUser->ID,
|
||||
'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 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 byFolder( $id, $limit = null ) {
|
||||
$whereClause = ['createdBy', '=', App::$activeUser->ID, 'AND'];
|
||||
|
||||
$whereClause = array_merge( $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 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;
|
||||
}
|
||||
$base_url = $this->getBaseUrl( $instance->url );
|
||||
|
||||
if ( empty( $instance->icon ) ) {
|
||||
$instance->iconHtml = '<i class="glyphicon glyphicon-link"></i>';
|
||||
} else {
|
||||
if (strpos($instance->icon, 'http') !== false) {
|
||||
$instance->iconHtml = '<img src="' . $instance->icon .'" />';
|
||||
} else {
|
||||
$instance->iconHtml = '<img src="' . $base_url . ltrim( $instance->icon, '/' ) .'" />';
|
||||
}
|
||||
}
|
||||
if ( empty( $instance->hiddenAt ) ) {
|
||||
$instance->hideBtn = '
|
||||
<a href="{ROOT_URL}bookmarks/hideBookmark/'.$instance->ID.'" class="btn btn-sm btn-warning" role="button">
|
||||
<i class="glyphicon glyphicon-eye-open"></i>
|
||||
</a>';
|
||||
} else {
|
||||
$instance->hideBtn = '
|
||||
<a href="{ROOT_URL}bookmarks/showBookmark/'.$instance->ID.'" class="btn btn-sm btn-default" role="button">
|
||||
<i class="glyphicon glyphicon-eye-open"></i>
|
||||
</a>';
|
||||
}
|
||||
if ( empty( $instance->archivedAt ) ) {
|
||||
$instance->archiveBtn = '
|
||||
<a href="{ROOT_URL}bookmarks/archiveBookmark/'.$instance->ID.'" class="btn btn-sm btn-info" role="button">
|
||||
<i class="glyphicon glyphicon-briefcase"></i>
|
||||
</a>';
|
||||
} else {
|
||||
$instance->archiveBtn = '
|
||||
<a href="{ROOT_URL}bookmarks/unarchiveBookmark/'.$instance->ID.'" class="btn btn-sm btn-default" role="button">
|
||||
<i class="glyphicon glyphicon-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" role="button">
|
||||
<i class="glyphicon glyphicon-refresh"></i>
|
||||
</a>';
|
||||
} else {
|
||||
$instance->refreshBtn = '
|
||||
<a href="{ROOT_URL}bookmarks/refreshBookmark/'.$instance->ID.'" class="btn btn-sm btn-success" role="button">
|
||||
<i class="glyphicon glyphicon-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' => 0,
|
||||
];
|
||||
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' => 0,
|
||||
];
|
||||
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 ) {
|
||||
$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
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
157
app/plugins/bookmarks/models/folders.php
Normal file
157
app/plugins/bookmarks/models/folders.php
Normal file
@ -0,0 +1,157 @@
|
||||
<?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\Classes\Config;
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Canary\Canary as Debug;
|
||||
use TheTempusProject\Classes\DatabaseModel;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Houdini\Classes\Filters;
|
||||
use TheTempusProject\Bedrock\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' ],
|
||||
];
|
||||
|
||||
/**
|
||||
* The model constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function create( $title, $folderID = 0, $description = '', $color = 'default', $privacy = 'private' ) {
|
||||
if ( ! Check::dataTitle( $title ) ) {
|
||||
Debug::info( 'Folders: illegal title.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'title' => $title,
|
||||
'description' => $description,
|
||||
'color' => $color,
|
||||
'privacy' => $privacy,
|
||||
'createdBy' => App::$activeUser->ID,
|
||||
'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 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;
|
||||
}
|
||||
}
|
62
app/plugins/bookmarks/plugin.php
Normal file
62
app/plugins/bookmarks/plugin.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/bookmarks/plugin.php
|
||||
*
|
||||
* This houses all of the main plugin info and functionality.
|
||||
*
|
||||
* @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;
|
||||
|
||||
use TheTempusProject\Classes\Plugin;
|
||||
use TheTempusProject\Models\Events;
|
||||
use TheTempusProject\Models\Bookmarks as Bookmark;
|
||||
use TheTempusProject\Models\Folders;
|
||||
use TheTempusProject\Houdini\Classes\Components;
|
||||
use TheTempusProject\Houdini\Classes\Template;
|
||||
|
||||
class Bookmarks extends Plugin {
|
||||
public $pluginName = 'TP Bookmarks';
|
||||
public $configName = 'bookmarks';
|
||||
public $pluginAuthor = 'JoeyK';
|
||||
public $pluginWebsite = 'https://TheTempusProject.com';
|
||||
public $modelVersion = '1.0';
|
||||
public $pluginVersion = '3.0';
|
||||
public $pluginDescription = 'A simple plugin which adds a site wide bookmark system.';
|
||||
public $permissionMatrix = [
|
||||
'useBookmarks' => [
|
||||
'pretty' => 'Can use the bookmarks feature',
|
||||
'default' => false,
|
||||
],
|
||||
'createEvents' => [
|
||||
'pretty' => 'Can add events to bookmarks',
|
||||
'default' => false,
|
||||
],
|
||||
];
|
||||
public $main_links = [
|
||||
[
|
||||
'text' => 'Bookmarks',
|
||||
'url' => '{ROOT_URL}bookmarks/index',
|
||||
'filter' => 'loggedin',
|
||||
],
|
||||
];
|
||||
public $configMatrix = [
|
||||
'enabled' => [
|
||||
'type' => 'radio',
|
||||
'pretty' => 'Enable Bookmarks.',
|
||||
'default' => true,
|
||||
],
|
||||
];
|
||||
public $bookmarks;
|
||||
public $folders;
|
||||
|
||||
public function __construct( $load = false ) {
|
||||
$this->bookmarks = new Bookmark;
|
||||
$this->folders = new Folders;
|
||||
parent::__construct( $load );
|
||||
}
|
||||
}
|
45
app/plugins/bookmarks/views/bookmarks/create.html
Normal file
45
app/plugins/bookmarks/views/bookmarks/create.html
Normal file
@ -0,0 +1,45 @@
|
||||
<legend>Create Bookmark</legend>
|
||||
{BookmarkBreadCrumbs}
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
<div class="form-group">
|
||||
<label for="title" class="col-lg-3 control-label">Title</label>
|
||||
<div class="col-lg-3">
|
||||
<input type="text" class="form-control" name="title" id="title">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="url" class="col-lg-3 control-label">URL:</label>
|
||||
<div class="col-lg-3">
|
||||
<input type="text" class="form-control" name="url" id="url">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description" class="col-lg-3 control-label">Description:</label>
|
||||
<div class="col-lg-3">
|
||||
<textarea class="form-control" name="description" maxlength="2000" rows="10" cols="50" id="description"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
{folderSelect}
|
||||
<div class="form-group">
|
||||
<label for="privacy" class="col-lg-3 control-label">Privacy</label>
|
||||
<div class="col-lg-3 select-container" id="colorContainer">
|
||||
<select id="privacy" name="privacy" class="form-control custom-select">
|
||||
<option value="private">Private</option>
|
||||
<option value="public">Public</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="color" class="col-lg-3 control-label">Color</label>
|
||||
<div class="col-lg-3 select-container" id="colorContainer">
|
||||
{colorSelect}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="submit" class="col-lg-3 control-label"></label>
|
||||
<div class="col-lg-3">
|
||||
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block ">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
45
app/plugins/bookmarks/views/bookmarks/edit.html
Normal file
45
app/plugins/bookmarks/views/bookmarks/edit.html
Normal file
@ -0,0 +1,45 @@
|
||||
<legend>Edit Bookmark</legend>
|
||||
{BookmarkBreadCrumbs}
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
<div class="form-group">
|
||||
<label for="title" class="col-lg-3 control-label">Title</label>
|
||||
<div class="col-lg-3">
|
||||
<input type="text" class="form-control" name="title" id="title" value="{title}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="url" class="col-lg-3 control-label">URL:</label>
|
||||
<div class="col-lg-3">
|
||||
<input type="text" class="form-control" name="url" id="url" value="{url}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description" class="col-lg-3 control-label">Description:</label>
|
||||
<div class="col-lg-3">
|
||||
<textarea class="form-control" name="description" maxlength="2000" rows="10" cols="50" id="description">{description}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
{folderSelect}
|
||||
<div class="form-group">
|
||||
<label for="privacy" class="col-lg-3 control-label">Privacy</label>
|
||||
<div class="col-lg-3 select-container" id="colorContainer">
|
||||
<select id="privacy" name="privacy" class="form-control custom-select" value="{privacy}">
|
||||
<option value="private">Private</option>
|
||||
<option value="public">Public</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="color" class="col-lg-3 control-label">Color</label>
|
||||
<div class="col-lg-3 select-container" id="colorContainer">
|
||||
{colorSelect}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="submit" class="col-lg-3 control-label"></label>
|
||||
<div class="col-lg-3">
|
||||
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block ">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
37
app/plugins/bookmarks/views/bookmarks/list.html
Normal file
37
app/plugins/bookmarks/views/bookmarks/list.html
Normal file
@ -0,0 +1,37 @@
|
||||
{BookmarkBreadCrumbs}
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 75%">Bookmark</th>
|
||||
<th style="width: 10%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{LOOP}
|
||||
<tr>
|
||||
<td style="text-align: center;">
|
||||
<a href="{url}" role="button">
|
||||
{title}
|
||||
</a>
|
||||
</td>
|
||||
<td style="text-align: center;">
|
||||
{privacy}
|
||||
</td>
|
||||
<td><a href="{ROOT_URL}bookmarks/bookmarks/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-open"></i></a></td>
|
||||
<td><a href="{ROOT_URL}bookmarks/editBookmark/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a></td>
|
||||
<td><a href="{ROOT_URL}bookmarks/deleteBookmark/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a></td>
|
||||
</tr>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<tr>
|
||||
<td style="text-align: center;" colspan="6">
|
||||
No results to show.
|
||||
</td>
|
||||
</tr>
|
||||
{/ALT}
|
||||
</tbody>
|
||||
</table>
|
||||
<a href="{ROOT_URL}bookmarks/createBookmark" class="btn btn-sm btn-primary" role="button">Create</a>
|
84
app/plugins/bookmarks/views/bookmarks/view.html
Normal file
84
app/plugins/bookmarks/views/bookmarks/view.html
Normal file
@ -0,0 +1,84 @@
|
||||
{BookmarkBreadCrumbs}<br />
|
||||
<div class="container col-md-4 col-lg-4">
|
||||
<div class="row">
|
||||
<div class="panel panel-{color}">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Bookmark</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="">
|
||||
<table class="table table-user-primary">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left" width="200"><b>Title</b></td>
|
||||
<td align="right">{title}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" width="200"><b>URL</b></td>
|
||||
<td align="right">{url}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" width="200"><b>Type</b></td>
|
||||
<td align="right">{linkType}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" width="200"><b>Privacy</b></td>
|
||||
<td align="right">{privacy}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" width="200"><b>Color</b></td>
|
||||
<td align="right">{color}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" colspan="2"><b>Description</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">{description}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" colspan="2"><b>Icon</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">{iconHtml}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">{icon}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" colspan="2"><b>Meta</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">{meta}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Created</b></td>
|
||||
<td align="right">{DTC}{createdAt}{/DTC}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Archived</b></td>
|
||||
<td align="right">{DTC}{archivedAt}{/DTC}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Hidden</b></td>
|
||||
<td align="right">{DTC}{hiddenAt}{/DTC}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Last Refreshed</b></td>
|
||||
<td align="right">{DTC}{refreshedAt}{/DTC}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
{refreshBtn}
|
||||
{hideBtn}
|
||||
{archiveBtn}
|
||||
<a href="{ROOT_URL}bookmarks/editBookmark/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a>
|
||||
<a href="{ROOT_URL}bookmarks/deleteBookmark/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,21 @@
|
||||
<div class="panel panel-{color}">
|
||||
<div class="panel-heading" data-target="#Collapse{ID}" data-toggle="collapse" aria-expanded="true" aria-controls="#Collapse{ID}">
|
||||
{title}
|
||||
</div>
|
||||
<div id="Collapse{ID}" class="panel-collapse collapse in" style="width:100%; position: relative;" role="tabpanel" aria-expanded="true">
|
||||
<div class="panel-body">
|
||||
<ul class="list-group">
|
||||
{bookmarkListRows}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<a href="{ROOT_URL}bookmarks/createBookmark/{ID}" class="btn btn-sm btn-success" role="button"><i class="glyphicon glyphicon-plus-sign"></i></a></td>
|
||||
<span class="pull-right">
|
||||
<a href="{ROOT_URL}bookmarks/bookmarks/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-th-list"></i></a>
|
||||
<a href="{ROOT_URL}bookmarks/folders/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-info-sign"></i></a></td>
|
||||
<a href="{ROOT_URL}bookmarks/editFolder/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a></td>
|
||||
<a href="{ROOT_URL}bookmarks/deleteFolder/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a></td>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
18
app/plugins/bookmarks/views/components/bookmarkListRows.html
Normal file
18
app/plugins/bookmarks/views/components/bookmarkListRows.html
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
{LOOP}
|
||||
<li class="list-group-item list-group-item-{color}">
|
||||
<a href="{ROOT_URL}bookmarks/bookmarks/{ID}" class="btn btn-sm" role="button">{iconHtml}</a>
|
||||
<a href="{url}" class="list-group"> {title}</a>
|
||||
<span class="pull-right">
|
||||
{hideBtn}
|
||||
{archiveBtn}
|
||||
<a href="{ROOT_URL}bookmarks/editBookmark/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a>
|
||||
<a href="{ROOT_URL}bookmarks/deleteBookmark/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a>
|
||||
</span>
|
||||
</li>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<li class="list-group-item">
|
||||
<a href="#" class="list-group">No Bookmarks</a>
|
||||
</li>
|
||||
{/ALT}
|
10
app/plugins/bookmarks/views/components/folderPanelList.html
Normal file
10
app/plugins/bookmarks/views/components/folderPanelList.html
Normal file
@ -0,0 +1,10 @@
|
||||
{LOOP}
|
||||
<div class="col-xlg-6 col-lg-6 col-md-6 col-sm-6 col-xs-6">
|
||||
{panel}
|
||||
</div>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<div class="col-xlg-6 col-lg-6 col-md-6 col-sm-6 col-xs-6">
|
||||
<p>no folders</p>
|
||||
</div>
|
||||
{/ALT}
|
16
app/plugins/bookmarks/views/dash.html
Normal file
16
app/plugins/bookmarks/views/dash.html
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
{BookmarkBreadCrumbs}
|
||||
<div class="row">
|
||||
<div class="col-xlg-6 col-lg-6 col-md-6 col-sm-6 col-xs-6">
|
||||
<legend>Unsorted Bookmarks</legend>
|
||||
{bookmarksList}
|
||||
</div>
|
||||
<div class="col-xlg-6 col-lg-6 col-md-6 col-sm-6 col-xs-6">
|
||||
<legend>Folders List</legend>
|
||||
{foldersList}
|
||||
</div>
|
||||
</div>
|
||||
<legend>Folders</legend>
|
||||
<div class="row">
|
||||
{folderPanels}
|
||||
</div>
|
39
app/plugins/bookmarks/views/folders/create.html
Normal file
39
app/plugins/bookmarks/views/folders/create.html
Normal file
@ -0,0 +1,39 @@
|
||||
<legend>Create Folder</legend>
|
||||
{BookmarkBreadCrumbs}
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
<div class="form-group">
|
||||
<label for="title" class="col-lg-3 control-label">Title</label>
|
||||
<div class="col-lg-3">
|
||||
<input type="text" class="form-control" name="title" id="title">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description" class="col-lg-3 control-label">Description:</label>
|
||||
<div class="col-lg-3">
|
||||
<textarea class="form-control" name="description" maxlength="2000" rows="10" cols="50" id="description"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
{folderSelect}
|
||||
<div class="form-group">
|
||||
<label for="privacy" class="col-lg-3 control-label">Privacy</label>
|
||||
<div class="col-lg-3 select-container" id="colorContainer">
|
||||
<select id="privacy" name="privacy" class="form-control custom-select">
|
||||
<option value="private">Private</option>
|
||||
<option value="public">Public</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="color" class="col-lg-3 control-label">Color</label>
|
||||
<div class="col-lg-3 select-container" id="colorContainer">
|
||||
{colorSelect}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="submit" class="col-lg-3 control-label"></label>
|
||||
<div class="col-lg-3">
|
||||
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block ">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
39
app/plugins/bookmarks/views/folders/edit.html
Normal file
39
app/plugins/bookmarks/views/folders/edit.html
Normal file
@ -0,0 +1,39 @@
|
||||
<legend>Edit Folder</legend>
|
||||
{BookmarkBreadCrumbs}
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
<div class="form-group">
|
||||
<label for="title" class="col-lg-3 control-label">Title</label>
|
||||
<div class="col-lg-3">
|
||||
<input type="text" class="form-control" name="title" id="title" value="{title}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description" class="col-lg-3 control-label">Description:</label>
|
||||
<div class="col-lg-3">
|
||||
<textarea class="form-control" name="description" maxlength="2000" rows="10" cols="50" id="description">{description}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
{folderSelect}
|
||||
<div class="form-group">
|
||||
<label for="privacy" class="col-lg-3 control-label">Privacy</label>
|
||||
<div class="col-lg-3 select-container" id="colorContainer">
|
||||
<select id="privacy" name="privacy" class="form-control custom-select" value="{privacy}">
|
||||
<option value="private">Private</option>
|
||||
<option value="public">Public</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="color" class="col-lg-3 control-label">Color</label>
|
||||
<div class="col-lg-3 select-container" id="colorContainer">
|
||||
{colorSelect}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="submit" class="col-lg-3 control-label"></label>
|
||||
<div class="col-lg-3">
|
||||
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block ">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
33
app/plugins/bookmarks/views/folders/list.html
Normal file
33
app/plugins/bookmarks/views/folders/list.html
Normal file
@ -0,0 +1,33 @@
|
||||
{BookmarkBreadCrumbs}
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 35%">Title</th>
|
||||
<th style="width: 20%">Privacy</th>
|
||||
<th style="width: 30%">Description</th>
|
||||
<th style="width: 5%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{LOOP}
|
||||
<tr>
|
||||
<td align="center">{title}</td>
|
||||
<td align="center">{privacy}</td>
|
||||
<td>{description}</td>
|
||||
<td><a href="{ROOT_URL}bookmarks/folders/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-info-sign"></i></a></td>
|
||||
<td><a href="{ROOT_URL}bookmarks/editFolder/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a></td>
|
||||
<td><a href="{ROOT_URL}bookmarks/deleteFolder/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a></td>
|
||||
</tr>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<tr>
|
||||
<td align="center" colspan="7">
|
||||
No results to show.
|
||||
</td>
|
||||
</tr>
|
||||
{/ALT}
|
||||
</tbody>
|
||||
</table>
|
||||
<a href="{ROOT_URL}bookmarks/createFolder" class="btn btn-sm btn-primary" role="button">Create</a>
|
47
app/plugins/bookmarks/views/folders/view.html
Normal file
47
app/plugins/bookmarks/views/folders/view.html
Normal file
@ -0,0 +1,47 @@
|
||||
{BookmarkBreadCrumbs}<br />
|
||||
<div class="container col-md-4 col-lg-4">
|
||||
<div class="row">
|
||||
<div class="panel panel-{color}">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Bookmark Folder</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="">
|
||||
<table class="table table-user-primary">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left" width="200"><b>Title</b></td>
|
||||
<td align="right">{title}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" width="200"><b>Privacy</b></td>
|
||||
<td align="right">{privacy}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left" width="200"><b>Color</b></td>
|
||||
<td align="right">{color}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" colspan="2"><b>Description</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">{description}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Created</b></td>
|
||||
<td align="right">{DTC}{createdAt}{/DTC}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<a href="{ROOT_URL}bookmarks/bookmarks/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-th-list"></i></a>
|
||||
<a href="{ROOT_URL}bookmarks/editFolder/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a>
|
||||
<a href="{ROOT_URL}bookmarks/deleteFolder/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
5
app/plugins/bookmarks/views/nav/folderTabs.html
Normal file
5
app/plugins/bookmarks/views/nav/folderTabs.html
Normal file
@ -0,0 +1,5 @@
|
||||
<ul class="nav nav-tabs">
|
||||
<li><a href="{ROOT_URL}bookmarks/index/">Dashboard</a></li>
|
||||
<li><a href="{ROOT_URL}bookmarks/folders/">Folders</a></li>
|
||||
</ul>
|
||||
{userFolderTabs}
|
9
app/plugins/bookmarks/views/nav/userFolderTabs.html
Normal file
9
app/plugins/bookmarks/views/nav/userFolderTabs.html
Normal file
@ -0,0 +1,9 @@
|
||||
<ul class="nav nav-tabs">
|
||||
<li><a href="{ROOT_URL}bookmarks/folders/">All</a></li>
|
||||
{LOOP}
|
||||
<li><a href="{ROOT_URL}bookmarks/bookmarks/{ID}">{title}</a></li>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<li></li>
|
||||
{/ALT}
|
||||
</ul>
|
Reference in New Issue
Block a user