aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/acl_selectors.php2
-rw-r--r--include/api_zot.php8
-rw-r--r--include/attach.php5
-rw-r--r--include/bookmarks.php5
-rw-r--r--include/channel.php10
-rw-r--r--include/connections.php4
-rw-r--r--include/conversation.php314
-rw-r--r--include/features.php455
-rw-r--r--include/group.php44
-rw-r--r--include/import.php3
-rwxr-xr-xinclude/items.php13
-rw-r--r--include/markdown.php10
-rw-r--r--include/message.php8
-rw-r--r--include/msglib.php28
-rw-r--r--include/nav.php94
-rw-r--r--include/network.php2
-rwxr-xr-xinclude/plugin.php77
-rw-r--r--include/security.php2
-rw-r--r--include/text.php10
-rw-r--r--include/xchan.php2
-rw-r--r--include/zot.php78
21 files changed, 441 insertions, 733 deletions
diff --git a/include/acl_selectors.php b/include/acl_selectors.php
index bada3e528..c7a87afee 100644
--- a/include/acl_selectors.php
+++ b/include/acl_selectors.php
@@ -89,7 +89,7 @@ function populate_acl($defaults = null,$show_jotnets = true, $emptyACL_descripti
}
}
- $r = q("SELECT id, hash, gname FROM groups WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
+ $r = q("SELECT id, hash, gname FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
intval(local_channel())
);
diff --git a/include/api_zot.php b/include/api_zot.php
index 921242152..6a5b9a268 100644
--- a/include/api_zot.php
+++ b/include/api_zot.php
@@ -350,20 +350,20 @@
$r = null;
if($_REQUEST['group_id']) {
- $r = q("select * from groups where uid = %d and id = %d limit 1",
+ $r = q("select * from pgrp where uid = %d and id = %d limit 1",
intval(api_user()),
intval($_REQUEST['group_id'])
);
}
elseif($_REQUEST['group_name']) {
- $r = q("select * from groups where uid = %d and gname = '%s' limit 1",
+ $r = q("select * from pgrp where uid = %d and gname = '%s' limit 1",
intval(api_user()),
dbesc($_REQUEST['group_name'])
);
}
if($r) {
- $x = q("select * from group_member left join abook on abook_xchan = xchan and abook_channel = group_member.uid left join xchan on group_member.xchan = xchan.xchan_hash
+ $x = q("select * from pgrp_member left join abook on abook_xchan = xchan and abook_channel = pgrp_member.uid left join xchan on pgrp_member.xchan = xchan.xchan_hash
where gid = %d",
intval($r[0]['id'])
);
@@ -376,7 +376,7 @@
if(api_user() === false)
return false;
- $r = q("select * from groups where uid = %d",
+ $r = q("select * from pgrp where uid = %d",
intval(api_user())
);
json_return_and_die($r);
diff --git a/include/attach.php b/include/attach.php
index 202412263..4db5bc435 100644
--- a/include/attach.php
+++ b/include/attach.php
@@ -1428,6 +1428,8 @@ function attach_delete($channel_id, $resource, $is_photo = 0) {
if(! $r) {
attach_drop_photo($channel_id,$resource);
+ $arr = ['channel_id' => $channel_id, 'resource' => $resource, 'is_photo'=>$is_photo];
+ call_hooks("attach_delete",$arr);
return;
}
@@ -1486,6 +1488,9 @@ function attach_delete($channel_id, $resource, $is_photo = 0) {
intval($channel_id)
);
+ $arr = ['channel_id' => $channel_id, 'resource' => $resource, 'is_photo'=>$is_photo];
+ call_hooks("attach_delete",$arr);
+
file_activity($channel_id, $object, $object['allow_cid'], $object['allow_gid'], $object['deny_cid'], $object['deny_gid'], 'update', true);
return;
diff --git a/include/bookmarks.php b/include/bookmarks.php
index 0db103054..21456c871 100644
--- a/include/bookmarks.php
+++ b/include/bookmarks.php
@@ -59,9 +59,10 @@ function bookmark_add($channel,$sender,$taxonomy,$private,$opts = null) {
);
if($r)
logger('add_bookmark: duplicate menu entry', LOGGER_DEBUG);
- if(! $r)
+ if(! $r) {
$r = menu_add_item($menu_id,$channel_id,$iarr);
-
+ menu_sync_packet($channel_id,get_observer_hash(),$menu_id);
+ }
return $r;
}
diff --git a/include/channel.php b/include/channel.php
index 7f49deb2e..33e438e53 100644
--- a/include/channel.php
+++ b/include/channel.php
@@ -447,7 +447,7 @@ function create_identity($arr) {
// if our role_permissions indicate that we're using a default collection ACL, add it.
if(is_array($role_permissions) && $role_permissions['default_collection']) {
- $r = q("select hash from groups where uid = %d and gname = '%s' limit 1",
+ $r = q("select hash from pgrp where uid = %d and gname = '%s' limit 1",
intval($newuid),
dbesc( t('Friends') )
);
@@ -837,14 +837,14 @@ function identity_basic_export($channel_id, $sections = null) {
$ret['hubloc'] = $r;
}
- $r = q("select * from groups where uid = %d ",
+ $r = q("select * from pgrp where uid = %d ",
intval($channel_id)
);
if($r)
$ret['group'] = $r;
- $r = q("select * from group_member where uid = %d ",
+ $r = q("select * from pgrp_member where uid = %d ",
intval($channel_id)
);
if($r)
@@ -2573,8 +2573,8 @@ function channel_remove($channel_id, $local = true, $unset_session = false) {
q("DELETE FROM chatroom WHERE cr_uid = %d", intval($channel_id));
q("DELETE FROM conv WHERE uid = %d", intval($channel_id));
- q("DELETE FROM groups WHERE uid = %d", intval($channel_id));
- q("DELETE FROM group_member WHERE uid = %d", intval($channel_id));
+ q("DELETE FROM pgrp WHERE uid = %d", intval($channel_id));
+ q("DELETE FROM pgrp_member WHERE uid = %d", intval($channel_id));
q("DELETE FROM event WHERE uid = %d", intval($channel_id));
q("DELETE FROM mail WHERE channel_id = %d", intval($channel_id));
q("DELETE FROM menu WHERE menu_channel_id = %d", intval($channel_id));
diff --git a/include/connections.php b/include/connections.php
index 129bcdc8d..d97ea3887 100644
--- a/include/connections.php
+++ b/include/connections.php
@@ -296,7 +296,7 @@ function remove_all_xchan_resources($xchan, $channel_id = 0) {
$r = q("delete from event where event_xchan = '%s'",
dbesc($xchan)
);
- $r = q("delete from group_member where xchan = '%s'",
+ $r = q("delete from pgrp_member where xchan = '%s'",
dbesc($xchan)
);
$r = q("delete from mail where ( from_xchan = '%s' or to_xchan = '%s' )",
@@ -402,7 +402,7 @@ function contact_remove($channel_id, $abook_id) {
intval($channel_id)
);
- $r = q("delete from group_member where xchan = '%s' and uid = %d",
+ $r = q("delete from pgrp_member where xchan = '%s' and uid = %d",
dbesc($abook['abook_xchan']),
intval($channel_id)
);
diff --git a/include/conversation.php b/include/conversation.php
index 4997bc2b7..dc3f45e45 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -888,6 +888,7 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa
'$user' => App::$user,
'$threads' => $threads,
'$wait' => t('Loading...'),
+ '$conversation_tools' => t('Conversation Tools'),
'$dropping' => ($page_dropping?t('Delete Selected Items'):False),
));
@@ -1644,319 +1645,6 @@ function prepare_page($item) {
));
}
-
-function network_tabs() {
-
- $no_active='';
- $starred_active = '';
- $new_active = '';
- $all_active = '';
- $search_active = '';
- $conv_active = '';
- $spam_active = '';
- $postord_active = '';
-
- if(x($_GET,'new')) {
- $new_active = 'active';
- }
-
- if(x($_GET,'search')) {
- $search_active = 'active';
- }
-
- if(x($_GET,'star')) {
- $starred_active = 'active';
- }
-
- if(x($_GET,'conv')) {
- $conv_active = 'active';
- }
-
- if(x($_GET,'spam')) {
- $spam_active = 'active';
- }
-
- if (($new_active == '')
- && ($starred_active == '')
- && ($conv_active == '')
- && ($search_active == '')
- && ($spam_active == '')) {
- $no_active = 'active';
- }
-
- if ($no_active=='active' && x($_GET,'order')) {
- switch($_GET['order']){
- case 'post': $postord_active = 'active'; $no_active=''; break;
- case 'comment' : $all_active = 'active'; $no_active=''; break;
- }
- }
-
- if ($no_active=='active') $all_active='active';
-
- $cmd = App::$cmd;
-
- // tabs
- $tabs = array();
-
- $tabs[] = array(
- 'label' => t('Commented Order'),
- 'url'=>z_root() . '/' . $cmd . '?f=&order=comment' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''),
- 'sel'=>$all_active,
- 'title'=> t('Sort by Comment Date'),
- );
-
- $tabs[] = array(
- 'label' => t('Posted Order'),
- 'url'=>z_root() . '/' . $cmd . '?f=&order=post' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''),
- 'sel'=>$postord_active,
- 'title' => t('Sort by Post Date'),
- );
-
- if(feature_enabled(local_channel(),'personal_tab')) {
- $tabs[] = array(
- 'label' => t('Personal'),
- 'url' => z_root() . '/' . $cmd . '?f=' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . '&conv=1',
- 'sel' => $conv_active,
- 'title' => t('Posts that mention or involve you'),
- );
- }
-
- if(feature_enabled(local_channel(),'new_tab')) {
- $tabs[] = array(
- 'label' => t('New'),
- 'url' => z_root() . '/' . $cmd . '?f=' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . '&new=1' . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''),
- 'sel' => $new_active,
- 'title' => t('Activity Stream - by date'),
- );
- }
-
- if(feature_enabled(local_channel(),'star_posts')) {
- $tabs[] = array(
- 'label' => t('Starred'),
- 'url'=>z_root() . '/' . $cmd . '/?f=' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . '&star=1',
- 'sel'=>$starred_active,
- 'title' => t('Favourite Posts'),
- );
- }
- // Not yet implemented
-
- if(feature_enabled(local_channel(),'spam_filter')) {
- $tabs[] = array(
- 'label' => t('Spam'),
- 'url'=> z_root() . '/network?f=&spam=1',
- 'sel'=> $spam_active,
- 'title' => t('Posts flagged as SPAM'),
- );
- }
-
- $arr = array('tabs' => $tabs);
- call_hooks('network_tabs', $arr);
-
- $tpl = get_markup_template('common_tabs.tpl');
-
- return replace_macros($tpl, array('$tabs' => $arr['tabs']));
-}
-
-/**
- * @brief
- *
- * @param App $a
- * @param boolean $is_owner default false
- * @param string $nickname default null
- * @return void|string
- */
-function profile_tabs($a, $is_owner = false, $nickname = null){
-
- // Don't provide any profile tabs if we're running as the sys channel
-
- if (App::$is_sys)
- return;
-
- if (get_pconfig($uid, 'system', 'noprofiletabs'))
- return;
-
- $channel = App::get_channel();
-
- if (is_null($nickname))
- $nickname = $channel['channel_address'];
-
-
- $uid = ((App::$profile['profile_uid']) ? App::$profile['profile_uid'] : local_channel());
- $account_id = ((App::$profile['profile_uid']) ? App::$profile['channel_account_id'] : App::$channel['channel_account_id']);
-
- if ($uid == local_channel())
- return;
-
- if($uid == local_channel()) {
- $cal_link = '';
- }
- else {
- $cal_link = '/cal/' . $nickname;
- }
-
- require_once('include/security.php');
- $sql_options = item_permissions_sql($uid);
-
- $r = q("select item.* from item left join iconfig on item.id = iconfig.iid
- where item.uid = %d and iconfig.cat = 'system' and iconfig.v = '%s'
- and item.item_delayed = 0 and item.item_deleted = 0
- and ( iconfig.k = 'WEBPAGE' and item_type = %d )
- $sql_options limit 1",
- intval($uid),
- dbesc('home'),
- intval(ITEM_TYPE_WEBPAGE)
- );
-
- $has_webpages = (($r) ? true : false);
-
- if (x($_GET, 'tab'))
- $tab = notags(trim($_GET['tab']));
-
- $url = z_root() . '/channel/' . $nickname;
- $pr = z_root() . '/profile/' . $nickname;
-
- $tabs = array(
- array(
- 'label' => t('Channel'),
- 'url' => $url,
- 'sel' => ((argv(0) == 'channel') ? 'active' : ''),
- 'title' => t('Status Messages and Posts'),
- 'id' => 'status-tab',
- 'icon' => 'home'
- ),
- );
-
- $p = get_all_perms($uid,get_observer_hash());
-
- if ($p['view_profile']) {
- $tabs[] = array(
- 'label' => t('About'),
- 'url' => $pr,
- 'sel' => ((argv(0) == 'profile') ? 'active' : ''),
- 'title' => t('Profile Details'),
- 'id' => 'profile-tab',
- 'icon' => 'user'
- );
- }
- if ($p['view_storage']) {
- $tabs[] = array(
- 'label' => t('Photos'),
- 'url' => z_root() . '/photos/' . $nickname,
- 'sel' => ((argv(0) == 'photos') ? 'active' : ''),
- 'title' => t('Photo Albums'),
- 'id' => 'photo-tab',
- 'icon' => 'photo'
- );
- $tabs[] = array(
- 'label' => t('Files'),
- 'url' => z_root() . '/cloud/' . $nickname,
- 'sel' => ((argv(0) == 'cloud' || argv(0) == 'sharedwithme') ? 'active' : ''),
- 'title' => t('Files and Storage'),
- 'id' => 'files-tab',
- 'icon' => 'folder-open'
- );
- }
-
- if($p['view_stream'] && $cal_link) {
- $tabs[] = array(
- 'label' => t('Events'),
- 'url' => z_root() . $cal_link,
- 'sel' => ((argv(0) == 'cal' || argv(0) == 'events') ? 'active' : ''),
- 'title' => t('Events'),
- 'id' => 'event-tab',
- 'icon' => 'calendar'
- );
- }
-
-
- if ($p['chat'] && feature_enabled($uid,'ajaxchat')) {
- $has_chats = Zotlabs\Lib\Chatroom::list_count($uid);
- if ($has_chats) {
- $tabs[] = array(
- 'label' => t('Chatrooms'),
- 'url' => z_root() . '/chat/' . $nickname,
- 'sel' => ((argv(0) == 'chat') ? 'active' : '' ),
- 'title' => t('Chatrooms'),
- 'id' => 'chat-tab',
- 'icon' => 'comments-o'
- );
- }
- }
-
- require_once('include/menu.php');
- $has_bookmarks = menu_list_count(local_channel(),'',MENU_BOOKMARK) + menu_list_count(local_channel(),'',MENU_SYSTEM|MENU_BOOKMARK);
-
- if($is_owner && $has_bookmarks) {
- $tabs[] = array(
- 'label' => t('Bookmarks'),
- 'url' => z_root() . '/bookmarks',
- 'sel' => ((argv(0) == 'bookmarks') ? 'active' : ''),
- 'title' => t('Saved Bookmarks'),
- 'id' => 'bookmarks-tab',
- 'icon' => 'bookmark'
- );
- }
-
- if(feature_enabled($uid,'cards')) {
- $tabs[] = array(
- 'label' => t('Cards'),
- 'url' => z_root() . '/cards/' . $nickname,
- 'sel' => ((argv(0) == 'cards') ? 'active' : ''),
- 'title' => t('View Cards'),
- 'id' => 'cards-tab',
- 'icon' => 'list'
- );
- }
-
- if(feature_enabled($uid,'articles')) {
- $tabs[] = array(
- 'label' => t('articles'),
- 'url' => z_root() . '/articles/' . $nickname,
- 'sel' => ((argv(0) == 'articles') ? 'active' : ''),
- 'title' => t('View Articles'),
- 'id' => 'articles-tab',
- 'icon' => 'file-text-o'
- );
- }
-
- if($has_webpages && feature_enabled($uid,'webpages')) {
- $tabs[] = array(
- 'label' => t('Webpages'),
- 'url' => z_root() . '/page/' . $nickname . '/home',
- 'sel' => ((argv(0) == 'webpages') ? 'active' : ''),
- 'title' => t('View Webpages'),
- 'id' => 'webpages-tab',
- 'icon' => 'newspaper-o'
- );
- }
-
-
- if ($p['view_wiki']) {
- if(feature_enabled($uid,'wiki') && (get_account_techlevel($account_id) > 3)) {
- $tabs[] = array(
- 'label' => t('Wikis'),
- 'url' => z_root() . '/wiki/' . $nickname,
- 'sel' => ((argv(0) == 'wiki') ? 'active' : ''),
- 'title' => t('Wiki'),
- 'id' => 'wiki-tab',
- 'icon' => 'pencil-square-o'
- );
- }
- }
-
- $arr = array('is_owner' => $is_owner, 'nickname' => $nickname, 'tab' => (($tab) ? $tab : false), 'tabs' => $tabs);
- call_hooks('profile_tabs', $arr);
-
- $tpl = get_markup_template('profile_tabs.tpl');
-
- return replace_macros($tpl, array(
- '$tabs' => $arr['tabs'],
- '$name' => App::$profile['channel_name'],
- '$thumb' => App::$profile['thumb']
- ));
-}
-
-
function get_responses($conv_responses,$response_verbs,$ob,$item) {
$ret = array();
diff --git a/include/features.php b/include/features.php
index 03f50c9a4..ccf3c5faf 100644
--- a/include/features.php
+++ b/include/features.php
@@ -44,265 +44,160 @@ function feature_level($feature,$def) {
return $def;
}
+function process_module_features_get($uid, $features) {
+ unset($features[0]);
+ foreach($features as $f) {
+ $arr[] = array('feature_' . $f[0],$f[1],((intval(feature_enabled($uid, $f[0]))) ? "1" : ''),$f[2],array(t('Off'),t('On')));
+ }
+ return $arr;
+}
+
+function process_module_features_post($uid, $features, $post_arr) {
+ unset($features[0]);
+ foreach($features as $f) {
+ $k = $f[0];
+ if(array_key_exists("feature_$k",$post_arr))
+ set_pconfig($uid,'feature',$k, (string) $post_arr["feature_$k"]);
+ else
+ set_pconfig($uid,'feature', $k, '');
+ }
+ if($post_arr['rpath'])
+ goaway($post_arr['rpath']);
+}
+
function get_features($filtered = true, $level = (-1)) {
$account = \App::get_account();
$arr = [
- // General
- 'general' => [
+ 'calendar' => [
- t('General Features'),
+ t('CalDAV'),
[
- 'start_menu',
- t('New Member Links'),
- t('Display new member quick links menu'),
- (($account['account_created'] > datetime_convert('','','now - 60 days')) ? true : false),
- get_config('feature_lock','start_menu'),
- feature_level('start_menu',1),
- ],
-
- [
- 'advanced_profiles',
- t('Advanced Profiles'),
- t('Additional profile sections and selections'),
+ 'cal_first_day',
+ t('Start calendar week on Monday'),
+ t('Default is Sunday'),
false,
- get_config('feature_lock','advanced_profiles'),
- feature_level('advanced_profiles',1),
- ],
+ get_config('feature_lock','cal_first_day')
+ ]
- [
- 'profile_export',
- t('Profile Import/Export'),
- t('Save and load profile details across sites/channels'),
- false,
- get_config('feature_lock','profile_export'),
- feature_level('profile_export',3),
- ],
+ ],
- [
- 'webpages',
- t('Web Pages'),
- t('Provide managed web pages on your channel'),
- false,
- get_config('feature_lock','webpages'),
- feature_level('webpages',3),
- ],
+ 'channel_home' => [
- [
- 'wiki',
- t('Wiki'),
- t('Provide a wiki for your channel'),
- false,
- get_config('feature_lock','wiki'),
- feature_level('wiki',2),
- ],
-/*
- [
- 'hide_rating',
- t('Hide Rating'),
- t('Hide the rating buttons on your channel and profile pages. Note: People can still rate you somewhere else.'),
- false,
- get_config('feature_lock','hide_rating'),
- feature_level('hide_rating',3),
- ],
-*/
- [
- 'private_notes',
- t('Private Notes'),
- t('Enables a tool to store notes and reminders (note: not encrypted)'),
- false,
- get_config('feature_lock','private_notes'),
- feature_level('private_notes',1),
- ],
+ t('Channel Home'),
[
- 'cards',
- t('Cards'),
- t('Create personal planning cards'),
+ 'tagadelic',
+ t('Tag Cloud'),
+ t('Provide a personal tag cloud on your channel page'),
false,
- get_config('feature_lock','cards'),
- feature_level('cards',1),
- ],
+ get_config('feature_lock','tagadelic'),
+ ]
+ ],
+ 'connections' => [
- [
- 'articles',
- t('Articles'),
- t('Create interactive articles'),
- false,
- get_config('feature_lock','articles'),
- feature_level('articles',1),
- ],
+ t('Connections'),
[
- 'nav_channel_select',
- t('Navigation Channel Select'),
- t('Change channels directly from within the navigation dropdown menu'),
+ 'connfilter',
+ t('Connection Filtering'),
+ t('Filter incoming posts from connections based on keywords/content'),
false,
- get_config('feature_lock','nav_channel_select'),
- feature_level('nav_channel_select',3),
- ],
+ get_config('feature_lock','connfilter')
+ ]
+ ],
+
+ 'conversation' => [
+
+ t('Conversation'),
[
- 'photo_location',
- t('Photo Location'),
- t('If location data is available on uploaded photos, link this to a map.'),
+ 'commtag',
+ t('Community Tagging'),
+ t('Ability to tag existing posts'),
false,
- get_config('feature_lock','photo_location'),
- feature_level('photo_location',2),
+ get_config('feature_lock','commtag'),
],
[
- 'ajaxchat',
- t('Access Controlled Chatrooms'),
- t('Provide chatrooms and chat services with access control.'),
+ 'emojis',
+ t('Emoji Reactions'),
+ t('Add emoji reaction ability to posts'),
true,
- get_config('feature_lock','ajaxchat'),
- feature_level('ajaxchat',1),
+ get_config('feature_lock','emojis'),
],
-
[
- 'smart_birthdays',
- t('Smart Birthdays'),
- t('Make birthday events timezone aware in case your friends are scattered across the planet.'),
- true,
- get_config('feature_lock','smart_birthdays'),
- feature_level('smart_birthdays',2),
+ 'filing',
+ t('Saved Folders'),
+ t('Ability to file posts under folders'),
+ false,
+ get_config('feature_lock','filing'),
],
[
- 'event_tz_select',
- t('Event Timezone Selection'),
- t('Allow event creation in timezones other than your own.'),
+ 'dislike',
+ t('Dislike Posts'),
+ t('Ability to dislike posts/comments'),
false,
- get_config('feature_lock','event_tz_select'),
- feature_level('event_tz_select',2),
+ get_config('feature_lock','dislike'),
],
-
[
- 'premium_channel',
- t('Premium Channel'),
- t('Allows you to set restrictions and terms on those that connect with your channel'),
+ 'star_posts',
+ t('Star Posts'),
+ t('Ability to mark special posts with a star indicator'),
false,
- get_config('feature_lock','premium_channel'),
- feature_level('premium_channel',4),
- ],
-
- [
- 'advanced_dirsearch',
- t('Advanced Directory Search'),
- t('Allows creation of complex directory search queries'),
- false,
- get_config('feature_lock','advanced_dirsearch'),
- feature_level('advanced_dirsearch',4),
- ],
+ get_config('feature_lock','star_posts'),
+ ]
- [
- 'advanced_theming',
- t('Advanced Theme and Layout Settings'),
- t('Allows fine tuning of themes and page layouts'),
- false,
- get_config('feature_lock','advanced_theming'),
- feature_level('advanced_theming',4),
- ],
],
+ 'directory' => [
- 'access_control' => [
- t('Access Control and Permissions'),
-
- [
- 'groups',
- t('Privacy Groups'),
- t('Enable management and selection of privacy groups'),
- true,
- get_config('feature_lock','groups'),
- feature_level('groups',0),
- ],
-
- [
- 'multi_profiles',
- t('Multiple Profiles'),
- t('Ability to create multiple profiles'),
- false,
- get_config('feature_lock','multi_profiles'),
- feature_level('multi_profiles',3),
- ],
-
+ t('Directory'),
[
- 'permcats',
- t('Permission Categories'),
- t('Create custom connection permission limits'),
+ 'advanced_dirsearch',
+ t('Advanced Directory Search'),
+ t('Allows creation of complex directory search queries'),
false,
- get_config('feature_lock','permcats'),
- feature_level('permcats',2),
- ],
+ get_config('feature_lock','advanced_dirsearch'),
+ ]
- [
- 'oauth_clients',
- t('OAuth1 Clients'),
- t('Manage OAuth1 authenticatication tokens for mobile and remote apps.'),
- false,
- get_config('feature_lock','oauth_clients'),
- feature_level('oauth_clients',1),
- ],
+ ],
- [
- 'oauth2_clients',
- t('OAuth2 Clients'),
- t('Manage OAuth2 authenticatication tokens for mobile and remote apps.'),
- false,
- get_config('feature_lock','oauth2_clients'),
- feature_level('oauth2_clients',1),
- ],
+ 'editor' => [
+
+ t('Editor'),
[
- 'access_tokens',
- t('Access Tokens'),
- t('Create access tokens so that non-members can access private content.'),
+ 'categories',
+ t('Post Categories'),
+ t('Add categories to your posts'),
false,
- get_config('feature_lock','access_tokens'),
- feature_level('access_tokens',2),
+ get_config('feature_lock','categories'),
+ feature_level('categories',1),
],
- ],
-
- // Post composition
- 'composition' => [
-
- t('Post Composition Features'),
-
[
'large_photos',
t('Large Photos'),
t('Include large (1024px) photo thumbnails in posts. If not enabled, use small (640px) photo thumbnails'),
false,
get_config('feature_lock','large_photos'),
- feature_level('large_photos',1),
],
[
- 'channel_sources',
- t('Channel Sources'),
- t('Automatically import channel content from other channels or feeds'),
- false,
- get_config('feature_lock','channel_sources'),
- feature_level('channel_sources',3),
- ],
-
- [
'content_encrypt',
t('Even More Encryption'),
t('Allow optional encryption of content end-to-end with a shared secret key'),
false,
get_config('feature_lock','content_encrypt'),
- feature_level('content_encrypt',3),
],
[
@@ -311,7 +206,6 @@ function get_features($filtered = true, $level = (-1)) {
t('Provide a class of post which others can vote on'),
false,
get_config('feature_lock','consensus_tools'),
- feature_level('consensus_tools',3),
],
[
@@ -320,7 +214,6 @@ function get_features($filtered = true, $level = (-1)) {
t('Provide the option to disable comments for a post'),
false,
get_config('feature_lock','disable_comments'),
- feature_level('disable_comments',2),
],
[
@@ -329,7 +222,6 @@ function get_features($filtered = true, $level = (-1)) {
t('Allow posts to be published at a later date'),
false,
get_config('feature_lock','delayed_posting'),
- feature_level('delayed_posting',2),
],
[
@@ -338,7 +230,6 @@ function get_features($filtered = true, $level = (-1)) {
t('Remove posts/comments and/or private messages at a future time'),
false,
get_config('feature_lock','content_expire'),
- feature_level('content_expire',1),
],
[
@@ -347,7 +238,6 @@ function get_features($filtered = true, $level = (-1)) {
t('Prevent posts with identical content to be published with less than two minutes in between submissions.'),
true,
get_config('feature_lock','suppress_duplicates'),
- feature_level('suppress_duplicates',1),
],
[
@@ -356,33 +246,72 @@ function get_features($filtered = true, $level = (-1)) {
t('Automatically saves post and comment drafts in local browser storage to help prevent accidental loss of compositions'),
true,
get_config('feature_lock','auto_save_draft'),
- feature_level('auto_save_draft',1),
+ ]
+
+ ],
+
+ 'events' => [
+
+ t('Events'),
+
+ [
+ 'events_cal_first_day',
+ t('Start calendar week on Monday'),
+ t('Default is Sunday'),
+ false,
+ get_config('feature_lock','events_cal_first_day')
+ ],
+
+ [
+ 'smart_birthdays',
+ t('Smart Birthdays'),
+ t('Make birthday events timezone aware in case your friends are scattered across the planet.'),
+ true,
+ get_config('feature_lock','smart_birthdays'),
],
+ [
+ 'event_tz_select',
+ t('Event Timezone Selection'),
+ t('Allow event creation in timezones other than your own.'),
+ false,
+ get_config('feature_lock','event_tz_select'),
+ ]
+
+ ],
+
+ 'manage' => [
+
+ t('Manage'),
+
+ [
+ 'nav_channel_select',
+ t('Navigation Channel Select'),
+ t('Change channels directly from within the navigation dropdown menu'),
+ false,
+ get_config('feature_lock','nav_channel_select'),
+ ]
+
],
- // Network Tools
- 'net_module' => [
+ 'network' => [
- t('Network and Stream Filtering'),
+ t('Network'),
[
'archives',
t('Search by Date'),
t('Ability to select posts by date ranges'),
false,
- get_config('feature_lock','archives'),
- feature_level('archives',1),
+ get_config('feature_lock','archives')
],
-
[
'savedsearch',
t('Saved Searches'),
t('Save search terms for re-use'),
false,
- get_config('feature_lock','savedsearch'),
- feature_level('savedsearch',2),
+ get_config('feature_lock','savedsearch')
],
[
@@ -390,8 +319,7 @@ function get_features($filtered = true, $level = (-1)) {
t('Alternate Stream Order'),
t('Ability to order the stream by last post date, last comment date or unthreaded activities'),
false,
- get_config('feature_lock','order_tab'),
- feature_level('order_tab',2),
+ get_config('feature_lock','order_tab')
],
[
@@ -399,8 +327,7 @@ function get_features($filtered = true, $level = (-1)) {
t('Contact Filter'),
t('Ability to display only posts of a selected contact'),
false,
- get_config('feature_lock','name_tab'),
- feature_level('name_tab',1),
+ get_config('feature_lock','name_tab')
],
[
@@ -408,8 +335,7 @@ function get_features($filtered = true, $level = (-1)) {
t('Forum Filter'),
t('Ability to display only posts of a specific forum'),
false,
- get_config('feature_lock','forums_tab'),
- feature_level('forums_tab',1),
+ get_config('feature_lock','forums_tab')
],
[
@@ -417,8 +343,7 @@ function get_features($filtered = true, $level = (-1)) {
t('Personal Posts Filter'),
t('Ability to display only posts that you\'ve interacted on'),
false,
- get_config('feature_lock','personal_tab'),
- feature_level('personal_tab',1),
+ get_config('feature_lock','personal_tab')
],
[
@@ -426,8 +351,7 @@ function get_features($filtered = true, $level = (-1)) {
t('Affinity Tool'),
t('Filter stream activity by depth of relationships'),
false,
- get_config('feature_lock','affinity'),
- feature_level('affinity',1),
+ get_config('feature_lock','affinity')
],
[
@@ -435,90 +359,56 @@ function get_features($filtered = true, $level = (-1)) {
t('Suggest Channels'),
t('Show friend and connection suggestions'),
false,
- get_config('feature_lock','suggest'),
- feature_level('suggest',1),
- ],
-
- [
- 'connfilter',
- t('Connection Filtering'),
- t('Filter incoming posts from connections based on keywords/content'),
- false,
- get_config('feature_lock','connfilter'),
- feature_level('connfilter',3),
- ],
-
+ get_config('feature_lock','suggest')
+ ]
],
- // Item tools
- 'tools' => [
+ 'photos' => [
- t('Post/Comment Tools'),
+ t('Photos'),
[
- 'commtag',
- t('Community Tagging'),
- t('Ability to tag existing posts'),
+ 'photo_location',
+ t('Photo Location'),
+ t('If location data is available on uploaded photos, link this to a map.'),
false,
- get_config('feature_lock','commtag'),
- feature_level('commtag',1),
- ],
+ get_config('feature_lock','photo_location'),
+ ]
- [
- 'categories',
- t('Post Categories'),
- t('Add categories to your posts'),
- false,
- get_config('feature_lock','categories'),
- feature_level('categories',1),
- ],
+ ],
- [
- 'emojis',
- t('Emoji Reactions'),
- t('Add emoji reaction ability to posts'),
- true,
- get_config('feature_lock','emojis'),
- feature_level('emojis',1),
- ],
+ 'profiles' => [
- [
- 'filing',
- t('Saved Folders'),
- t('Ability to file posts under folders'),
- false,
- get_config('feature_lock','filing'),
- feature_level('filing',2),
- ],
+ t('Profiles'),
[
- 'dislike',
- t('Dislike Posts'),
- t('Ability to dislike posts/comments'),
+ 'advanced_profiles',
+ t('Advanced Profiles'),
+ t('Additional profile sections and selections'),
false,
- get_config('feature_lock','dislike'),
- feature_level('dislike',1),
+ get_config('feature_lock','advanced_profiles')
],
[
- 'star_posts',
- t('Star Posts'),
- t('Ability to mark special posts with a star indicator'),
+ 'profile_export',
+ t('Profile Import/Export'),
+ t('Save and load profile details across sites/channels'),
false,
- get_config('feature_lock','star_posts'),
- feature_level('star_posts',1),
+ get_config('feature_lock','profile_export')
],
[
- 'tagadelic',
- t('Tag Cloud'),
- t('Provide a personal tag cloud on your channel page'),
- false,
- get_config('feature_lock','tagadelic'),
- feature_level('tagadelic',2),
- ],
- ],
+ 'multi_profiles',
+ t('Multiple Profiles'),
+ t('Ability to create multiple profiles'),
+ false,
+ get_config('feature_lock','multi_profiles')
+ ]
+
+ ]
+
+
];
$x = [ 'features' => $arr, ];
@@ -561,3 +451,8 @@ function get_features($filtered = true, $level = (-1)) {
return $narr;
}
+
+function get_module_features($module) {
+ $features = get_features(false);
+ return $features[$module];
+}
diff --git a/include/group.php b/include/group.php
index 56bf210ff..6011af08f 100644
--- a/include/group.php
+++ b/include/group.php
@@ -14,11 +14,11 @@ function group_add($uid,$name,$public = 0) {
// access lists. What we're doing here is reviving the dead group, but old content which
// was restricted to this group may now be seen by the new group members.
- $z = q("SELECT * FROM groups WHERE id = %d LIMIT 1",
+ $z = q("SELECT * FROM pgrp WHERE id = %d LIMIT 1",
intval($r)
);
if(($z) && $z[0]['deleted']) {
- q('UPDATE groups SET deleted = 0 WHERE id = %d', intval($z[0]['id']));
+ q('UPDATE pgrp SET deleted = 0 WHERE id = %d', intval($z[0]['id']));
notice( t('A deleted group with this name was revived. Existing item permissions <strong>may</strong> apply to this group and any future members. If this is not what you intended, please create another group with a different name.') . EOL);
}
return true;
@@ -28,13 +28,13 @@ function group_add($uid,$name,$public = 0) {
$dups = false;
$hash = random_string() . $name;
- $r = q("SELECT id FROM groups WHERE hash = '%s' LIMIT 1", dbesc($hash));
+ $r = q("SELECT id FROM pgrp WHERE hash = '%s' LIMIT 1", dbesc($hash));
if($r)
$dups = true;
} while($dups == true);
- $r = q("INSERT INTO groups ( hash, uid, visible, gname )
+ $r = q("INSERT INTO pgrp ( hash, uid, visible, gname )
VALUES( '%s', %d, %d, '%s' ) ",
dbesc($hash),
intval($uid),
@@ -53,7 +53,7 @@ function group_add($uid,$name,$public = 0) {
function group_rmv($uid,$name) {
$ret = false;
if(x($uid) && x($name)) {
- $r = q("SELECT id, hash FROM groups WHERE uid = %d AND gname = '%s' LIMIT 1",
+ $r = q("SELECT id, hash FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
intval($uid),
dbesc($name)
);
@@ -98,13 +98,13 @@ function group_rmv($uid,$name) {
}
// remove all members
- $r = q("DELETE FROM group_member WHERE uid = %d AND gid = %d ",
+ $r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d ",
intval($uid),
intval($group_id)
);
// remove group
- $r = q("UPDATE groups SET deleted = 1 WHERE uid = %d AND gname = '%s'",
+ $r = q("UPDATE pgrp SET deleted = 1 WHERE uid = %d AND gname = '%s'",
intval($uid),
dbesc($name)
);
@@ -121,7 +121,7 @@ function group_rmv($uid,$name) {
function group_byname($uid,$name) {
if((! $uid) || (! strlen($name)))
return false;
- $r = q("SELECT * FROM groups WHERE uid = %d AND gname = '%s' LIMIT 1",
+ $r = q("SELECT * FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
intval($uid),
dbesc($name)
);
@@ -134,7 +134,7 @@ function group_byname($uid,$name) {
function group_rec_byhash($uid,$hash) {
if((! $uid) || (! strlen($hash)))
return false;
- $r = q("SELECT * FROM groups WHERE uid = %d AND hash = '%s' LIMIT 1",
+ $r = q("SELECT * FROM pgrp WHERE uid = %d AND hash = '%s' LIMIT 1",
intval($uid),
dbesc($hash)
);
@@ -149,7 +149,7 @@ function group_rmv_member($uid,$name,$member) {
return false;
if(! ( $uid && $gid && $member))
return false;
- $r = q("DELETE FROM group_member WHERE uid = %d AND gid = %d AND xchan = '%s' ",
+ $r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' ",
intval($uid),
intval($gid),
dbesc($member)
@@ -169,7 +169,7 @@ function group_add_member($uid,$name,$member,$gid = 0) {
if((! $gid) || (! $uid) || (! $member))
return false;
- $r = q("SELECT * FROM group_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",
+ $r = q("SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",
intval($uid),
intval($gid),
dbesc($member)
@@ -179,7 +179,7 @@ function group_add_member($uid,$name,$member,$gid = 0) {
// we indicate success because the group member was in fact created
// -- It was just created at another time
if(! $r)
- $r = q("INSERT INTO group_member (uid, gid, xchan)
+ $r = q("INSERT INTO pgrp_member (uid, gid, xchan)
VALUES( %d, %d, '%s' ) ",
intval($uid),
intval($gid),
@@ -194,9 +194,9 @@ function group_add_member($uid,$name,$member,$gid = 0) {
function group_get_members($gid) {
$ret = array();
if(intval($gid)) {
- $r = q("SELECT * FROM group_member
- LEFT JOIN abook ON abook_xchan = group_member.xchan left join xchan on xchan_hash = abook_xchan
- WHERE gid = %d AND abook_channel = %d and group_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ",
+ $r = q("SELECT * FROM pgrp_member
+ LEFT JOIN abook ON abook_xchan = pgrp_member.xchan left join xchan on xchan_hash = abook_xchan
+ WHERE gid = %d AND abook_channel = %d and pgrp_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ",
intval($gid),
intval(local_channel()),
intval(local_channel())
@@ -210,7 +210,7 @@ function group_get_members($gid) {
function group_get_members_xchan($gid) {
$ret = array();
if(intval($gid)) {
- $r = q("SELECT xchan FROM group_member WHERE gid = %d AND uid = %d",
+ $r = q("SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d",
intval($gid),
intval(local_channel())
);
@@ -248,7 +248,7 @@ function mini_group_select($uid,$group = '') {
$grps = array();
$o = '';
- $r = q("SELECT * FROM groups WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
+ $r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
intval($uid)
);
$grps[] = array('name' => '', 'hash' => '0', 'selected' => '');
@@ -274,13 +274,13 @@ function group_side($every="connections",$each="group",$edit = false, $group_id
$o = '';
- if(! (local_channel() && feature_enabled(local_channel(),'groups'))) {
+ if(! (local_channel() && \Zotlabs\Lib\Apps::system_app_installed(local_channel(), 'Privacy Groups'))) {
return '';
}
$groups = array();
- $r = q("SELECT * FROM groups WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
+ $r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
intval($_SESSION['uid'])
);
$member_of = array();
@@ -361,7 +361,7 @@ function expand_groups($g) {
stringify_array_elms($x,true);
$groups = implode(',', $x);
if($groups) {
- $r = q("SELECT xchan FROM group_member WHERE gid IN ( select id from groups where hash in ( $groups ))");
+ $r = q("SELECT xchan FROM pgrp_member WHERE gid IN ( select id from pgrp where hash in ( $groups ))");
if($r) {
foreach($r as $rr) {
$ret[] = $rr['xchan'];
@@ -375,7 +375,7 @@ function expand_groups($g) {
function member_of($c) {
- $r = q("SELECT groups.gname, groups.id FROM groups LEFT JOIN group_member ON group_member.gid = groups.id WHERE group_member.xchan = '%s' AND groups.deleted = 0 ORDER BY groups.gname ASC ",
+ $r = q("SELECT pgrp.gname, pgrp.id FROM pgrp LEFT JOIN pgrp_member ON pgrp_member.gid = pgrp.id WHERE pgrp_member.xchan = '%s' AND pgrp.deleted = 0 ORDER BY pgrp.gname ASC ",
dbesc($c)
);
@@ -385,7 +385,7 @@ function member_of($c) {
function groups_containing($uid,$c) {
- $r = q("SELECT gid FROM group_member WHERE uid = %d AND group_member.xchan = '%s' ",
+ $r = q("SELECT gid FROM pgrp_member WHERE uid = %d AND pgrp_member.xchan = '%s' ",
intval($uid),
dbesc($c)
);
diff --git a/include/import.php b/include/import.php
index 91a26b23b..0fc24a26f 100644
--- a/include/import.php
+++ b/include/import.php
@@ -93,7 +93,8 @@ function import_channel($channel, $account_id, $seize, $newname = '') {
'channel_w_comment', 'channel_w_mail', 'channel_w_like', 'channel_w_tagwall',
'channel_w_chat', 'channel_w_storage', 'channel_w_pages', 'channel_a_republish',
'channel_a_delegate', 'perm_limits', 'channel_password', 'channel_salt',
- 'channel_moved'
+ 'channel_moved', 'channel_primary', 'channel_removed', 'channel_deleted',
+ 'channel_system'
];
$clean = array();
diff --git a/include/items.php b/include/items.php
index b0f6a89cf..58461cc3a 100755
--- a/include/items.php
+++ b/include/items.php
@@ -3997,6 +3997,7 @@ function zot_feed($uid, $observer_hash, $arr) {
$result = array();
$mindate = null;
$message_id = null;
+ $wall = true;
require_once('include/security.php');
@@ -4008,6 +4009,10 @@ function zot_feed($uid, $observer_hash, $arr) {
$message_id = $arr['message_id'];
}
+ if(array_key_exists('wall',$arr)) {
+ $wall = intval($arr['wall']);
+ }
+
if(! $mindate)
$mindate = NULL_DATE;
@@ -4036,6 +4041,10 @@ function zot_feed($uid, $observer_hash, $arr) {
$limit = '';
}
+ if($wall) {
+ $sql_extra .= " and item_wall = 1 ";
+ }
+
$items = [];
@@ -4048,7 +4057,6 @@ function zot_feed($uid, $observer_hash, $arr) {
$r = q("SELECT parent, postopts FROM item
WHERE uid IN ( %s )
- AND item_wall = 1
AND item_private = 0
$item_normal
$sql_extra ORDER BY created ASC $limit",
@@ -4058,7 +4066,6 @@ function zot_feed($uid, $observer_hash, $arr) {
else {
$r = q("SELECT parent, postopts FROM item
WHERE uid = %d
- AND item_wall = 1
$item_normal
$sql_extra ORDER BY created ASC $limit",
intval($uid)
@@ -4152,7 +4159,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
$sql_extra .= protect_sprintf(term_query('item', $arr['cat'], TERM_CATEGORY));
if($arr['gid'] && $uid) {
- $r = q("SELECT * FROM groups WHERE id = %d AND uid = %d LIMIT 1",
+ $r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d LIMIT 1",
intval($arr['group']),
intval($uid)
);
diff --git a/include/markdown.php b/include/markdown.php
index f4944e2cc..6af055366 100644
--- a/include/markdown.php
+++ b/include/markdown.php
@@ -251,10 +251,16 @@ function bb_to_markdown($Text, $options = []) {
// Markdownify does not preserve previously escaped html entities such as <> and &.
//$Text = str_replace(array('&lt;','&gt;','&amp;'),array('&_lt_;','&_gt_;','&_amp_;'),$Text);
+ // This might fix PHP Warning: DOMDocument::loadHTML(): htmlParseEntityRef: no name in Entity
+ $Text = str_replace("&", "&amp;", $Text);
+
// Now convert HTML to Markdown
$Text = html2markdown($Text);
+ //html2markdown adds backslashes infront of hashes after a new line. remove them
+ $Text = str_replace("\n\#", "\n#", $Text);
+
// It also adds backslashes to our attempt at getting around the html entity preservation for some weird reason.
//$Text = str_replace(array('&\\_lt\\_;','&\\_gt\\_;','&\\_amp\\_;'),array('&lt;','&gt;','&amp;'),$Text);
@@ -292,7 +298,7 @@ function bb_to_markdown($Text, $options = []) {
*/
function html2markdown($html,$options = []) {
$markdown = '';
-
+
$environment = Environment::createDefaultEnvironment($options);
$environment->addConverter(new TableConverter());
$converter = new HtmlConverter($environment);
@@ -374,4 +380,4 @@ class TableConverter implements ConverterInterface
{
return array('table', 'tr', 'thead', 'td', 'tbody');
}
-} \ No newline at end of file
+}
diff --git a/include/message.php b/include/message.php
index 4a673b961..936c01631 100644
--- a/include/message.php
+++ b/include/message.php
@@ -4,6 +4,7 @@
require_once('include/crypto.php');
require_once('include/attach.php');
+require_once('include/msglib.php');
function mail_prepare_binary($item) {
@@ -498,11 +499,8 @@ function private_messages_drop($channel_id, $messageitem_id, $drop_conversation
}
else {
xchan_mail_query($x[0]);
- $x[0]['mail_deleted'] = true;
- $r = q("DELETE FROM mail WHERE id = %d AND channel_id = %d",
- intval($messageitem_id),
- intval($channel_id)
- );
+ $x[0]['mail_deleted'] = true;
+ msg_drop($messageitem_id, $channel_id, $x[0]['conv_guid']);
build_sync_packet($channel_id,array('mail' => array(encode_mail($x,true))));
return true;
}
diff --git a/include/msglib.php b/include/msglib.php
new file mode 100644
index 000000000..f0bf523de
--- /dev/null
+++ b/include/msglib.php
@@ -0,0 +1,28 @@
+<?php
+
+/* Common private message processing functions */
+
+function msg_drop($message_id, $channel_id, $conv_guid) {
+
+ // Delete message
+ $r = q("DELETE FROM mail WHERE id = %d AND channel_id = %d",
+ intval($message_id),
+ intval($channel_id)
+ );
+
+ // Get new first message...
+ $r = q("SELECT mid, parent_mid FROM mail WHERE conv_guid = '%s' AND channel_id = %d ORDER BY id ASC LIMIT 1",
+ dbesc($conv_guid),
+ intval($channel_id)
+ );
+ // ...and if wasn't first before...
+ if ($r[0]['mid'] != $r[0]['parent_mid']) {
+ // ...refer whole thread to it
+ q("UPDATE mail SET parent_mid = '%s', mail_isreply = abs(mail_isreply - 1) WHERE conv_guid = '%s' AND channel_id = %d",
+ dbesc($r[0]['mid']),
+ dbesc($conv_guid),
+ intval($channel_id)
+ );
+ }
+
+}
diff --git a/include/nav.php b/include/nav.php
index 56fe9b901..988a07b7c 100644
--- a/include/nav.php
+++ b/include/nav.php
@@ -1,11 +1,11 @@
<?php /** @file */
-use \Zotlabs\Lib as Zlib;
+use \Zotlabs\Lib\Apps;
+use \Zotlabs\Lib\Chatroom;
require_once('include/security.php');
require_once('include/menu.php');
-
function nav($template = 'default') {
/**
@@ -93,7 +93,7 @@ function nav($template = 'default') {
if(! $_SESSION['delegate']) {
$nav['manage'] = array('manage', t('Channel Manager'), "", t('Manage your channels'),'manage_nav_btn');
}
- if(feature_enabled(local_channel(),'groups'))
+ if(Apps::system_app_installed(local_channel(), 'Privacy Groups'))
$nav['group'] = array('group', t('Privacy Groups'),"", t('Manage your privacy groups'),'group_nav_btn');
$nav['settings'] = array('settings', t('Settings'),"", t('Account/Channel Settings'),'settings_nav_btn');
@@ -199,40 +199,54 @@ function nav($template = 'default') {
// turned off until somebody discovers this and figures out a good location for it.
$powered_by = '';
+ $url = '';
+ $settings_url = '';
+
if(App::$profile_uid && App::$nav_sel['raw_name']) {
$active_app = q("SELECT app_url FROM app WHERE app_channel = %d AND app_name = '%s' LIMIT 1",
intval(App::$profile_uid),
dbesc(App::$nav_sel['raw_name'])
);
-
+
if($active_app) {
- $url = $active_app[0]['app_url'];
+ if(strpos($active_app[0]['app_url'], ',')) {
+ $urls = explode(',', $active_app[0]['app_url']);
+ $url = trim($urls[0]);
+ if($is_owner)
+ $settings_url = trim($urls[1]);
+ }
+ else {
+ $url = $active_app[0]['app_url'];
+ }
}
}
+ if(! $settings_url && isset(App::$nav_sel['settings_url']))
+ $settings_url = App::$nav_sel['settings_url'];
+
//app bin
if($is_owner) {
if(get_pconfig(local_channel(), 'system','import_system_apps') !== datetime_convert('UTC','UTC','now','Y-m-d')) {
- Zlib\Apps::import_system_apps();
+ Apps::import_system_apps();
set_pconfig(local_channel(), 'system','import_system_apps', datetime_convert('UTC','UTC','now','Y-m-d'));
}
$syslist = array();
- $list = Zlib\Apps::app_list(local_channel(), false, ['nav_featured_app', 'nav_pinned_app']);
+ $list = Apps::app_list(local_channel(), false, ['nav_featured_app', 'nav_pinned_app']);
if($list) {
foreach($list as $li) {
- $syslist[] = Zlib\Apps::app_encode($li);
+ $syslist[] = Apps::app_encode($li);
}
}
- Zlib\Apps::translate_system_apps($syslist);
+ Apps::translate_system_apps($syslist);
}
else {
- $syslist = Zlib\Apps::get_system_apps(true);
+ $syslist = Apps::get_system_apps(true);
}
usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');
- $syslist = Zlib\Apps::app_order(local_channel(),$syslist);
+ $syslist = Apps::app_order(local_channel(),$syslist);
foreach($syslist as $app) {
if(\App::$nav_sel['name'] == $app['name'])
@@ -240,18 +254,18 @@ function nav($template = 'default') {
if($is_owner) {
if(strpos($app['categories'],'nav_pinned_app') !== false) {
- $navbar_apps[] = Zlib\Apps::app_render($app,'navbar');
+ $navbar_apps[] = Apps::app_render($app,'navbar');
}
else {
- $nav_apps[] = Zlib\Apps::app_render($app,'nav');
+ $nav_apps[] = Apps::app_render($app,'nav');
}
}
elseif(! $is_owner && strpos($app['requires'], 'local_channel') === false) {
if(strpos($app['categories'],'nav_pinned_app') !== false) {
- $navbar_apps[] = Zlib\Apps::app_render($app,'navbar');
+ $navbar_apps[] = Apps::app_render($app,'navbar');
}
else {
- $nav_apps[] = Zlib\Apps::app_render($app,'nav');
+ $nav_apps[] = Apps::app_render($app,'nav');
}
}
}
@@ -289,7 +303,8 @@ function nav($template = 'default') {
'$addapps' => t('Add Apps'),
'$orderapps' => t('Arrange Apps'),
'$sysapps_toggle' => t('Toggle System Apps'),
- '$url' => (($url) ? $url : App::$cmd)
+ '$url' => (($url) ? $url : z_root() . '/' . App::$cmd),
+ '$settings_url' => $settings_url
));
if(x($_SESSION, 'reload_avatar') && $observer) {
@@ -311,14 +326,17 @@ function nav($template = 'default') {
* Set a menu item in navbar as selected
*
*/
-function nav_set_selected($item){
- App::$nav_sel['raw_name'] = $item;
- $item = ['name' => $item];
- Zlib\Apps::translate_system_apps($item);
- App::$nav_sel['name'] = $item['name'];
-}
+function nav_set_selected($raw_name, $settings_url = ''){
+ App::$nav_sel['raw_name'] = $raw_name;
+ $item = ['name' => $raw_name];
+ Apps::translate_system_apps($item);
+ App::$nav_sel['name'] = $item['name'];
+
+ if($settings_url)
+ App::$nav_sel['settings_url'] = z_root() . '/' . $settings_url;
+}
function channel_apps($is_owner = false, $nickname = null) {
@@ -419,8 +437,8 @@ function channel_apps($is_owner = false, $nickname = null) {
}
- if ($p['chat'] && feature_enabled($uid,'ajaxchat')) {
- $has_chats = ZLib\Chatroom::list_count($uid);
+ if ($p['chat'] && Apps::system_app_installed($uid,'Chatrooms')) {
+ $has_chats = Chatroom::list_count($uid);
if ($has_chats) {
$tabs[] = [
'label' => t('Chatrooms'),
@@ -445,7 +463,7 @@ function channel_apps($is_owner = false, $nickname = null) {
];
}
- if($p['view_pages'] && feature_enabled($uid,'cards')) {
+ if($p['view_pages'] && Apps::system_app_installed($uid, 'Cards')) {
$tabs[] = [
'label' => t('Cards'),
'url' => z_root() . '/cards/' . $nickname ,
@@ -456,7 +474,7 @@ function channel_apps($is_owner = false, $nickname = null) {
];
}
- if($p['view_pages'] && feature_enabled($uid,'articles')) {
+ if($p['view_pages'] && Apps::system_app_installed($uid, 'Articles')) {
$tabs[] = [
'label' => t('Articles'),
'url' => z_root() . '/articles/' . $nickname ,
@@ -468,7 +486,7 @@ function channel_apps($is_owner = false, $nickname = null) {
}
- if($has_webpages && feature_enabled($uid,'webpages')) {
+ if($has_webpages && Apps::system_app_installed($uid, 'Webpages')) {
$tabs[] = [
'label' => t('Webpages'),
'url' => z_root() . '/page/' . $nickname . '/home',
@@ -480,21 +498,19 @@ function channel_apps($is_owner = false, $nickname = null) {
}
- if ($p['view_wiki']) {
- if(feature_enabled($uid,'wiki') && (get_account_techlevel($account_id) > 3)) {
- $tabs[] = [
- 'label' => t('Wikis'),
- 'url' => z_root() . '/wiki/' . $nickname,
- 'sel' => ((argv(0) == 'wiki') ? 'active' : ''),
- 'title' => t('Wiki'),
- 'id' => 'wiki-tab',
- 'icon' => 'pencil-square-o'
- ];
- }
+ if ($p['view_wiki'] && Apps::system_app_installed($uid, 'Wiki')) {
+ $tabs[] = [
+ 'label' => t('Wikis'),
+ 'url' => z_root() . '/wiki/' . $nickname,
+ 'sel' => ((argv(0) == 'wiki') ? 'active' : ''),
+ 'title' => t('Wiki'),
+ 'id' => 'wiki-tab',
+ 'icon' => 'pencil-square-o'
+ ];
}
$arr = array('is_owner' => $is_owner, 'nickname' => $nickname, 'tab' => (($tab) ? $tab : false), 'tabs' => $tabs);
- call_hooks('profile_tabs', $arr);
+
call_hooks('channel_apps', $arr);
return replace_macros(get_markup_template('profile_tabs.tpl'),
diff --git a/include/network.php b/include/network.php
index d4f4f27c6..5ae02deff 100644
--- a/include/network.php
+++ b/include/network.php
@@ -157,7 +157,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
if($http_code == 301 || $http_code == 302 || $http_code == 303 || $http_code == 307 || $http_code == 308) {
$matches = array();
- preg_match('/(Location:|URI:)(.*?)\n/', $header, $matches);
+ preg_match('/(Location:|URI:)(.*?)\n/i', $header, $matches);
$newurl = trim(array_pop($matches));
if(strpos($newurl,'/') === 0)
$newurl = $url . $newurl;
diff --git a/include/plugin.php b/include/plugin.php
index 23cb2b5f6..fdc62b3a7 100755
--- a/include/plugin.php
+++ b/include/plugin.php
@@ -109,11 +109,16 @@ function install_plugin($plugin) {
$plugin_admin = (function_exists($plugin . '_plugin_admin') ? 1 : 0);
- q("INSERT INTO addon (aname, installed, tstamp, plugin_admin) VALUES ( '%s', 1, %d , %d ) ",
- dbesc($plugin),
- intval($t),
- $plugin_admin
+ $d = q("select * from addon where aname = '%s' limit 1",
+ dbesc($plugin)
);
+ if(! $d) {
+ q("INSERT INTO addon (aname, installed, tstamp, plugin_admin) VALUES ( '%s', 1, %d , %d ) ",
+ dbesc($plugin),
+ intval($t),
+ $plugin_admin
+ );
+ }
load_plugin($plugin);
}
@@ -366,28 +371,47 @@ function unregister_hook($hook, $file, $function) {
return $r;
}
-
-//
-// It might not be obvious but themes can manually add hooks to the App::$hooks
-// array in their theme_init() and use this to customise the app behaviour.
-// UPDATE: use insert_hook($hookname,$function_name) to do this
-//
+/**
+ * @brief loads all active hooks into memory
+ * alters: App::$hooks
+ * Called during initialisation
+ * Duplicated hooks are removed and the duplicates ignored
+ *
+ * It might not be obvious but themes can manually add hooks to the App::$hooks
+ * array in their theme_init() and use this to customise the app behaviour.
+ * use insert_hook($hookname,$function_name) to do this.
+ */
function load_hooks() {
- App::$hooks = array();
+ App::$hooks = [];
$r = q("SELECT * FROM hook WHERE true ORDER BY priority DESC");
if($r) {
- foreach($r as $rr) {
- if(! array_key_exists($rr['hook'],App::$hooks))
- App::$hooks[$rr['hook']] = array();
- App::$hooks[$rr['hook']][] = array($rr['file'],$rr['fn'],$rr['priority'],$rr['hook_version']);
+ foreach($r as $rv) {
+ $duplicated = false;
+ if(! array_key_exists($rv['hook'],App::$hooks)) {
+ App::$hooks[$rv['hook']] = [];
+ }
+ else {
+ foreach(App::$hooks[$rv['hook']] as $h) {
+ if($h[0] === $rv['file'] && $h[1] === $rv['fn']) {
+ $duplicated = true;
+ q("delete from hook where id = %d",
+ intval($rv['id'])
+ );
+ logger('duplicate hook ' . $h[1] . ' removed');
+ }
+ }
+ }
+ if(! $duplicated) {
+ App::$hooks[$rv['hook']][] = [ $rv['file'], $rv['fn'], $rv['priority'], $rv['hook_version']];
+ }
}
}
- //logger('hooks: ' . print_r(App::$hooks,true));
+ // logger('hooks: ' . print_r(App::$hooks,true));
}
/**
@@ -432,8 +456,27 @@ function insert_hook($hook, $fn, $version = 0, $priority = 0) {
function call_hooks($name, &$data = null) {
$a = 0;
- if((is_array(App::$hooks)) && (array_key_exists($name, App::$hooks))) {
+ if (isset(App::$hooks[$name])) {
foreach(App::$hooks[$name] as $hook) {
+
+ if ($name != 'permit_hook') { // avoid looping
+ $checkhook = [
+ 'name'=>$name,
+ 'hook'=>$hook,
+ 'data'=>$data,
+ // Note: Since PHP uses COPY-ON-WRITE
+ // for variables, there is no cost to
+ // passing the $data structure (unless
+ // the permit_hook processors change the
+ // information it contains.
+ 'permit'=>true
+ ];
+ call_hooks('permit_hook',$checkhook);
+ if (!$checkhook['permit']) {
+ continue;
+ }
+ $data = $checkhook['data'];
+ }
$origfn = $hook[1];
if($hook[0])
@include_once($hook[0]);
diff --git a/include/security.php b/include/security.php
index ffdd1d7ea..493d34699 100644
--- a/include/security.php
+++ b/include/security.php
@@ -577,7 +577,7 @@ function init_groups_visitor($contact_id) {
// physical groups this channel is a member of
- $r = q("SELECT hash FROM groups left join group_member on groups.id = group_member.gid WHERE xchan = '%s' ",
+ $r = q("SELECT hash FROM pgrp left join pgrp_member on pgrp.id = pgrp_member.gid WHERE xchan = '%s' ",
dbesc($contact_id)
);
if($r) {
diff --git a/include/text.php b/include/text.php
index 8a07dc113..7782eac40 100644
--- a/include/text.php
+++ b/include/text.php
@@ -37,7 +37,13 @@ function replace_macros($s, $r) {
call_hooks('replace_macros', $arr);
$t = App::template_engine();
- $output = $t->replace_macros($arr['template'], $arr['params']);
+
+ try {
+ $output = $t->replace_macros($arr['template'], $arr['params']);
+ } catch (Exception $e) {
+ logger("Unable to render template: ",$e->getMessage());
+ $output = "<h3>ERROR: there was an error creating the output.</h3>";
+ }
return $output;
}
@@ -2731,7 +2737,7 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
$grp = group_byname($profile_uid,$name);
if($grp) {
- $g = q("select hash from groups where id = %d and visible = 1 limit 1",
+ $g = q("select hash from pgrp where id = %d and visible = 1 limit 1",
intval($grp)
);
if($g && $exclusive) {
diff --git a/include/xchan.php b/include/xchan.php
index 8c9c09c72..aad56063f 100644
--- a/include/xchan.php
+++ b/include/xchan.php
@@ -176,7 +176,7 @@ function xchan_change_key($oldx,$newx,$data) {
$tables = [
'abook' => 'abook_xchan',
'abconfig' => 'xchan',
- 'group_member' => 'xchan',
+ 'pgrp_member' => 'xchan',
'chat' => 'chat_xchan',
'chatpresence' => 'cp_xchan',
'event' => 'event_xchan',
diff --git a/include/zot.php b/include/zot.php
index 5c79dd4fa..1a632cf87 100644
--- a/include/zot.php
+++ b/include/zot.php
@@ -12,6 +12,7 @@ require_once('include/crypto.php');
require_once('include/items.php');
require_once('include/queue_fn.php');
require_once('include/perm_upgrade.php');
+require_once('include/msglib.php');
/**
@@ -1118,6 +1119,7 @@ function zot_process_response($hub, $arr, $outq) {
}
foreach($x['delivery_report'] as $xx) {
+ call_hooks('dreport_process',$xx);
if(is_array($xx) && array_key_exists('message_id',$xx) && delivery_report_is_storable($xx)) {
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s' ) ",
dbesc($xx['message_id']),
@@ -1807,13 +1809,28 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $
else {
$arr['item_wall'] = 0;
}
-
- if((! perm_is_allowed($channel['channel_id'],$sender['hash'],$perm)) && (! $tag_delivery) && (! $local_public)) {
- logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}");
- $DR->update('permission denied');
- $result[] = $DR->get();
- continue;
- }
+
+
+ if ((! $tag_delivery) && (! $local_public)) {
+ $allowed = (perm_is_allowed($channel['channel_id'],$sender['hash'],$perm));
+
+ if((! $allowed) && $perm == 'post_comments') {
+ $parent = q("select * from item where mid = '%s' and uid = %d limit 1",
+ dbesc($arr['parent_mid']),
+ intval($channel['channel_id'])
+ );
+ if ($parent) {
+ $allowed = can_comment_on_post($d['hash'],$parent[0]);
+ }
+ }
+
+ if (! $allowed) {
+ logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}");
+ $DR->update('permission denied');
+ $result[] = $DR->get();
+ continue;
+ }
+ }
if($arr['mid'] != $arr['parent_mid']) {
@@ -2315,16 +2332,13 @@ function process_mail_delivery($sender, $arr, $deliveries) {
}
- $r = q("select id from mail where mid = '%s' and channel_id = %d limit 1",
+ $r = q("select id, conv_guid from mail where mid = '%s' and channel_id = %d limit 1",
dbesc($arr['mid']),
intval($channel['channel_id'])
);
if($r) {
if(intval($arr['mail_recalled'])) {
- $x = q("delete from mail where id = %d and channel_id = %d",
- intval($r[0]['id']),
- intval($channel['channel_id'])
- );
+ msg_drop($r[0]['id'], $channel['channel_id'], $r[0]['conv_guid']);
$DR->update('mail recalled');
$result[] = $DR->get();
logger('mail_recalled');
@@ -3306,13 +3320,13 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
}
if($groups_changed) {
- $r = q("select hash as collection, visible, deleted, gname as name from groups where uid = %d",
+ $r = q("select hash as collection, visible, deleted, gname as name from pgrp where uid = %d",
intval($uid)
);
if($r)
$info['collections'] = $r;
- $r = q("select groups.hash as collection, group_member.xchan as member from groups left join group_member on groups.id = group_member.gid where group_member.uid = %d",
+ $r = q("select pgrp.hash as collection, pgrp_member.xchan as member from pgrp left join pgrp_member on pgrp.id = pgrp_member.gid where pgrp_member.uid = %d",
intval($uid)
);
if($r)
@@ -3557,13 +3571,13 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
}
$disallowed = [
- 'channel_id', 'channel_account_id', 'channel_primary', 'channel_prvkey',
- 'channel_address', 'channel_notifyflags', 'channel_removed', 'channel_deleted',
- 'channel_system', 'channel_r_stream', 'channel_r_profile', 'channel_r_abook',
- 'channel_r_storage', 'channel_r_pages', 'channel_w_stream', 'channel_w_wall',
- 'channel_w_comment', 'channel_w_mail', 'channel_w_like', 'channel_w_tagwall',
- 'channel_w_chat', 'channel_w_storage', 'channel_w_pages', 'channel_a_republish',
- 'channel_a_delegate'
+ 'channel_id', 'channel_account_id', 'channel_primary', 'channel_prvkey',
+ 'channel_address', 'channel_notifyflags', 'channel_removed', 'channel_deleted',
+ 'channel_system', 'channel_r_stream', 'channel_r_profile', 'channel_r_abook',
+ 'channel_r_storage', 'channel_r_pages', 'channel_w_stream', 'channel_w_wall',
+ 'channel_w_comment', 'channel_w_mail', 'channel_w_like', 'channel_w_tagwall',
+ 'channel_w_chat', 'channel_w_storage', 'channel_w_pages', 'channel_a_republish',
+ 'channel_a_delegate', 'channel_moved'
];
$clean = array();
@@ -3720,7 +3734,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
// sync collections (privacy groups) oh joy...
if(array_key_exists('collections',$arr) && is_array($arr['collections']) && count($arr['collections'])) {
- $x = q("select * from groups where uid = %d",
+ $x = q("select * from pgrp where uid = %d",
intval($channel['channel_id'])
);
foreach($arr['collections'] as $cl) {
@@ -3736,7 +3750,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
if(($y['gname'] != $cl['name'])
|| ($y['visible'] != $cl['visible'])
|| ($y['deleted'] != $cl['deleted'])) {
- q("update groups set gname = '%s', visible = %d, deleted = %d where hash = '%s' and uid = %d",
+ q("update pgrp set gname = '%s', visible = %d, deleted = %d where hash = '%s' and uid = %d",
dbesc($cl['name']),
intval($cl['visible']),
intval($cl['deleted']),
@@ -3745,14 +3759,14 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
);
}
if(intval($cl['deleted']) && (! intval($y['deleted']))) {
- q("delete from group_member where gid = %d",
+ q("delete from pgrp_member where gid = %d",
intval($y['id'])
);
}
}
}
if(! $found) {
- $r = q("INSERT INTO groups ( hash, uid, visible, deleted, gname )
+ $r = q("INSERT INTO pgrp ( hash, uid, visible, deleted, gname )
VALUES( '%s', %d, %d, %d, '%s' ) ",
dbesc($cl['collection']),
intval($channel['channel_id']),
@@ -3776,10 +3790,10 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
}
}
if(! $found_local) {
- q("delete from group_member where gid = %d",
+ q("delete from pgrp_member where gid = %d",
intval($y['id'])
);
- q("update groups set deleted = 1 where id = %d and uid = %d",
+ q("update pgrp set deleted = 1 where id = %d and uid = %d",
intval($y['id']),
intval($channel['channel_id'])
);
@@ -3789,7 +3803,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
}
// reload the group list with any updates
- $x = q("select * from groups where uid = %d",
+ $x = q("select * from pgrp where uid = %d",
intval($channel['channel_id'])
);
@@ -3816,7 +3830,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
if(isset($y['hash']) && isset($members[$y['hash']])) {
foreach($members[$y['hash']] as $member) {
$found = false;
- $z = q("select xchan from group_member where gid = %d and uid = %d and xchan = '%s' limit 1",
+ $z = q("select xchan from pgrp_member where gid = %d and uid = %d and xchan = '%s' limit 1",
intval($y['id']),
intval($channel['channel_id']),
dbesc($member)
@@ -3827,7 +3841,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
// if somebody is in the group that wasn't before - add them
if(! $found) {
- q("INSERT INTO group_member (uid, gid, xchan)
+ q("INSERT INTO pgrp_member (uid, gid, xchan)
VALUES( %d, %d, '%s' ) ",
intval($channel['channel_id']),
intval($y['id']),
@@ -3838,7 +3852,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
}
// now retrieve a list of members we have on this site
- $m = q("select xchan from group_member where gid = %d and uid = %d",
+ $m = q("select xchan from pgrp_member where gid = %d and uid = %d",
intval($y['id']),
intval($channel['channel_id'])
);
@@ -3846,7 +3860,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
foreach($m as $mm) {
// if the local existing member isn't in the list we just received - remove them
if(! in_array($mm['xchan'],$members[$y['hash']])) {
- q("delete from group_member where xchan = '%s' and gid = %d and uid = %d",
+ q("delete from pgrp_member where xchan = '%s' and gid = %d and uid = %d",
dbesc($mm['xchan']),
intval($y['id']),
intval($channel['channel_id'])