- original code
- Ben Chavet
trean-1.1.4/docs/INSTALL 0000664 0001750 0001750 00000011437 12654212671 012727 0 ustar jan jan =====================
Installing Trean H5
=====================
:Contact: horde@lists.horde.org
.. contents:: Contents
.. section-numbering::
This document contains instructions for installing the Trean web-based
bookmarks application on your system.
For information on the capabilities and features of Trean, see the
file README_ in the top-level directory of the Trean distribution.
Prerequisites
=============
To function properly, Trean **requires** the following:
1. A working Horde installation.
Trean runs within the `Horde Application Framework`_, a set of common tools
for web applications written in PHP. You must install Horde before
installing Trean.
.. Important:: Trean H5 requires version 5.0.2+ of the Horde Framework -
earlier versions of Horde will **not** work.
.. Important:: Be sure to have completed all of the steps in the
`horde/docs/INSTALL`_ file for the Horde Framework before
installing Trean. Many of Trean's prerequisites are also
Horde prerequisites. Additionally, many of Trean's optional
features are configured via the Horde install.
.. _`Horde Application Framework`: http://www.horde.org/apps/horde
The following non-PHP prerequisites are **RECOMMENDED**:
1. ElasticSearch server.
An ElasticSearch_ server or cluster running on localhost can be used to
provide indexing of bookmarks data and quick searching of the indexed
content.
.. _ElasticSearch: http://www.elasticsearch.org/
Installing Trean
================
The **RECOMMENDED** way to install Trean is using the PEAR installer.
Alternatively, if you want to run the latest development code or get the
latest not yet released fixes, you can install Trean from Git.
Installing with PEAR
~~~~~~~~~~~~~~~~~~~~
First follow the instructions in `horde/docs/INSTALL`_ to prepare a PEAR
environment for Horde and install the Horde Framework.
When installing Trean through PEAR now, the installer will automatically
install any dependencies of Trean too. If you want to install Trean with all
optional dependencies, but without the binary PECL packages that need to be
compiled, specify both the ``-a`` and the ``-B`` flag::
pear install -a -B horde/trean
By default, only the required dependencies will be installed::
pear install horde/trean
If you want to install Trean even with all binary dependencies, you need to
remove the ``-B`` flag. Please note that this might also try to install PHP
extensions through PECL that might need further configuration or activation in
your PHP configuration::
pear install -a horde/trean
Installing from Git
~~~~~~~~~~~~~~~~~~~
See http://www.horde.org/source/git.php
Configuring Trean
=================
1. Configuring Trean
To configure Trean, you must login to Horde as a Horde Administrator. Use
the Horde ``Administration`` menu item to get to the administration page,
and then click on the ``Configuration`` icon to get the configuration page.
Select ``Bookmarks`` from the selection list of applications, and click on
the ``Configure`` button. Fill in or change any configuration values as
needed. When done click on ``Generate Bookmarks Configuration`` to
generate the ``conf.php`` file. If your web server doesn't have write
permissions to the Trean configuration directory or file, it will not be
able to write the file. In this case, go back to ``Configuration`` and
choose one of the other methods to create the configuration file
``trean/config/conf.php``.
Documentation on the format and purpose of the other configuration files in
the ``config/`` directory can be found in each file. You may create
``*.local.php`` versions of these files if you wish to customize Trean's
appearance and behavior. See the header of the configuration files for
details and examples. The defaults will be correct for most sites.
Obtaining Support
=================
If you encounter problems with Trean, help is available!
The Horde Frequently Asked Questions List (FAQ), available on the Web at
http://wiki.horde.org/FAQ
The Horde Project runs a number of mailing lists, for individual applications
and for issues relating to the project as a whole. Information, archives, and
subscription information can be found at
http://www.horde.org/community/mail
Lastly, Horde developers, contributors and users may also be found on IRC,
on the channel #horde on the Freenode Network (irc.freenode.net).
Please keep in mind that Trean is free software written by volunteers. For
information on reasonable support expectations, please read
http://www.horde.org/community/support
Thanks for using Trean!
The Trean team
.. _README: README
.. _`horde/docs/INSTALL`: ../../horde/docs/INSTALL
.. _`horde/docs/TRANSLATIONS`: ../../horde/docs/TRANSLATIONS
trean-1.1.4/docs/lighttpd-trean.conf 0000664 0001750 0001750 00000001173 12654212671 015467 0 ustar jan jan ## This file should be reviewed prior to inclusion in your lighttpd
## configuration. Specifically, if you have horde somewhere other than
## /horde you will need to edit the following rules to match your server
## configuration.
## This file should be included in your lighttpd.conf file with the "include"
## directive. Example:
## include "path/to/lighttpd-trean.conf"
## The exact path you use will of course depend on your specific configuration.
url.rewrite-once += (
## Rampage Rewrite Rules
"^/horde/trean/b/(.*)$" => "/horde/rampage.php/$1",
"^/horde/trean/tag/(.*)$" => "/horde/rampage.php/$1"
)
trean-1.1.4/docs/RELEASE_NOTES 0000664 0001750 0001750 00000001532 12654212671 013644 0 ustar jan jan
* @category Horde
* @license http://www.horde.org/licenses/bsdl.php BSD
* @package Trean
*/
class Trean_Ajax_Imple_TagAutoCompleter extends Horde_Core_Ajax_Imple_AutoCompleter
{
/**
*/
protected function _getAutoCompleter()
{
$opts = array();
foreach (array('box', 'triggerContainer', 'existing', 'boxClass') as $val) {
if (isset($this->_params[$val])) {
$opts[$val] = $this->_params[$val];
}
}
return empty($this->_params['pretty'])
? new Horde_Core_Ajax_Imple_AutoCompleter_Ajax($opts)
: new Horde_Core_Ajax_Imple_AutoCompleter_Pretty($opts);
}
/**
*/
protected function _handleAutoCompleter($input)
{
$tagger = new Trean_Tagger();
return array_values($tagger->listTags($input));
}
}
trean-1.1.4/lib/Ajax/Imple/TopTags.php 0000664 0001750 0001750 00000003335 12654212671 015535 0 ustar jan jan
* @category Horde
* @license http://www.horde.org/licenses/bsdl.php BSD
* @package Trean
*/
class Trean_Ajax_Imple_TopTags extends Horde_Core_Ajax_Imple
{
/**
* Attach the object to a javascript event.
*
* @param boolean $init Is this the first time this imple has been
* initialized?
*
* @return mixed An array of javascript parameters. If false, the imple
* handler will ignore this instance (calling code will be
* responsible for calling imple endpoint).
*/
protected function _attach($init)
{
if ($init) {
$this->_jsOnComplete('TreanTopTags.loadTags(e.memo)');
$GLOBALS['page_output']->addScriptFile('toptags.js');
$GLOBALS['page_output']->addScriptFile('scriptaculous/effects.js', 'horde');
}
return array('imple' => 'TopTags');
}
/**
* Imple handler.
*
* @param Horde_Variables $vars A variables object.
*
* @return stdClass The top 10 most popular tags for the current user.
*/
protected function _handle(Horde_Variables $vars)
{
$tagger = new Trean_Tagger();
$result = new stdClass();
$result->tags = array();
$tags = $tagger->getCloud(
$GLOBALS['registry']->getAuth(), 10, true);
foreach ($tags as $tag) {
$results->tags[] = $tag['tag_name'];
}
return $results;
}
}
trean-1.1.4/lib/Ajax/Application.php 0000664 0001750 0001750 00000001164 12654212671 015347 0 ustar jan jan
* @category Horde
* @package Trean
*/
class Trean_Ajax_Application extends Horde_Core_Ajax_Application
{
/**
*/
protected function _init()
{
$this->addHandler('Horde_Core_Ajax_Application_Handler_Imple');
$this->addHandler('Horde_Core_Ajax_Application_Handler_Prefs');
}
}
trean-1.1.4/lib/Block/Bookmarks.php 0000664 0001750 0001750 00000005051 12654212671 015202 0 ustar jan jan
*/
class Trean_Block_Bookmarks extends Horde_Core_Block
{
/**
*/
public function __construct($app, $params = array())
{
parent::__construct($app, $params);
$this->_name = _("Bookmarks");
}
/**
*/
protected function _params()
{
return array(
'bookmarks' => array(
'name' => _("Sort by"),
'type' => 'enum',
'default' => 'title',
'values' => array(
'title' => _("Title"),
'most_clicked' => _("Most Clicked")
)
),
'rows' => array(
'name' => _("Display Rows"),
'type' => 'enum',
'default' => '10',
'values' => array(
'10' => _("10 rows"),
'15' => _("15 rows"),
'25' => _("25 rows")
)
),
'template' => array(
'name' => _("Template"),
'type' => 'enum',
'default' => '1line',
'values' => array(
'standard' => _("3 Line"),
'2line' => _("2 Line"),
'1line' => _("1 Line")
)
)
);
}
/**
*/
protected function _title()
{
global $registry;
return Horde::url($registry->getInitialPage(), true)->link() . _("Bookmarks") . '';
}
/**
*/
protected function _content()
{
$template = TREAN_TEMPLATES . '/block/' . $this->_params['template'] . '.inc';
$sortby = 'title';
$sortdir = 0;
switch ($this->_params['bookmarks']) {
case 'most_clicked':
$sortby = 'clicks';
$sortdir = 1;
break;
}
$html = '';
$bookmarks = $GLOBALS['trean_gateway']->listBookmarks($sortby, $sortdir, 0, $this->_params['rows']);
foreach ($bookmarks as $bookmark) {
ob_start();
require $template;
$html .= '' . ob_get_clean() . '
';
}
if (!$bookmarks) {
return '' . _("No bookmarks to display") . '
';
}
return $html;
}
}
trean-1.1.4/lib/Block/Mostclicked.php 0000664 0001750 0001750 00000004070 12654212671 015513 0 ustar jan jan
*/
class Trean_Block_Mostclicked extends Horde_Core_Block
{
/**
*/
public function __construct($app, $params = array())
{
parent::__construct($app, $params);
$this->_name = _("Most-clicked Bookmarks");
}
/**
*/
protected function _params()
{
return array(
'rows' => array(
'name' => _("Number of bookmarks to show"),
'type' => 'enum',
'default' => '10',
'values' => array(
'10' => _("10 rows"),
'15' => _("15 rows"),
'25' => _("25 rows")
)
),
'template' => array(
'name' => _("Template"),
'type' => 'enum',
'default' => '1line',
'values' => array(
'standard' => _("3 Line"),
'2line' => _("2 Line"),
'1line' => _("1 Line")
)
)
);
}
/**
*/
protected function _title()
{
return Horde::url($GLOBALS['registry']->getInitialPage(), true)->link() . $this->getName() . '';
}
/**
*/
protected function _content()
{
$template = TREAN_TEMPLATES . '/block/' . $this->_params['template'] . '.inc';
$html = '';
$bookmarks = $GLOBALS['trean_gateway']->listBookmarks('clicks', 1, 0, $this->_params['rows']);
foreach ($bookmarks as $bookmark) {
ob_start();
require $template;
$html .= '' . ob_get_clean() . '
';
}
if (!$bookmarks) {
return '' . _("No bookmarks to display") . '
';
}
return $html;
}
}
trean-1.1.4/lib/Data/Json.php 0000664 0001750 0001750 00000011026 12654212671 014001 0 ustar jan jan
* @package Trean
*/
class Trean_Data_Json extends Horde_Data_Base
{
protected $_extension = 'json';
protected $_contentType = 'text/json';
protected $_tagMap = array();
protected $_parentMap = array();
public function importData($contents, $header = false)
{
$data = array();
$json = Horde_Serialize::unserialize($contents, Horde_Serialize::JSON);
return $this->_parseJson($json->children, null);
}
protected function _parseFolders($data)
{
// Need a first pass to grab all the folders
foreach ($data as $child) {
if ($child->type == 'text/x-moz-place-container') {
if (empty($child->root)) {
$this->_tagMap[$child->id] = $child->title;
$this->_parentMap[$child->id] = $child->parent;
}
if (!empty($child->children)) {
$this->_parseFolders($child->children);
}
}
}
}
protected function _parseJson($data, $container)
{
// Need a first pass to grab all the folders
$this->_parseFolders($data);
return $this->_parseBookmarks($data);
}
protected function _parseBookmarks($data, $container = null)
{
$rows = array();
foreach ($data as $child) {
if ($child->type == 'text/x-moz-place-container') {
$rows = array_merge($this->_parseBookmarks($child->children, $child), $rows);
}
if ($child->type == 'text/x-moz-place') {
$desc = '';
if (!empty($child->annos)) {
foreach ($child->annos as $property) {
switch ($property->name) {
case 'Places/SmartBookmark':
// Ignore "SmartBookmarks"
continue 3;
case 'bookmarkProperties/description':
$desc = $property->value;
break 2;
}
}
}
$tags = !empty($child->tags) ? explode(',', $child->tags) : array();
$current_parent = $container->parent;
while (!empty($current_parent)) {
if (!empty($this->_tagMap[$current_parent])) {
$tags[] = $this->_tagMap[$current_parent];
}
$current_parent = !empty($this->_parentMap[$current_parent])
? $this->_parentMap[$current_parent]
: false;
}
if (!empty($container) && empty($container->root)) {
$tags[] = $container->title;
}
$rows[] = array(
'bookmark_url' => $child->uri,
'bookmark_title' => $child->title,
'bookmark_description' => $desc,
'bookmark_tags' => $tags,
'bookmark_dt' => !empty($child->dateAdded) ? new Horde_Date(substr($child->dateAdded, 0, 10)) : false
);
}
}
return $rows;
}
/**
* Takes all necessary actions for the given import step, parameters and
* form values and returns the next necessary step.
*
* @param integer $action The current step. One of the IMPORT_* constants.
* @param array $param An associative array containing needed
* parameters for the current step.
*
* @return mixed Either the next step as an integer constant or imported
* data set after the final step.
* @throws Horde_Data_Exception
*/
public function nextStep($action, $param = array())
{
switch ($action) {
case Horde_Data::IMPORT_FILE:
parent::nextStep($action, $param);
return $this->importFile($_FILES['import_file']['tmp_name']);
}
}
/**
* Stub to return exported data.
*/
public function exportData($data, $method = 'REQUEST')
{
// TODO
}
/**
* Stub to export data to a file.
*/
public function exportFile($filename, $data)
{
// TODO
}
}
trean-1.1.4/lib/Factory/TagBrowser.php 0000664 0001750 0001750 00000001773 12654212671 015715 0 ustar jan jan
* @package Kronolith
*/
class Trean_Factory_TagBrowser
{
/*
* The injector.
*
* @var Horde_Injector
*/
protected $_injector;
/**
* The tag browser
*
* @var Trean_TagBrowser
*/
protected $_browser;
/**
* Constructor.
*
* @param Horde_Injector $injector The injector to use.
*/
public function __construct(Horde_Injector $injector)
{
$this->_injector = $injector;
}
/**
* Return a Trean_TagBrowser
*
* @return Trean_TagBrowser
*/
public function create()
{
if (empty($_browser)) {
$this->_browser = new Trean_TagBrowser($this->_injector->getInstance('Trean_Tagger'));
}
return $this->_browser;
}
}
trean-1.1.4/lib/Queue/Task/Crawl.php 0000664 0001750 0001750 00000007131 12654212671 015257 0 ustar jan jan _url = $url;
$this->_userTitle = $userTitle;
$this->_userDesc = $userDesc;
$this->_bookmarkId = $bookmarkId;
$this->_userId = $userId;
}
/**
*/
public function run()
{
$injector = $GLOBALS['injector'];
// Get Horde_Http_Client
$client = $injector->getInstance('Horde_Http_Client');
// Fetch full text of $url
try {
$page = $client->get($this->_url);
$body = $page->getBody();
} catch (Horde_Http_Exception $e) {
Horde::log($e, 'ERR');
return;
}
$gateway = $injector->getInstance('Trean_Bookmarks');
$bookmark = $gateway->getBookmark($this->_bookmarkId);
$changed = false;
// update URL if we were redirected
if ($page->uri && ($page->uri != $this->_url)) {
$bookmark->url = $page->uri;
$this->_url = $page->uri;
$changed = true;
}
// update bookmark_http_status
if ($bookmark->http_status != $page->code) {
$bookmark->http_status = $page->code;
$changed = true;
}
// submit text to ElasticSearch, under $userId's index
if ($body && $page->code == 200) {
try {
$indexer = $injector->getInstance('Content_Indexer');
$indexer->index('horde-user-' . $this->_userId, 'trean-bookmark', $this->_bookmarkId, json_encode(array(
'title' => $this->_userTitle,
'description' => $this->_userDesc,
'url' => $this->_url,
'headers' => $page->headers,
'body' => $body,
)));
} catch (Exception $e) {
Horde::log($e, 'INFO');
}
}
if ($changed) {
$bookmark->save(false);
}
// @TODO: crawl resources from the page to make a fully local version
// (http://bugs.horde.org/ticket/10753)
// Favicon
if ($body) {
if ($type = $page->getHeader('Content-Type') &&
preg_match('/.*;\s*charset="?([^" ]*)/', $type, $match)) {
$charset = $match[1];
} else {
$charset = null;
}
try {
$queue = $injector->getInstance('Horde_Queue_Storage');
$queue->add(new Trean_Queue_Task_Favicon(
$this->_url,
$this->_bookmarkId,
$this->_userId,
$body,
$charset
));
} catch (Exception $e) {
Horde::log($e, 'INFO');
}
}
}
}
trean-1.1.4/lib/Queue/Task/Favicon.php 0000664 0001750 0001750 00000012561 12654212671 015577 0 ustar jan jan _url = $url;
$this->_bookmarkId = $bookmarkId;
$this->_userId = $userId;
$this->_body = $body;
$this->_charset = $charset;
}
/**
*/
public function run()
{
$injector = $GLOBALS['injector'];
$client = $injector->getInstance('Horde_Http_Client');
if (!$this->_body) {
// Fetch full text of $url
try {
$page = $client->get($this->_url);
$this->_body = $page->getBody();
if ($type = $page->getHeader('Content-Type') &&
preg_match('/.*;\s*charset="?([^" ]*)/', $type, $match)) {
$this->_charset = $match[1];
}
} catch (Horde_Http_Exception $e) {
}
}
$url = parse_url($this->_url);
if ($favicon = $this->_findByRel($client, $url, $this->_body, $this->_charset)) {
$this->_storeFavicon($favicon);
} elseif ($favicon = $this->_findByRoot($client, $url)) {
$this->_storeFavicon($favicon);
} elseif ($favicon = $this->_findByPath($client, $url)) {
$this->_storeFavicon($favicon);
}
}
/**
* @param Horde_Http_Response_Base $response HTTP response; body of this is the favicon
*/
protected function _storeFavicon(Horde_Http_Response_Base $response)
{
global $injector;
$gateway = $injector->getInstance('Trean_Bookmarks');
$bookmark = $gateway->getBookmark($this->_bookmarkId);
if ($bookmark) {
$bookmark->favicon_url = $response->uri;
$bookmark->save(false);
}
// Initialize VFS
$vfs = $GLOBALS['injector']
->getInstance('Horde_Core_Factory_Vfs')
->create();
$vfs->writeData('.horde/trean/favicons/',
md5($bookmark->favicon_url),
$response->getBody(),
true);
}
protected function _findByRel($client, $url, $body, $charset)
{
try {
$dom = new Horde_Domhtml($body, $charset);
foreach ($dom as $node) {
if ($node instanceof DOMElement &&
Horde_String::lower($node->tagName) == 'link' &&
($rel = Horde_String::lower($node->getAttribute('rel'))) &&
($rel == 'shortcut icon' || $rel == 'icon')) {
$favicon = $node->getAttribute('href');
// Make sure $favicon is a full URL.
$favicon_url = parse_url($favicon);
if (empty($favicon_url['scheme'])) {
if (substr($favicon, 0, 1) == '/') {
$favicon = $url['scheme'] . '://' . $url['host'] . $favicon;
} else {
$path = pathinfo($url['path']);
$favicon = $url['scheme'] . '://' . $url['host'] . $path['dirname'] . '/' . $favicon;
}
}
try {
$response = $client->get($favicon);
if ($this->_isValidFavicon($response)) {
return $response;
}
} catch (Horde_Http_Exception $e) {
}
}
}
} catch (Exception $e) {
}
}
protected function _findByRoot($client, $url)
{
try {
$response = $client->get($url['scheme'] . '://' . $url['host'] . '/favicon.ico');
if ($this->_isValidFavicon($response)) {
return $response;
}
} catch (Horde_Http_Exception $e) {
}
}
protected function _findByPath($client, $url)
{
if (isset($url['path'])) {
$path = pathinfo($url['path']);
if (strlen($path['dirname'])) {
try {
$response = $client->get($url['scheme'] . '://' . $url['host'] . $path['dirname'] . '/favicon.ico');
if ($this->_isValidFavicon($response)) {
return $response;
}
} catch (Horde_Http_Exception $e) {
}
}
}
}
protected function _isValidFavicon($response)
{
return ($response->code == 200)
&& (substr($response->getHeader('content-type'), 0, 5) == 'image')
&& (strlen($response->getBody()) > 0);
}
}
trean-1.1.4/lib/View/BookmarkList.php 0000664 0001750 0001750 00000014327 12654212671 015541 0 ustar jan jan
* @package Trean
*/
class Trean_View_BookmarkList
{
/**
* Tag Browser
*
* @var Trean_TagBrowser
*/
protected $_browser;
/**
* The loaded bookmarks.
*
* @var array
*/
protected $_bookmarks;
/**
* Current page
*
* @var int
*/
protected $_page = 0;
/**
* Bookmarks to display per page
*
* @var int
*/
protected $_perPage = 999;
/**
* Flag to indicate we have an empty search.
*
* @var boolean
*/
protected $_noSearch = false;
/**
* Flag to indicate whether or not to show the tag browser
* @var boolean
*/
protected $_showTagBrowser = true;
/**
* Const'r
*
*/
public function __construct($bookmarks = null, $browser = null)
{
$this->_bookmarks = $bookmarks;
if ($browser) {
$this->_browser = $browser;
} else {
$this->_browser = $GLOBALS['injector']->getInstance('Trean_TagBrowser');
}
$action = Horde_Util::getFormData('actionID', '');
switch ($action) {
case 'remove':
$tag = Horde_Util::getFormData('tag');
if (isset($tag)) {
$this->_browser->removeTag($tag);
$this->_browser->save();
}
break;
case 'add':
default:
// Add new tag to the stack, save to session.
$tag = Horde_Util::getFormData('tag');
if (isset($tag)) {
$this->_browser->addTag($tag);
$this->_browser->save();
}
}
// Check for empty tag search.. then do what?
$this->_noSearch = $this->_browser->tagCount() < 1;
}
/**
* Toggle showing of the tag browser
*/
public function showTagBrowser($showTagBrowser)
{
$this->_showTagBrowser = $showTagBrowser;
}
/**
* Returns whether bookmarks currently exist.
*
* @return boolean True if there exist any bookmarks in the backend.
*/
public function hasBookmarks()
{
$this->_getBookmarks();
return (bool)count($this->_bookmarks) ||
(bool)$this->_browser->tagCount();
}
/**
* Renders the view.
*/
public function render($title = null)
{
if (is_null($title)) {
$title = _("Bookmarks");
}
$this->_getBookmarks();
$browser = '';
if ($this->_showTagBrowser) {
$browser = '
' . $this->_getRelatedTags() . $this->_getTagTrail();
}
return '' . $browser . $this->_getBookmarkList();
}
/**
* Loads the bookmarks from the backend.
*/
protected function _getBookmarks()
{
if (!is_null($this->_bookmarks)) {
return;
}
// @TODO: paging
if ($this->_noSearch) {
$this->_bookmarks = $GLOBALS['trean_gateway']
->listBookmarks(
$GLOBALS['prefs']->getValue('sortby'),
$GLOBALS['prefs']->getValue('sortdir'),
$this->_page,
$this->_perPage);
} else {
$this->_bookmarks = $this->_browser->getSlice($this->_page, $this->_perPage);
}
}
/**
* Returns the HTML to display a bookmark list.
*
* @param array $bookmarks A list of bookmarks.
*
* @return string Bookmark list HTML.
*/
protected function _getBookmarkList()
{
$GLOBALS['page_output']->addScriptFile('tables.js', 'horde');
$view = $GLOBALS['injector']->createInstance('Horde_View');
$view->bookmarks = $this->_bookmarks;
$view->target = $GLOBALS['prefs']->getValue('show_in_new_window') ? '_blank' : '';
$view->redirectUrl = Horde::url('redirect.php');
$view->sortby = $GLOBALS['prefs']->getValue('sortby');
$view->sortdir = $GLOBALS['prefs']->getValue('sortdir');
$view->sortdirclass = $view->sortdir ? 'sortup' : 'sortdown';
return $view->render('list');
}
/**
* Get HTML to display the related tags links.
*
* @return string
*/
protected function _getRelatedTags()
{
$uids = array();
foreach ($this->_bookmarks as $bookmark) {
$uids[] = (string)$bookmark->id;
}
$rtags = $this->_browser->getRelatedTags($uids);
if (count($rtags)) {
$html = '';
}
return '';
}
/**
* Get HTML to represent the currently selected tags.
*
* @return string
*/
protected function _getTagTrail()
{
if ($this->_browser->tagCount() >= 1) {
$html = '';
}
return '';
}
/**
* Get HTML for a link to remove a tag from the current search.
*
* @param string $tag The tag we want the link for.
*
* @return string
*/
protected function _linkRemoveTag($tag)
{
return Horde::url('browse.php')
->add(array('actionID' => 'remove', 'tag' => $tag));
}
}
trean-1.1.4/lib/.htaccess 0000664 0001750 0001750 00000000174 12654212671 013306 0 ustar jan jan
Require all denied
Deny from all
trean-1.1.4/lib/Api.php 0000664 0001750 0001750 00000014501 12654212671 012731 0 ustar jan jan
*/
class Trean_Api extends Horde_Registry_Api
{
/**
* Delete a given bookmark.
*
* @param integer $bookmarkId The ID of the bookmark to delete
*/
public function deleteBookmark($bookmarkId)
{
$bookmark = $GLOBALS['trean_gateway']->getBookmark($bookmarkId);
$GLOBALS['trean_gateway']->removeBookmark($bookmark);
}
/**
* Delete multiple bookmarks.
*
* @param array $bookmarkIds The IDs of the bookmarks to delete
*/
public function deleteBookmarks($bookmarkIds)
{
foreach ($bookmarkIds as $bookmarkId) {
$this->deleteBookmark($bookmarkId);
}
}
/**
* Retrieve the list of used tag_names, tag_ids and the total number
* of resources that are linked to that tag.
*
* @param array $tags An optional array of tag_ids. If omitted, all tags
* will be included.
* @param string $user Restrict result to those tagged by $user.
*
* @return array An array containing tag_name, and total
*/
public function listTagInfo($tags = null, $user = null)
{
return $GLOBALS['injector']
->getInstance('Trean_Tagger')->getTagInfo($tags, 500, null, $user);
}
/**
* SearchTags API:
* Returns an application-agnostic array (useful for when doing a tag search
* across multiple applications)
*
* The 'raw' results array can be returned instead by setting $raw = true.
*
* @param array $names An array of tag_names to search for.
* @param integer $max The maximum number of resources to return.
* @param integer $from The number of the resource to start with.
* @param string $resource_type The resource type [bookmark, '']
* @param string $user Restrict results to resources owned by $user.
* @param boolean $raw Return the raw data?
*
* @return array An array of results:
*
* 'title' - The title for this resource.
* 'desc' - A terse description of this resource.
* 'view_url' - The URL to view this resource.
* 'app' - The Horde application this resource belongs to.
*
*/
public function searchTags($names, $max = 10, $from = 0,
$resource_type = '', $user = null, $raw = false)
{
// TODO: $max, $from, $resource_type not honored
$results = $GLOBALS['injector']
->getInstance('Trean_Tagger')
->search(
$names,
array('type' => 'bookmark', 'user' => $user));
// Check for error or if we requested the raw data array.
if ($raw) {
return $results;
}
$return = array();
$redirectUrl = Horde::url('redirect.php');
foreach ($results as $bookmark_id) {
try {
$bookmark = $GLOBALS['trean_gateway']->getBookmark($bookmark_id);
$return[] = array(
'title' => $bookmark->title,
'desc' => empty($bookmark->description) ? $bookmark->title : $bookmark->description,
'view_url' => $redirectUrl->add('b', $bookmark->id),
'app' => 'trean',
'icon' => $bookmark->favicon_url
);
} catch (Exception $e) {
}
}
return $return;
}
/**
* Returns a URL that can be used in other applications to add the currently
* displayed page as a bookmark. If javascript and DOM is available, an overlay
* is used, if javascript and no DOM, then a pop-up is used and if no javascript
* is available a URL to Trean's add.php page is returned.
*
* @param array $params A hash of 'url' and 'title' properties of the requested
* bookmark.
* @return string The URL suitable for use in a tag.
*/
public function getAddUrl($params = array())
{
$GLOBALS['no_compress'] = true;
$browser = $GLOBALS['injector']->getInstance('Horde_Browser');
if ($browser->hasFeature('javascript')) {
if ($browser->hasFeature('dom')) {
$addurl = Horde::url('add.php', true, -1)->add('iframe', 1);
$url = "javascript:(function(){o=document.createElement('div');o.id='overlay';o.style.background='#000';o.style.position='absolute';o.style.top=0;o.style.left=0;o.style.width='100%';o.style.height='100%';o.style.zIndex=5000;o.style.opacity=.8;document.body.appendChild(o);i=document.createElement('iframe');i.id='frame';i.style.zIndex=5001;i.style.border='thin solid #000';i.src='$addurl'+'&title=' + encodeURIComponent(document.title) + '&url=' + encodeURIComponent(location.href);i.style.position='absolute';i.style.width='350px';i.style.height='150px';i.style.left='100px';i.style.top='100px';document.body.appendChild(i);l=document.createElement('a');l.style.position='absolute';l.style.background='#ccc';l.style.color='#000';l.style.border='thin solid #000';l.style.display='block';l.style.top='250px';l.style.left='100px';l.style.zIndex=5001;l.style.padding='5px';l.appendChild(document.createTextNode('" . _("Close") . "'));l.onclick=function(){var o=document.getElementById('overlay');o.parentNode.removeChild(o);var i=document.getElementById('frame');i.parentNode.removeChild(i);this.parentNode.removeChild(this);};document.body.appendChild(l);})()";
} else {
$addurl = Horde::url('add.php', true, -1)->add('popup', 1);
$url = "javascript:d = new Date(); w = window.open('$addurl' + '&title=' + encodeURIComponent(document.title) + '&url=' + encodeURIComponent(location.href) + '&d=' + d.getTime(), d.getTime(), 'height=200,width=400'); w.focus();";
}
} else {
// Fallback to a regular URL
$url = Horde::url('add.php', true)->add($params);
}
return $url;
}
}
trean-1.1.4/lib/Application.php 0000664 0001750 0001750 00000007546 12654212671 014476 0 ustar jan jan
*/
/* Determine the base directories. */
if (!defined('TREAN_BASE')) {
define('TREAN_BASE', realpath(__DIR__ . '/..'));
}
if (!defined('HORDE_BASE')) {
/* If Horde does not live directly under the app directory, the HORDE_BASE
* constant should be defined in config/horde.local.php. */
if (file_exists(TREAN_BASE . '/config/horde.local.php')) {
include TREAN_BASE . '/config/horde.local.php';
} else {
define('HORDE_BASE', realpath(TREAN_BASE . '/..'));
}
}
/* Load the Horde Framework core (needed to autoload
* Horde_Registry_Application::). */
require_once HORDE_BASE . '/lib/core.php';
class Trean_Application extends Horde_Registry_Application
{
/**
*/
public $version = 'H5 (1.1.4)';
/**
* Global variables defined:
* - $trean_db: Horde_Db object
* - $trean_gateway: Trean_Bookmarks object
*/
protected function _init()
{
/* For now, autoloading the Content_* classes depend on there being a
* registry entry for the 'content' application that contains at least
* the fileroot entry. */
$GLOBALS['injector']->getInstance('Horde_Autoloader')
->addClassPathMapper(new Horde_Autoloader_ClassPathMapper_Prefix(
'/^Content_/',
$GLOBALS['registry']->get('fileroot', 'content') . '/lib/'
));
if (!class_exists('Content_Tagger')) {
throw new Horde_Exception('The Content_Tagger class could not be found. Make sure the Content application is installed.');
}
$GLOBALS['injector']->bindFactory('Trean_TagBrowser', 'Trean_Factory_TagBrowser', 'create');
// Set the timezone variable.
$GLOBALS['registry']->setTimeZone();
// Create db and gateway instances.
$GLOBALS['trean_db'] = $GLOBALS['injector']
->getInstance('Horde_Core_Factory_Db')
->create('trean', 'storage');
$GLOBALS['trean_gateway'] = $GLOBALS['injector']
->getInstance('Trean_Bookmarks');
}
/**
*/
public function perms()
{
return array(
'max_bookmarks' => array(
'title' => _("Maximum Number of Bookmarks"),
'type' => 'int'
),
);
}
/**
*/
public function menu($menu)
{
$menu->add(Horde::url('browse.php'), _("_Browse"), 'trean-browse', null, null, null, basename($_SERVER['PHP_SELF']) == 'index.php' ? 'current' : null);
$menu->add(Horde::url('data.php'), _("_Import"), 'horde-data');
}
/**
* Add additional items to the sidebar.
*
* @param Horde_View_Sidebar $sidebar The sidebar object.
*/
public function sidebar($sidebar)
{
$sidebar->addNewButton(_("_New Bookmark"), Horde::url('add.php'));
$sidebar->containers['tags'] = array(
'header' => array(
'id' => 'trean-toggle-tags',
'label' => _("Tags"),
'collapsed' => false,
),
);
$tagger = $GLOBALS['injector']->getInstance('Trean_Tagger');
$tags = $tagger->listBookmarkTags();
natcasesort($tags);
foreach ($tags as $tag) {;
$url = Horde::url('tag/' . urlencode($tag));
$row = array(
'url' => $url,
'cssClass' => 'trean-tag',
'label' => $tag,
);
$sidebar->addRow($row, 'tags');
}
}
/**
*/
public function cleanupData()
{
$GLOBALS['import_step'] = 1;
return Horde_Data::IMPORT_FILE;
}
}
trean-1.1.4/lib/Bookmark.php 0000664 0001750 0001750 00000010660 12654212671 013767 0 ustar jan jan
* @package Trean
*/
class Trean_Bookmark
{
public $id = null;
public $userId = null;
public $url = null;
public $title = '';
public $description = '';
public $clicks = 0;
public $http_status = null;
public $favicon_url;
public $dt;
public $tags = array();
/**
*/
public function __construct($bookmark = array())
{
if ($bookmark) {
$this->userId = $bookmark['user_id'];
$this->url = $bookmark['bookmark_url'];
$this->title = $bookmark['bookmark_title'];
$this->description = $bookmark['bookmark_description'];
if (!empty($bookmark['bookmark_id'])) {
$this->id = (int)$bookmark['bookmark_id'];
}
if (!empty($bookmark['bookmark_clicks'])) {
$this->clicks = (int)$bookmark['bookmark_clicks'];
}
if (!empty($bookmark['bookmark_http_status'])) {
$this->http_status = $bookmark['bookmark_http_status'];
}
if (!empty($bookmark['favicon_url'])) {
$this->favicon_url = $bookmark['favicon_url'];
}
if (!empty($bookmark['bookmark_dt'])) {
$this->dt = $bookmark['bookmark_dt'];
}
if (!empty($bookmark['bookmark_tags'])) {
$this->tags = $bookmark['bookmark_tags'];
}
}
}
/**
* Save bookmark.
*/
public function save($crawl = true)
{
if (!strlen($this->url)) {
throw new Trean_Exception('Incomplete bookmark');
}
$charset = $GLOBALS['trean_db']->getOption('charset');
$c_url = Horde_String::convertCharset($this->url, 'UTF-8', $charset);
$c_title = Horde_String::convertCharset($this->title, 'UTF-8', $charset);
$c_description = Horde_String::convertCharset($this->description, 'UTF-8', $charset);
$c_favicon_url = Horde_String::convertCharset($this->favicon_url, 'UTF-8', $charset);
if ($this->id) {
// Update an existing bookmark.
$GLOBALS['trean_db']->update('
UPDATE trean_bookmarks
SET user_id = ?,
bookmark_url = ?,
bookmark_title = ?,
bookmark_description = ?,
bookmark_clicks = ?,
bookmark_http_status = ?,
favicon_url = ?
WHERE bookmark_id = ?',
array(
$this->userId,
$c_url,
$c_title,
$c_description,
$this->clicks,
$this->http_status,
$c_favicon_url,
$this->id,
));
$GLOBALS['injector']->getInstance('Trean_Tagger')->replaceTags((string)$this->id, $this->tags, $GLOBALS['registry']->getAuth(), 'bookmark');
} else {
// Saving a new bookmark.
$bookmark_id = $GLOBALS['trean_db']->insert('
INSERT INTO trean_bookmarks (
user_id,
bookmark_url,
bookmark_title,
bookmark_description,
bookmark_clicks,
bookmark_http_status,
favicon_url,
bookmark_dt
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
array(
$this->userId,
$c_url,
$c_title,
$c_description,
$this->clicks,
$this->http_status,
$c_favicon_url,
$this->dt,
));
$this->id = (int)$bookmark_id;
$GLOBALS['injector']->getInstance('Trean_Tagger')->tag((string)$this->id, $this->tags, $GLOBALS['registry']->getAuth(), 'bookmark');
}
if ($crawl) {
try {
$queue = $GLOBALS['injector']->getInstance('Horde_Queue_Storage');
$queue->add(new Trean_Queue_Task_Crawl(
$this->url,
$this->title,
$this->description,
$this->id,
$this->userId
));
} catch (Exception $e) {
Horde::log($e, 'INFO');
}
}
return $this->id;
}
}
trean-1.1.4/lib/Bookmarks.php 0000664 0001750 0001750 00000020600 12654212671 014145 0 ustar jan jan
* @author Chuck Hagenbuch
* @author Michael J Rubinsky
* @license http://www.horde.org/licenses/bsdl.php
* @package Trean
*/
/**
* Trean_Bookmarks:: Handles basic management of bookmark storage.
*
* @author Ben Chavet
* @author Chuck Hagenbuch
* @author Michael J Rubinsky
* @license http://www.horde.org/licenses/bsdl.php
* @package Trean
*/
class Trean_Bookmarks
{
/**
* @var Content_Users_Manager
*/
protected $_userManager;
/**
* @var integer
*/
protected $_userId;
/**
* Constructor.
*
* @param Content_Users_Manager A user manager object.
*/
public function __construct(Content_Users_Manager $userManager)
{
$this->_userManager = $userManager;
try {
$this->_userId = current($this->_userManager->ensureUsers($GLOBALS['registry']->getAuth()));
} catch (Content_Exception $e) {
throw new Trean_Exception($e);
}
}
/**
* Create a new bookmark for the current user.
*
* @param array $properties The bookmark property array.
* @param boolean $crawl If true (default) attempt to crawl the URL.
*
* @return Trean_Bookmark
*/
public function newBookmark(array $properties, $crawl = true)
{
$properties['user_id'] = $this->_userId;
if (empty($properties['bookmark_dt'])) {
$properties['bookmark_dt'] = new Horde_Date(time());
}
$bookmark = new Trean_Bookmark($properties);
$bookmark->save($crawl);
return $bookmark;
}
/**
* List bookmarks, sorted and paged as specified.
*
* @param string $sortyby Field to sort by.
* @param integer $sortdir Direction of sort.
* @param integer $from Starting bookmark.
* @param integer $to Ending bookmark.
*
* @return array An array of Trean_Bookmark objects.
*/
public function listBookmarks($sortby = 'title', $sortdir = 0, $from = 0, $count = 0)
{
$values = array($this->_userId);
$sql = 'SELECT bookmark_id, user_id, bookmark_url, bookmark_title, bookmark_description, bookmark_clicks, bookmark_http_status, favicon_url, bookmark_dt
FROM trean_bookmarks
WHERE user_id = ?
ORDER BY bookmark_' . $sortby . ($sortdir ? ' DESC' : '');
$sql = $GLOBALS['trean_db']->addLimitOffset($sql, array('limit' => $count, 'offset' => $from));
return $this->_resultSet($GLOBALS['trean_db']->selectAll($sql, $values));
}
/**
* Search bookmarks.
*
* @param string $q The search text.
*
* @return array An array of Trean_Bookmark objects that match the search.
* @throws Trean_Exception
*/
public function searchBookmarks($q)
{
$indexer = $GLOBALS['injector']->getInstance('Content_Indexer');
try {
$search = $indexer->search('horde-user-' . $this->_userId, 'trean-bookmark', $q);
} catch (Content_Exception $e) {
throw new Trean_Exception($e);
}
if (!$search->hits->total) {
return array();
}
$bookmarkIds = array();
foreach ($search->hits->hits as $bookmarkHit) {
$bookmarkIds[] = (int)$bookmarkHit->_id;
}
$sql = 'SELECT bookmark_id, user_id, bookmark_url, bookmark_title, bookmark_description, bookmark_clicks, bookmark_http_status, favicon_url, bookmark_dt
FROM trean_bookmarks
WHERE user_id = ? AND bookmark_id IN (' . implode(',', $bookmarkIds) . ')';
$values = array($this->_userId);
return $this->_resultSet($GLOBALS['trean_db']->selectAll($sql, $values));
}
/**
* Returns the number of bookmarks.
*
* @return integer The number of all bookmarks.
* @throws Trean_Exception
*/
public function countBookmarks()
{
$sql = 'SELECT COUNT(*) FROM trean_bookmarks WHERE user_id = ?';
try {
return $GLOBALS['trean_db']->selectValue($sql, array($this->_userId));
} catch (Horde_Db_Exception $e) {
throw new Trean_Exception($e);
}
}
/**
* Return counts on grouping bookmarks by a specific property.
*
* @param string $groupby The field to group on. (i.e., 'status').
*
* @return array A hash of results.
* @throws Trean_Exception
*/
public function groupBookmarks($groupby)
{
switch ($groupby) {
case 'status':
$sql = 'SELECT bookmark_http_status AS status, COUNT(*) AS count
FROM trean_bookmarks
GROUP BY bookmark_http_status';
break;
default:
return array();
}
try {
return $GLOBALS['trean_db']->selectAll($sql);
} catch (Horde_Db_Exception $e) {
throw new Trean_Exception($e);
}
}
/**
* Returns the bookmark corresponding to the given id.
*
* @param integer $id The ID of the bookmark to retrieve.
*
* @return Trean_Bookmark The bookmark object corresponding to the given name.
* @throws Horde_Exception_NotFound, Trean_Exception
*/
public function getBookmark($id)
{
try {
$bookmark = $GLOBALS['trean_db']->selectOne('
SELECT bookmark_id, user_id, bookmark_url, bookmark_title, bookmark_description, bookmark_clicks, bookmark_http_status, favicon_url, bookmark_dt
FROM trean_bookmarks
WHERE bookmark_id = ' . (int)$id);
} catch (Horde_Db_Exception $e) {
throw new Trean_Exception($e);
}
if (is_null($bookmark)) {
throw new Horde_Exception_NotFound();
}
$bookmark = $this->_resultSet(array($bookmark));
return array_pop($bookmark);
}
/**
* Removes a Trean_Bookmark from the backend.
*
* @param Trean_Bookmark $bookmark The bookmark to remove.
* @throws Horde_Exception_PermissionDenied, Trean_Exception
*/
public function removeBookmark(Trean_Bookmark $bookmark)
{
/* Check permissions. */
if ($bookmark->userId != $this->_userId) {
throw new Horde_Exception_PermissionDenied();
}
/* Untag */
$tagger = $GLOBALS['injector']->getInstance('Trean_Tagger');
$tagger->replaceTags((string)$bookmark->id, array(), $GLOBALS['registry']->getAuth(), 'bookmark');
$GLOBALS['injector']->getInstance('Content_Objects_Mapper')
->delete($bookmark->id, 'bookmark');
/* @TODO delete from content index? */
//$indexer->index('horde-user-' . $this->_userId, 'trean-bookmark', $this->_bookmarkId, json_encode(array(
/* Delete from SQL. */
try {
$GLOBALS['trean_db']->delete('DELETE FROM trean_bookmarks WHERE bookmark_id = ' . (int)$bookmark->id);
} catch (Horde_Db_Exception $e) {
throw new Trean_Exception($e);
}
return true;
}
/**
* Creates Trean_Bookmark objects for each row in a SQL result.
*
* @param array $bookmarks An array of query results.
*
* @return array An array of Trean_Bookmark objects.
*/
protected function _resultSet($bookmarks)
{
if (is_null($bookmarks)) {
return array();
}
$objects = array();
$tagger = $GLOBALS['injector']->getInstance('Trean_Tagger');
$charset = $GLOBALS['trean_db']->getOption('charset');
foreach ($bookmarks as $bookmark) {
$cvBookmarks = array();
foreach ($bookmark as $key => $value) {
if (!empty($value) && !is_numeric($value)) {
$cvBookmarks[$key] = Horde_String::convertCharset($value, $charset, 'UTF-8');
} else {
$cvBookmarks[$key] = $value;
}
}
$cvBookmarks['bookmark_tags'] = $tagger->getTags((string)$cvBookmarks['bookmark_id'], 'bookmark');
$objects[] = new Trean_Bookmark($cvBookmarks);
}
return $objects;
}
}
trean-1.1.4/lib/Exception.php 0000664 0001750 0001750 00000000070 12654212671 014152 0 ustar jan jan
* @category Horde
* @license http://www.horde.org/licenses/bsdl.php BSD
* @package Trean
*/
class Trean_TagBrowser extends Horde_Core_TagBrowser
{
protected $_app = 'trean';
/**
* Get breadcrumb style navigation html for choosen tags
*
* @return Return information useful for building a tag trail.
*/
public function getTagTrail()
{
}
/**
* Fetch the matching resources that should appear on the current page
*
* @return Array An array of Trean_Bookmark objects.
*/
public function getSlice($page = 0, $perpage = null)
{
global $injector;
// Refresh the search
$this->runSearch();
$totals = $this->count();
$start = $page * $perpage;
$results = array_slice($this->_results, $start, $perpage);
$bookmarks = array();
foreach ($results as $id) {
try {
$bookmarks[] = $injector
->getInstance('Trean_Bookmarks')
->getBookmark($id);
} catch (Horde_Exception_NotFound $e) {
Horde::log('Bookmark not found: ' . $id, 'ERR');
}
}
return $bookmarks;
}
/**
* Return a URL to add a new tag to the current search.
*
* @param string $tag The tag we want to add.
*
* @return string
*/
public function addTagLink($tag)
{
return Horde::url('browse.php')->add(array('tag' => $tag));
}
}
trean-1.1.4/lib/Tagger.php 0000664 0001750 0001750 00000003621 12654212671 013432 0 ustar jan jan
*
* @package Trean
*/
class Trean_Tagger extends Horde_Core_Tagger
{
protected $_app = 'trean';
protected $_types = array('bookmark');
/**
* Searches for resources that are tagged with all of the requested tags.
*
* @param array $tags Either a tag_id, tag_name or an array.
* @param array $filter Array of filter parameters.
* - user (array) - only include objects owned by
* these users.
*
* @return array An array of bookmark ids
* @throws Trean_Exception
*/
public function search($tags, $filter = array())
{
$args = array();
/* Add the tags to the search */
$args['tagId'] = $GLOBALS['injector']
->getInstance('Content_Tagger')
->getTagIds($tags);
$args['typeId'] = $this->_type_ids['bookmark'];
try {
$results = $GLOBALS['injector']
->getInstance('Content_Tagger')
->getObjects($args);
} catch (Content_Exception $e) {
throw new Trean_Exception($e);
}
$results = array_values($results);
return $results;
}
/**
* Returns tags on bookmarks belonging to the current user.
*
* @return A tag_id => tag_name hash
* @throws Trean_Exception
*/
public function listBookmarkTags()
{
try {
return $GLOBALS['injector']->getInstance('Content_Tagger')
->getTags(array(
'typeId' => $this->_type_ids['bookmark'],
'userId' => $GLOBALS['registry']->getAuth())
);
} catch (Content_Exception $e) {
throw new Trean_Exception($e);
}
}
}
trean-1.1.4/lib/Trean.php 0000664 0001750 0001750 00000004711 12654212671 013273 0 ustar jan jan
* @package Trean
*/
class Trean
{
/**
* Returns the specified permission for the current user.
*
* @param string $permission A permission, currently only 'max_folders'
* and 'max_bookmarks'.
*
* @return mixed The value of the specified permission.
*/
static function hasPermission($permission)
{
$perms = $GLOBALS['injector']->getInstance('Horde_Perms');
if (!$perms->exists('trean:' . $permission)) {
return true;
}
$allowed = $perms->getPermissions(
'trean:' . $permission, $GLOBALS['registry']->getAuth());
if (is_array($allowed)) {
switch ($permission) {
case 'max_folders':
case 'max_bookmarks':
$allowed = max($allowed);
break;
}
}
return $allowed;
}
/**
* Returns an apropriate icon for the given bookmark.
*
* @param Trean_Bookmark $bookmark The bookmark object.
*
* @return Horde_Url The URL for the image.
*/
static function getFavicon($bookmark)
{
if ($bookmark->favicon_url) {
return Horde::url('favicon.php')->add('bookmark_id', $bookmark->id);
} else {
// Default to the protocol icon.
$protocol = substr($bookmark->url, 0, strpos($bookmark->url, '://'));
return Horde_Themes::img('protocol/' . (empty($protocol) ? 'http' : $protocol) . '.png');
}
}
static public function addFeedLink()
{
$rss = Horde::url('rss.php', true, -1);
if ($label = Horde_Util::getFormData('label')) {
$rss->add('label', $label);
}
$GLOBALS['page_output']->addLinkTag(array(
'href' => $rss,
'title' => _("Bookmarks Feed")
));
}
static public function bookmarkletLink()
{
$view = $GLOBALS['injector']->createInstance('Horde_View');
$view->url = Horde::url('add.php', true, array('append_session' => -1))
->add('popup', 1);
$view->image = Horde::img('add.png');
return $view->render('bookmarklet');
}
}
trean-1.1.4/lib/Url.php 0000664 0001750 0001750 00000000626 12654212671 012765 0 ustar jan jan _url = new Horde_Url($url);
$this->_url->remove(array(
'utm_source',
'utm_medium',
'utm_term',
'utm_campaign',
'utm_content',
));
}
public function __toString()
{
return (string)$this->_url;
}
}
trean-1.1.4/locale/da/LC_MESSAGES/trean.mo 0000664 0001750 0001750 00000206451 12654212671 016026 0 ustar jan jan 9 0M $ 1M ) VM M &