streams/include/widgets.php

989 lines
24 KiB
PHP
Raw Normal View History

<?php
/**
* @file include/widgets.php
*
* @brief This file contains the widgets.
*/
require_once('include/dir_fns.php');
require_once('include/contact_widgets.php');
function widget_profile($args) {
$a = get_app();
2015-01-29 04:58:59 +00:00
$block = (((get_config('system', 'block_public')) && (! local_channel()) && (! remote_channel())) ? true : false);
return profile_sidebar($a->profile, $block, true);
}
// FIXME The problem with the next widget is that we don't have a search function for webpages that we can send the links to.
// Then we should also provide an option to search webpages and conversations.
function widget_tagcloud($args) {
$o = '';
//$tab = 0;
$a = get_app();
$uid = $a->profile_uid;
$count = ((x($args,'count')) ? intval($args['count']) : 24);
$flags = 0;
$type = TERM_CATEGORY;
// FIXME there exists no $authors variable
$r = tagadelic($uid, $count, $authors, $flags, ITEM_WEBPAGE, $type);
if($r) {
$o = '<div class="tagblock widget"><h3>' . t('Categories') . '</h3><div class="tags" align="center">';
foreach($r as $rr) {
$o .= '<span class="tag'.$rr[2].'">'.$rr[0].'</span> ' . "\r\n";
}
$o .= '</div></div>';
}
return $o;
}
function widget_collections($args) {
require_once('include/group.php');
2013-12-20 07:56:37 +00:00
$mode = ((array_key_exists('mode',$args)) ? $args['mode'] : 'conversation');
switch($mode) {
case 'conversation':
$every = argv(0);
$each = argv(0);
$edit = true;
$current = $_REQUEST['gid'];
$abook_id = 0;
$wmode = 0;
break;
case 'connections':
$every = 'connections';
$each = 'group';
$edit = true;
$current = $_REQUEST['gid'];
$abook_id = 0;
$wmode = 0;
2013-12-20 07:56:37 +00:00
case 'groups':
$every = 'connections';
$each = argv(0);
$edit = false;
$current = intval(argv(1));
$abook_id = 0;
$wmode = 1;
break;
case 'abook':
$every = 'connections';
$each = 'group';
$edit = false;
$current = 0;
$abook_id = get_app()->poi['abook_xchan'];
$wmode = 1;
break;
default:
return '';
break;
}
return group_side($every, $each, $edit, $current, $abook_id, $wmode);
}
function widget_appselect($arr) {
return replace_macros(get_markup_template('app_select.tpl'),array(
2014-05-22 03:54:09 +00:00
'$title' => t('Apps'),
'$system' => t('System'),
2015-01-29 04:56:04 +00:00
'$authed' => ((local_channel()) ? true : false),
2014-05-22 03:54:09 +00:00
'$personal' => t('Personal'),
'$new' => t('Create Personal App'),
'$edit' => t('Edit Personal App')
));
}
function widget_suggestions($arr) {
2015-01-29 04:56:04 +00:00
if((! local_channel()) || (! feature_enabled(local_channel(),'suggest')))
2013-12-11 11:01:28 +00:00
return '';
require_once('include/socgraph.php');
2015-01-29 04:56:04 +00:00
$r = suggestion_query(local_channel(),get_observer_hash(),0,20);
if(! $r) {
return;
}
$arr = array();
// Get two random entries from the top 20 returned.
// We'll grab the first one and the one immediately following.
// This will throw some entropy intot he situation so you won't
// be looking at the same two mug shots every time the widget runs
$index = ((count($r) > 2) ? mt_rand(0,count($r) - 2) : 0);
for($x = $index; $x <= ($index+1); $x ++) {
$rr = $r[$x];
if(! $rr['xchan_url'])
break;
$connlnk = z_root() . '/follow/?url=' . $rr['xchan_addr'];
$arr[] = array(
'url' => chanlink_url($rr['xchan_url']),
'profile' => $rr['xchan_url'],
'name' => $rr['xchan_name'],
'photo' => $rr['xchan_photo_m'],
'ignlnk' => z_root() . '/suggest?ignore=' . $rr['xchan_hash'],
'conntxt' => t('Connect'),
'connlnk' => $connlnk,
'ignore' => t('Ignore/Hide')
);
}
$o = replace_macros(get_markup_template('suggest_widget.tpl'),array(
'$title' => t('Suggestions'),
'$more' => t('See more...'),
'$entries' => $arr
));
return $o;
}
function widget_follow($args) {
2015-01-29 04:56:04 +00:00
if(! local_channel())
return '';
$a = get_app();
$uid =$a->channel['channel_id'];
PostgreSQL support initial commit There were 11 main types of changes: - UPDATE's and DELETE's sometimes had LIMIT 1 at the end of them. This is not only non-compliant but it would certainly not do what whoever wrote it thought it would. It is likely this mistake was just copied from Friendica. All of these instances, the LIMIT 1 was simply removed. - Bitwise operations (and even some non-zero int checks) erroneously rely on MySQL implicit integer-boolean conversion in the WHERE clauses. This is non-compliant (and bad programming practice to boot). Proper explicit boolean conversions were added. New queries should use proper conventions. - MySQL has a different operator for bitwise XOR than postgres. Rather than add yet another dba_ func, I converted them to "& ~" ("AND NOT") when turning off, and "|" ("OR") when turning on. There were no true toggles (XOR). New queries should refrain from using XOR when not necessary. - There are several fields which the schema has marked as NOT NULL, but the inserts don't specify them. The reason this works is because mysql totally ignores the constraint and adds an empty text default automatically. Again, non-compliant, obviously. In these cases a default of empty text was added. - Several statements rely on a non-standard MySQL feature (http://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html). These queries can all be rewritten to be standards compliant. Interestingly enough, the newly rewritten standards compliant queries run a zillion times faster, even on MySQL. - A couple of function/operator name translations were needed (RAND/RANDOM, GROUP_CONCAT/STRING_AGG, UTC_NOW, REGEXP/~, ^/#) -- assist functions added in the dba_ - INTERVALs: postgres requires quotes around the value, mysql requires that there are not quotes around the value -- assist functions added in the dba_ - NULL_DATE's -- Postgres does not allow the invalid date '0000-00-00 00:00:00' (there is no such thing as year 0 or month 0 or day 0). We use '0001-01-01 00:00:00' for postgres. Conversions are handled in Zot/item packets automagically by quoting all dates with dbescdate(). - char(##) specifications in the schema creates fields with blank spaces that aren't trimmed in the code. MySQL apparently treats char(##) as varchar(##), again, non-compliant. Since postgres works better with text fields anyway, this ball of bugs was simply side-stepped by using 'text' datatype for all text fields in the postgres schema. varchar was used in a couple of places where it actually seemed appropriate (size constraint), but without rigorously vetting that all of the PHP code actually validates data, new bugs might come out from under the rug. - postgres doesn't store nul bytes and a few other non-printables in text fields, even when quoted. bytea fields were used when storing binary data (photo.data, attach.data). A new dbescbin() function was added to handle this transparently. - postgres does not support LIMIT #,# syntax. All databases support LIMIT # OFFSET # syntax. Statements were updated to be standard. These changes require corresponding changes in the coding standards. Please review those before adding any code going forward. Still on my TODO list: - remove quotes from non-reserved identifiers and make reserved identifiers use dba func for quoting - Rewrite search queries for better results (both MySQL and Postgres)
2014-11-13 20:21:58 +00:00
$r = q("select count(*) as total from abook where abook_channel = %d and not (abook_flags & %d)>0 ",
intval($uid),
intval(ABOOK_FLAG_SELF)
);
if($r)
$total_channels = $r[0]['total'];
$limit = service_class_fetch($uid,'total_channels');
if($limit !== false) {
$abook_usage_message = sprintf( t("You have %1$.0f of %2$.0f allowed connections."), $total_channels, $limit);
}
else {
$abook_usage_message = '';
}
return replace_macros(get_markup_template('follow.tpl'),array(
'$connect' => t('Add New Connection'),
'$desc' => t('Enter the channel address'),
'$hint' => t('Example: bob@example.com, http://example.com/barbara'),
'$follow' => t('Connect'),
'$abook_usage_message' => $abook_usage_message
));
}
2013-12-09 23:27:46 +00:00
function widget_notes($arr) {
2015-01-29 04:56:04 +00:00
if(! local_channel())
2013-12-09 23:27:46 +00:00
return '';
2015-01-29 04:56:04 +00:00
if(! feature_enabled(local_channel(),'private_notes'))
2013-12-10 02:54:50 +00:00
return '';
2015-01-29 04:56:04 +00:00
$text = get_pconfig(local_channel(),'notes','text');
2013-12-09 23:27:46 +00:00
$o = replace_macros(get_markup_template('notes.tpl'), array(
'$banner' => t('Notes'),
'$text' => $text,
'$save' => t('Save'),
));
2013-12-09 23:27:46 +00:00
return $o;
}
2013-12-10 05:20:55 +00:00
function widget_savedsearch($arr) {
2015-01-29 04:56:04 +00:00
if((! local_channel()) || (! feature_enabled(local_channel(),'savedsearch')))
2013-12-10 05:20:55 +00:00
return '';
$a = get_app();
$search = ((x($_GET,'search')) ? $_GET['search'] : '');
2013-12-10 05:20:55 +00:00
if(x($_GET,'searchsave') && $search) {
$r = q("select * from `term` where `uid` = %d and `type` = %d and `term` = '%s' limit 1",
2015-01-29 04:56:04 +00:00
intval(local_channel()),
2013-12-10 05:20:55 +00:00
intval(TERM_SAVEDSEARCH),
dbesc($search)
);
if(! $r) {
q("insert into `term` ( `uid`,`type`,`term` ) values ( %d, %d, '%s') ",
2015-01-29 04:56:04 +00:00
intval(local_channel()),
2013-12-10 05:20:55 +00:00
intval(TERM_SAVEDSEARCH),
dbesc($search)
);
}
}
if(x($_GET,'searchremove') && $search) {
PostgreSQL support initial commit There were 11 main types of changes: - UPDATE's and DELETE's sometimes had LIMIT 1 at the end of them. This is not only non-compliant but it would certainly not do what whoever wrote it thought it would. It is likely this mistake was just copied from Friendica. All of these instances, the LIMIT 1 was simply removed. - Bitwise operations (and even some non-zero int checks) erroneously rely on MySQL implicit integer-boolean conversion in the WHERE clauses. This is non-compliant (and bad programming practice to boot). Proper explicit boolean conversions were added. New queries should use proper conventions. - MySQL has a different operator for bitwise XOR than postgres. Rather than add yet another dba_ func, I converted them to "& ~" ("AND NOT") when turning off, and "|" ("OR") when turning on. There were no true toggles (XOR). New queries should refrain from using XOR when not necessary. - There are several fields which the schema has marked as NOT NULL, but the inserts don't specify them. The reason this works is because mysql totally ignores the constraint and adds an empty text default automatically. Again, non-compliant, obviously. In these cases a default of empty text was added. - Several statements rely on a non-standard MySQL feature (http://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html). These queries can all be rewritten to be standards compliant. Interestingly enough, the newly rewritten standards compliant queries run a zillion times faster, even on MySQL. - A couple of function/operator name translations were needed (RAND/RANDOM, GROUP_CONCAT/STRING_AGG, UTC_NOW, REGEXP/~, ^/#) -- assist functions added in the dba_ - INTERVALs: postgres requires quotes around the value, mysql requires that there are not quotes around the value -- assist functions added in the dba_ - NULL_DATE's -- Postgres does not allow the invalid date '0000-00-00 00:00:00' (there is no such thing as year 0 or month 0 or day 0). We use '0001-01-01 00:00:00' for postgres. Conversions are handled in Zot/item packets automagically by quoting all dates with dbescdate(). - char(##) specifications in the schema creates fields with blank spaces that aren't trimmed in the code. MySQL apparently treats char(##) as varchar(##), again, non-compliant. Since postgres works better with text fields anyway, this ball of bugs was simply side-stepped by using 'text' datatype for all text fields in the postgres schema. varchar was used in a couple of places where it actually seemed appropriate (size constraint), but without rigorously vetting that all of the PHP code actually validates data, new bugs might come out from under the rug. - postgres doesn't store nul bytes and a few other non-printables in text fields, even when quoted. bytea fields were used when storing binary data (photo.data, attach.data). A new dbescbin() function was added to handle this transparently. - postgres does not support LIMIT #,# syntax. All databases support LIMIT # OFFSET # syntax. Statements were updated to be standard. These changes require corresponding changes in the coding standards. Please review those before adding any code going forward. Still on my TODO list: - remove quotes from non-reserved identifiers and make reserved identifiers use dba func for quoting - Rewrite search queries for better results (both MySQL and Postgres)
2014-11-13 20:21:58 +00:00
q("delete from `term` where `uid` = %d and `type` = %d and `term` = '%s'",
2015-01-29 04:56:04 +00:00
intval(local_channel()),
2013-12-10 05:20:55 +00:00
intval(TERM_SAVEDSEARCH),
dbesc($search)
);
$search = '';
}
$srchurl = $a->query_string;
$srchurl = rtrim(preg_replace('/searchsave\=[^\&].*?(\&|$)/is','',$srchurl),'&');
$hasq = ((strpos($srchurl,'?') !== false) ? true : false);
$srchurl = rtrim(preg_replace('/searchremove\=[^\&].*?(\&|$)/is','',$srchurl),'&');
$srchurl = rtrim(preg_replace('/search\=[^\&].*?(\&|$)/is','',$srchurl),'&');
2014-12-15 22:37:31 +00:00
$srchurl = rtrim(preg_replace('/submit\=[^\&].*?(\&|$)/is','',$srchurl),'&');
2013-12-11 04:36:11 +00:00
$srchurl = str_replace(array('?f=','&f='),array('',''),$srchurl);
2014-12-15 22:37:31 +00:00
2013-12-10 05:20:55 +00:00
$hasq = ((strpos($srchurl,'?') !== false) ? true : false);
$hasamp = ((strpos($srchurl,'&') !== false) ? true : false);
if(($hasamp) && (! $hasq))
$srchurl = substr($srchurl,0,strpos($srchurl,'&')) . '?f=&' . substr($srchurl,strpos($srchurl,'&')+1);
2014-12-15 22:37:31 +00:00
2013-12-10 05:20:55 +00:00
$o = '';
$r = q("select `tid`,`term` from `term` WHERE `uid` = %d and `type` = %d ",
2015-01-29 04:56:04 +00:00
intval(local_channel()),
2013-12-10 05:20:55 +00:00
intval(TERM_SAVEDSEARCH)
);
$saved = array();
if(count($r)) {
foreach($r as $rr) {
$saved[] = array(
'id' => $rr['tid'],
'term' => $rr['term'],
'dellink' => z_root() . '/' . $srchurl . (($hasq || $hasamp) ? '' : '?f=') . '&amp;searchremove=1&amp;search=' . urlencode($rr['term']),
'srchlink' => z_root() . '/' . $srchurl . (($hasq || $hasamp) ? '' : '?f=') . '&amp;search=' . urlencode($rr['term']),
2013-12-12 10:15:02 +00:00
'displayterm' => htmlspecialchars($rr['term'], ENT_COMPAT,'UTF-8'),
'encodedterm' => urlencode($rr['term']),
'delete' => t('Remove term'),
'selected' => ($search==$rr['term']),
2013-12-10 05:20:55 +00:00
);
}
}
2013-12-10 05:20:55 +00:00
$tpl = get_markup_template("saved_searches.tpl");
$o = replace_macros($tpl, array(
'$title' => t('Saved Searches'),
'$add' => t('add'),
'$searchbox' => searchbox($search, 'netsearch-box', $srchurl . (($hasq) ? '' : '?f='), true),
2013-12-10 05:20:55 +00:00
'$saved' => $saved,
));
2013-12-10 05:20:55 +00:00
return $o;
}
function widget_filer($arr) {
2015-01-29 04:56:04 +00:00
if(! local_channel())
return '';
$a = get_app();
$selected = ((x($_REQUEST,'file')) ? $_REQUEST['file'] : '');
$terms = array();
$r = q("select distinct(term) from term where uid = %d and type = %d order by term asc",
2015-01-29 04:56:04 +00:00
intval(local_channel()),
intval(TERM_FILE)
);
if(! $r)
return;
foreach($r as $rr)
$terms[] = array('name' => $rr['term'], 'selected' => (($selected == $rr['term']) ? 'selected' : ''));
return replace_macros(get_markup_template('fileas_widget.tpl'),array(
'$title' => t('Saved Folders'),
'$desc' => '',
'$sel_all' => (($selected == '') ? 'selected' : ''),
'$all' => t('Everything'),
'$terms' => $terms,
'$base' => z_root() . '/' . $a->cmd
));
}
function widget_archive($arr) {
$o = '';
$a = get_app();
if(! $a->profile_uid) {
return '';
}
$uid = $a->profile_uid;
if(! feature_enabled($uid,'archives'))
return '';
if(! perm_is_allowed($uid,get_observer_hash(),'view_stream'))
return '';
$wall = ((array_key_exists('wall', $arr)) ? intval($arr['wall']) : 0);
$style = ((array_key_exists('style', $arr)) ? $arr['style'] : 'select');
$showend = ((get_pconfig($uid,'system','archive_show_end_date')) ? true : false);
$mindate = get_pconfig($uid,'system','archive_mindate');
$visible_years = get_pconfig($uid,'system','archive_visible_years');
if(! $visible_years)
$visible_years = 5;
$url = z_root() . '/' . $a->cmd;
$ret = list_post_dates($uid,$wall,$mindate);
if(! count($ret))
return '';
$cutoff_year = intval(datetime_convert('',date_default_timezone_get(),'now','Y')) - $visible_years;
$cutoff = ((array_key_exists($cutoff_year,$ret))? true : false);
$o = replace_macros(get_markup_template('posted_date_widget.tpl'),array(
'$title' => t('Archives'),
'$size' => $visible_years,
'$cutoff_year' => $cutoff_year,
'$cutoff' => $cutoff,
'$url' => $url,
'$style' => $style,
'$showend' => $showend,
'$dates' => $ret
));
return $o;
}
2013-12-11 04:36:11 +00:00
function widget_fullprofile($arr) {
$a = get_app();
if(! $a->profile['profile_uid'])
return;
2015-01-29 04:58:59 +00:00
$block = (((get_config('system', 'block_public')) && (! local_channel()) && (! remote_channel())) ? true : false);
2013-12-11 04:36:11 +00:00
return profile_sidebar($a->profile, $block);
}
function widget_categories($arr) {
$a = get_app();
if($a->profile['profile_uid'] && (! perm_is_allowed($a->profile['profile_uid'],get_observer_hash(),'view_stream')))
return '';
2013-12-12 10:15:02 +00:00
$cat = ((x($_REQUEST,'cat')) ? htmlspecialchars($_REQUEST['cat'],ENT_COMPAT,'UTF-8') : '');
2013-12-11 04:36:11 +00:00
$srchurl = $a->query_string;
$srchurl = rtrim(preg_replace('/cat\=[^\&].*?(\&|$)/is','',$srchurl),'&');
$srchurl = str_replace(array('?f=','&f='),array('',''),$srchurl);
return categories_widget($srchurl, $cat);
2013-12-11 04:36:11 +00:00
}
function widget_tagcloud_wall($arr) {
$a = get_app();
2013-12-11 04:36:11 +00:00
if((! $a->profile['profile_uid']) || (! $a->profile['channel_hash']))
return '';
if(! perm_is_allowed($a->profile['profile_uid'], get_observer_hash(), 'view_stream'))
return '';
$limit = ((array_key_exists('limit', $arr)) ? intval($arr['limit']) : 50);
if(feature_enabled($a->profile['profile_uid'], 'tagadelic'))
2014-12-15 22:37:31 +00:00
return wtagblock($a->profile['profile_uid'], $limit, $a->profile['channel_hash'], ITEM_WALL);
2013-12-11 04:36:11 +00:00
return '';
2013-12-11 11:01:28 +00:00
}
2014-11-06 09:24:04 +00:00
function widget_catcloud_wall($arr) {
$a = get_app();
2014-11-06 09:24:04 +00:00
if((! $a->profile['profile_uid']) || (! $a->profile['channel_hash']))
return '';
if(! perm_is_allowed($a->profile['profile_uid'], get_observer_hash(), 'view_stream'))
2014-11-06 09:24:04 +00:00
return '';
$limit = ((array_key_exists('limit',$arr)) ? intval($arr['limit']) : 50);
return catblock($a->profile['profile_uid'], $limit, $a->profile['channel_hash'], ITEM_WALL);
2014-11-06 09:24:04 +00:00
}
function widget_affinity($arr) {
2015-01-29 04:56:04 +00:00
if(! local_channel())
return '';
2013-12-12 03:56:57 +00:00
$cmin = ((x($_REQUEST,'cmin')) ? intval($_REQUEST['cmin']) : 0);
$cmax = ((x($_REQUEST,'cmax')) ? intval($_REQUEST['cmax']) : 99);
2015-04-10 02:51:58 +00:00
2015-01-29 04:56:04 +00:00
if(feature_enabled(local_channel(),'affinity')) {
2015-04-10 02:51:58 +00:00
$labels = array(
t('Me'),
t('Family'),
t('Friends'),
t('Acquaintances'),
t('All')
);
call_hooks('affinity_labels',$labels);
$label_str = '';
if($labels) {
foreach($labels as $l) {
if($label_str) {
$label_str .= ", '|'";
$label_str .= ", '" . $l . "'";
}
else
$label_str .= "'" . $l . "'";
}
}
$tpl = get_markup_template('main_slider.tpl');
$x = replace_macros($tpl,array(
2015-01-05 17:30:12 +00:00
'$val' => $cmin . ',' . $cmax,
'$refresh' => t('Refresh'),
2015-04-10 02:51:58 +00:00
'$labels' => $label_str,
));
$arr = array('html' => $x);
call_hooks('main_slider',$arr);
return $arr['html'];
}
return '';
2013-12-14 21:26:40 +00:00
}
function widget_settings_menu($arr) {
2015-01-29 04:56:04 +00:00
if(! local_channel())
2013-12-14 21:26:40 +00:00
return;
$a = get_app();
$channel = $a->get_channel();
$abook_self_id = 0;
// Retrieve the 'self' address book entry for use in the auto-permissions link
2015-01-29 04:56:04 +00:00
$role = get_pconfig(local_channel(),'system','permissions_role');
PostgreSQL support initial commit There were 11 main types of changes: - UPDATE's and DELETE's sometimes had LIMIT 1 at the end of them. This is not only non-compliant but it would certainly not do what whoever wrote it thought it would. It is likely this mistake was just copied from Friendica. All of these instances, the LIMIT 1 was simply removed. - Bitwise operations (and even some non-zero int checks) erroneously rely on MySQL implicit integer-boolean conversion in the WHERE clauses. This is non-compliant (and bad programming practice to boot). Proper explicit boolean conversions were added. New queries should use proper conventions. - MySQL has a different operator for bitwise XOR than postgres. Rather than add yet another dba_ func, I converted them to "& ~" ("AND NOT") when turning off, and "|" ("OR") when turning on. There were no true toggles (XOR). New queries should refrain from using XOR when not necessary. - There are several fields which the schema has marked as NOT NULL, but the inserts don't specify them. The reason this works is because mysql totally ignores the constraint and adds an empty text default automatically. Again, non-compliant, obviously. In these cases a default of empty text was added. - Several statements rely on a non-standard MySQL feature (http://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html). These queries can all be rewritten to be standards compliant. Interestingly enough, the newly rewritten standards compliant queries run a zillion times faster, even on MySQL. - A couple of function/operator name translations were needed (RAND/RANDOM, GROUP_CONCAT/STRING_AGG, UTC_NOW, REGEXP/~, ^/#) -- assist functions added in the dba_ - INTERVALs: postgres requires quotes around the value, mysql requires that there are not quotes around the value -- assist functions added in the dba_ - NULL_DATE's -- Postgres does not allow the invalid date '0000-00-00 00:00:00' (there is no such thing as year 0 or month 0 or day 0). We use '0001-01-01 00:00:00' for postgres. Conversions are handled in Zot/item packets automagically by quoting all dates with dbescdate(). - char(##) specifications in the schema creates fields with blank spaces that aren't trimmed in the code. MySQL apparently treats char(##) as varchar(##), again, non-compliant. Since postgres works better with text fields anyway, this ball of bugs was simply side-stepped by using 'text' datatype for all text fields in the postgres schema. varchar was used in a couple of places where it actually seemed appropriate (size constraint), but without rigorously vetting that all of the PHP code actually validates data, new bugs might come out from under the rug. - postgres doesn't store nul bytes and a few other non-printables in text fields, even when quoted. bytea fields were used when storing binary data (photo.data, attach.data). A new dbescbin() function was added to handle this transparently. - postgres does not support LIMIT #,# syntax. All databases support LIMIT # OFFSET # syntax. Statements were updated to be standard. These changes require corresponding changes in the coding standards. Please review those before adding any code going forward. Still on my TODO list: - remove quotes from non-reserved identifiers and make reserved identifiers use dba func for quoting - Rewrite search queries for better results (both MySQL and Postgres)
2014-11-13 20:21:58 +00:00
$abk = q("select abook_id from abook where abook_channel = %d and ( abook_flags & %d )>0 limit 1",
2015-01-29 04:56:04 +00:00
intval(local_channel()),
2013-12-14 21:26:40 +00:00
intval(ABOOK_FLAG_SELF)
);
if($abk)
$abook_self_id = $abk[0]['abook_id'];
$tabs = array(
array(
'label' => t('Account settings'),
'url' => $a->get_baseurl(true).'/settings/account',
'selected' => ((argv(1) === 'account') ? 'active' : ''),
),
2013-12-14 21:26:40 +00:00
array(
'label' => t('Channel settings'),
'url' => $a->get_baseurl(true).'/settings/channel',
'selected' => ((argv(1) === 'channel') ? 'active' : ''),
),
2013-12-14 21:26:40 +00:00
array(
'label' => t('Additional features'),
'url' => $a->get_baseurl(true).'/settings/features',
'selected' => ((argv(1) === 'features') ? 'active' : ''),
),
array(
'label' => t('Feature/Addon settings'),
2013-12-14 21:26:40 +00:00
'url' => $a->get_baseurl(true).'/settings/featured',
'selected' => ((argv(1) === 'featured') ? 'active' : ''),
),
array(
'label' => t('Display settings'),
'url' => $a->get_baseurl(true).'/settings/display',
'selected' => ((argv(1) === 'display') ? 'active' : ''),
),
2013-12-14 21:26:40 +00:00
array(
'label' => t('Connected apps'),
'url' => $a->get_baseurl(true) . '/settings/oauth',
'selected' => ((argv(1) === 'oauth') ? 'active' : ''),
),
array(
'label' => t('Export channel'),
2014-12-15 19:32:28 +00:00
'url' => $a->get_baseurl(true) . '/uexport',
2013-12-14 21:26:40 +00:00
'selected' => ''
),
);
if($role === false || $role === 'custom') {
$tabs[] = array(
'label' => t('Connection Default Permissions'),
'url' => $a->get_baseurl(true) . '/connedit/' . $abook_self_id,
2013-12-14 21:26:40 +00:00
'selected' => ''
);
}
2013-12-14 21:26:40 +00:00
2015-01-29 04:56:04 +00:00
if(feature_enabled(local_channel(),'premium_channel')) {
2013-12-14 21:26:40 +00:00
$tabs[] = array(
'label' => t('Premium Channel Settings'),
'url' => $a->get_baseurl(true) . '/connect/' . $channel['channel_address'],
'selected' => ''
);
}
2015-01-29 04:56:04 +00:00
if(feature_enabled(local_channel(),'channel_sources')) {
2013-12-14 21:26:40 +00:00
$tabs[] = array(
'label' => t('Channel Sources'),
'url' => $a->get_baseurl(true) . '/sources',
'selected' => ''
);
}
$tabtpl = get_markup_template("generic_links_widget.tpl");
return replace_macros($tabtpl, array(
'$title' => t('Settings'),
'$class' => 'settings-widget',
'$items' => $tabs,
));
}
function widget_mailmenu($arr) {
2015-01-29 04:56:04 +00:00
if (! local_channel())
2013-12-14 21:26:40 +00:00
return;
$a = get_app();
return replace_macros(get_markup_template('message_side.tpl'), array(
2014-10-07 16:11:36 +00:00
'$title' => t('Messages'),
2013-12-14 21:26:40 +00:00
'$tabs'=> array(),
'$check'=>array(
'label' => t('Check Mail'),
'url' => $a->get_baseurl(true) . '/message',
'sel' => (argv(1) == ''),
),
'$new'=>array(
'label' => t('New Message'),
'url' => $a->get_baseurl(true) . '/mail/new',
2013-12-14 21:26:40 +00:00
'sel'=> (argv(1) == 'new'),
)
));
2013-12-19 10:16:14 +00:00
}
function widget_design_tools($arr) {
$a = get_app();
// mod menu doesn't load a profile. For any modules which load a profile, check it.
2015-01-29 04:56:04 +00:00
// otherwise local_channel() is sufficient for permissions.
2013-12-19 10:16:14 +00:00
if($a->profile['profile_uid'])
2015-01-29 04:56:04 +00:00
if(($a->profile['profile_uid'] != local_channel()) && (! $a->is_sys))
return '';
2013-12-19 10:16:14 +00:00
2015-01-29 04:56:04 +00:00
if(! local_channel())
2013-12-19 10:16:14 +00:00
return '';
return design_tools();
2013-12-19 10:25:44 +00:00
}
function widget_findpeople($arr) {
return findpeople_widget();
2013-12-20 01:36:31 +00:00
}
function widget_photo_albums($arr) {
$a = get_app();
2013-12-20 01:36:31 +00:00
if(! $a->profile['profile_uid'])
return '';
$channelx = channelx_by_n($a->profile['profile_uid']);
if((! $channelx) || (! perm_is_allowed($a->profile['profile_uid'], get_observer_hash(), 'view_photos')))
2013-12-20 01:36:31 +00:00
return '';
require_once('include/photos.php');
2013-12-20 01:36:31 +00:00
return photos_album_widget($channelx, $a->get_observer());
2013-12-20 01:36:31 +00:00
}
function widget_vcard($arr) {
require_once ('include/Contact.php');
return vcard_from_xchan('', get_app()->get_observer());
2013-12-20 01:36:31 +00:00
}
/*
* The following directory widgets are only useful on the directory page
*/
function widget_dirsort($arr) {
return dir_sort_links();
}
function widget_dirtags($arr) {
return dir_tagblock(z_root() . '/directory', null);
}
function widget_menu_preview($arr) {
if(! get_app()->data['menu_item'])
return;
require_once('include/menu.php');
return menu_render(get_app()->data['menu_item']);
}
2014-01-29 09:52:23 +00:00
function widget_chatroom_list($arr) {
$a = get_app();
2014-01-29 09:52:23 +00:00
require_once("include/chat.php");
$r = chatroom_list($a->profile['profile_uid']);
return replace_macros(get_markup_template('chatroomlist.tpl'), array(
2014-01-29 09:52:23 +00:00
'$header' => t('Chat Rooms'),
'$baseurl' => z_root(),
'$nickname' => $a->profile['channel_address'],
2014-01-29 09:52:23 +00:00
'$items' => $r,
));
2014-01-30 05:29:48 +00:00
}
2014-02-28 01:07:11 +00:00
function widget_bookmarkedchats($arr) {
$h = get_observer_hash();
if(! $h)
return;
$r = q("select xchat_url, xchat_desc from xchat where xchat_xchan = '%s' order by xchat_desc",
dbesc($h)
2014-02-28 01:07:11 +00:00
);
2014-11-24 04:29:34 +00:00
if($r) {
for($x = 0; $x < count($r); $x ++) {
$r[$x]['xchat_url'] = zid($r[$x]['xchat_url']);
}
}
2014-02-28 01:07:11 +00:00
return replace_macros(get_markup_template('bookmarkedchats.tpl'),array(
'$header' => t('Bookmarked Chatrooms'),
'$rooms' => $r
));
}
function widget_suggestedchats($arr) {
// probably should restrict this to your friends, but then the widget will only work
// if you are logged in locally.
$h = get_observer_hash();
if(! $h)
return;
$r = q("select xchat_url, xchat_desc, count(xchat_xchan) as total from xchat group by xchat_url, xchat_desc order by total desc, xchat_desc limit 24");
2014-11-24 04:29:34 +00:00
if($r) {
for($x = 0; $x < count($r); $x ++) {
$r[$x]['xchat_url'] = zid($r[$x]['xchat_url']);
}
}
2014-02-28 01:07:11 +00:00
return replace_macros(get_markup_template('bookmarkedchats.tpl'),array(
'$header' => t('Suggested Chatrooms'),
'$rooms' => $r
));
}
function widget_item($arr) {
// FIXME there is no $a here
$uid = $a->profile['profile_uid'];
if((! $uid) || (! $arr['mid']))
return '';
if(! perm_is_allowed($uid, get_observer_hash(), 'view_pages'))
return '';
require_once('include/security.php');
$sql_extra = item_permissions_sql($uid);
$r = q("select * from item where mid = '%s' and uid = %d and item_restrict = " . intval(ITEM_WEBPAGE) . " $sql_extra limit 1",
dbesc($arr['mid']),
intval($uid)
);
if(! $r)
return '';
xchan_query($r);
$r = fetch_post_tags($r, true);
$o = prepare_page($r[0]);
return $o;
2014-03-05 12:28:48 +00:00
}
function widget_clock($arr) {
$miltime = 0;
if(isset($arr['military']) && $arr['military'])
$miltime = 1;
$o = <<< EOT
<div class="widget">
<h3 class="clockface"></h3>
<script>
var timerID = null
var timerRunning = false
function stopclock(){
if(timerRunning)
clearTimeout(timerID)
timerRunning = false
}
function startclock(){
stopclock()
showtime()
}
function showtime(){
var now = new Date()
var hours = now.getHours()
var minutes = now.getMinutes()
var seconds = now.getSeconds()
var military = $miltime
var timeValue = ""
if(military)
timeValue = hours
else
timeValue = ((hours > 12) ? hours - 12 : hours)
timeValue += ((minutes < 10) ? ":0" : ":") + minutes
// timeValue += ((seconds < 10) ? ":0" : ":") + seconds
if(! military)
timeValue += (hours >= 12) ? " P.M." : " A.M."
$('.clockface').html(timeValue)
timerID = setTimeout("showtime()",1000)
timerRunning = true
}
$(document).ready(function() {
startclock();
});
</script>
</div>
EOT;
return $o;
2014-05-14 04:33:39 +00:00
}
/**
* @function widget_photo($arr)
* widget to display a single photo.
* @param array $arr;
* 'src' => URL of photo
* 'zrl' => true or false, use zid in url
* 'style' => CSS string
* URL must be an http or https URL
*/
function widget_photo($arr) {
$style = $zrl = false;
if(array_key_exists('src', $arr) && isset($arr['src']))
2014-05-14 04:33:39 +00:00
$url = $arr['src'];
if(strpos($url,'http') !== 0)
return '';
if(array_key_exists('style', $arr) && isset($arr['style']))
2014-05-14 04:33:39 +00:00
$style = $arr['style'];
2014-05-14 07:55:32 +00:00
// ensure they can't sneak in an eval(js) function
if(strpos($style,'(') !== false)
return '';
if(array_key_exists('zrl', $arr) && isset($arr['zrl']))
2014-05-14 04:33:39 +00:00
$zrl = (($arr['zrl']) ? true : false);
if($zrl)
$url = zid($url);
$o = '<div class="widget">';
$o .= '<img ' . (($zrl) ? ' class="zrl" ' : '')
. (($style) ? ' style="' . $style . '"' : '')
. ' src="' . $url . '" alt="' . t('photo/image') . '">';
2014-11-20 23:34:49 +00:00
$o .= '</div>';
return $o;
}
function widget_photo_rand($arr) {
require_once('include/photos.php');
$style = false;
if(array_key_exists('album', $arr) && isset($arr['album']))
2014-11-20 23:34:49 +00:00
$album = $arr['album'];
else
$album = '';
$channel_id = 0;
if(array_key_exists('channel_id', $arr) && intval($arr['channel_id']))
$channel_id = intval($arr['channel_id']);
if(! $channel_id)
$channel_id = get_app()->profile_uid;
2014-11-20 23:34:49 +00:00
if(! $channel_id)
return '';
$scale = ((array_key_exists('scale',$arr)) ? intval($arr['scale']) : 0);
$ret = photos_list_photos(array('channel_id' => $channel_id),get_app()->get_observer(),$album);
2014-11-20 23:34:49 +00:00
$filtered = array();
if($ret['success'] && $ret['photos'])
foreach($ret['photos'] as $p)
if($p['scale'] == $scale)
$filtered[] = $p['src'];
if($filtered) {
$e = mt_rand(0, count($filtered) - 1);
2014-11-20 23:34:49 +00:00
$url = $filtered[$e];
}
if(strpos($url, 'http') !== 0)
2014-11-20 23:34:49 +00:00
return '';
if(array_key_exists('style', $arr) && isset($arr['style']))
2014-11-20 23:34:49 +00:00
$style = $arr['style'];
// ensure they can't sneak in an eval(js) function
if(strpos($style,'(') !== false)
return '';
$url = zid($url);
$o = '<div class="widget">';
$o .= '<img class="zrl" '
. (($style) ? ' style="' . $style . '"' : '')
. ' src="' . $url . '" alt="' . t('photo/image') . '">';
2014-05-14 04:33:39 +00:00
$o .= '</div>';
return $o;
}
2014-11-22 20:26:04 +00:00
function widget_random_block($arr) {
$channel_id = 0;
if(array_key_exists('channel_id',$arr) && intval($arr['channel_id']))
$channel_id = intval($arr['channel_id']);
if(! $channel_id)
$channel_id = get_app()->profile_uid;
if(! $channel_id)
return '';
if(array_key_exists('contains',$arr))
$contains = $arr['contains'];
$o = '';
require_once('include/security.php');
$sql_options = item_permissions_sql($channel_id);
$randfunc = db_getfunc('RAND');
$r = q("select item.* from item left join item_id on item.id = item_id.iid
where item.uid = %d and sid like '%s' and service = 'BUILDBLOCK' and
item_restrict = %d $sql_options order by $randfunc limit 1",
intval($channel_id),
dbesc('%' . $contains . '%'),
intval(ITEM_BUILDBLOCK)
);
if($r) {
$o = '<div class="widget bblock">';
if($r[0]['title'])
$o .= '<h3>' . $r[0]['title'] . '</h3>';
2014-11-22 20:26:04 +00:00
$o .= prepare_text($r[0]['body'],$r[0]['mimetype']);
$o .= '</div>';
}
return $o;
}
function widget_rating($arr) {
$a = get_app();
$poco_rating = get_config('system','poco_rating_enable');
if((! $poco_rating) && ($poco_rating !== false)) {
return;
}
if($arr['target'])
$hash = $arr['target'];
else
$hash = $a->poi['xchan_hash'];
if(! $hash)
return;
$url = '';
$remote = false;
if(remote_channel() && ! local_channel()) {
$ob = $a->get_observer();
if($ob && $ob['xchan_url']) {
$p = parse_url($ob['xchan_url']);
if($p) {
$url = $p['scheme'] . '://' . $p['host'] . (($p['port']) ? ':' . $p['port'] : '');
$url .= '/rate?f=&target=' . urlencode($hash);
}
$remote = true;
}
}
2015-02-05 02:31:12 +00:00
$self = false;
if(local_channel()) {
$channel = $a->get_channel();
if($hash == $channel['channel_hash'])
2015-02-05 02:31:12 +00:00
$self = true;
head_add_js('ratings.js');
}
2015-02-05 02:31:12 +00:00
if((($remote) || (local_channel())) && (! $self)) {
$o = '<div class="widget rateme">';
if($remote)
$o .= '<a class="rateme" href="' . $url . '"><i class="icon-pencil"></i> ' . t('Rate Me') . '</a>';
else
$o .= '<div class="rateme fakelink" onclick="doRatings(\'' . $hash . '\'); return false;"><i class="icon-pencil"></i> ' . t('Rate Me') . '</div>';
$o .= '</div>';
}
$o .= '<div class="widget rateme"><a class="rateme" href="ratings/' . $hash . '"><i class="icon-eye-open"></i> ' . t('View Ratings') . '</a>';
$o .= '</div>';
return $o;
2015-02-16 19:09:12 +00:00
}
// used by site ratings pages to provide a return link
function widget_pubsites() {
if(get_app()->poi)
return;
return '<div class="widget"><ul class="nav nav-pills"><li><a href="pubsites">' . t('Public Hubs') . '</a></li></ul></div>';
2015-04-09 08:53:37 +00:00
}