aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Zotlabs/Access/PermissionLimits.php2
-rw-r--r--Zotlabs/Access/PermissionRoles.php79
-rw-r--r--Zotlabs/Access/Permissions.php37
-rw-r--r--Zotlabs/Daemon/Notifier.php12
-rw-r--r--Zotlabs/Lib/AccessList.php239
-rw-r--r--Zotlabs/Lib/Activity.php30
-rw-r--r--Zotlabs/Lib/Connect.php5
-rw-r--r--Zotlabs/Lib/Enotify.php2
-rw-r--r--Zotlabs/Lib/Group.php405
-rw-r--r--Zotlabs/Lib/Libzot.php43
-rw-r--r--Zotlabs/Lib/Permcat.php130
-rw-r--r--Zotlabs/Lib/ThreadItem.php31
-rw-r--r--Zotlabs/Module/Acl.php8
-rw-r--r--Zotlabs/Module/Admin/Site.php4
-rw-r--r--Zotlabs/Module/Apschema.php5
-rw-r--r--Zotlabs/Module/Channel.php4
-rw-r--r--Zotlabs/Module/Connections.php126
-rw-r--r--Zotlabs/Module/Connedit.php798
-rw-r--r--Zotlabs/Module/Contactedit.php668
-rw-r--r--Zotlabs/Module/Contactgroup.php26
-rw-r--r--Zotlabs/Module/Defperms.php21
-rw-r--r--Zotlabs/Module/Follow.php4
-rw-r--r--Zotlabs/Module/Group.php67
-rw-r--r--Zotlabs/Module/Item.php36
-rw-r--r--Zotlabs/Module/Network.php7
-rw-r--r--Zotlabs/Module/New_channel.php4
-rw-r--r--Zotlabs/Module/Permcats.php148
-rw-r--r--Zotlabs/Module/Profiles.php71
-rw-r--r--Zotlabs/Module/Regate.php2
-rw-r--r--Zotlabs/Module/Settings/Channel.php714
-rw-r--r--Zotlabs/Module/Settings/Privacy.php127
-rw-r--r--Zotlabs/Module/Uexport.php4
-rw-r--r--Zotlabs/Update/_1249.php31
-rw-r--r--Zotlabs/Widget/Collections.php6
-rw-r--r--Zotlabs/Widget/Messages.php2
-rw-r--r--Zotlabs/Widget/Permcats.php79
-rw-r--r--Zotlabs/Widget/Profile.php10
-rw-r--r--Zotlabs/Widget/Settings_menu.php5
-rw-r--r--app/group.apd4
-rw-r--r--boot.php8
-rw-r--r--include/attach.php6
-rw-r--r--include/channel.php49
-rw-r--r--include/connections.php3
-rw-r--r--include/conversation.php28
-rw-r--r--include/group.php2
-rw-r--r--include/items.php202
-rw-r--r--include/nav.php6
-rw-r--r--include/permissions.php40
-rw-r--r--include/selectors.php14
-rw-r--r--include/text.php64
-rw-r--r--tests/unit/Access/PermissionLimitsTest.php7
-rw-r--r--tests/unit/Access/PermissionRolesTest.php26
-rw-r--r--tests/unit/Access/PermissionsTest.php14
-rw-r--r--view/css/mod_connections.css18
-rw-r--r--view/css/widgets.css5
-rw-r--r--view/js/main.js15
-rw-r--r--view/js/mod_connections.js2
-rw-r--r--view/pdl/mod_chat.pdl2
-rw-r--r--view/pdl/mod_connections.pdl3
-rw-r--r--view/pdl/mod_connedit.pdl2
-rw-r--r--view/pdl/mod_import_items.pdl3
-rw-r--r--view/pdl/mod_permcats.pdl7
-rw-r--r--view/pdl/mod_profperm.pdl2
-rw-r--r--view/pdl/mod_viewconnections.pdl2
-rw-r--r--view/theme/redbasic/css/style.css19
-rw-r--r--view/theme/redbasic/schema/Focus-Boxy.css22
-rw-r--r--view/tpl/abook_edit.tpl164
-rw-r--r--view/tpl/admin_site.tpl2
-rw-r--r--view/tpl/connection_template.tpl21
-rw-r--r--view/tpl/connections.tpl24
-rw-r--r--view/tpl/connstatus.tpl2
-rw-r--r--view/tpl/contact_edit.tpl133
-rw-r--r--view/tpl/contact_edit_header.tpl9
-rw-r--r--view/tpl/contact_edit_modal.tpl152
-rw-r--r--view/tpl/contact_edit_tools.tpl14
-rw-r--r--view/tpl/conv_frame.tpl1
-rw-r--r--view/tpl/conv_item.tpl4
-rw-r--r--view/tpl/conv_list.tpl2
-rw-r--r--view/tpl/conversation.tpl6
-rw-r--r--view/tpl/field_acheckbox.tpl41
-rw-r--r--view/tpl/field_checkbox.tpl2
-rw-r--r--view/tpl/group_edit.tpl2
-rw-r--r--view/tpl/group_selection.tpl12
-rw-r--r--view/tpl/group_side.tpl4
-rw-r--r--view/tpl/micropro_card.tpl2
-rw-r--r--view/tpl/new_channel.tpl12
-rw-r--r--view/tpl/notes.tpl2
-rw-r--r--view/tpl/permcats.tpl68
-rw-r--r--view/tpl/privacy_groups.tpl2
-rw-r--r--view/tpl/profile_edit.tpl12
-rw-r--r--view/tpl/profile_vcard.tpl16
-rw-r--r--view/tpl/search_item.tpl2
-rw-r--r--view/tpl/settings.tpl63
-rw-r--r--view/tpl/settings_privacy.tpl56
94 files changed, 3138 insertions, 2259 deletions
diff --git a/Zotlabs/Access/PermissionLimits.php b/Zotlabs/Access/PermissionLimits.php
index fb5fe6133..7a574ba6a 100644
--- a/Zotlabs/Access/PermissionLimits.php
+++ b/Zotlabs/Access/PermissionLimits.php
@@ -89,4 +89,4 @@ class PermissionLimits {
return false;
}
-} \ No newline at end of file
+}
diff --git a/Zotlabs/Access/PermissionRoles.php b/Zotlabs/Access/PermissionRoles.php
index 998b6d8d2..2078b52a8 100644
--- a/Zotlabs/Access/PermissionRoles.php
+++ b/Zotlabs/Access/PermissionRoles.php
@@ -17,7 +17,7 @@ class PermissionRoles {
* @return number
*/
static public function version() {
- return 2;
+ return 3;
}
static function role_perms($role) {
@@ -27,6 +27,54 @@ class PermissionRoles {
$ret['role'] = $role;
switch($role) {
+
+ case 'public':
+ $ret['default_collection'] = false;
+ $ret['perms_connect'] = [
+ 'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'view_wiki',
+ 'send_stream', 'post_comments', 'post_mail', 'post_wall', 'chat', 'post_like', 'republish'
+ ];
+ $ret['limits'] = PermissionLimits::Std_Limits();
+ $ret['limits']['post_comments'] = PERMS_AUTHED;
+ $ret['limits']['post_mail'] = PERMS_AUTHED;
+ $ret['limits']['post_like'] = PERMS_AUTHED;
+ $ret['limits']['chat'] = PERMS_AUTHED;
+ break;
+
+ // Hubzilla default role
+ case 'personal':
+ $ret['default_collection'] = true;
+ $ret['perms_connect'] = [
+ 'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'view_wiki',
+ 'send_stream', 'post_comments', 'post_mail', 'chat', 'post_like'
+ ];
+ $ret['limits'] = PermissionLimits::Std_Limits();
+ $ret['limits']['view_contacts'] = PERMS_SPECIFIC;
+ break;
+
+ case 'group':
+ $ret['default_collection'] = false;
+ $ret['perms_connect'] = [
+ 'view_stream', 'view_profile', 'view_contacts', 'view_storage',
+ 'view_pages', 'view_wiki', 'post_wall', 'post_comments',
+ 'post_mail', 'post_like', 'chat'
+ ];
+ $ret['limits'] = PermissionLimits::Std_Limits();
+ $ret['channel_type'] = 'group';
+ break;
+
+ // Provide some defaults for the custom role so that we do not start
+ // with no permissions at all if we create a new channel with this role
+ case 'custom':
+ $ret['default_collection'] = true;
+ $ret['perms_connect'] = [
+ 'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'view_wiki',
+ 'send_stream', 'post_comments', 'post_mail', 'chat', 'post_like'
+ ];
+ $ret['limits'] = PermissionLimits::Std_Limits();
+ break;
+
+/*
case 'social':
$ret['perms_auto'] = false;
$ret['default_collection'] = false;
@@ -193,13 +241,14 @@ class PermissionRoles {
$ret['channel_type'] = 'group';
break;
+*/
- case 'custom':
default:
break;
}
$x = get_config('system','role_perms');
+
// let system settings over-ride any or all
if($x && is_array($x) && array_key_exists($role,$x))
$ret = array_merge($ret,$x[$role]);
@@ -284,6 +333,7 @@ class PermissionRoles {
*/
static public function roles() {
$roles = [
+
t('Social Networking') => [
'social_federation' => t('Social - Federation'),
'social' => t('Social - Mostly Public'),
@@ -317,4 +367,29 @@ class PermissionRoles {
return $roles;
}
+ /**
+ * @brief Array with translated role names and grouping.
+ *
+ * Return an associative array with role names that can be used
+ * to create select groups like in \e field_select_grouped.tpl.
+ *
+ * @return array
+ */
+ static public function channel_roles() {
+ $channel_roles = [
+ //'public' => [t('Public'), t('A very permissive role suited for participation in the fediverse')],
+ //'personal' => [t('Personal'), t('The $Projectname default role suited for a personal channel')],
+ //'forum' => [t('Community forum'), t('This role configures your channel to act as an community forum')],
+ //'custom' => [t('Custom'), t('This role comes with the presets of the personal role but allows you to configure it to your needs')]
+ 'public' => t('Public'),
+ 'personal' => t('Personal'),
+ 'group' => t('Community forum'),
+ 'custom' => t('Custom')
+ ];
+
+ call_hooks('list_channel_roles', $channel_roles);
+
+ return $channel_roles;
+ }
+
}
diff --git a/Zotlabs/Access/Permissions.php b/Zotlabs/Access/Permissions.php
index 45dd30d69..09f4c9678 100644
--- a/Zotlabs/Access/Permissions.php
+++ b/Zotlabs/Access/Permissions.php
@@ -41,7 +41,7 @@ class Permissions {
* @return number
*/
static public function version() {
- return 2;
+ return 3;
}
/**
@@ -67,9 +67,9 @@ class Permissions {
'post_comments' => t('Can comment on or like my posts'),
'post_mail' => t('Can send me direct messages'),
'post_like' => t('Can like/dislike profiles and profile things'),
- 'tag_deliver' => t('Can forward direct messages to all my channel connections (forum)'),
'chat' => t('Can chat with me'),
- 'republish' => t('Can source my public posts in derived channels'),
+ 'republish' => t('Can source/mirror my public posts in derived channels'),
+ //'tag_deliver' => t('Can forward to my contacts via direct messages (forum)'),
'delegate' => t('Can administer my channel')
];
@@ -217,25 +217,23 @@ class Permissions {
$my_perms = [];
$permcat = null;
- $automatic = 0;
+ $automatic = get_pconfig($channel_id, 'system', 'autoperms');
// If a default permcat exists, use that
- $pc = ((feature_enabled($channel_id, 'permcats')) ? get_pconfig($channel_id, 'system', 'default_permcat') : 'default');
- if (!in_array($pc, ['', 'default'])) {
- $pcp = new Zlib\Permcat($channel_id);
- $permcat = $pcp->fetch($pc);
- if ($permcat && $permcat['perms']) {
- foreach ($permcat['perms'] as $p) {
- $my_perms[$p['name']] = $p['value'];
- }
+ $pc = get_pconfig($channel_id, 'system', 'default_permcat', 'default');
+ $pcp = new Zlib\Permcat($channel_id);
+ $permcat = $pcp->fetch($pc);
+ if ($permcat && $permcat['perms']) {
+ foreach ($permcat['perms'] as $p) {
+ $my_perms[$p['name']] = $p['value'];
}
}
// look up the permission role to see if it specified auto-connect
// and if there was no permcat or a default permcat, set the perms
// from the role
-
+/*
$role = get_pconfig($channel_id, 'system', 'permissions_role');
if ($role) {
$xx = PermissionRoles::role_perms($role);
@@ -247,11 +245,12 @@ class Permissions {
$my_perms = Permissions::FilledPerms($default_perms);
}
}
+*/
// If we reached this point without having any permission information,
// it is likely a custom permissions role. First see if there are any
// automatic permissions.
-
+/*
if (!$my_perms) {
$m = Permissions::FilledAutoperms($channel_id);
if ($m) {
@@ -259,11 +258,12 @@ class Permissions {
$my_perms = $m;
}
}
-
+*/
// If we reached this point with no permissions, the channel is using
// custom perms but they are not automatic. They will be stored in abconfig with
// the channel's channel_hash (the 'self' connection).
+/*
if (!$my_perms) {
$r = q("select channel_hash from channel where channel_id = %d",
intval($channel_id)
@@ -280,10 +280,10 @@ class Permissions {
}
}
}
-
- return (['perms' => $my_perms, 'automatic' => $automatic]);
+*/
+ return (['perms' => $my_perms, 'automatic' => $automatic, 'role' => $pc]);
}
-
+/*
static public function serialise($p) {
$n = [];
if ($p) {
@@ -295,4 +295,5 @@ class Permissions {
}
return implode(',', $n);
}
+*/
}
diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php
index 4ca109495..23bddae8f 100644
--- a/Zotlabs/Daemon/Notifier.php
+++ b/Zotlabs/Daemon/Notifier.php
@@ -630,6 +630,18 @@ class Notifier {
// default: zot protocol
+ // Prevent zot6 delivery of group comment boosts, which are not required for conversational platforms.
+ // ActivityPub conversational platforms may wish to filter these if they don't want or require them.
+ // We will assume here that if $target_item exists and has a verb that it is an actual item structure
+ // so we won't need to check the existence of the other item fields prior to evaluation.
+
+ // This shouldn't produce false positives on comment boosts that were generated on other platforms
+ // because we won't be delivering them.
+
+ if (isset($target_item) && isset($target_item['verb']) && $target_item['verb'] === 'Announce' && $target_item['author_xchan'] === $target_item['owner_xchan'] && ! intval($target_item['item_thread_top'])) {
+ continue;
+ }
+
$hash = new_uuid();
$env = (($hub_env && $hub_env[$hub['hubloc_site_id']]) ? $hub_env[$hub['hubloc_site_id']] : '');
diff --git a/Zotlabs/Lib/AccessList.php b/Zotlabs/Lib/AccessList.php
index 3c008f8c7..51c100afb 100644
--- a/Zotlabs/Lib/AccessList.php
+++ b/Zotlabs/Lib/AccessList.php
@@ -1,38 +1,37 @@
-<?php
+<?php
namespace Zotlabs\Lib;
-use Zotlabs\Lib\Libsync;
-
-
class AccessList {
-
- static function add($uid,$name,$public = 0) {
- $ret = false;
+ static function add($uid, $name, $public = 0) {
+
+ $ret = false;
+ $hash = '';
if ($uid && $name) {
- $r = self::byname($uid,$name); // check for dups
+ $r = self::by_name($uid, $name); // check for dups
if ($r !== false) {
- // This could be a problem.
+ // This could be a problem.
// Let's assume we've just created a list which we once deleted
// all the old members are gone, but the list remains so we don't break any security
// access lists. What we're doing here is reviving the dead list, but old content which
- // was restricted to this list may now be seen by the new list members.
+ // was restricted to this list may now be seen by the new list members.
$z = q("SELECT * FROM pgrp WHERE id = %d LIMIT 1",
intval($r)
);
- if(($z) && $z[0]['deleted']) {
+ if (($z) && $z[0]['deleted']) {
q('UPDATE pgrp SET deleted = 0 WHERE id = %d', intval($z[0]['id']));
- notice( t('A deleted list with this name was revived. Existing item permissions <strong>may</strong> apply to this list and any future members. If this is not what you intended, please create another list with a different name.') . EOL);
+ notice(t('A deleted list with this name was revived. Existing item permissions <strong>may</strong> apply to this list and any future members. If this is not what you intended, please create another list with a different name.') . EOL);
}
- return true;
+ $hash = self::by_id($uid, $r);
+ return $hash;
}
$hash = new_uuid();
- $r = q("INSERT INTO pgrp ( hash, uid, visible, gname )
+ $r = q("INSERT INTO pgrp ( hash, uid, visible, gname )
VALUES( '%s', %d, %d, '%s' ) ",
dbesc($hash),
intval($uid),
@@ -42,12 +41,12 @@ class AccessList {
$ret = $r;
}
- Libsync::build_sync_packet($uid,null,true);
- return $ret;
- }
+ Libsync::build_sync_packet($uid, null, true);
+ return (($ret) ? $hash : $ret);
+ }
- static function remove($uid,$name) {
+ static function remove($uid, $name) {
$ret = false;
if ($uid && $name) {
$r = q("SELECT id, hash FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
@@ -55,36 +54,36 @@ class AccessList {
dbesc($name)
);
if ($r) {
- $group_id = $r[0]['id'];
+ $group_id = $r[0]['id'];
$group_hash = $r[0]['hash'];
}
else {
return false;
}
-
+
// remove group from default posting lists
$r = q("SELECT channel_default_group, channel_allow_gid, channel_deny_gid FROM channel WHERE channel_id = %d LIMIT 1",
- intval($uid)
+ intval($uid)
);
if ($r) {
$user_info = array_shift($r);
- $change = false;
+ $change = false;
if ($user_info['channel_default_group'] == $group_hash) {
$user_info['channel_default_group'] = '';
- $change = true;
+ $change = true;
}
if (strpos($user_info['channel_allow_gid'], '<' . $group_hash . '>') !== false) {
$user_info['channel_allow_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_allow_gid']);
- $change = true;
+ $change = true;
}
if (strpos($user_info['channel_deny_gid'], '<' . $group_hash . '>') !== false) {
$user_info['channel_deny_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_deny_gid']);
- $change = true;
+ $change = true;
}
if ($change) {
- q("UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s'
+ q("UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s'
WHERE channel_id = %d",
intval($user_info['channel_default_group']),
dbesc($user_info['channel_allow_gid']),
@@ -110,16 +109,16 @@ class AccessList {
}
- Libsync::build_sync_packet($uid,null,true);
+ Libsync::build_sync_packet($uid, null, true);
return $ret;
}
// returns the integer id of an access group owned by $uid and named $name
// or false.
-
- static function byname($uid,$name) {
- if (! ($uid && $name)) {
+
+ static function by_name($uid, $name) {
+ if (!($uid && $name)) {
return false;
}
$r = q("SELECT id FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
@@ -132,11 +131,11 @@ class AccessList {
return false;
}
- static function by_id($uid,$id) {
- if (! ($uid && $id)) {
+ static function by_id($uid, $id) {
+ if (!($uid && $id)) {
return false;
}
-
+
$r = q("SELECT * FROM pgrp WHERE uid = %d AND id = %d and deleted = 0",
intval($uid),
intval($id)
@@ -147,10 +146,8 @@ class AccessList {
return false;
}
-
-
- static function rec_byhash($uid,$hash) {
- if (! ( $uid && $hash)) {
+ static function by_hash($uid, $hash) {
+ if (!($uid && $hash)) {
return false;
}
$r = q("SELECT * FROM pgrp WHERE uid = %d AND hash = '%s' LIMIT 1",
@@ -163,46 +160,43 @@ class AccessList {
return false;
}
+ static function member_remove($uid, $name, $member) {
+ $gid = self::by_name($uid, $name);
- static function member_remove($uid,$name,$member) {
- $gid = self::byname($uid,$name);
- if (! $gid) {
- return false;
- }
- if (! ($uid && $gid && $member)) {
+ if (!($uid && $gid && $member)) {
return false;
}
+
$r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' ",
intval($uid),
intval($gid),
dbesc($member)
);
- Libsync::build_sync_packet($uid,null,true);
+ Libsync::build_sync_packet($uid, null, true);
return $r;
}
-
- static function member_add($uid,$name,$member,$gid = 0) {
- if (! $gid) {
- $gid = self::byname($uid,$name);
+ static function member_add($uid, $name, $member, $gid = 0) {
+ if (!$gid) {
+ $gid = self::by_name($uid, $name);
}
- if (! ($gid && $uid && $member)) {
+ if (!($gid && $uid && $member)) {
return false;
}
- $r = q("SELECT * FROM pgrp_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)
);
if ($r) {
- return true; // You might question this, but
- // we indicate success because the group member was in fact created
- // -- It was just created at another time
+ return true; // You might question this, but
+ // we indicate success because the group member was in fact created
+ // -- It was just created at another time
}
- else {
+ else {
$r = q("INSERT INTO pgrp_member (uid, gid, xchan)
VALUES( %d, %d, '%s' ) ",
intval($uid),
@@ -210,15 +204,14 @@ class AccessList {
dbesc($member)
);
}
- Libsync::build_sync_packet($uid,null,true);
+ Libsync::build_sync_packet($uid, null, true);
return $r;
}
-
static function members($uid, $gid) {
$ret = [];
if (intval($gid)) {
- $r = q("SELECT * FROM pgrp_member
+ $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),
@@ -232,7 +225,7 @@ class AccessList {
return $ret;
}
- static function members_xchan($uid,$gid) {
+ static function members_xchan($uid, $gid) {
$ret = [];
if (intval($gid)) {
$r = q("SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d",
@@ -248,99 +241,123 @@ class AccessList {
return $ret;
}
- static function members_profile_xchan($uid,$gid) {
+ static function profile_members_xchan($uid,$gid) {
$ret = [];
- if (intval($gid)) {
+
+ if(intval($gid)) {
$r = q("SELECT abook_xchan as xchan from abook left join profile on abook_profile = profile_guid where profile.id = %d and profile.uid = %d",
intval($gid),
intval($uid)
);
- if ($r) {
- foreach($r as $rv) {
- $ret[] = $rv['xchan'];
+ if($r) {
+ foreach($r as $rr) {
+ $ret[] = $rr['xchan'];
}
}
}
return $ret;
}
+ static function select($uid, $options) {
+ $selected = $options['selected'] ?? '';
+ $form_id = $options['form_id'] ?? 'accesslist_select';
+ $label = $options['label'] ?? t('Select a privacy group');
+ $before = $options['before'] ?? [];
+ $after = $options['after'] ?? [];
-
- static function select($uid,$group = '') {
-
$grps = [];
+ $o = '';
+
+ $grps[] = [
+ 'name' => '',
+ 'id' => '0',
+ 'selected' => false
+ ];
+
+ if ($before) {
+ $grps[] = $before;
+ }
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
intval($uid)
);
- $grps[] = [ 'name' => '', 'hash' => '0', 'selected' => '' ];
- if ($r) {
- foreach ($r as $rr) {
- $grps[] = [ 'name' => $rr['gname'], 'id' => $rr['hash'], 'selected' => (($group == $rr['hash']) ? 'true' : '') ];
+
+ if($r) {
+ foreach($r as $rr) {
+ $grps[] = [
+ 'name' => $rr['gname'],
+ 'id' => $rr['hash'],
+ 'selected' => ($selected == $rr['hash'])
+ ];
}
+ }
+ if ($after) {
+ $grps[] = $after;
}
-
- return replace_macros(get_markup_template('group_selection.tpl'), [
- '$label' => t('Add new connections to this access list'),
- '$groups' => $grps
- ]);
- }
+ logger('select: ' . print_r($grps,true), LOGGER_DATA);
- static function widget($every="connections",$each="lists",$edit = false, $group_id = 0, $cid = '',$mode = 1) {
+ $o = replace_macros(get_markup_template('group_selection.tpl'), array(
+ '$label' => $label,
+ '$form_id' => $form_id,
+ '$groups' => $grps
+ ));
+
+ return $o;
+ }
- $o = '';
+
+ static function widget($every = "connections", $each = "lists", $edit = false, $group_id = 0, $cid = '', $mode = 1) {
$groups = [];
- $r = q("SELECT * FROM pgrp 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 = [];
if ($cid) {
- $member_of = self::containing(local_channel(),$cid);
- }
+ $member_of = self::containing(local_channel(), $cid);
+ }
if ($r) {
foreach ($r as $rr) {
$selected = (($group_id == $rr['id']) ? ' group-selected' : '');
-
+
if ($edit) {
- $groupedit = [ 'href' => "lists/".$rr['id'], 'title' => t('edit') ];
- }
+ $groupedit = ['href' => "lists/" . $rr['id'], 'title' => t('edit')];
+ }
else {
$groupedit = null;
}
-
+
$groups[] = [
- 'id' => $rr['id'],
- 'enc_cid' => base64url_encode($cid),
- 'cid' => $cid,
- 'text' => $rr['gname'],
- 'selected' => $selected,
- 'href' => (($mode == 0) ? $each.'?f=&gid='.$rr['id'] : $each."/".$rr['id']) . ((x($_GET,'new')) ? '&new=' . $_GET['new'] : '') . ((x($_GET,'order')) ? '&order=' . $_GET['order'] : ''),
- 'edit' => $groupedit,
- 'ismember' => in_array($rr['id'],$member_of),
+ 'id' => $rr['id'],
+ 'enc_cid' => base64url_encode($cid),
+ 'cid' => $cid,
+ 'text' => $rr['gname'],
+ 'selected' => $selected,
+ 'href' => (($mode == 0) ? $each . '?f=&gid=' . $rr['id'] : $each . "/" . $rr['id']) . ((x($_GET, 'new')) ? '&new=' . $_GET['new'] : '') . ((x($_GET, 'order')) ? '&order=' . $_GET['order'] : ''),
+ 'edit' => $groupedit,
+ 'ismember' => in_array($rr['id'], $member_of),
];
}
}
-
+
return replace_macros(get_markup_template('group_side.tpl'), [
- '$title' => t('Lists'),
- '$edittext' => t('Edit list'),
- '$createtext' => t('Create new list'),
- '$ungrouped' => (($every === 'contacts') ? t('Channels not in any access list') : ''),
- '$groups' => $groups,
- '$add' => t('add'),
+ '$title' => t('Lists'),
+ '$edittext' => t('Edit list'),
+ '$createtext' => t('Create new list'),
+ '$ungrouped' => (($every === 'contacts') ? t('Channels not in any access list') : ''),
+ '$groups' => $groups,
+ '$add' => t('add'),
]);
}
-
static function expand($g) {
- if (! (is_array($g) && count($g))) {
+ if (!(is_array($g) && count($g))) {
return [];
}
@@ -350,8 +367,8 @@ class AccessList {
// private profile linked virtual groups
foreach ($g as $gv) {
- if (substr($gv,0,3) === 'vp.') {
- $profile_hash = substr($gv,3);
+ if (substr($gv, 0, 3) === 'vp.') {
+ $profile_hash = substr($gv, 3);
if ($profile_hash) {
$r = q("select abook_xchan from abook where abook_profile = '%s'",
dbesc($profile_hash)
@@ -366,10 +383,10 @@ class AccessList {
else {
$x[] = $gv;
}
- }
+ }
if ($x) {
- stringify_array_elms($x,true);
+ stringify_array_elms($x, true);
$groups = implode(',', $x);
if ($groups) {
$r = q("SELECT xchan FROM pgrp_member WHERE gid IN ( select id from pgrp where hash in ( $groups ))");
@@ -383,9 +400,8 @@ class AccessList {
return $ret;
}
-
static function member_of($c) {
- $r = q("SELECT pgrp.gname, pgrp.id FROM pgrp LEFT JOIN pgrp_member ON pgrp_member.gid = pgrp.id
+ $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)
);
@@ -393,7 +409,7 @@ class AccessList {
return $r;
}
- static function containing($uid,$c) {
+ static function containing($uid, $c) {
$r = q("SELECT gid FROM pgrp_member WHERE uid = %d AND pgrp_member.xchan = '%s' ",
intval($uid),
@@ -405,7 +421,8 @@ class AccessList {
foreach ($r as $rv)
$ret[] = $rv['gid'];
}
-
+
return $ret;
}
-} \ No newline at end of file
+
+}
diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php
index 664886fc2..8e5a4e1a6 100644
--- a/Zotlabs/Lib/Activity.php
+++ b/Zotlabs/Lib/Activity.php
@@ -886,10 +886,6 @@ class Activity {
else
return [];
- if (strpos($i['body'], '[/share]') !== false) {
- $i['obj'] = null;
- }
-
if ($i['obj']) {
if (!is_array($i['obj'])) {
$i['obj'] = json_decode($i['obj'], true);
@@ -899,8 +895,10 @@ class Activity {
}
$obj = self::encode_object($i['obj']);
- if ($obj)
+
+ if ($obj) {
$ret['object'] = $obj;
+ }
else
return [];
}
@@ -1042,7 +1040,7 @@ class Activity {
$tmp = expand_acl($i['allow_cid']);
$list = stringify_array($tmp, true);
if ($list) {
- $details = q("select hubloc_id_url from hubloc where hubloc_hash in (" . $list . ") and hubloc_id_url != ''");
+ $details = q("select hubloc_id_url from hubloc where hubloc_hash in (" . $list . ") and hubloc_id_url != '' and hubloc_deleted = 0");
if ($details) {
foreach ($details as $d) {
$ret[] = $d['hubloc_id_url'];
@@ -1089,10 +1087,11 @@ class Activity {
$ret['type'] = 'Person';
if ($c) {
- $role = get_pconfig($c['channel_id'], 'system', 'permissions_role');
- if (strpos($role, 'forum') !== false) {
+ if (get_pconfig($c['channel_id'], 'system', 'group_actor')) {
$ret['type'] = 'Group';
}
+
+ $ret['manuallyApprovesFollowers'] = ((get_pconfig($c['channel_id'], 'system', 'autoperms')) ? false : true);
}
if ($c) {
@@ -1554,9 +1553,9 @@ class Activity {
/* If there is a default group for this channel and permissions are automatic, add this member to it */
if ($channel['channel_default_group'] && $automatic) {
- $g = Group::rec_byhash($channel['channel_id'], $channel['channel_default_group']);
+ $g = AccessList::by_hash($channel['channel_id'], $channel['channel_default_group']);
if ($g)
- Group::member_add($channel['channel_id'], '', $ret['xchan_hash'], $g['id']);
+ AccessList::member_add($channel['channel_id'], '', $ret['xchan_hash'], $g['id']);
}
@@ -2692,6 +2691,17 @@ class Activity {
// set the owner to the owner of the parent
$item['owner_xchan'] = $p[0]['owner_xchan'];
+ // quietly reject group comment boosts by group owner
+ // (usually only sent via ActivityPub so groups will work on microblog platforms)
+ // This catches those activities if they slipped in via a conversation fetch
+
+ if ($p[0]['parent_mid'] !== $item['parent_mid']) {
+ if ($item['verb'] === 'Announce' && $item['author_xchan'] === $item['owner_xchan']) {
+ logger('group boost activity by group owner rejected');
+ return;
+ }
+ }
+
// check permissions against the author, not the sender
$allowed = perm_is_allowed($channel['channel_id'], $item['author_xchan'], 'post_comments');
if ((!$allowed)/* && $permit_mentions*/) {
diff --git a/Zotlabs/Lib/Connect.php b/Zotlabs/Lib/Connect.php
index 38fe69995..0b9ff7089 100644
--- a/Zotlabs/Lib/Connect.php
+++ b/Zotlabs/Lib/Connect.php
@@ -261,7 +261,8 @@ class Connect {
'abook_feed' => intval(($xchan['xchan_network'] === 'rss') ? 1 : 0),
'abook_created' => datetime_convert(),
'abook_updated' => datetime_convert(),
- 'abook_instance' => (($singleton) ? z_root() : '')
+ 'abook_instance' => (($singleton) ? z_root() : ''),
+ 'abook_role' => get_pconfig($uid, 'system', 'default_permcat', 'default')
]
);
}
@@ -300,7 +301,7 @@ class Connect {
/** If there is a default group for this channel, add this connection to it */
if ($default_group) {
- $g = AccessList::rec_byhash($uid,$default_group);
+ $g = AccessList::by_hash($uid,$default_group);
if ($g) {
AccessList::member_add($uid,'',$xchan_hash,$g['id']);
}
diff --git a/Zotlabs/Lib/Enotify.php b/Zotlabs/Lib/Enotify.php
index fdc7d4567..2e483cb92 100644
--- a/Zotlabs/Lib/Enotify.php
+++ b/Zotlabs/Lib/Enotify.php
@@ -902,7 +902,7 @@ class Enotify {
static public function format_intros($rr) {
return [
- 'notify_link' => z_root() . '/connections/ifpending',
+ 'notify_link' => z_root() . '/connections#' . $rr['abook_id'],
'name' => $rr['xchan_name'],
'addr' => $rr['xchan_addr'],
'url' => $rr['xchan_url'],
diff --git a/Zotlabs/Lib/Group.php b/Zotlabs/Lib/Group.php
deleted file mode 100644
index a4ff4fced..000000000
--- a/Zotlabs/Lib/Group.php
+++ /dev/null
@@ -1,405 +0,0 @@
-<?php
-
-namespace Zotlabs\Lib;
-
-use Zotlabs\Lib\Libsync;
-
-
-class Group {
-
- static function add($uid,$name,$public = 0) {
-
- $ret = false;
- if(x($uid) && x($name)) {
- $r = self::byname($uid,$name); // check for dups
- if($r !== false) {
-
- // This could be a problem.
- // Let's assume we've just created a group which we once deleted
- // all the old members are gone, but the group remains so we don't break any security
- // 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 pgrp WHERE id = %d LIMIT 1",
- intval($r)
- );
- if(($z) && $z[0]['deleted']) {
- 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;
- }
-
- do {
- $dups = false;
- $hash = random_string(32) . str_replace(['<','>'],['.','.'], $name);
-
- $r = q("SELECT id FROM pgrp WHERE hash = '%s' LIMIT 1", dbesc($hash));
- if($r)
- $dups = true;
- } while($dups == true);
-
-
- $r = q("INSERT INTO pgrp ( hash, uid, visible, gname )
- VALUES( '%s', %d, %d, '%s' ) ",
- dbesc($hash),
- intval($uid),
- intval($public),
- dbesc($name)
- );
- $ret = $r;
- }
-
- Libsync::build_sync_packet($uid,null,true);
- return $ret;
- }
-
-
- static function remove($uid,$name) {
- $ret = false;
- if(x($uid) && x($name)) {
- $r = q("SELECT id, hash FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
- intval($uid),
- dbesc($name)
- );
- if($r) {
- $group_id = $r[0]['id'];
- $group_hash = $r[0]['hash'];
- }
-
- if(! $group_id)
- return false;
-
- // remove group from default posting lists
- $r = q("SELECT channel_default_group, channel_allow_gid, channel_deny_gid FROM channel WHERE channel_id = %d LIMIT 1",
- intval($uid)
- );
- if($r) {
- $user_info = $r[0];
- $change = false;
-
- if($user_info['channel_default_group'] == $group_hash) {
- $user_info['channel_default_group'] = '';
- $change = true;
- }
- if(strpos($user_info['channel_allow_gid'], '<' . $group_hash . '>') !== false) {
- $user_info['channel_allow_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_allow_gid']);
- $change = true;
- }
- if(strpos($user_info['channel_deny_gid'], '<' . $group_hash . '>') !== false) {
- $user_info['channel_deny_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_deny_gid']);
- $change = true;
- }
-
- if($change) {
- q("UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s'
- WHERE channel_id = %d",
- intval($user_info['channel_default_group']),
- dbesc($user_info['channel_allow_gid']),
- dbesc($user_info['channel_deny_gid']),
- intval($uid)
- );
- }
- }
-
- // remove all members
- $r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d ",
- intval($uid),
- intval($group_id)
- );
-
- // remove group
- $r = q("UPDATE pgrp SET deleted = 1 WHERE uid = %d AND gname = '%s'",
- intval($uid),
- dbesc($name)
- );
-
- $ret = $r;
-
- }
-
- Libsync::build_sync_packet($uid,null,true);
-
- return $ret;
- }
-
-
- static function byname($uid,$name) {
- if((! $uid) || (! strlen($name)))
- return false;
- $r = q("SELECT * FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
- intval($uid),
- dbesc($name)
- );
- if($r)
- return $r[0]['id'];
- return false;
- }
-
-
- static function rec_byhash($uid,$hash) {
- if((! $uid) || (! strlen($hash)))
- return false;
- $r = q("SELECT * FROM pgrp WHERE uid = %d AND hash = '%s' LIMIT 1",
- intval($uid),
- dbesc($hash)
- );
- if($r)
- return $r[0];
- return false;
- }
-
-
- static function member_remove($uid,$name,$member) {
- $gid = self::byname($uid,$name);
- if(! $gid)
- return false;
- if(! ( $uid && $gid && $member))
- return false;
- $r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' ",
- intval($uid),
- intval($gid),
- dbesc($member)
- );
-
- Libsync::build_sync_packet($uid,null,true);
-
- return $r;
- }
-
-
- static function member_add($uid,$name,$member,$gid = 0) {
- if(! $gid)
- $gid = self::byname($uid,$name);
- if((! $gid) || (! $uid) || (! $member))
- return false;
-
- $r = q("SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",
- intval($uid),
- intval($gid),
- dbesc($member)
- );
- if($r)
- return true; // You might question this, but
- // we indicate success because the group member was in fact created
- // -- It was just created at another time
- if(! $r)
- $r = q("INSERT INTO pgrp_member (uid, gid, xchan)
- VALUES( %d, %d, '%s' ) ",
- intval($uid),
- intval($gid),
- dbesc($member)
- );
-
- Libsync::build_sync_packet($uid,null,true);
-
- return $r;
- }
-
-
- static function members($gid) {
- $ret = array();
- if(intval($gid)) {
- $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())
- );
- if($r)
- $ret = $r;
- }
- return $ret;
- }
-
- static function members_xchan($gid) {
- $ret = [];
- if(intval($gid)) {
- $r = q("SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d",
- intval($gid),
- intval(local_channel())
- );
- if($r) {
- foreach($r as $rr) {
- $ret[] = $rr['xchan'];
- }
- }
- }
- return $ret;
- }
-
- static function members_profile_xchan($uid,$gid) {
- $ret = [];
-
- if(intval($gid)) {
- $r = q("SELECT abook_xchan as xchan from abook left join profile on abook_profile = profile_guid where profile.id = %d and profile.uid = %d",
- intval($gid),
- intval($uid)
- );
- if($r) {
- foreach($r as $rr) {
- $ret[] = $rr['xchan'];
- }
- }
- }
- return $ret;
- }
-
-
-
-
- static function select($uid,$group = '') {
-
- $grps = [];
- $o = '';
-
- $r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
- intval($uid)
- );
- $grps[] = array('name' => '', 'hash' => '0', 'selected' => '');
- if($r) {
- foreach($r as $rr) {
- $grps[] = array('name' => $rr['gname'], 'id' => $rr['hash'], 'selected' => (($group == $rr['hash']) ? 'true' : ''));
- }
-
- }
- logger('select: ' . print_r($grps,true), LOGGER_DATA);
-
- $o = replace_macros(get_markup_template('group_selection.tpl'), array(
- '$label' => t('Add new connections to this privacy group'),
- '$groups' => $grps
- ));
- return $o;
- }
-
-
-
-
- static function widget($every="connections",$each="group",$edit = false, $group_id = 0, $cid = '',$mode = 1) {
-
- $o = '';
-
- if(! (local_channel() && feature_enabled(local_channel(),'groups'))) {
- return '';
- }
-
- $groups = array();
-
- $r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
- intval($_SESSION['uid'])
- );
- $member_of = array();
- if($cid) {
- $member_of = self::containing(local_channel(),$cid);
- }
-
- if($r) {
- foreach($r as $rr) {
- $selected = (($group_id == $rr['id']) ? ' group-selected' : '');
-
- if ($edit) {
- $groupedit = [ 'href' => "group/".$rr['id'], 'title' => t('edit') ];
- }
- else {
- $groupedit = null;
- }
-
- $groups[] = [
- 'id' => $rr['id'],
- 'enc_cid' => base64url_encode($cid),
- 'cid' => $cid,
- 'text' => $rr['gname'],
- 'selected' => $selected,
- 'href' => (($mode == 0) ? $each.'?f=&gid='.$rr['id'] : $each."/".$rr['id']) . ((x($_GET,'new')) ? '&new=' . $_GET['new'] : '') . ((x($_GET,'order')) ? '&order=' . $_GET['order'] : ''),
- 'edit' => $groupedit,
- 'ismember' => in_array($rr['id'],$member_of),
- ];
- }
- }
-
-
- $tpl = get_markup_template("group_side.tpl");
- $o = replace_macros($tpl, array(
- '$title' => t('Privacy Groups'),
- '$edittext' => t('Edit group'),
- '$createtext' => t('Add privacy group'),
- '$ungrouped' => (($every === 'contacts') ? t('Channels not in any privacy group') : ''),
- '$groups' => $groups,
- '$add' => t('add'),
- ));
-
-
- return $o;
- }
-
-
- static function expand($g) {
- if(! (is_array($g) && count($g)))
- return array();
-
- $ret = [];
- $x = [];
-
- // private profile linked virtual groups
-
- foreach($g as $gv) {
- if(substr($gv,0,3) === 'vp.') {
- $profile_hash = substr($gv,3);
- if($profile_hash) {
- $r = q("select abook_xchan from abook where abook_profile = '%s'",
- dbesc($profile_hash)
- );
- if($r) {
- foreach($r as $rv) {
- $ret[] = $rv['abook_xchan'];
- }
- }
- }
- }
- else {
- $x[] = $gv;
- }
- }
-
- if($x) {
- stringify_array_elms($x,true);
- $groups = implode(',', $x);
- if($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'];
- }
- }
- }
- }
- return $ret;
- }
-
-
- static function member_of($c) {
- $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)
- );
-
- return $r;
-
- }
-
- static function containing($uid,$c) {
-
- $r = q("SELECT gid FROM pgrp_member WHERE uid = %d AND pgrp_member.xchan = '%s' ",
- intval($uid),
- dbesc($c)
- );
-
- $ret = array();
- if($r) {
- foreach($r as $rr)
- $ret[] = $rr['gid'];
- }
-
- return $ret;
- }
-} \ No newline at end of file
diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php
index 31b8f04de..e2cbc66e6 100644
--- a/Zotlabs/Lib/Libzot.php
+++ b/Zotlabs/Lib/Libzot.php
@@ -386,9 +386,10 @@ class Libzot {
else {
$p = Permissions::connect_perms($channel['channel_id']);
- $my_perms = $p['perms'];
+ $my_perms = $p['perms'];
$automatic = $p['automatic'];
+ $role = (($automatic) ? $p['role'] : '');
// new connection
@@ -410,7 +411,8 @@ class Libzot {
'abook_created' => datetime_convert(),
'abook_updated' => datetime_convert(),
'abook_dob' => $next_birthday,
- 'abook_pending' => intval(($automatic) ? 0 : 1)
+ 'abook_pending' => intval(($automatic) ? 0 : 1),
+ 'abook_role' => $role
]
);
@@ -435,7 +437,7 @@ class Libzot {
'type' => NOTIFY_INTRO,
'from_xchan' => $x['hash'],
'to_xchan' => $channel['channel_hash'],
- 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id']
+ 'link' => z_root() . '/connections#' . $new_connection[0]['abook_id']
]
);
@@ -453,10 +455,10 @@ class Libzot {
$default_group = $channel['channel_default_group'];
if ($default_group) {
- $g = Group::rec_byhash($channel['channel_id'], $default_group);
+ $g = AccessList::by_hash($channel['channel_id'], $default_group);
if ($g) {
- Group::member_add($channel['channel_id'], '', $x['hash'], $g['id']);
+ AccessList::member_add($channel['channel_id'], '', $x['hash'], $g['id']);
}
}
}
@@ -1143,6 +1145,7 @@ class Libzot {
if ($env['encoding'] === 'activitystreams') {
$AS = new ActivityStreams($data);
+
if (!$AS->is_valid()) {
logger('Activity rejected: ' . print_r($data, true));
return;
@@ -1158,8 +1161,6 @@ class Libzot {
}
-
-
$deliveries = null;
if (array_key_exists('recipients', $env) && count($env['recipients'])) {
@@ -1592,6 +1593,7 @@ class Libzot {
if ((!$tag_delivery) && (!$local_public)) {
$allowed = (perm_is_allowed($channel['channel_id'], $sender, $perm));
+
if ((!$allowed) && $perm === 'post_comments') {
$parent = q("select * from item where mid = '%s' and uid = %d limit 1",
dbesc($arr['parent_mid']),
@@ -2785,28 +2787,6 @@ class Libzot {
if ($deleted || $censored || $sys_channel)
$searchable = false;
- $public_forum = false;
-
- $role = get_pconfig($e['channel_id'], 'system', 'permissions_role');
- if ($role === 'forum' || $role === 'repository') {
- $public_forum = true;
- }
- else {
- // check if it has characteristics of a public forum based on custom permissions.
- $m = Permissions::FilledAutoperms($e['channel_id']);
- if ($m) {
- foreach ($m as $k => $v) {
- if ($k == 'tag_deliver' && intval($v) == 1)
- $ch++;
- if ($k == 'send_stream' && intval($v) == 0)
- $ch++;
- }
- if ($ch == 2)
- $public_forum = true;
- }
- }
-
-
// This is for birthdays and keywords, but must check access permissions
$p = q("select * from profile where uid = %d and is_default = 1",
intval($e['channel_id'])
@@ -2875,6 +2855,7 @@ class Libzot {
];
$ret['channel_role'] = get_pconfig($e['channel_id'], 'system', 'permissions_role', 'custom');
+ $ret['channel_type'] = ((get_pconfig($e['channel_id'], 'system', 'group_actor')) ? 'group' : 'normal');
$hookinfo = [
'channel_id' => $id,
@@ -2890,8 +2871,10 @@ class Libzot {
$ret['protocols'] = $hookinfo['protocols'];
$ret['searchable'] = $searchable;
$ret['adult_content'] = $adult_channel;
- $ret['public_forum'] = $public_forum;
+ // now all forums (public, restricted, and private) set the public_forum flag. So it really means "is a group"
+ // and has nothing to do with accessibility.
+ $ret['public_forum'] = get_pconfig($e['channel_id'], 'system', 'group_actor');
$ret['comments'] = map_scope(PermissionLimits::Get($e['channel_id'], 'post_comments'));
$ret['mail'] = map_scope(PermissionLimits::Get($e['channel_id'], 'post_mail'));
diff --git a/Zotlabs/Lib/Permcat.php b/Zotlabs/Lib/Permcat.php
index ca4aed9ed..bda35a9cb 100644
--- a/Zotlabs/Lib/Permcat.php
+++ b/Zotlabs/Lib/Permcat.php
@@ -4,6 +4,8 @@ namespace Zotlabs\Lib;
use Zotlabs\Access\PermissionRoles;
use Zotlabs\Access\Permissions;
+use Zotlabs\Lib\Libsync;
+use Zotlabs\Daemon\Master;
/**
* @brief Permission Categories. Permission rules for various classes of connections.
@@ -79,8 +81,9 @@ class Permcat {
$this->permcats[] = [
'name' => 'default',
- 'localname' => t('default','permcat'),
+ 'localname' => t('Default','permcat'),
'perms' => Permissions::Operms($perms),
+ 'raw_perms' => $perms,
'system' => 1
];
@@ -92,6 +95,7 @@ class Permcat {
'name' => $p[$x][0],
'localname' => $p[$x][1],
'perms' => Permissions::Operms(Permissions::FilledPerms($p[$x][2])),
+ 'raw_perms' => Permissions::FilledPerms($p[$x][2]),
'system' => intval($p[$x][3])
];
}
@@ -128,27 +132,24 @@ class Permcat {
}
public function load_permcats($uid) {
-
+/*
$permcats = [
- [ 'follower', t('follower','permcat'),
- [ 'view_stream','view_profile','view_contacts','view_storage','view_pages','view_wiki',
- 'post_like' ], 1
+ [ 'contributor', t('Contributor','permcat'),
+ [ 'view_stream','view_profile','view_contacts','view_storage','view_pages',
+ 'write_storage','post_wall','write_pages','write_wiki','post_comments', 'post_mail', 'post_like',
+ 'chat' ], 1
],
- [ 'contributor', t('contributor','permcat'),
+ [ 'muted', t('Muted','permcat'),
[ 'view_stream','view_profile','view_contacts','view_storage','view_pages','view_wiki',
- 'post_wall','post_comments','write_wiki','post_like','tag_deliver','chat' ], 1
+ 'post_comments','write_wiki','post_like' ], 1
],
- [ 'publisher', t('publisher','permcat'),
- [ 'view_stream','view_profile','view_contacts','view_storage','view_pages',
- 'write_storage','post_wall','write_pages','write_wiki','post_comments','post_like','tag_deliver',
- 'chat', 'republish' ], 1
- ]
];
-
+*/
if($uid) {
$x = q("select * from pconfig where uid = %d and cat = 'permcat'",
intval($uid)
);
+
if($x) {
foreach($x as $xv) {
$value = ((preg_match('|^a:[0-9]+:{.*}$|s', $xv['v'])) ? unserialize($xv['v']) : $xv['v']);
@@ -183,4 +184,105 @@ class Permcat {
PConfig::Delete($channel_id, 'permcat', $name);
}
-} \ No newline at end of file
+ /**
+ * @brief assign a contact role to contacts
+ *
+ * @param int $channel_id
+ * @param string $role the name of the role
+ * @param array $contacts an array of contact hashes
+ */
+ public static function assign($channel, $role, $contacts) {
+
+ if(!isset($channel['channel_id'])) {
+ return;
+ }
+
+ if(!is_array($contacts) || empty($contacts)) {
+ return;
+ }
+
+ if(!$role) {
+ // lookup the default
+ $role = get_pconfig($channel_id, 'system', 'default_permcat', 'default');
+ }
+
+
+ // Doublecheck that we do not assign a role to ourself.
+ // It does not make a difference but could be confusing.
+ if (in_array($channel['channel_hash'], $contacts)) {
+ $contacts = array_diff($contacts, [$channel['channel_hash']]);
+ }
+
+ $all_perms = Permissions::Perms();
+ $permcats = new Permcat($channel['channel_id']);
+ $role_perms = $permcats->fetch($role);
+
+ if (isset($role_perms['error'])) {
+ return false;
+ }
+
+ $perms = $role_perms['raw_perms'];
+
+ $values_sql = '';
+ stringify_array_elms($contacts, true);
+
+ if ($all_perms && $perms) {
+
+ foreach ($contacts as $contact) {
+ foreach ($all_perms as $perm => $desc) {
+ if (array_key_exists($perm, $perms)) {
+ $values_sql .= " (" . intval($channel['channel_id']) . ", " . protect_sprintf($contact) . ", 'my_perms', '" . dbesc($perm) . "', " . intval($perms[$perm]) . "),";
+ }
+ else {
+ $values_sql .= " (" . intval($channel['channel_id']) . ", " . protect_sprintf($contact) . ", 'my_perms', '" . dbesc($perm) . "', 0), ";
+ }
+ }
+ }
+ }
+
+ $values_sql = rtrim($values_sql, ',');
+
+ dbq("DELETE FROM abconfig WHERE chan = " . intval($channel['channel_id']) . " AND cat = 'my_perms' AND xchan IN (" . protect_sprintf(implode(',', $contacts)) . ")");
+
+ dbq("INSERT INTO abconfig ( chan, xchan, cat, k, v ) VALUES $values_sql");
+
+ q("UPDATE abook SET abook_role = '%s'
+ WHERE abook_xchan IN (" . protect_sprintf(implode(',', $contacts)) . ") AND abook_channel = %d",
+ dbesc($role),
+ intval($channel['channel_id'])
+ );
+
+ $r = q("SELECT abook.*, xchan.* FROM abook LEFT JOIN xchan ON abook.abook_xchan = xchan.xchan_hash WHERE abook.abook_xchan IN (" . protect_sprintf(implode(',', $contacts)) . ") AND abook.abook_channel = %d AND abook_self = 0",
+ intval($channel['channel_id'])
+ );
+
+ foreach ($r as $rr) {
+
+ if (intval($rr['abook_self'])) {
+ continue;
+ }
+
+ Master::Summon([
+ 'Notifier',
+ 'permission_update',
+ $rr['abook_id']
+ ]);
+
+ $clone = $rr;
+
+ unset($clone['abook_id']);
+ unset($clone['abook_account']);
+ unset($clone['abook_channel']);
+
+ $abconfig = load_abconfig($channel['channel_id'], $clone['abook_xchan']);
+ if ($abconfig)
+ $clone['abconfig'] = $abconfig;
+
+ Libsync::build_sync_packet(0 /* use the current local_channel */, ['abook' => [$clone]]);
+
+ }
+
+ return true;
+ }
+
+}
diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php
index cd54fea17..e7cb2d5de 100644
--- a/Zotlabs/Lib/ThreadItem.php
+++ b/Zotlabs/Lib/ThreadItem.php
@@ -3,6 +3,7 @@
namespace Zotlabs\Lib;
use Zotlabs\Lib\Apps;
+use Zotlabs\Access\AccessList;
require_once('include/text.php');
@@ -58,6 +59,9 @@ class ThreadItem {
$child = new ThreadItem($item);
$this->add_child($child);
}
+
+ // performance: we have already added the children
+ unset($this->data['children']);
}
// allow a site to configure the order and content of the reaction emoji list
@@ -98,11 +102,20 @@ class ThreadItem {
$conv = $this->get_conversation();
$observer = $conv->get_observer();
- $lock = (((intval($item['item_private'])) || (($item['uid'] == local_channel()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
- || strlen($item['deny_cid']) || strlen($item['deny_gid']))))
- ? t('Private Message')
+ $acl = new AccessList(false);
+ $acl->set($item);
+
+ $lock = ((intval($item['item_private']) || ($item['uid'] == local_channel() && $acl->is_private()))
+ ? t('Restricted message')
: false);
- $locktype = $item['item_private'];
+
+ // 1 = restricted message, 2 = direct message
+ $locktype = intval($item['item_private']);
+ // 0 = limited based on public policy
+ if ($item['uid'] == local_channel() && intval($item['item_private']) && !$acl->is_private() && strlen($item['public_policy'])) {
+ $lock = t('Public Policy');
+ $locktype = 0;
+ }
$shareable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && ($item['item_private'] != 1)) ? true : false);
@@ -110,6 +123,16 @@ class ThreadItem {
if($item['author']['xchan_network'] === 'rss')
$shareable = true;
+ // @fixme
+ // Have recently added code to properly handle polls in group reshares by redirecting all of the poll responses to the group.
+ // Sharing a poll using a regular embedded share is harder because the poll will need to fork. This is due to comment permissions.
+ // The original poll author may not accept responses from strangers. Forking the poll will receive responses from the sharer's
+ // followers, but there's no elegant way to merge these two sets of results together. For now, we'll disable sharing polls.
+
+ if ($item['obj_type'] === 'Question') {
+ $shareable = false;
+ }
+
$privacy_warning = false;
if(intval($item['item_private']) && ($item['owner']['xchan_network'] === 'activitypub')) {
$recips = get_iconfig($item['parent'], 'activitypub', 'recips');
diff --git a/Zotlabs/Module/Acl.php b/Zotlabs/Module/Acl.php
index aeb02eeaa..5b37f2707 100644
--- a/Zotlabs/Module/Acl.php
+++ b/Zotlabs/Module/Acl.php
@@ -3,9 +3,9 @@
namespace Zotlabs\Module;
use Zotlabs\Lib\Libzotdir;
+use Zotlabs\Lib\AccessList;
require_once 'include/acl_selectors.php';
-require_once 'include/group.php';
/**
* @brief ACL selector json backend.
@@ -123,7 +123,7 @@ class Acl extends \Zotlabs\Web\Controller {
"name" => t('Profile','acl') . ' ' . $rv['profile_name'],
"id" => 'vp' . $rv['id'],
"xid" => 'vp.' . $rv['profile_guid'],
- "uids" => group_get_profile_members_xchan(local_channel(), $rv['id']),
+ "uids" => AccessList::profile_members_xchan(local_channel(), $rv['id']),
"link" => ''
);
}
@@ -146,14 +146,14 @@ class Acl extends \Zotlabs\Web\Controller {
if($r) {
foreach($r as $g){
- // logger('acl: group: ' . $g['gname'] . ' members: ' . group_get_members_xchan($g['id']));
+ // logger('acl: group: ' . $g['gname'] . ' members: ' . AccessList::members_xchan(local_channel(), $g['id']));
$groups[] = array(
"type" => "g",
"photo" => "images/twopeople.png",
"name" => $g['gname'],
"id" => $g['id'],
"xid" => $g['hash'],
- "uids" => group_get_members_xchan($g['id']),
+ "uids" => AccessList::members_xchan(local_channel(), $g['id']),
"link" => ''
);
}
diff --git a/Zotlabs/Module/Admin/Site.php b/Zotlabs/Module/Admin/Site.php
index 76e117a84..00095187d 100644
--- a/Zotlabs/Module/Admin/Site.php
+++ b/Zotlabs/Module/Admin/Site.php
@@ -339,8 +339,8 @@ class Site {
// now invert the logic for the setting.
$discover_tab = (1 - $discover_tab);
- $perm_roles = \Zotlabs\Access\PermissionRoles::roles();
- $default_role = get_config('system','default_permissions_role','social');
+ $perm_roles = \Zotlabs\Access\PermissionRoles::channel_roles();
+ $default_role = get_config('system','default_permissions_role','personal');
$role = array('permissions_role' , t('Default permission role for new accounts'), $default_role, t('This role will be used for the first channel created after registration.'),$perm_roles);
diff --git a/Zotlabs/Module/Apschema.php b/Zotlabs/Module/Apschema.php
index eab82eb29..e8d45c522 100644
--- a/Zotlabs/Module/Apschema.php
+++ b/Zotlabs/Module/Apschema.php
@@ -14,7 +14,7 @@ class Apschema extends \Zotlabs\Web\Controller {
'zot' => z_root() . '/apschema#',
'id' => '@id',
'type' => '@type',
- 'commentPolicy' => 'as:commentPolicy',
+ 'commentPolicy' => 'zot:commentPolicy',
'meData' => 'zot:meData',
'meDataType' => 'zot:meDataType',
'meEncoding' => 'zot:meEncoding',
@@ -33,6 +33,9 @@ class Apschema extends \Zotlabs\Web\Controller {
'PropertyValue' => 'schema:PropertyValue',
'value' => 'schema:value',
+ 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
+
+
'magicEnv' => [
'@id' => 'zot:magicEnv',
'@type' => '@id'
diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php
index 4ebd2ee29..aebc70c15 100644
--- a/Zotlabs/Module/Channel.php
+++ b/Zotlabs/Module/Channel.php
@@ -95,6 +95,10 @@ class Channel extends Controller {
http_status_exit(410, 'Gone');
}
+ if (get_pconfig($channel['channel_id'], 'system', 'index_opt_out')) {
+ App::$meta->set('robots', 'noindex, noarchive');
+ }
+
if (ActivityStreams::is_as_request($channel)) {
// Somebody may attempt an ActivityStreams fetch on one of our message permalinks
diff --git a/Zotlabs/Module/Connections.php b/Zotlabs/Module/Connections.php
index 5025f4e22..b77e5d06d 100644
--- a/Zotlabs/Module/Connections.php
+++ b/Zotlabs/Module/Connections.php
@@ -2,32 +2,32 @@
namespace Zotlabs\Module;
use App;
+use Zotlabs\Lib\Permcat;
require_once('include/socgraph.php');
require_once('include/selectors.php');
-require_once('include/group.php');
class Connections extends \Zotlabs\Web\Controller {
function init() {
-
+
if(! local_channel())
return;
App::$profile_uid = local_channel();
-
+
$channel = App::get_channel();
if($channel)
head_set_icon($channel['xchan_photo_s']);
-
+
}
-
+
function get() {
-
+
$sort_type = 0;
$o = '';
-
-
+
+
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return login();
@@ -44,13 +44,13 @@ class Connections extends \Zotlabs\Web\Controller {
$pending = false;
$unconnected = false;
$all = false;
-
+
if(! $_REQUEST['aj'])
$_SESSION['return_url'] = App::$query_string;
-
+
$search_flags = "";
$head = '';
-
+
if(argc() == 2) {
switch(argv(1)) {
case 'active':
@@ -106,7 +106,7 @@ class Connections extends \Zotlabs\Web\Controller {
// $head = t('Unconnected');
// $unconnected = true;
// break;
-
+
case 'all':
$head = t('All');
break;
@@ -115,19 +115,19 @@ class Connections extends \Zotlabs\Web\Controller {
$active = true;
$head = t('Active');
break;
-
+
}
-
+
$sql_extra = $search_flags;
if(argv(1) === 'pending')
$sql_extra .= " and abook_ignored = 0 ";
-
+
}
else {
$sql_extra = " and abook_blocked = 0 ";
$unblocked = true;
}
-
+
switch($_REQUEST['order']) {
case 'name_desc':
$sql_order = 'xchan_name DESC';
@@ -143,32 +143,32 @@ class Connections extends \Zotlabs\Web\Controller {
}
$search = ((x($_REQUEST,'search')) ? notags(trim($_REQUEST['search'])) : '');
-
+
$tabs = array(
/*
array(
'label' => t('Suggestions'),
- 'url' => z_root() . '/suggest',
+ 'url' => z_root() . '/suggest',
'sel' => '',
'title' => t('Suggest new connections'),
),
*/
-
+
'active' => array(
'label' => t('Active Connections'),
- 'url' => z_root() . '/connections/active',
+ 'url' => z_root() . '/connections/active',
'sel' => ($active) ? 'active' : '',
'title' => t('Show active connections'),
),
'pending' => array(
'label' => t('New Connections'),
- 'url' => z_root() . '/connections/pending',
+ 'url' => z_root() . '/connections/pending',
'sel' => ($pending) ? 'active' : '',
'title' => t('Show pending (new) connections'),
),
-
-
+
+
/*
array(
'label' => t('Unblocked'),
@@ -177,55 +177,55 @@ class Connections extends \Zotlabs\Web\Controller {
'title' => t('Only show unblocked connections'),
),
*/
-
+
'blocked' => array(
'label' => t('Blocked'),
'url' => z_root() . '/connections/blocked',
'sel' => ($blocked) ? 'active' : '',
'title' => t('Only show blocked connections'),
),
-
+
'ignored' => array(
'label' => t('Ignored'),
'url' => z_root() . '/connections/ignored',
'sel' => ($ignored) ? 'active' : '',
'title' => t('Only show ignored connections'),
),
-
+
'archived' => array(
'label' => t('Archived/Unreachable'),
'url' => z_root() . '/connections/archived',
'sel' => ($archived) ? 'active' : '',
'title' => t('Only show archived/unreachable connections'),
),
-
+
'hidden' => array(
'label' => t('Hidden'),
'url' => z_root() . '/connections/hidden',
'sel' => ($hidden) ? 'active' : '',
'title' => t('Only show hidden connections'),
),
-
+
// array(
// 'label' => t('Unconnected'),
// 'url' => z_root() . '/connections/unconnected',
// 'sel' => ($unconnected) ? 'active' : '',
// 'title' => t('Only show one-way connections'),
// ),
-
+
'all' => array(
'label' => t('All Connections'),
- 'url' => z_root() . '/connections',
+ 'url' => z_root() . '/connections',
'sel' => ($all) ? 'active' : '',
'title' => t('Show all connections'),
),
-
+
);
-
+
//$tab_tpl = get_markup_template('common_tabs.tpl');
//$t = replace_macros($tab_tpl, array('$tabs'=>$tabs));
-
+
$searching = false;
if($search) {
$search_hdr = $search;
@@ -233,12 +233,12 @@ class Connections extends \Zotlabs\Web\Controller {
$searching = true;
}
$sql_extra .= (($searching) ? protect_sprintf(" AND xchan_name like '%$search_txt%' ") : "");
-
+
if($_REQUEST['gid']) {
$sql_extra .= " and xchan_hash in ( select xchan from pgrp_member where gid = " . intval($_REQUEST['gid']) . " and uid = " . intval(local_channel()) . " ) ";
}
-
- $r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
+
+ $r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
where abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra ",
intval(local_channel())
);
@@ -246,19 +246,27 @@ class Connections extends \Zotlabs\Web\Controller {
App::set_pager_total($r[0]['total']);
$total = $r[0]['total'];
}
-
+
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
WHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra ORDER BY $sql_order LIMIT %d OFFSET %d ",
intval(local_channel()),
intval(App::$pager['itemspage']),
intval(App::$pager['start'])
);
-
+
+ $roles = new Permcat(local_channel());
+ $roles_list = $roles->listing();
+ $roles_dict = [];
+
+ foreach ($roles_list as $role) {
+ $roles_dict[$role['name']] = $role['localname'];
+ }
+
$contacts = array();
-
+
if($r) {
- vcard_query($r);
+ //vcard_query($r);
foreach($r as $rr) {
@@ -268,7 +276,7 @@ class Connections extends \Zotlabs\Web\Controller {
$phone = $rr['vcard']['tels'][0]['nr'];
else
$phone = '';
-
+
$status_str = '';
$status = array(
((intval($rr['abook_active'])) ? t('Active') : ''),
@@ -306,7 +314,7 @@ class Connections extends \Zotlabs\Web\Controller {
$perminfo['connperms'] .= t('Nothing');
}
-
+
foreach($status as $str) {
if(!$str)
continue;
@@ -314,14 +322,14 @@ class Connections extends \Zotlabs\Web\Controller {
$status_str .= ', ';
}
$status_str = rtrim($status_str, ', ');
-
+
$contacts[] = array(
'img_hover' => sprintf( t('%1$s [%2$s]'),$rr['xchan_name'],$rr['xchan_url']),
'edit_hover' => t('Edit connection'),
'edit' => t('Edit'),
'delete_hover' => t('Delete connection'),
'id' => $rr['abook_id'],
- 'thumb' => $rr['xchan_photo_m'],
+ 'thumb' => $rr['xchan_photo_m'],
'name' => $rr['xchan_name'],
'classes' => ((intval($rr['abook_archived']) || intval($rr['abook_not_here'])) ? 'archived' : ''),
'link' => z_root() . '/connedit/' . $rr['abook_id'],
@@ -349,13 +357,21 @@ class Connections extends \Zotlabs\Web\Controller {
'perminfo' => $perminfo,
'connect' => (intval($rr['abook_not_here']) ? t('Connect') : ''),
'follow' => z_root() . '/follow/?f=&url=' . urlencode($rr['xchan_hash']) . '&interactive=0',
- 'connect_hover' => t('Connect at this location')
+ 'connect_hover' => t('Connect at this location'),
+ 'role' => $roles_dict[$rr['abook_role']]
);
}
}
}
-
-
+
+ $limit = service_class_fetch(local_channel(),'total_channels');
+ if($limit !== false) {
+ $abook_usage_message = sprintf( t("You have %1$.0f of %2$.0f allowed connections."), $$total, $limit);
+ }
+ else {
+ $abook_usage_message = '';
+ }
+
if($_REQUEST['aj']) {
if($contacts) {
$o = replace_macros(get_markup_template('contactsajax.tpl'),array(
@@ -371,27 +387,29 @@ class Connections extends \Zotlabs\Web\Controller {
}
else {
$o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['q'])) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
- $o .= replace_macros(get_markup_template('connections.tpl'),array(
+ $o .= replace_macros(get_markup_template('connections.tpl'), [
'$header' => t('Connections') . (($head) ? ': ' . $head : ''),
'$tabs' => $tabs,
'$total' => $total,
'$search' => $search_hdr,
'$label' => t('Search'),
+ '$role_label' => t('Contact role'),
'$desc' => t('Search your connections'),
- '$finding' => (($searching) ? t('Connections search') . ": '" . $search . "'" : ""),
+ '$finding' => (($searching) ? t('Contact search') . ": '" . $search . "'" : ""),
'$submit' => t('Find'),
'$edit' => t('Edit'),
'$cmd' => App::$cmd,
'$contacts' => $contacts,
'$paginate' => paginate($a),
-
- ));
+ '$abook_usage_message' => $abook_usage_message,
+ '$group_label' => t('This is a group/forum channel')
+ ]);
}
-
+
if(! $contacts)
$o .= '<div id="content-complete"></div>';
-
+
return $o;
}
-
+
}
diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php
index 7fabf1224..6bebef026 100644
--- a/Zotlabs/Module/Connedit.php
+++ b/Zotlabs/Module/Connedit.php
@@ -1,4 +1,5 @@
<?php
+
namespace Zotlabs\Module;
/* @file connedit.php
@@ -8,8 +9,8 @@ namespace Zotlabs\Module;
*/
use App;
+use Sabre\VObject\Reader;
use Zotlabs\Lib\Apps;
-use Zotlabs\Lib\Crypto;
use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\Libsync;
use Zotlabs\Daemon\Master;
@@ -18,13 +19,12 @@ use Zotlabs\Access\Permissions;
use Zotlabs\Access\PermissionLimits;
use Zotlabs\Web\HTTPHeaders;
use Zotlabs\Lib\Permcat;
+use Zotlabs\Lib\AccessList;
require_once('include/socgraph.php');
require_once('include/selectors.php');
-require_once('include/group.php');
require_once('include/photos.php');
-
class Connedit extends Controller {
/* @brief Initialize the connection-editor
@@ -34,26 +34,25 @@ class Connedit extends Controller {
function init() {
- if(! local_channel())
+ if (!local_channel())
return;
- if((argc() >= 2) && intval(argv(1))) {
+ if ((argc() >= 2) && intval(argv(1))) {
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
- WHERE abook_channel = %d and abook_id = %d and xchan_deleted = 0 LIMIT 1",
+ WHERE abook_channel = %d and abook_id = %d and abook_self = 0 and xchan_deleted = 0 LIMIT 1",
intval(local_channel()),
intval(argv(1))
);
- if($r) {
+ if ($r) {
App::$poi = $r[0];
}
}
-
$channel = App::get_channel();
- if($channel)
+ if ($channel) {
head_set_icon($channel['xchan_photo_s']);
-
+ }
}
@@ -63,188 +62,98 @@ class Connedit extends Controller {
function post() {
- if(! local_channel())
+ if (!local_channel())
return;
$contact_id = intval(argv(1));
- if(! $contact_id)
+ if (!$contact_id)
return;
$channel = App::get_channel();
- // TODO if configured for hassle-free permissions, we'll post the form with ajax as soon as the
- // connection enable is toggled to a special autopost url and set permissions immediately, leaving
- // the other form elements alone pending a manual submit of the form. The downside is that there
- // will be a window of opportunity when the permissions have been set but before you've had a chance
- // to review and possibly restrict them. The upside is we won't have to warn you that your connection
- // can't do anything until you save the bloody form.
-
- $autopost = (((argc() > 2) && (argv(2) === 'auto')) ? true : false);
-
- $orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1",
+ $orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d AND abook_self = 0 LIMIT 1",
intval($contact_id),
intval(local_channel())
);
- if(! $orig_record) {
- notice( t('Could not access contact record.') . EOL);
+ if (!$orig_record) {
+ notice(t('Could not access contact record.') . EOL);
goaway(z_root() . '/connections');
return; // NOTREACHED
}
call_hooks('contact_edit_post', $_POST);
- $vc = get_abconfig(local_channel(),$orig_record['abook_xchan'],'system','vcard');
- $vcard = (($vc) ? \Sabre\VObject\Reader::read($vc) : null);
- $serialised_vcard = update_vcard($_REQUEST,$vcard);
- if($serialised_vcard)
- set_abconfig(local_channel(),$orig_record[0]['abook_xchan'],'system','vcard',$serialised_vcard);
-
- if(intval($orig_record[0]['abook_self'])) {
- $autoperms = intval($_POST['autoperms']);
- $is_self = true;
- }
- else {
- $autoperms = null;
- $is_self = false;
- }
+ $vc = get_abconfig(local_channel(), $orig_record['abook_xchan'], 'system', 'vcard');
+ $vcard = (($vc) ? Reader::read($vc) : null);
+ $serialised_vcard = update_vcard($_REQUEST, $vcard);
+ if ($serialised_vcard)
+ set_abconfig(local_channel(), $orig_record[0]['abook_xchan'], 'system', 'vcard', $serialised_vcard);
+ $profile_id = ((array_key_exists('profile_assign', $_POST)) ? $_POST['profile_assign'] : $orig_record[0]['abook_profile']);
- $profile_id = ((array_key_exists('profile_assign',$_POST)) ? $_POST['profile_assign'] : $orig_record[0]['abook_profile']);
-
- if($profile_id) {
+ if ($profile_id) {
$r = q("SELECT profile_guid FROM profile WHERE profile_guid = '%s' AND uid = %d LIMIT 1",
dbesc($profile_id),
intval(local_channel())
);
- if(! count($r)) {
- notice( t('Could not locate selected profile.') . EOL);
+ if (!count($r)) {
+ notice(t('Could not locate selected profile.') . EOL);
return;
}
}
- $abook_incl = ((array_key_exists('abook_incl',$_POST)) ? escape_tags($_POST['abook_incl']) : $orig_record[0]['abook_incl']);
- $abook_excl = ((array_key_exists('abook_excl',$_POST)) ? escape_tags($_POST['abook_excl']) : $orig_record[0]['abook_excl']);
-
-
- $hidden = intval($_POST['hidden']);
+ $abook_incl = ((array_key_exists('abook_incl', $_POST)) ? escape_tags($_POST['abook_incl']) : $orig_record[0]['abook_incl']);
+ $abook_excl = ((array_key_exists('abook_excl', $_POST)) ? escape_tags($_POST['abook_excl']) : $orig_record[0]['abook_excl']);
+ $abook_role = ((array_key_exists('permcat', $_POST)) ? escape_tags($_POST['permcat']) : $orig_record[0]['abook_role']);
- $priority = intval($_POST['poll']);
- if($priority > 5 || $priority < 0)
- $priority = 0;
-
- if(! array_key_exists('closeness',$_POST)) {
+ if (!array_key_exists('closeness', $_POST)) {
$_POST['closeness'] = 80;
}
$closeness = intval($_POST['closeness']);
- if($closeness < 0 || $closeness > 99) {
+ if ($closeness < 0 || $closeness > 99) {
$closeness = 80;
}
- $rating = intval($_POST['rating']);
- if($rating < (-10))
- $rating = (-10);
- if($rating > 10)
- $rating = 10;
-
- $rating_text = trim(escape_tags($_REQUEST['rating_text']));
+ $new_friend = ((intval($orig_record[0]['abook_pending'])) ? true : false);
- $all_perms = Permissions::Perms();
+/*
+ $perms = [];
+ $permcats = new Permcat(local_channel());
+ $role_perms = $permcats->fetch($abook_role);
+ $all_perms = Permissions::Perms();
- if($all_perms) {
- foreach($all_perms as $perm => $desc) {
- if(array_key_exists('perms_' . $perm, $_POST)) {
- set_abconfig($channel['channel_id'],$orig_record[0]['abook_xchan'],'my_perms',$perm,
- intval($_POST['perms_' . $perm]));
- if($autoperms) {
- set_pconfig($channel['channel_id'],'autoperms',$perm,intval($_POST['perms_' . $perm]));
- }
- }
- else {
- set_abconfig($channel['channel_id'],$orig_record[0]['abook_xchan'],'my_perms',$perm,0);
- if($autoperms) {
- set_pconfig($channel['channel_id'],'autoperms',$perm,0);
- }
- }
- }
+ // if we got a valid role use the role (default behaviour because a role is mandatory since version 7.0)
+ if (!isset($role_perms['error'])) {
+ $perms = $role_perms['raw_perms'];
+ if (intval($orig_record[0]['abook_pending']))
+ $new_friend = true;
}
- if(! is_null($autoperms))
- set_pconfig($channel['channel_id'],'system','autoperms',$autoperms);
-
- $new_friend = false;
-
- // only store a record and notify the directory if the rating changed
-
- if(! $is_self) {
-
- $signed = $orig_record[0]['abook_xchan'] . '.' . $rating . '.' . $rating_text;
- $sig = base64url_encode(Crypto::sign($signed,$channel['channel_prvkey']));
-
- $rated = ((intval($rating) || strlen($rating_text)) ? true : false);
-
- $record = 0;
-
- $z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1",
- dbesc($channel['channel_hash']),
- dbesc($orig_record[0]['abook_xchan'])
- );
-
- if($z) {
- if(($z[0]['xlink_rating'] != $rating) || ($z[0]['xlink_rating_text'] != $rating_text)) {
- $record = $z[0]['xlink_id'];
- $w = q("update xlink set xlink_rating = '%d', xlink_rating_text = '%s', xlink_sig = '%s', xlink_updated = '%s'
- where xlink_id = %d",
- intval($rating),
- dbesc($rating_text),
- dbesc($sig),
- dbesc(datetime_convert()),
- intval($record)
- );
- }
- }
- elseif($rated) {
- // only create a record if there's something to save
- $w = q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values ( '%s', '%s', %d, '%s', '%s', '%s', 1 ) ",
- dbesc($channel['channel_hash']),
- dbesc($orig_record[0]['abook_xchan']),
- intval($rating),
- dbesc($rating_text),
- dbesc($sig),
- dbesc(datetime_convert())
- );
- $z = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1",
- dbesc($channel['channel_hash']),
- dbesc($orig_record[0]['abook_xchan'])
- );
- if($z)
- $record = $z[0]['xlink_id'];
- }
- }
-
- if(($_REQUEST['pending']) && intval($orig_record[0]['abook_pending'])) {
-
+ // approve shortcut (no role provided)
+ if (!$perms && intval($orig_record[0]['abook_pending'])) {
+ $connect_perms = Permissions::connect_perms(local_channel());
+ $perms = $connect_perms['perms'];
+ // set the role from $connect_perms
+ $abook_role = $connect_perms['role'];
$new_friend = true;
+ }
- // @fixme it won't be common, but when you accept a new connection request
- // the permissions will now be that of your permissions role and ignore
- // any you may have set manually on the form. We'll probably see a bug if somebody
- // tries to set the permissions *and* approve the connection in the same
- // request. The workaround is to approve the connection, then go back and
- // adjust permissions as desired.
-
- $p = Permissions::connect_perms(local_channel());
- $my_perms = $p['perms'];
- if($my_perms) {
- foreach($my_perms as $k => $v) {
- set_abconfig($channel['channel_id'],$orig_record[0]['abook_xchan'],'my_perms',$k,$v);
+ if ($all_perms && $perms) {
+ foreach ($all_perms as $perm => $desc) {
+ if (array_key_exists($perm, $perms)) {
+ set_abconfig($channel['channel_id'], $orig_record[0]['abook_xchan'], 'my_perms', $perm, intval($perms[$perm]));
+ }
+ else {
+ set_abconfig($channel['channel_id'], $orig_record[0]['abook_xchan'], 'my_perms', $perm, 0);
}
}
}
+*/
- $abook_pending = (($new_friend) ? 0 : $orig_record[0]['abook_pending']);
-
+ \Zotlabs\Lib\Permcat::assign($channel, $abook_role, [$orig_record[0]['abook_xchan']]);
+ $abook_pending = (($new_friend) ? 0 : $orig_record[0]['abook_pending']);
$r = q("UPDATE abook SET abook_profile = '%s', abook_closeness = %d, abook_pending = %d,
abook_incl = '%s', abook_excl = '%s'
@@ -258,30 +167,29 @@ class Connedit extends Controller {
intval(local_channel())
);
- if($r)
- info( t('Connection updated.') . EOL);
+ if ($r)
+ info(t('Connection updated.') . EOL);
else
- notice( t('Failed to update connection record.') . EOL);
+ notice(t('Failed to update connection record.') . EOL);
- if(! intval(App::$poi['abook_self'])) {
- if($new_friend) {
- Master::Summon( [ 'Notifier', 'permission_accept', $contact_id ] );
+ if (!intval(App::$poi['abook_self'])) {
+ if ($new_friend) {
+ Master::Summon(['Notifier', 'permission_accept', $contact_id]);
}
- Master::Summon( [
+ Master::Summon([
'Notifier',
(($new_friend) ? 'permission_create' : 'permission_update'),
$contact_id
]);
}
- if($new_friend) {
+ if ($new_friend) {
$default_group = $channel['channel_default_group'];
- if($default_group) {
- require_once('include/group.php');
- $g = group_rec_byhash(local_channel(),$default_group);
- if($g)
- group_add_member(local_channel(),'',App::$poi['abook_xchan'],$g['id']);
+ if ($default_group) {
+ $g = AccessList::by_hash(local_channel(), $default_group);
+ if ($g)
+ AccessList::member_add(local_channel(), '', App::$poi['abook_xchan'], $g['id']);
}
// Check if settings permit ("post new friend activity" is allowed, and
@@ -291,18 +199,18 @@ class Connedit extends Controller {
$pr = q("select * from profile where uid = %d and is_default = 1 and hide_friends = 0",
intval($channel['channel_id'])
);
- if(($pr) && (! intval($orig_record[0]['abook_hidden'])) && (intval(get_pconfig($channel['channel_id'],'system','post_newfriend')))) {
+ if (($pr) && (!intval($orig_record[0]['abook_hidden'])) && (intval(get_pconfig($channel['channel_id'], 'system', 'post_newfriend')))) {
$xarr = [];
- $xarr['item_wall'] = 1;
- $xarr['item_origin'] = 1;
+ $xarr['item_wall'] = 1;
+ $xarr['item_origin'] = 1;
$xarr['item_thread_top'] = 1;
- $xarr['owner_xchan'] = $xarr['author_xchan'] = $channel['channel_hash'];
- $xarr['allow_cid'] = $channel['channel_allow_cid'];
- $xarr['allow_gid'] = $channel['channel_allow_gid'];
- $xarr['deny_cid'] = $channel['channel_deny_cid'];
- $xarr['deny_gid'] = $channel['channel_deny_gid'];
- $xarr['item_private'] = (($xarr['allow_cid']||$xarr['allow_gid']||$xarr['deny_cid']||$xarr['deny_gid']) ? 1 : 0);
+ $xarr['owner_xchan'] = $xarr['author_xchan'] = $channel['channel_hash'];
+ $xarr['allow_cid'] = $channel['channel_allow_cid'];
+ $xarr['allow_gid'] = $channel['channel_allow_gid'];
+ $xarr['deny_cid'] = $channel['channel_deny_cid'];
+ $xarr['deny_gid'] = $channel['channel_deny_gid'];
+ $xarr['item_private'] = (($xarr['allow_cid'] || $xarr['allow_gid'] || $xarr['deny_cid'] || $xarr['deny_gid']) ? 1 : 0);
$xarr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t('is now connected to') . ' ' . '[zrl=' . App::$poi['xchan_url'] . ']' . App::$poi['xchan_name'] . '[/zrl]';
@@ -312,9 +220,8 @@ class Connedit extends Controller {
}
-
// pull in a bit of content if there is any to pull in
- Master::Summon(array('Onepoll',$contact_id));
+ Master::Summon(['Onepoll', $contact_id]);
}
@@ -326,18 +233,18 @@ class Connedit extends Controller {
intval(local_channel()),
intval($contact_id)
);
- if($r) {
+ if ($r) {
App::$poi = $r[0];
}
- if($new_friend) {
- $arr = array('channel_id' => local_channel(), 'abook' => App::$poi);
+ if ($new_friend) {
+ $arr = ['channel_id' => local_channel(), 'abook' => App::$poi];
call_hooks('accept_follow', $arr);
}
- $this->connedit_clone($a);
+ $this->connedit_clone();
- if(($_REQUEST['pending']) && (!$_REQUEST['done']))
+ if (($_REQUEST['pending']) && (!$_REQUEST['done']))
goaway(z_root() . '/connections/ifpending');
return;
@@ -349,35 +256,34 @@ class Connedit extends Controller {
*
*/
- function connedit_clone(&$a) {
-
- if(! App::$poi)
- return;
+ function connedit_clone() {
+ if (!App::$poi)
+ return;
- $channel = App::get_channel();
+ $channel = App::get_channel();
- $r = q("SELECT abook.*, xchan.*
+ $r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
- intval(local_channel()),
- intval(App::$poi['abook_id'])
- );
- if($r) {
- App::$poi = array_shift($r);
- }
+ intval(local_channel()),
+ intval(App::$poi['abook_id'])
+ );
+ if ($r) {
+ App::$poi = $r[0];
+ }
- $clone = App::$poi;
+ $clone = App::$poi;
- unset($clone['abook_id']);
- unset($clone['abook_account']);
- unset($clone['abook_channel']);
+ unset($clone['abook_id']);
+ unset($clone['abook_account']);
+ unset($clone['abook_channel']);
- $abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
- if($abconfig)
- $clone['abconfig'] = $abconfig;
+ $abconfig = load_abconfig($channel['channel_id'], $clone['abook_xchan']);
+ if ($abconfig)
+ $clone['abconfig'] = $abconfig;
- Libsync::build_sync_packet(0 /* use the current local_channel */, array('abook' => array($clone)));
+ Libsync::build_sync_packet(0 /* use the current local_channel */, ['abook' => [$clone]]);
}
/* @brief Generate content of connection edit page
@@ -387,37 +293,19 @@ class Connedit extends Controller {
function get() {
- $sort_type = 0;
$o = '';
- if(! local_channel()) {
- notice( t('Permission denied.') . EOL);
+ if (!local_channel()) {
+ notice(t('Permission denied.') . EOL);
return login();
}
- $section = ((array_key_exists('section',$_REQUEST)) ? $_REQUEST['section'] : '');
- $channel = App::get_channel();
-
- $yes_no = array(t('No'),t('Yes'));
-
- $connect_perms = Permissions::connect_perms(local_channel());
-
- $o .= "<script>function connectDefaultShare() {
- \$('.abook-edit-me').each(function() {
- if(! $(this).is(':disabled'))
- $(this).prop('checked', false);
- });\n\n";
- foreach($connect_perms['perms'] as $p => $v) {
- if($v) {
- $o .= "\$('#me_id_perms_" . $p . "').prop('checked', true); \n";
- }
- }
- $o .= " }\n</script>\n";
+ $section = ((array_key_exists('section', $_REQUEST)) ? $_REQUEST['section'] : '');
- if(argc() == 3) {
+ if (argc() == 3) {
$contact_id = intval(argv(1));
- if(! $contact_id)
+ if (!$contact_id)
return;
$cmd = argv(2);
@@ -428,35 +316,35 @@ class Connedit extends Controller {
intval(local_channel())
);
- if(! count($orig_record)) {
- notice( t('Could not access address book record.') . EOL);
+ if (!count($orig_record)) {
+ notice(t('Could not access address book record.') . EOL);
goaway(z_root() . '/connections');
}
- if($cmd === 'update') {
+ if ($cmd === 'update') {
// pull feed and consume it, which should subscribe to the hub.
- Master::Summon(array('Poller',$contact_id));
+ Master::Summon(['Poller', $contact_id]);
goaway(z_root() . '/connedit/' . $contact_id);
}
- if($cmd === 'fetchvc') {
- $url = str_replace('/channel/','/profile/',$orig_record[0]['xchan_url']) . '/vcard';
+ if ($cmd === 'fetchvc') {
+ $url = str_replace('/channel/', '/profile/', $orig_record[0]['xchan_url']) . '/vcard';
$recurse = 0;
- $x = z_fetch_url(zid($url),false,$recurse,['session' => true]);
- if($x['success']) {
- $h = new HTTPHeaders($x['header']);
+ $x = z_fetch_url(zid($url), false, $recurse, ['session' => true]);
+ if ($x['success']) {
+ $h = new HTTPHeaders($x['header']);
$fields = $h->fetch();
- if($fields) {
- foreach($fields as $y) {
- if(array_key_exists('content-type',$y)) {
- $type = explode(';',trim($y['content-type']));
- if($type && $type[0] === 'text/vcard' && $x['body']) {
- $vc = \Sabre\VObject\Reader::read($x['body']);
+ if ($fields) {
+ foreach ($fields as $y) {
+ if (array_key_exists('content-type', $y)) {
+ $type = explode(';', trim($y['content-type']));
+ if ($type && $type[0] === 'text/vcard' && $x['body']) {
+ $vc = Reader::read($x['body']);
$vcard = $vc->serialize();
- if($vcard) {
- set_abconfig(local_channel(),$orig_record[0]['abook_xchan'],'system','vcard',$vcard);
- $this->connedit_clone($a);
+ if ($vcard) {
+ set_abconfig(local_channel(), $orig_record[0]['abook_xchan'], 'system', 'vcard', $vcard);
+ $this->connedit_clone();
}
}
}
@@ -467,55 +355,55 @@ class Connedit extends Controller {
}
- if($cmd === 'resetphoto') {
+ if ($cmd === 'resetphoto') {
q("update xchan set xchan_photo_date = '2001-01-01 00:00:00' where xchan_hash = '%s'",
dbesc($orig_record[0]['xchan_hash'])
);
$cmd = 'refresh';
}
- if($cmd === 'refresh') {
- if($orig_record[0]['xchan_network'] === 'zot6') {
- if(! Libzot::refresh($orig_record[0],App::get_channel()))
- notice( t('Refresh failed - channel is currently unavailable.') );
+ if ($cmd === 'refresh') {
+ if ($orig_record[0]['xchan_network'] === 'zot6') {
+ if (!Libzot::refresh($orig_record[0], App::get_channel()))
+ notice(t('Refresh failed - channel is currently unavailable.'));
}
else {
// if you are on a different network we'll force a refresh of the connection basic info
- Master::Summon(array('Notifier','permission_update',$contact_id));
+ Master::Summon(['Notifier', 'permission_update', $contact_id]);
}
goaway(z_root() . '/connedit/' . $contact_id);
}
- if($cmd === 'block') {
- if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_BLOCKED)) {
- $this->connedit_clone($a);
+ if ($cmd === 'block') {
+ if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_BLOCKED)) {
+ $this->connedit_clone();
}
else
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
- if($cmd === 'ignore') {
- if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_IGNORED)) {
- $this->connedit_clone($a);
+ if ($cmd === 'ignore') {
+ if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_IGNORED)) {
+ $this->connedit_clone();
}
else
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
- if($cmd === 'archive') {
- if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_ARCHIVED)) {
- $this->connedit_clone($a);
+ if ($cmd === 'archive') {
+ if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_ARCHIVED)) {
+ $this->connedit_clone();
}
else
notice(t('Unable to set address book parameters.') . EOL);
goaway(z_root() . '/connedit/' . $contact_id);
}
- if($cmd === 'hide') {
- if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_HIDDEN)) {
- $this->connedit_clone($a);
+ if ($cmd === 'hide') {
+ if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_HIDDEN)) {
+ $this->connedit_clone();
}
else
notice(t('Unable to set address book parameters.') . EOL);
@@ -525,10 +413,10 @@ class Connedit extends Controller {
// We'll prevent somebody from unapproving an already approved contact.
// Though maybe somebody will want this eventually (??)
- if($cmd === 'approve') {
- if(intval($orig_record[0]['abook_pending'])) {
- if(abook_toggle_flag($orig_record[0],ABOOK_FLAG_PENDING)) {
- $this->connedit_clone($a);
+ if ($cmd === 'approve') {
+ if (intval($orig_record[0]['abook_pending'])) {
+ if (abook_toggle_flag($orig_record[0], ABOOK_FLAG_PENDING)) {
+ $this->connedit_clone();
}
else
notice(t('Unable to set address book parameters.') . EOL);
@@ -537,132 +425,130 @@ class Connedit extends Controller {
}
- if($cmd === 'drop') {
+ if ($cmd === 'drop') {
contact_remove(local_channel(), $orig_record[0]['abook_id']);
- Master::Summon( [ 'Notifier', 'purge', local_channel(), $orig_record[0]['xchan_hash'] ] );
+ Master::Summon(['Notifier', 'purge', local_channel(), $orig_record[0]['xchan_hash']]);
Libsync::build_sync_packet(0 /* use the current local_channel */,
- array('abook' => array(array(
- 'abook_xchan' => $orig_record[0]['abook_xchan'],
- 'entry_deleted' => true))
- )
+ ['abook' => [[
+ 'abook_xchan' => $orig_record[0]['abook_xchan'],
+ 'entry_deleted' => true]]
+ ]
);
- info( t('Connection has been removed.') . EOL );
- if(x($_SESSION,'return_url'))
+ info(t('Connection has been removed.') . EOL);
+ if (x($_SESSION, 'return_url'))
goaway(z_root() . '/' . $_SESSION['return_url']);
goaway(z_root() . '/contacts');
}
}
- if(App::$poi) {
+ if (App::$poi) {
$abook_prev = 0;
$abook_next = 0;
-
$contact_id = App::$poi['abook_id'];
- $contact = App::$poi;
+ $contact = App::$poi;
$cn = q("SELECT abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and xchan_deleted = 0 order by xchan_name",
intval(local_channel())
);
- if($cn) {
+ if ($cn) {
$pntotal = count($cn);
- for($x = 0; $x < $pntotal; $x ++) {
- if($cn[$x]['abook_id'] == $contact_id) {
- if($x === 0)
+ for ($x = 0; $x < $pntotal; $x++) {
+ if ($cn[$x]['abook_id'] == $contact_id) {
+ if ($x === 0)
$abook_prev = 0;
else
$abook_prev = $cn[$x - 1]['abook_id'];
- if($x === $pntotal)
+ if ($x === $pntotal)
$abook_next = 0;
else
- $abook_next = $cn[$x +1]['abook_id'];
+ $abook_next = $cn[$x + 1]['abook_id'];
}
}
- }
+ }
- $tools = array(
+ $tools = [
- 'view' => array(
+ 'view' => [
'label' => t('View Profile'),
'url' => chanlink_cid($contact['abook_id']),
'sel' => '',
- 'title' => sprintf( t('View %s\'s profile'), $contact['xchan_name']),
- ),
+ 'title' => sprintf(t('View %s\'s profile'), $contact['xchan_name']),
+ ],
- 'refresh' => array(
+ 'refresh' => [
'label' => t('Refresh Permissions'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/refresh',
'sel' => '',
'title' => t('Fetch updated permissions'),
- ),
+ ],
- 'rephoto' => array(
+ 'rephoto' => [
'label' => t('Refresh Photo'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/resetphoto',
'sel' => '',
'title' => t('Fetch updated photo'),
- ),
+ ],
- 'recent' => array(
+ 'recent' => [
'label' => t('Recent Activity'),
'url' => z_root() . '/network/?f=&cid=' . $contact['abook_id'],
'sel' => '',
'title' => t('View recent posts and comments'),
- ),
+ ],
- 'block' => array(
+ 'block' => [
'label' => (intval($contact['abook_blocked']) ? t('Unblock') : t('Block')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/block',
'sel' => (intval($contact['abook_blocked']) ? 'active' : ''),
'title' => t('Block (or Unblock) all communications with this connection'),
- 'info' => (intval($contact['abook_blocked']) ? t('This connection is blocked!') : ''),
- ),
+ 'info' => (intval($contact['abook_blocked']) ? t('This connection is blocked!') : ''),
+ ],
- 'ignore' => array(
+ 'ignore' => [
'label' => (intval($contact['abook_ignored']) ? t('Unignore') : t('Ignore')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/ignore',
'sel' => (intval($contact['abook_ignored']) ? 'active' : ''),
'title' => t('Ignore (or Unignore) all inbound communications from this connection'),
- 'info' => (intval($contact['abook_ignored']) ? t('This connection is ignored!') : ''),
- ),
+ 'info' => (intval($contact['abook_ignored']) ? t('This connection is ignored!') : ''),
+ ],
- 'archive' => array(
+ 'archive' => [
'label' => (intval($contact['abook_archived']) ? t('Unarchive') : t('Archive')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/archive',
'sel' => (intval($contact['abook_archived']) ? 'active' : ''),
'title' => t('Archive (or Unarchive) this connection - mark channel dead but keep content'),
- 'info' => (intval($contact['abook_archived']) ? t('This connection is archived!') : ''),
- ),
+ 'info' => (intval($contact['abook_archived']) ? t('This connection is archived!') : ''),
+ ],
- 'hide' => array(
+ 'hide' => [
'label' => (intval($contact['abook_hidden']) ? t('Unhide') : t('Hide')),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/hide',
'sel' => (intval($contact['abook_hidden']) ? 'active' : ''),
'title' => t('Hide or Unhide this connection from your other connections'),
- 'info' => (intval($contact['abook_hidden']) ? t('This connection is hidden!') : ''),
- ),
+ 'info' => (intval($contact['abook_hidden']) ? t('This connection is hidden!') : ''),
+ ],
- 'delete' => array(
+ 'delete' => [
'label' => t('Delete'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/drop',
'sel' => '',
'title' => t('Delete this connection'),
- ),
-
- );
+ ],
+ ];
- if($contact['xchan_network'] === 'zot6') {
+ if ($contact['xchan_network'] === 'zot6') {
$tools['fetchvc'] = [
'label' => t('Fetch Vcard'),
- 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/fetchvc',
+ 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/fetchvc',
'sel' => '',
'title' => t('Fetch electronic calling card for this connection')
];
@@ -671,31 +557,16 @@ class Connedit extends Controller {
$sections = [];
- $sections['perms'] = [
- 'label' => t('Permissions'),
- 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/?f=&section=perms',
- 'sel' => '',
- 'title' => t('Open Individual Permissions section by default'),
- ];
-
- $self = false;
-
- if(intval($contact['abook_self'])) {
- $self = true;
- $abook_prev = $abook_next = 0;
- }
-
- $vc = get_abconfig(local_channel(),$contact['abook_xchan'],'system','vcard');
+ $vc = get_abconfig(local_channel(), $contact['abook_xchan'], 'system', 'vcard');
- $vctmp = (($vc) ? \Sabre\VObject\Reader::read($vc) : null);
- $vcard = (($vctmp) ? get_vcard_array($vctmp,$contact['abook_id']) : [] );
- if(! $vcard)
+ $vctmp = (($vc) ? Reader::read($vc) : null);
+ $vcard = (($vctmp) ? get_vcard_array($vctmp, $contact['abook_id']) : []);
+ if (!$vcard['fn'])
$vcard['fn'] = $contact['xchan_name'];
-
$tpl = get_markup_template("abook_edit.tpl");
- if(Apps::system_app_installed(local_channel(),'Affinity Tool')) {
+ if (Apps::system_app_installed(local_channel(), 'Affinity Tool')) {
$sections['affinity'] = [
'label' => t('Affinity'),
@@ -711,12 +582,12 @@ class Connedit extends Controller {
t('Acquaintances'),
t('All')
];
- call_hooks('affinity_labels',$labels);
+ call_hooks('affinity_labels', $labels);
$label_str = '';
- if($labels) {
- foreach($labels as $l) {
- if($label_str) {
+ if ($labels) {
+ foreach ($labels as $l) {
+ if ($label_str) {
$label_str .= ", '|'";
$label_str .= ", '" . $l . "'";
}
@@ -729,14 +600,14 @@ class Connedit extends Controller {
$slideval = intval($contact['abook_closeness']);
- $slide = replace_macros($slider_tpl,array(
- '$min' => 1,
- '$val' => $slideval,
+ $slide = replace_macros($slider_tpl, [
+ '$min' => 1,
+ '$val' => $slideval,
'$labels' => $label_str,
- ));
+ ]);
}
- if(feature_enabled(local_channel(),'connfilter')) {
+ if (feature_enabled(local_channel(), 'connfilter')) {
$sections['filter'] = [
'label' => t('Filter'),
'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/?f=&section=filter',
@@ -745,195 +616,148 @@ class Connedit extends Controller {
];
}
- $rating_val = 0;
- $rating_text = '';
-
- $xl = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1",
- dbesc($channel['channel_hash']),
- dbesc($contact['xchan_hash'])
- );
-
- if($xl) {
- $rating_val = intval($xl[0]['xlink_rating']);
- $rating_text = $xl[0]['xlink_rating_text'];
- }
-
- $rating_enabled = get_config('system','rating_enabled');
-
- if($rating_enabled) {
- $rating = replace_macros(get_markup_template('rating_slider.tpl'),array(
- '$min' => -10,
- '$val' => $rating_val
- ));
- }
- else {
- $rating = false;
- }
-
-
- $perms = array();
- $channel = App::get_channel();
-
+ $perms = [];
$global_perms = Permissions::Perms();
+ $existing = get_all_perms(local_channel(), $contact['abook_xchan'], false);
+ $unapproved = ['pending', t('Approve this contact'), '', t('Accept contact to allow communication'), [t('No'), ('Yes')]];
+ $multiprofs = ((feature_enabled(local_channel(), 'multi_profiles')) ? true : false);
- $existing = get_all_perms(local_channel(),$contact['abook_xchan'],false);
-
- $unapproved = array('pending', t('Approve this connection'), '', t('Accept connection to allow communication'), array(t('No'),('Yes')));
-
- $multiprofs = ((feature_enabled(local_channel(),'multi_profiles')) ? true : false);
-
- if($slide && !$multiprofs)
+ if ($slide && !$multiprofs)
$affinity = t('Set Affinity');
- if(!$slide && $multiprofs)
+ if (!$slide && $multiprofs)
$affinity = t('Set Profile');
- if($slide && $multiprofs)
+ if ($slide && $multiprofs)
$affinity = t('Set Affinity & Profile');
$theirs = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'their_perms'",
- intval(local_channel()),
- dbesc($contact['abook_xchan'])
+ intval(local_channel()),
+ dbesc($contact['abook_xchan'])
);
- $their_perms = array();
- if($theirs) {
- foreach($theirs as $t) {
+
+ $their_perms = [];
+ if ($theirs) {
+ foreach ($theirs as $t) {
$their_perms[$t['k']] = $t['v'];
}
}
- foreach($global_perms as $k => $v) {
- $thisperm = get_abconfig(local_channel(),$contact['abook_xchan'],'my_perms',$k);
-//fixme
-
- $checkinherited = PermissionLimits::Get(local_channel(),$k);
-
- // For auto permissions (when $self is true) we don't want to look at existing
- // permissions because they are enabled for the channel owner
- if((! $self) && ($existing[$k]))
- $thisperm = "1";
-
-
+ foreach ($global_perms as $k => $v) {
+ $thisperm = $existing[$k];
+ $checkinherited = PermissionLimits::Get(local_channel(), $k);
+ $perms[] = ['perms_' . $k, $v, ((array_key_exists($k, $their_perms)) ? intval($their_perms[$k]) : ''), $thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '0' : '1'), '', $checkinherited];
+ }
+ $pcat = new Permcat(local_channel());
+ $pcatlist = $pcat->listing();
+ $default_role = get_pconfig(local_channel(), 'system', 'default_permcat');
+ $current_permcat = (($contact['abook_pending']) ? $default_role : $contact['abook_role']);
- $perms[] = array('perms_' . $k, $v, ((array_key_exists($k,$their_perms)) ? intval($their_perms[$k]) : ''),$thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited);
+ if (!$current_permcat) {
+ notice(t('Please select a role for this contact!') . EOL);
+ $permcats[] = '';
}
- $pcat = new Permcat(local_channel());
- $pcatlist = $pcat->listing();
- $permcats = [];
- if($pcatlist) {
- foreach($pcatlist as $pc) {
+ if ($pcatlist) {
+ foreach ($pcatlist as $pc) {
$permcats[$pc['name']] = $pc['localname'];
}
}
$locstr = locations_by_netid($contact['xchan_hash']);
- if(! $locstr)
+ if (!$locstr) {
$locstr = unpunify($contact['xchan_url']);
+ }
$clone_warn = '';
- $clonable = in_array($contact['xchan_network'], ['zot6', 'rss']);
- if(! $clonable) {
+ $clonable = in_array($contact['xchan_network'], ['zot6', 'rss']);
+ if (!$clonable) {
$clone_warn = '<strong>';
$clone_warn .= ((intval($contact['abook_not_here']))
- ? t('This connection is unreachable from this location.')
- : t('This connection may be unreachable from other channel locations.')
+ ? t('This contact is unreachable from this location.')
+ : t('This contact may be unreachable from other channel locations.')
);
$clone_warn .= '</strong><br>' . t('Location independence is not supported by their network.');
}
-
-
- if(intval($contact['abook_not_here']) && $unclonable)
- $not_here = t('This connection is unreachable from this location. Location independence is not supported by their network.');
-
$o .= replace_macros($tpl, [
- '$header' => (($self) ? t('Connection Default Permissions') : sprintf( t('Connection: %s'),$contact['xchan_name'])),
- '$autoperms' => array('autoperms',t('Apply these permissions automatically'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('Connection requests will be approved without your interaction'), $yes_no),
- '$permcat' => [ 'permcat', t('Permission role'), '', '<span class="loading invisible">' . t('Loading') . '<span class="jumping-dots"><span class="dot-1">.</span><span class="dot-2">.</span><span class="dot-3">.</span></span></span>',$permcats ],
- '$permcat_new' => t('Add permission role'),
- '$permcat_enable' => Apps::system_app_installed(local_channel(), 'Permission Categories'),
- '$addr' => unpunify($contact['xchan_addr']),
- '$primeurl' => unpunify($contact['xchan_url']),
- '$section' => $section,
- '$sections' => $sections,
- '$vcard' => $vcard,
- '$addr_text' => t('This connection\'s primary address is'),
- '$loc_text' => t('Available locations:'),
- '$locstr' => $locstr,
- '$unclonable' => $clone_warn,
- '$notself' => (($self) ? '' : '1'),
- '$self' => (($self) ? '1' : ''),
- '$autolbl' => t('The permissions indicated on this page will be applied to all new connections.'),
- '$tools_label' => t('Connection Tools'),
- '$tools' => (($self) ? '' : $tools),
- '$lbl_slider' => t('Slide to adjust your degree of friendship'),
- '$lbl_rating' => t('Rating'),
- '$lbl_rating_label' => t('Slide to adjust your rating'),
- '$lbl_rating_txt' => t('Optionally explain your rating'),
- '$connfilter' => feature_enabled(local_channel(),'connfilter'),
+ '$header' => sprintf(t('Contact: %s'), $contact['xchan_name']),
+ '$permcat' => ['permcat', t('Contact role'), $current_permcat, '', $permcats],
+ '$permcat_new' => t('Manage contact roles'),
+ '$permcat_value' => bin2hex($current_permcat),
+ '$addr' => unpunify($contact['xchan_addr']),
+ '$primeurl' => unpunify($contact['xchan_url']),
+ '$section' => $section,
+ '$sections' => $sections,
+ '$vcard' => $vcard,
+ '$addr_text' => t('This contacts\'s primary address is'),
+ '$loc_text' => t('Available locations:'),
+ '$locstr' => $locstr,
+ '$unclonable' => $clone_warn,
+ '$notself' => '1',
+ '$self' => '',
+ '$autolbl' => t('The permissions indicated on this page will be applied to all new connections.'),
+ '$tools_label' => t('Contact Tools'),
+ '$tools' => $tools,
+ '$lbl_slider' => t('Slide to adjust your degree of friendship'),
+ '$connfilter' => feature_enabled(local_channel(), 'connfilter'),
'$connfilter_label' => t('Custom Filter'),
- '$incl' => array('abook_incl',t('Only import posts with this text'), $contact['abook_incl'],t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')),
- '$excl' => array('abook_excl',t('Do not import posts with this text'), $contact['abook_excl'],t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')),
- '$rating_text' => array('rating_text', t('Optionally explain your rating'),$rating_text,''),
- '$rating_info' => t('This information is public!'),
- '$rating' => $rating,
- '$rating_val' => $rating_val,
- '$slide' => $slide,
- '$affinity' => $affinity,
- '$pending_label' => t('Connection Pending Approval'),
- '$is_pending' => (intval($contact['abook_pending']) ? 1 : ''),
- '$unapproved' => $unapproved,
- '$inherited' => t('inherited'),
- '$submit' => t('Submit'),
- '$lbl_vis2' => sprintf( t('Please choose the profile you would like to display to %s when viewing your profile securely.'), $contact['xchan_name']),
- '$close' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 80),
- '$them' => t('Their Settings'),
- '$me' => t('My Settings'),
- '$perms' => $perms,
- '$permlbl' => t('Individual Permissions'),
- '$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'),
- '$permnote_self' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can change those settings here but they wont have any impact unless the inherited setting changes.'),
- '$lastupdtext' => t('Last update:'),
- '$last_update' => relative_date($contact['abook_connected']),
- '$profile_select' => contact_profile_assign($contact['abook_profile']),
- '$multiprofs' => $multiprofs,
- '$contact_id' => $contact['abook_id'],
- '$name' => $contact['xchan_name'],
- '$abook_prev' => $abook_prev,
- '$abook_next' => $abook_next,
- '$vcard_label' => t('Details'),
- '$displayname' => $displayname,
- '$name_label' => t('Name'),
- '$org_label' => t('Organisation'),
- '$title_label' => t('Title'),
- '$tel_label' => t('Phone'),
- '$email_label' => t('Email'),
- '$impp_label' => t('Instant messenger'),
- '$url_label' => t('Website'),
- '$adr_label' => t('Address'),
- '$note_label' => t('Note'),
- '$mobile' => t('Mobile'),
- '$home' => t('Home'),
- '$work' => t('Work'),
- '$other' => t('Other'),
- '$add_card' => t('Add Contact'),
- '$add_field' => t('Add Field'),
- '$create' => t('Create'),
- '$update' => t('Update'),
- '$delete' => t('Delete'),
- '$cancel' => t('Cancel'),
- '$po_box' => t('P.O. Box'),
- '$extra' => t('Additional'),
- '$street' => t('Street'),
- '$locality' => t('Locality'),
- '$region' => t('Region'),
- '$zip_code' => t('ZIP Code'),
- '$country' => t('Country')
+ '$incl' => ['abook_incl', t('Only import posts with this text'), $contact['abook_incl'], t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')],
+ '$excl' => ['abook_excl', t('Do not import posts with this text'), $contact['abook_excl'], t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')],
+ '$slide' => $slide,
+ '$affinity' => $affinity,
+ '$pending_label' => t('Contact Pending Approval'),
+ '$is_pending' => (intval($contact['abook_pending']) ? 1 : ''),
+ '$unapproved' => $unapproved,
+ '$inherited' => t('inherited'),
+ '$submit' => ((intval($contact['abook_pending'])) ? t('Approve contact') : t('Submit')),
+ '$lbl_vis2' => sprintf(t('Please choose the profile you would like to display to %s when viewing your profile securely.'), $contact['xchan_name']),
+ '$close' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 80),
+ '$them' => t('Their'),
+ '$me' => t('My'),
+ '$perms' => $perms,
+ '$permlbl' => t('Individual Permissions'),
+ '$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'),
+ '$permnote_self' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can change those settings here but they wont have any impact unless the inherited setting changes.'),
+ '$lastupdtext' => t('Last update:'),
+ '$last_update' => relative_date($contact['abook_connected']),
+ '$profile_select' => contact_profile_assign($contact['abook_profile']),
+ '$multiprofs' => $multiprofs,
+ '$contact_id' => $contact['abook_id'],
+ '$name' => $contact['xchan_name'],
+ '$abook_prev' => $abook_prev,
+ '$abook_next' => $abook_next,
+ '$vcard_label' => t('Details'),
+ '$name_label' => t('Name'),
+ '$org_label' => t('Organisation'),
+ '$title_label' => t('Title'),
+ '$tel_label' => t('Phone'),
+ '$email_label' => t('Email'),
+ '$impp_label' => t('Instant messenger'),
+ '$url_label' => t('Website'),
+ '$adr_label' => t('Address'),
+ '$note_label' => t('Note'),
+ '$mobile' => t('Mobile'),
+ '$home' => t('Home'),
+ '$work' => t('Work'),
+ '$other' => t('Other'),
+ '$add_card' => t('Add Contact'),
+ '$add_field' => t('Add Field'),
+ '$create' => t('Create'),
+ '$update' => t('Update'),
+ '$delete' => t('Delete'),
+ '$cancel' => t('Cancel'),
+ '$po_box' => t('P.O. Box'),
+ '$extra' => t('Additional'),
+ '$street' => t('Street'),
+ '$locality' => t('Locality'),
+ '$region' => t('Region'),
+ '$zip_code' => t('ZIP Code'),
+ '$country' => t('Country')
]);
- $arr = array('contact' => $contact,'output' => $o);
+ $arr = ['contact' => $contact, 'output' => $o];
call_hooks('contact_edit', $arr);
diff --git a/Zotlabs/Module/Contactedit.php b/Zotlabs/Module/Contactedit.php
new file mode 100644
index 000000000..b09b5b1ec
--- /dev/null
+++ b/Zotlabs/Module/Contactedit.php
@@ -0,0 +1,668 @@
+<?php
+
+namespace Zotlabs\Module;
+
+/* @file Cobtactedit.php
+ * @brief In this file the connection-editor form is generated and evaluated.
+ *
+ *
+ */
+
+use App;
+use Sabre\VObject\Reader;
+use Zotlabs\Lib\Apps;
+use Zotlabs\Lib\Libzot;
+use Zotlabs\Lib\Libsync;
+use Zotlabs\Daemon\Master;
+use Zotlabs\Web\Controller;
+use Zotlabs\Access\Permissions;
+use Zotlabs\Access\PermissionLimits;
+use Zotlabs\Web\HTTPHeaders;
+use Zotlabs\Lib\Permcat;
+use Zotlabs\Lib\AccessList;
+
+require_once('include/socgraph.php');
+require_once('include/selectors.php');
+require_once('include/group.php');
+require_once('include/photos.php');
+
+class Contactedit extends Controller {
+
+ /* @brief Initialize the connection-editor
+ *
+ *
+ */
+
+ function init() {
+
+ if (!local_channel())
+ return;
+
+ if ((argc() >= 2) && intval(argv(1))) {
+ $r = q("SELECT abook.*, xchan.* FROM abook LEFT JOIN xchan ON abook_xchan = xchan_hash
+ WHERE abook_channel = %d AND abook_id = %d AND abook_self = 0 AND xchan_deleted = 0",
+ intval(local_channel()),
+ intval(argv(1))
+ );
+ if (!$r) {
+ json_return_and_die([
+ 'success' => false,
+ 'message' => t('Invalid abook_id')
+ ]);
+ }
+
+ App::$poi = $r[0];
+
+ }
+ }
+
+
+ /* @brief Evaluate posted values and set changes
+ *
+ */
+
+ function post() {
+
+ if (!local_channel())
+ return;
+
+ $contact_id = intval(argv(1));
+ if (!$contact_id)
+ return;
+
+ $channel = App::get_channel();
+
+ $contact = App::$poi;
+
+ if (!$contact) {
+ notice(t('Could not access contact record.') . EOL);
+ killme();
+ }
+
+ call_hooks('contact_edit_post', $_REQUEST);
+
+ if (Apps::system_app_installed(local_channel(), 'Privacy Groups')) {
+ $pgrp_ids = q("SELECT id FROM pgrp WHERE deleted = 0 AND uid = %d",
+ intval(local_channel())
+ );
+
+ foreach($pgrp_ids as $pgrp) {
+ if (array_key_exists('pgrp_id_' . $pgrp['id'], $_REQUEST)) {
+ AccessList::member_add(local_channel(), '', $contact['abook_xchan'], $pgrp['id']);
+ }
+ else {
+ AccessList::member_remove(local_channel(), '', $contact['abook_xchan'], $pgrp['id']);
+ }
+ }
+ }
+
+ $profile_id = ((array_key_exists('profile_assign', $_REQUEST)) ? $_REQUEST['profile_assign'] : $contact['abook_profile']);
+
+ if ($profile_id) {
+ $r = q("SELECT profile_guid FROM profile WHERE profile_guid = '%s' AND uid = %d LIMIT 1",
+ dbesc($profile_id),
+ intval(local_channel())
+ );
+ if (!count($r)) {
+ notice(t('Could not locate selected profile.') . EOL);
+ return;
+ }
+ }
+
+ $abook_incl = ((array_key_exists('abook_incl', $_REQUEST)) ? escape_tags($_REQUEST['abook_incl']) : $contact['abook_incl']);
+ $abook_excl = ((array_key_exists('abook_excl', $_REQUEST)) ? escape_tags($_REQUEST['abook_excl']) : $contact['abook_excl']);
+ $abook_role = ((array_key_exists('permcat', $_REQUEST)) ? escape_tags($_REQUEST['permcat']) : $contact['abook_role']);
+
+ if (!array_key_exists('closeness', $_REQUEST)) {
+ $_REQUEST['closeness'] = 80;
+ }
+
+ $closeness = intval($_REQUEST['closeness']);
+
+ if ($closeness < 0 || $closeness > 99) {
+ $closeness = 80;
+ }
+
+ $new_friend = ((intval($contact['abook_pending'])) ? true : false);
+
+ \Zotlabs\Lib\Permcat::assign($channel, $abook_role, [$contact['abook_xchan']]);
+
+ $abook_pending = (($new_friend) ? 0 : $contact['abook_pending']);
+
+ $r = q("UPDATE abook SET abook_profile = '%s', abook_closeness = %d, abook_pending = %d,
+ abook_incl = '%s', abook_excl = '%s'
+ where abook_id = %d AND abook_channel = %d",
+ dbesc($profile_id),
+ intval($closeness),
+ intval($abook_pending),
+ dbesc($abook_incl),
+ dbesc($abook_excl),
+ intval($contact_id),
+ intval(local_channel())
+ );
+
+ $_REQUEST['success'] = false;
+
+ if ($r) {
+ $_REQUEST['success'] = true;
+ }
+
+
+ if (!intval($contact['abook_self'])) {
+ if ($new_friend) {
+ Master::Summon(['Notifier', 'permission_accept', $contact_id]);
+ }
+
+ Master::Summon([
+ 'Notifier',
+ (($new_friend) ? 'permission_create' : 'permission_update'),
+ $contact_id
+ ]);
+ }
+
+ if ($new_friend) {
+ $default_group = $channel['channel_default_group'];
+ if ($default_group) {
+ $g = AccessList::by_hash(local_channel(), $default_group);
+ if ($g) {
+ AccessList::member_add(local_channel(), '', $contact['abook_xchan'], $g['id']);
+ }
+ }
+
+ // Check if settings permit ("post new friend activity" is allowed, and
+ // friends in general or this friend in particular aren't hidden)
+ // and send out a new friend activity
+
+ $pr = q("select * from profile where uid = %d and is_default = 1 and hide_friends = 0",
+ intval($channel['channel_id'])
+ );
+ if (($pr) && (!intval($contact['abook_hidden'])) && (intval(get_pconfig($channel['channel_id'], 'system', 'post_newfriend')))) {
+ $xarr = [];
+
+ $xarr['item_wall'] = 1;
+ $xarr['item_origin'] = 1;
+ $xarr['item_thread_top'] = 1;
+ $xarr['owner_xchan'] = $xarr['author_xchan'] = $channel['channel_hash'];
+ $xarr['allow_cid'] = $channel['channel_allow_cid'];
+ $xarr['allow_gid'] = $channel['channel_allow_gid'];
+ $xarr['deny_cid'] = $channel['channel_deny_cid'];
+ $xarr['deny_gid'] = $channel['channel_deny_gid'];
+ $xarr['item_private'] = (($xarr['allow_cid'] || $xarr['allow_gid'] || $xarr['deny_cid'] || $xarr['deny_gid']) ? 1 : 0);
+
+ $xarr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t('is now connected to') . ' ' . '[zrl=' . $contact['xchan_url'] . ']' . $contact['xchan_name'] . '[/zrl]';
+
+ $xarr['body'] .= "\n\n\n" . '[zrl=' . $contact['xchan_url'] . '][zmg=80x80]' . $contact['xchan_photo_m'] . '[/zmg][/zrl]';
+
+ post_activity_item($xarr);
+
+ }
+
+ // pull in a bit of content if there is any to pull in
+ Master::Summon(['Onepoll', $contact_id]);
+
+ }
+
+ // Refresh the structure in memory with the new data
+ $this->init();
+
+ if ($new_friend) {
+ $arr = ['channel_id' => local_channel(), 'abook' => App::$poi];
+ call_hooks('accept_follow', $arr);
+ }
+
+ $this->contactedit_clone();
+ $this->get();
+
+ killme();
+
+ return;
+
+ }
+
+
+ /* @brief Generate content of contact edit page
+ *
+ *
+ */
+
+ function get() {
+
+ if (!local_channel()) {
+ killme();
+ }
+
+ if (!App::$poi) {
+ killme();
+ }
+
+
+ $channel = App::get_channel();
+ $contact_id = App::$poi['abook_id'];
+ $contact = App::$poi;
+ $section = ((array_key_exists('section', $_REQUEST)) ? $_REQUEST['section'] : 'roles');
+ $sub_section = ((array_key_exists('sub_section', $_REQUEST)) ? $_REQUEST['sub_section'] : '');
+
+
+ if (argc() == 3) {
+ $cmd = argv(2);
+ $ret = $this->do_action($contact, $cmd);
+ $contact = App::$poi;
+
+ $tools_html = replace_macros(get_markup_template("contact_edit_tools.tpl"), [
+ '$tools_label' => t('Contact Tools'),
+ '$tools' => $this->get_tools($contact),
+ ]);
+
+ $ret['tools'] = $tools_html;
+
+ json_return_and_die($ret);
+ }
+
+ $groups = [];
+
+ if (Apps::system_app_installed(local_channel(), 'Privacy Groups')) {
+
+ $r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
+ intval(local_channel())
+ );
+
+ $member_of = AccessList::containing(local_channel(), $contact['xchan_hash']);
+
+ if ($r) {
+ foreach ($r as $rr) {
+ $default_group = false;
+ if ($rr['hash'] === $channel['channel_default_group']) {
+ $default_group = true;
+ }
+
+ $groups[] = [
+ 'pgrp_id_' . $rr['id'],
+ $rr['gname'],
+ // if it's a new contact preset the default group if we have one
+ (($default_group && $contact['abook_pending']) ? 1 : in_array($rr['id'], $member_of)),
+ '',
+ [t('No'), t('Yes')]
+ ];
+ }
+ }
+ }
+
+ $slide = '';
+
+ if (Apps::system_app_installed(local_channel(), 'Affinity Tool')) {
+
+ $labels = [
+ 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 . "'";
+ }
+ }
+
+ $slider_tpl = get_markup_template('contact_slider.tpl');
+
+ $slideval = intval($contact['abook_closeness']);
+
+ $slide = replace_macros($slider_tpl, [
+ '$min' => 1,
+ '$val' => $slideval,
+ '$labels' => $label_str,
+ ]);
+ }
+
+ $perms = [];
+ $global_perms = Permissions::Perms();
+ $existing = get_all_perms(local_channel(), $contact['abook_xchan'], false);
+ $unapproved = ['pending', t('Approve this contact'), '', t('Accept contact to allow communication'), [t('No'), ('Yes')]];
+ $multiprofs = ((feature_enabled(local_channel(), 'multi_profiles')) ? true : false);
+
+ $theirs = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'their_perms'",
+ intval(local_channel()),
+ dbesc($contact['abook_xchan'])
+ );
+
+ $their_perms = [];
+ if ($theirs) {
+ foreach ($theirs as $t) {
+ $their_perms[$t['k']] = $t['v'];
+ }
+ }
+
+ foreach ($global_perms as $k => $v) {
+ $thisperm = $existing[$k];
+ $checkinherited = PermissionLimits::Get(local_channel(), $k);
+ $perms[] = ['perms_' . $k, $v, ((array_key_exists($k, $their_perms)) ? intval($their_perms[$k]) : ''), $thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '0' : '1'), '', $checkinherited];
+ }
+
+ $pcat = new Permcat(local_channel());
+ $pcatlist = $pcat->listing();
+ $default_role = get_pconfig(local_channel(), 'system', 'default_permcat');
+ $current_permcat = (($contact['abook_pending']) ? $default_role : $contact['abook_role']);
+
+ $roles_dict = [];
+ foreach ($pcatlist as $role) {
+ $roles_dict[$role['name']] = $role['localname'];
+ }
+
+
+ if (!$current_permcat) {
+ notice(t('Please select a role for this contact!') . EOL);
+ $permcats[] = '';
+ }
+
+ if ($pcatlist) {
+ foreach ($pcatlist as $pc) {
+ $permcats[$pc['name']] = $pc['localname'];
+ }
+ }
+
+ $locstr = locations_by_netid($contact['xchan_hash']);
+ if (!$locstr) {
+ $locstr = unpunify($contact['xchan_url']);
+ }
+
+ $clone_warn = '';
+ $clonable = in_array($contact['xchan_network'], ['zot6', 'rss']);
+ if (!$clonable) {
+ $clone_warn = '<strong>';
+ $clone_warn .= ((intval($contact['abook_not_here']))
+ ? t('This contact is unreachable from this location.')
+ : t('This contact may be unreachable from other channel locations.')
+ );
+ $clone_warn .= '</strong><br>' . t('Location independence is not supported by their network.');
+ }
+
+ $header_card = '<img src="' . $contact['xchan_photo_s'] . '" class="rounded" style="width: 3rem; height: 3rem;">&nbsp; ' . $contact['xchan_name'];
+
+ $header_html = replace_macros(get_markup_template("contact_edit_header.tpl"), [
+ '$img_src' => $contact['xchan_photo_s'],
+ '$name' => $contact['xchan_name'],
+ '$addr' => (($contact['xchan_addr']) ? $contact['xchan_addr'] : $contact['xchan_url']),
+ '$href' => ((is_matrix_url($contact['xchan_url'])) ? zid($contact['xchan_url']) : $contact['xchan_url']),
+ '$link_label' => t('View profile'),
+ '$is_group' => $contact['xchan_pubforum'],
+ '$group_label' => t('This is a group/forum channel')
+ ]);
+
+ $tools_html = replace_macros(get_markup_template("contact_edit_tools.tpl"), [
+ '$tools_label' => t('Contact Tools'),
+ '$tools' => $this->get_tools($contact),
+ ]);
+
+ $tpl = get_markup_template("contact_edit.tpl");
+
+ $o = replace_macros($tpl, [
+ '$permcat' => ['permcat', t('Select a role for this contact'), $current_permcat, '', $permcats],
+ '$permcat_new' => t('Contact roles'),
+ '$permcat_value' => bin2hex($current_permcat),
+// '$addr' => unpunify($contact['xchan_addr']),
+// '$primeurl' => unpunify($contact['xchan_url']),
+ '$section' => $section,
+ '$sub_section' => $sub_section,
+ '$groups' => $groups,
+// '$addr_text' => t('This contacts\'s primary address is'),
+// '$loc_text' => t('Available locations:'),
+// '$locstr' => $locstr,
+// '$unclonable' => $clone_warn,
+ '$lbl_slider' => t('Slide to adjust your degree of friendship'),
+ '$connfilter' => feature_enabled(local_channel(), 'connfilter'),
+ '$connfilter_label' => t('Custom Filter'),
+ '$incl' => ['abook_incl', t('Only import posts with this text'), $contact['abook_incl'], t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')],
+ '$excl' => ['abook_excl', t('Do not import posts with this text'), $contact['abook_excl'], t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')],
+ '$slide' => $slide,
+// '$pending_label' => t('Contact Pending Approval'),
+// '$is_pending' => (intval($contact['abook_pending']) ? 1 : ''),
+// '$unapproved' => $unapproved,
+ '$submit' => ((intval($contact['abook_pending'])) ? t('Approve contact') : t('Submit')),
+ '$close' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 80),
+ '$them' => t('Their'),
+ '$me' => t('My'),
+ '$perms' => $perms,
+// '$lastupdtext' => t('Last update:'),
+// '$last_update' => relative_date($contact['abook_connected']),
+ '$profile_select' => contact_profile_assign($contact['abook_profile']),
+ '$multiprofs' => $multiprofs,
+ '$contact_id' => $contact['abook_id'],
+// '$name' => $contact['xchan_name'],
+ ]);
+
+ $arr = ['contact' => $contact, 'output' => $o];
+
+ call_hooks('contact_edit', $arr);
+
+ if (is_ajax()) {
+ json_return_and_die([
+ 'success' => ((intval($_REQUEST['success'])) ? intval($_REQUEST['success']) : 1),
+ 'message' => (($_REQUEST['success']) ? t('Contact updated') : t('Contact update failed')),
+ 'id' => $contact_id,
+ 'title' => $header_html,
+ 'role' => ((intval($contact['abook_pending'])) ? '' : $roles_dict[$current_permcat]),
+ 'body' => $arr['output'],
+ 'tools' => $tools_html,
+ 'submit' => ((intval($contact['abook_pending'])) ? t('Approve connection') : t('Submit')),
+ 'pending' => intval($contact['abook_pending'])
+ ]);
+ }
+
+ return $arr['output'];
+
+ }
+
+ function contactedit_clone() {
+
+ if (!App::$poi)
+ return;
+
+ $channel = App::get_channel();
+
+ $clone = App::$poi;
+
+ unset($clone['abook_id']);
+ unset($clone['abook_account']);
+ unset($clone['abook_channel']);
+
+ $abconfig = load_abconfig($channel['channel_id'], $clone['abook_xchan']);
+ if ($abconfig)
+ $clone['abconfig'] = $abconfig;
+
+ Libsync::build_sync_packet(0 /* use the current local_channel */, ['abook' => [$clone]]);
+ }
+
+ function do_action($contact, $cmd) {
+ $ret = [
+ 'sucess' => false,
+ 'message' => ''
+ ];
+
+ if ($cmd === 'resetphoto') {
+ q("update xchan set xchan_photo_date = '2001-01-01 00:00:00' where xchan_hash = '%s'",
+ dbesc($contact['xchan_hash'])
+ );
+ $cmd = 'refresh';
+ }
+
+ if ($cmd === 'refresh') {
+ if ($contact['xchan_network'] === 'zot6') {
+ if (Libzot::refresh($contact, App::get_channel())) {
+ $ret['success'] = true;
+ $ret['message'] = t('Refresh succeeded');
+ }
+ else {
+ $ret['message'] = t('Refresh failed - channel is currently unavailable');
+ }
+ }
+ else {
+ // if you are on a different network we'll force a refresh of the connection basic info
+ Master::Summon(['Notifier', 'permission_update', $contact['abook_id']]);
+ $ret['success'] = true;
+ $ret['message'] = t('Refresh succeeded');
+ }
+
+ return $ret;
+ }
+
+ if ($cmd === 'block') {
+ if (abook_toggle_flag($contact, ABOOK_FLAG_BLOCKED)) {
+ $this->init(); // refresh data
+
+ $this->contactedit_clone();
+ $ret['success'] = true;
+ $ret['message'] = t('Block status updated');
+ }
+ else {
+ $ret['success'] = false;
+ $ret['message'] = t('Block failed');
+ }
+ return $ret;
+ }
+
+ if ($cmd === 'ignore') {
+ if (abook_toggle_flag($contact, ABOOK_FLAG_IGNORED)) {
+ $this->init(); // refresh data
+
+ $this->contactedit_clone();
+ $ret['success'] = true;
+ $ret['message'] = t('Ignore status updated');
+ }
+ else {
+ $ret['success'] = false;
+ $ret['message'] = t('Ignore failed');
+ }
+ return $ret;
+ }
+
+ if ($cmd === 'archive') {
+ if (abook_toggle_flag($contact, ABOOK_FLAG_ARCHIVED)) {
+ $this->init(); // refresh data
+
+ $this->contactedit_clone();
+ $ret['success'] = true;
+ $ret['message'] = t('Archive status updated');
+ }
+ else {
+ $ret['success'] = false;
+ $ret['message'] = t('Archive failed');
+ }
+ return $ret;
+ }
+
+ if ($cmd === 'hide') {
+ if (abook_toggle_flag($contact, ABOOK_FLAG_HIDDEN)) {
+ $this->init(); // refresh data
+
+ $this->contactedit_clone();
+ $ret['success'] = true;
+ $ret['message'] = t('Hide status updated');
+ }
+ else {
+ $ret['success'] = false;
+ $ret['message'] = t('Hide failed');
+ }
+ return $ret;
+ }
+
+ // We'll prevent somebody from unapproving an already approved contact.
+ // Though maybe somebody will want this eventually (??)
+
+ //if ($cmd === 'approve') {
+ //if (intval($contact['abook_pending'])) {
+ //if (abook_toggle_flag($contact, ABOOK_FLAG_PENDING)) {
+ //$this->contactedit_clone();
+ //}
+ //else
+ //notice(t('Unable to set address book parameters.') . EOL);
+ //}
+ //goaway(z_root() . '/connedit/' . $contact_id);
+ //}
+
+
+ if ($cmd === 'drop') {
+
+ if (contact_remove(local_channel(), $contact['abook_id'])) {
+
+ Master::Summon(['Notifier', 'purge', local_channel(), $contact['xchan_hash']]);
+ Libsync::build_sync_packet(0 /* use the current local_channel */,
+ ['abook' => [
+ [
+ 'abook_xchan' => $contact['abook_xchan'],
+ 'entry_deleted' => true
+ ]
+ ]
+ ]);
+
+ $ret['success'] = true;
+ $ret['message'] = t('Contact removed');
+ }
+ else {
+ $ret['success'] = false;
+ $ret['message'] = t('Delete failed');
+ }
+ return $ret;
+ }
+ }
+
+ function get_tools($contact) {
+ return [
+
+ 'refresh' => [
+ 'label' => t('Refresh Permissions'),
+ 'title' => t('Fetch updated permissions'),
+ ],
+
+ 'rephoto' => [
+ 'label' => t('Refresh Photo'),
+ 'title' => t('Fetch updated photo'),
+ ],
+
+
+ 'block' => [
+ 'label' => (intval($contact['abook_blocked']) ? t('Unblock') : t('Block')),
+ 'sel' => (intval($contact['abook_blocked']) ? 'active' : ''),
+ 'title' => t('Block (or Unblock) all communications with this connection'),
+ 'info' => (intval($contact['abook_blocked']) ? t('This connection is blocked!') : ''),
+ ],
+
+ 'ignore' => [
+ 'label' => (intval($contact['abook_ignored']) ? t('Unignore') : t('Ignore')),
+ 'sel' => (intval($contact['abook_ignored']) ? 'active' : ''),
+ 'title' => t('Ignore (or Unignore) all inbound communications from this connection'),
+ 'info' => (intval($contact['abook_ignored']) ? t('This connection is ignored!') : ''),
+ ],
+
+ 'archive' => [
+ 'label' => (intval($contact['abook_archived']) ? t('Unarchive') : t('Archive')),
+ 'sel' => (intval($contact['abook_archived']) ? 'active' : ''),
+ 'title' => t('Archive (or Unarchive) this connection - mark channel dead but keep content'),
+ 'info' => (intval($contact['abook_archived']) ? t('This connection is archived!') : ''),
+ ],
+
+ 'hide' => [
+ 'label' => (intval($contact['abook_hidden']) ? t('Unhide') : t('Hide')),
+ 'sel' => (intval($contact['abook_hidden']) ? 'active' : ''),
+ 'title' => t('Hide or Unhide this connection from your other connections'),
+ 'info' => (intval($contact['abook_hidden']) ? t('This connection is hidden!') : ''),
+ ],
+
+ 'delete' => [
+ 'label' => t('Delete'),
+ 'sel' => '',
+ 'title' => t('Delete this connection'),
+ ],
+
+ ];
+ }
+
+}
diff --git a/Zotlabs/Module/Contactgroup.php b/Zotlabs/Module/Contactgroup.php
index 36aaf7da0..3e88179fb 100644
--- a/Zotlabs/Module/Contactgroup.php
+++ b/Zotlabs/Module/Contactgroup.php
@@ -1,17 +1,17 @@
<?php
namespace Zotlabs\Module;
-require_once('include/group.php');
+use Zotlabs\Lib\AccessList;
+use Zotlabs\Web\Controller;
-
-class Contactgroup extends \Zotlabs\Web\Controller {
+class Contactgroup extends Controller {
function get() {
-
+
if(! local_channel()) {
killme();
}
-
+
if((argc() > 2) && (intval(argv(1))) && (argv(2))) {
$r = q("SELECT abook_xchan from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1",
dbesc(base64url_decode(argv(2))),
@@ -20,9 +20,9 @@ class Contactgroup extends \Zotlabs\Web\Controller {
if($r)
$change = $r[0]['abook_xchan'];
}
-
+
if((argc() > 1) && (intval(argv(1)))) {
-
+
$r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d AND deleted = 0 LIMIT 1",
intval(argv(1)),
intval(local_channel())
@@ -30,25 +30,25 @@ class Contactgroup extends \Zotlabs\Web\Controller {
if(! $r) {
killme();
}
-
+
$group = $r[0];
- $members = group_get_members($group['id']);
+ $members = AccessList::members(local_channel(), $group['id']);
$preselected = array();
if(count($members)) {
foreach($members as $member)
$preselected[] = $member['xchan_hash'];
}
-
+
if($change) {
if(in_array($change,$preselected)) {
- group_rmv_member(local_channel(),$group['gname'],$change);
+ AccessList::member_remove(local_channel(),$group['gname'],$change);
}
else {
- group_add_member(local_channel(),$group['gname'],$change);
+ AccessList::member_add(local_channel(),$group['gname'],$change);
}
}
}
-
+
killme();
}
}
diff --git a/Zotlabs/Module/Defperms.php b/Zotlabs/Module/Defperms.php
index 309a5a65a..70270d36b 100644
--- a/Zotlabs/Module/Defperms.php
+++ b/Zotlabs/Module/Defperms.php
@@ -8,7 +8,6 @@ use Zotlabs\Lib\Libsync;
require_once('include/socgraph.php');
require_once('include/selectors.php');
-require_once('include/group.php');
require_once('include/photos.php');
class Defperms extends Controller {
@@ -23,8 +22,8 @@ class Defperms extends Controller {
if(! local_channel())
return;
- if(! Apps::system_app_installed(local_channel(), 'Default Permissions'))
- return;
+ //if(! Apps::system_app_installed(local_channel(), 'Default Permissions'))
+ // return;
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
@@ -50,8 +49,8 @@ class Defperms extends Controller {
if(! local_channel())
return;
- if(! Apps::system_app_installed(local_channel(), 'Default Permissions'))
- return;
+ //if(! Apps::system_app_installed(local_channel(), 'Default Permissions'))
+ // return;
$contact_id = intval(argv(1));
if(! $contact_id)
@@ -183,12 +182,12 @@ class Defperms extends Controller {
return login();
}
- if(! Apps::system_app_installed(local_channel(), 'Default Permissions')) {
- //Do not display any associated widgets at this point
- App::$pdl = '';
- $papp = Apps::get_papp('Default Permissions');
- return Apps::app_render($papp, 'module');
- }
+ //~ if(! Apps::system_app_installed(local_channel(), 'Default Permissions')) {
+ //~ //Do not display any associated widgets at this point
+ //~ App::$pdl = '';
+ //~ $papp = Apps::get_papp('Default Permissions');
+ //~ return Apps::app_render($papp, 'module');
+ //~ }
$section = ((array_key_exists('section',$_REQUEST)) ? $_REQUEST['section'] : '');
$channel = App::get_channel();
diff --git a/Zotlabs/Module/Follow.php b/Zotlabs/Module/Follow.php
index 4fe20f56b..94daa4c70 100644
--- a/Zotlabs/Module/Follow.php
+++ b/Zotlabs/Module/Follow.php
@@ -108,7 +108,7 @@ class Follow extends Controller {
}
Libsync::build_sync_packet(0, [ 'abook' => [ $clone ] ], true);
- $can_view_stream = their_perms_contains($channel['channel_id'],$clone['abook_xchan'],'view_stream');
+ $can_view_stream = intval(get_abconfig($channel['channel_id'], $clone['abook_xchan'], 'their_perms', 'view_stream'));
// If we can view their stream, pull in some posts
@@ -117,7 +117,7 @@ class Follow extends Controller {
}
if ($interactive) {
- goaway(z_root() . '/connedit/' . $result['abook']['abook_id'] . '?follow=1');
+ goaway(z_root() . '/connections#' . $result['abook']['abook_id']);
}
else {
json_return_and_die([ 'success' => true ]);
diff --git a/Zotlabs/Module/Group.php b/Zotlabs/Module/Group.php
index a2d55a325..4c6b0c838 100644
--- a/Zotlabs/Module/Group.php
+++ b/Zotlabs/Module/Group.php
@@ -5,8 +5,7 @@ use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Apps;
use Zotlabs\Lib\Libsync;
-
-require_once('include/group.php');
+use Zotlabs\Lib\AccessList;
class Group extends Controller {
@@ -41,16 +40,17 @@ class Group extends Controller {
$name = notags(trim($_POST['groupname']));
$public = intval($_POST['public']);
- $r = group_add(local_channel(),$name,$public);
+ $r = AccessList::add(local_channel(),$name,$public);
+ $group_hash = $r;
+
if($r) {
info( t('Privacy group created.') . EOL );
}
else {
notice( t('Could not create privacy group.') . EOL );
}
- goaway(z_root() . '/group');
-
}
+
if((argc() == 2) && (intval(argv(1)))) {
check_form_security_token_redirectOnErr('/group', 'group_edit');
@@ -65,10 +65,11 @@ class Group extends Controller {
}
$group = $r[0];
$groupname = notags(trim($_POST['groupname']));
+ $group_hash = $group['hash'];
$public = intval($_POST['public']);
$hookinfo = [ 'pgrp_extras' => '', 'group'=>$group['id'] ];
- call_hooks ('privacygroup_extras_post',$hookinfo);
+ call_hooks('privacygroup_extras_post',$hookinfo);
if((strlen($groupname)) && (($groupname != $group['gname']) || ($public != $group['visible']))) {
$r = q("UPDATE pgrp SET gname = '%s', visible = %d WHERE uid = %d AND id = %d",
@@ -79,13 +80,25 @@ class Group extends Controller {
);
if($r)
info( t('Privacy group updated.') . EOL );
+ }
+ }
+ $channel = App::get_channel();
- Libsync::build_sync_packet(local_channel(),null,true);
- }
+ $default_group = ((isset($_POST['set_default_group'])) ? $group_hash : (($channel['channel_default_group'] === $group_hash) ? '' : $channel['channel_default_group']));
+ $default_acl = ((isset($_POST['set_default_acl'])) ? '<' . $group_hash . '>' : (($channel['channel_allow_gid'] === '<' . $group_hash . '>') ? '' : $channel['channel_allow_gid']));
+
+ q("update channel set channel_default_group = '%s', channel_allow_gid = '%s'
+ where channel_id = %d",
+ dbesc($default_group),
+ dbesc($default_acl),
+ intval(local_channel())
+ );
+
+ Libsync::build_sync_packet(local_channel(),null,true);
+
+ goaway(z_root() . '/group/' . argv(1) . ((argv(2)) ? '/' . argv(2) : ''));
- goaway(z_root() . '/group/' . argv(1) . '/' . argv(2));
- }
return;
}
@@ -127,7 +140,7 @@ class Group extends Controller {
foreach($groups as $group) {
$entries[$i]['name'] = $group['gname'];
$entries[$i]['id'] = $group['id'];
- $entries[$i]['count'] = count(group_get_members($group['id']));
+ $entries[$i]['count'] = count(AccessList::members(local_channel(), $group['id']));
$i++;
}
@@ -135,6 +148,10 @@ class Group extends Controller {
call_hooks ('privacygroup_extras',$hookinfo);
$pgrp_extras = $hookinfo['pgrp_extras'];
+ $is_default_acl = ['set_default_acl', t('Post to this group by default'), 0, '', [t('No'), t('Yes')]];
+ $is_default_group = ['set_default_group', t('Add new contacts to this group by default'), 0, '', [t('No'), t('Yes')]];
+
+
$tpl = get_markup_template('privacy_groups.tpl');
$o = replace_macros($tpl, [
'$title' => t('Privacy Groups'),
@@ -143,16 +160,19 @@ class Group extends Controller {
// new group form
'$gname' => array('groupname',t('Privacy group name')),
- '$public' => array('public',t('Members are visible to other channels'), false),
+ '$public' => array('public',t('Members are visible to other channels'), 0, '', [t('No'), t('Yes')]),
'$pgrp_extras' => $pgrp_extras,
'$form_security_token' => get_form_security_token("group_edit"),
'$submit' => t('Submit'),
+ '$is_default_acl' => $is_default_acl,
+ '$is_default_group' => $is_default_group,
// groups list
'$title' => t('Privacy Groups'),
'$name_label' => t('Name'),
'$count_label' => t('Members'),
'$entries' => $entries
+
]);
return $o;
@@ -174,7 +194,7 @@ class Group extends Controller {
intval(local_channel())
);
if($r)
- $result = group_rmv(local_channel(),$r[0]['gname']);
+ $result = AccessList::remove(local_channel(),$r[0]['gname']);
if($result) {
$hookinfo = [ 'pgrp_extras' => '', 'group' => argv(2) ];
call_hooks ('privacygroup_extras_drop',$hookinfo);
@@ -215,7 +235,7 @@ class Group extends Controller {
$group = $r[0];
- $members = group_get_members($group['id']);
+ $members = AccessList::members(local_channel(), $group['id']);
$preselected = array();
if(count($members)) {
@@ -227,13 +247,13 @@ class Group extends Controller {
if($change) {
if(in_array($change,$preselected)) {
- group_rmv_member(local_channel(),$group['gname'],$change);
+ AccessList::member_remove(local_channel(),$group['gname'],$change);
}
else {
- group_add_member(local_channel(),$group['gname'],$change);
+ AccessList::member_add(local_channel(),$group['gname'],$change);
}
- $members = group_get_members($group['id']);
+ $members = AccessList::members(local_channel(), $group['id']);
$preselected = array();
if(count($members)) {
@@ -252,7 +272,7 @@ class Group extends Controller {
'$gname' => array('groupname',t('Privacy group name: '),$group['gname'], ''),
'$gid' => $group['id'],
'$drop' => $drop_txt,
- '$public' => array('public',t('Members are visible to other channels'), $group['visible'], ''),
+ '$public' => array('public',t('Members are visible to other channels'), $group['visible'], '', [t('No'), t('Yes')]),
'$form_security_token_edit' => get_form_security_token('group_edit'),
'$delete' => t('Delete Group'),
'$form_security_token_drop' => get_form_security_token("group_drop"),
@@ -280,7 +300,7 @@ class Group extends Controller {
$groupeditor['members'][] = micropro($member,true,'mpgroup', $textmode);
}
else
- group_rmv_member(local_channel(),$group['gname'],$member['xchan_hash']);
+ AccessList::member_remove(local_channel(),$group['gname'],$member['xchan_hash']);
}
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d AND abook_self = 0 and abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 order by xchan_name asc",
@@ -302,6 +322,15 @@ class Group extends Controller {
$context['$desc'] = t('Click a channel to toggle membership');
$context['$pgrp_extras'] = $pgrp_extras;
+ $channel = App::get_channel();
+
+//hz_syslog(print_r($group,true));
+//hz_syslog(print_r($channel,true));
+
+ $context['$is_default_acl'] = ['set_default_acl', t('Post to this group by default'), intval($group['hash'] === trim($channel['channel_allow_gid'], '<>')), '', [t('No'), t('Yes')]];
+ $context['$is_default_group'] = ['set_default_group', t('Add new contacts to this group by default'), intval($group['hash'] === $channel['channel_default_group']), '', [t('No'), t('Yes')]];
+
+
if($change) {
$tpl = get_markup_template('groupeditor.tpl');
echo replace_macros($tpl, $context);
diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php
index 9b76c7569..66629fa2b 100644
--- a/Zotlabs/Module/Item.php
+++ b/Zotlabs/Module/Item.php
@@ -416,6 +416,7 @@ class Item extends Controller {
$expires = NULL_DATE;
+ $comments_closed = NULL_DATE;
$route = '';
$parent_item = null;
@@ -692,6 +693,7 @@ class Item extends Controller {
$postopts = $orig_post['postopts'];
$created = $orig_post['created'];
$expires = $orig_post['expires'];
+ $comments_closed = $orig_post['comments_closed'];
$mid = $orig_post['mid'];
$parent_mid = $orig_post['parent_mid'];
$plink = $orig_post['plink'];
@@ -794,13 +796,7 @@ class Item extends Controller {
// if this is a wall-to-wall post to a group, turn it into a direct message
- $role = get_pconfig($profile_uid, 'system', 'permissions_role');
-
- $rolesettings = PermissionRoles::role_perms($role);
-
- $channel_type = isset($rolesettings['channel_type']) ? $rolesettings['channel_type'] : 'normal';
-
- $is_group = (($channel_type === 'group') ? true : false);
+ $is_group = get_pconfig($profile_uid, 'system', 'group_actor');
if (($is_group) && ($walltowall) && (!$walltowall_comment)) {
$groupww = true;
@@ -994,8 +990,9 @@ class Item extends Controller {
$notify_type = (($parent) ? 'comment-new' : 'wall-new');
+ $uuid = (($message_id) ? $message_id : item_message_id());
+
if (!$mid) {
- $uuid = (($message_id) ? $message_id : item_message_id());
$mid = z_root() . '/item/' . $uuid;
}
@@ -1015,10 +1012,22 @@ class Item extends Controller {
}
if ($obj) {
- $obj['url'] = $mid;
- $obj['attributedTo'] = channel_url($channel);
- $datarray['obj'] = $obj;
- $obj_type = 'Question';
+ $obj['url'] = $mid;
+ $obj['id'] = $mid;
+ $obj['diaspora:guid'] = $uuid;
+ $obj['attributedTo'] = channel_url($channel);
+ $obj['published'] = $created;
+
+ $datarray['obj'] = $obj;
+
+ if ($obj['endTime']) {
+ $d = datetime_convert('UTC','UTC', $obj['endTime']);
+ if ($d > NULL_DATE) {
+ $comments_closed = $d;
+ }
+ }
+
+ $obj_type = 'Question';
}
if (!$parent_mid) {
@@ -1082,6 +1091,7 @@ class Item extends Controller {
$datarray['created'] = $created;
$datarray['edited'] = (($orig_post) ? datetime_convert() : $created);
$datarray['expires'] = $expires;
+ $datarray['comments_closed'] = $comments_closed;
$datarray['commented'] = (($orig_post) ? datetime_convert() : $created);
$datarray['received'] = (($orig_post) ? datetime_convert() : $created);
$datarray['changed'] = (($orig_post) ? datetime_convert() : $created);
@@ -1594,6 +1604,8 @@ class Item extends Controller {
$obj['endTime'] = datetime_convert(date_default_timezone_get(), 'UTC', 'now + ' . $expire_value . ' ' . $expire_unit, ATOM_TIME);
+ $obj['directMessage'] = (intval($item['item_private']) === 2);
+
if ($item['item_private']) {
$obj['to'] = Activity::map_acl($item);
}
diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php
index 03c56b9a2..016a0a309 100644
--- a/Zotlabs/Module/Network.php
+++ b/Zotlabs/Module/Network.php
@@ -1,12 +1,11 @@
<?php
namespace Zotlabs\Module;
-use Zotlabs\Lib\Group;
+use Zotlabs\Lib\AccessList;
use Zotlabs\Lib\Apps;
use App;
require_once('include/items.php');
-require_once('include/group.php');
require_once('include/contact_widgets.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
@@ -233,7 +232,7 @@ class Network extends \Zotlabs\Web\Controller {
if($group) {
$contact_str = '';
- $contacts = group_get_members($group);
+ $contacts = AccessList::members(local_channel(), $group);
if($contacts) {
$contact_str = ids_to_querystr($contacts, 'xchan', true);
}
@@ -246,7 +245,7 @@ class Network extends \Zotlabs\Web\Controller {
$item_thread_top = '';
$sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND (( author_xchan IN ( $contact_str ) OR owner_xchan in ( $contact_str )) or allow_gid like '" . protect_sprintf('%<' . dbesc($group_hash) . '>%') . "' ) and id = parent $item_normal ) ";
- $x = group_rec_byhash(local_channel(), $group_hash);
+ $x = AccessList::by_hash(local_channel(), $group_hash);
if($x) {
$title = replace_macros(get_markup_template('section_title.tpl'), array(
diff --git a/Zotlabs/Module/New_channel.php b/Zotlabs/Module/New_channel.php
index 3b0b35258..5989e3da6 100644
--- a/Zotlabs/Module/New_channel.php
+++ b/Zotlabs/Module/New_channel.php
@@ -170,12 +170,12 @@ class New_channel extends \Zotlabs\Web\Controller {
$privacy_role = ((x($_REQUEST,'permissions_role')) ? $_REQUEST['permissions_role'] : "" );
- $perm_roles = \Zotlabs\Access\PermissionRoles::roles();
+ $perm_roles = \Zotlabs\Access\PermissionRoles::channel_roles();
$name = array('name', t('Channel name'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), $name_help, "*");
$nickhub = '@' . \App::get_hostname();
$nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), $nick_help, "*");
- $role = array('permissions_role' , t('Channel role and privacy'), ($privacy_role) ? $privacy_role : 'social', t('Select a channel permission role compatible with your usage needs and privacy requirements.') . '<br>' . '<a href="help/member/member_guide#Channel_Permission_Roles" target="_blank">' . t('Read more about channel permission roles') . '</a>',$perm_roles);
+ $role = array('permissions_role' , t('Channel role'), ($privacy_role) ? $privacy_role : 'personal', '', $perm_roles);
$o = replace_macros(get_markup_template('new_channel.tpl'), array(
'$title' => t('Create a Channel'),
diff --git a/Zotlabs/Module/Permcats.php b/Zotlabs/Module/Permcats.php
index 58566373a..a46253ec2 100644
--- a/Zotlabs/Module/Permcats.php
+++ b/Zotlabs/Module/Permcats.php
@@ -6,6 +6,7 @@ use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Apps;
use Zotlabs\Lib\Libsync;
+use Zotlabs\Lib\AccessList;
class Permcats extends Controller {
@@ -14,24 +15,59 @@ class Permcats extends Controller {
if(! local_channel())
return;
- if(! Apps::system_app_installed(local_channel(), 'Permission Categories'))
- return;
-
$channel = App::get_channel();
check_form_security_token_redirectOnErr('/permcats', 'permcats');
- $all_perms = \Zotlabs\Access\Permissions::Perms();
-
$name = escape_tags(trim($_POST['name']));
- if(! $name) {
+ $is_system_role = isset($_POST['is_system_role']);
+ $return_path = z_root() . '/permcats/' . $_POST['return_path'];
+ $group_hash = ((isset($_POST['group_select'])) ? $_POST['group_select'] : '');
+ $contacts = [];
+
+ if ($group_hash === 'all_contacts') {
+ $r = q("SELECT abook_xchan FROM abook WHERE abook_channel = %d and abook_self = 0 and abook_pending = 0",
+ intval(local_channel())
+ );
+
+ if ($r) {
+ $contacts = ids_to_array($r, 'abook_xchan');
+ }
+ }
+
+ if (!$contacts && $group_hash) {
+ $group = AccessList::by_hash(local_channel(), $group_hash);
+ }
+
+ if ($group) {
+ $contacts = AccessList::members_xchan(local_channel(), $group['id']);
+ }
+
+ if(! $name ) {
notice( t('Permission category name is required.') . EOL);
return;
}
+ set_pconfig(local_channel(), 'system', 'default_permcat', 'default');
+
+ if (isset($_POST['default_role'])) {
+ set_pconfig(local_channel(), 'system', 'default_permcat', $name);
+ }
+
+ if ($is_system_role) {
+ // if we have a system role just set the default and assign if aplicable and be done with it
+ if ($contacts)
+ \Zotlabs\Lib\Permcat::assign($channel, $name, $contacts);
+
+ info( t('Contact role saved.') . EOL);
+ Libsync::build_sync_packet();
+ goaway($return_path);
+ return;
+ }
$pcarr = [];
+ $all_perms = \Zotlabs\Access\Permissions::Perms();
if($all_perms) {
foreach($all_perms as $perm => $desc) {
@@ -41,11 +77,16 @@ class Permcats extends Controller {
}
}
- \Zotlabs\Lib\Permcat::update(local_channel(),$name,$pcarr);
+ \Zotlabs\Lib\Permcat::update(local_channel(), $name, $pcarr);
+
+ if ($contacts) {
+ \Zotlabs\Lib\Permcat::assign($channel, $name, $contacts);
+ }
Libsync::build_sync_packet();
- info( t('Permission category saved.') . EOL);
+ info( t('Contact role saved.') . EOL);
+ goaway($return_path);
return;
}
@@ -56,13 +97,6 @@ class Permcats extends Controller {
if(! local_channel())
return;
- if(! Apps::system_app_installed(local_channel(), 'Permission Categories')) {
- //Do not display any associated widgets at this point
- App::$pdl = '';
- $papp = Apps::get_papp('Permission Categories');
- return Apps::app_render($papp, 'module');
- }
-
$channel = App::get_channel();
if(argc() > 1)
@@ -70,24 +104,49 @@ class Permcats extends Controller {
if(argc() > 2 && argv(2) === 'drop') {
\Zotlabs\Lib\Permcat::delete(local_channel(),$name);
+
+ // TODO: assign all members of the deleted role to the default role
+
Libsync::build_sync_packet();
json_return_and_die([ 'success' => true ]);
}
- $desc = t('Use this form to create permission rules for various classes of people or connections.');
-
$existing = [];
$pcat = new \Zotlabs\Lib\Permcat(local_channel());
$pcatlist = $pcat->listing();
+
+/* not yet ready
+ $test = $pcatlist[4]['perms'];
+ $role_sql = '';
+
+ foreach ($test as $t)
+ $role_sql .= "( k = '" . dbesc($t['name']) . "' AND v = '" . intval($t['value']) . "' ) OR ";
+
+ $role_sql = rtrim($role_sql, ' OR ');
+
+ // get all xchans belonging to a permission role
+ $q = q("SELECT xchan FROM abconfig WHERE chan = %d AND cat = 'my_perms' AND ( $role_sql ) GROUP BY xchan HAVING count(xchan) = %d",
+ intval(local_channel()),
+ intval(count($test))
+ );
+*/
+
+ $is_system_role = false;
$permcats = [];
if($pcatlist) {
foreach($pcatlist as $pc) {
- if(($pc['name']) && ($name) && ($pc['name'] == $name))
+ if(($pc['name']) && ($name) && ($pc['name'] == $name)) {
$existing = $pc['perms'];
- if(! $pc['system'])
- $permcats[bin2hex($pc['name'])] = $pc['localname'];
+ if (isset($pc['system']) && intval($pc['system']))
+ $is_system_role = $pc['name'];
+ }
+
+ $permcats[bin2hex($pc['name'])] = $pc['localname'];
+
+ if($pc['name'] == $name)
+ $localname = $pc['localname'];
}
}
@@ -98,33 +157,56 @@ class Permcats extends Controller {
$checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$k);
if($existing[$k])
- $thisperm = "1";
-
- $perms[] = array('perms_' . $k, $v, '',$thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited);
+ $thisperm = 1;
+
+ $perms[] = [
+ 'perms_' . $k,
+ $v,
+ '',
+ $thisperm,
+ 1,
+ (($checkinherited & PERMS_SPECIFIC) ? '' : '1'),
+ '',
+ $checkinherited
+ ];
}
+ $is_default_role = (get_pconfig(local_channel(),'system','default_permcat','default') == $name);
+
+ $group_select_options = [
+ 'selected' => '',
+ 'form_id' => 'group_select',
+ 'label' => t('Assign this role to'),
+ 'after' => [
+ 'name' => t('All my contacts'),
+ 'id' => 'all_contacts',
+ 'selected' => false
+ ]
+ ];
+ $group_select = AccessList::select(local_channel(), $group_select_options);
$tpl = get_markup_template("permcats.tpl");
$o .= replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("permcats"),
- '$title' => t('Permission Categories'),
- '$desc' => $desc,
- '$desc2' => $desc2,
+ '$default_role' => array('default_role', t('Use this role as default for new contacts'), intval($is_default_role), '', [t('No'), t('Yes')]),
+
+ '$title' => t('Contact Roles'),
'$tokens' => $t,
'$permcats' => $permcats,
'$atoken' => $atoken,
'$url1' => z_root() . '/channel/' . $channel['channel_address'],
'$url2' => z_root() . '/photos/' . $channel['channel_address'],
- '$name' => array('name', t('Permission category name') . ' <span class="required">*</span>', (($name) ? $name : ''), ''),
- '$me' => t('My Settings'),
+ '$name' => ['name', t('Role name') . ' <span class="required">*</span>', (($localname) ? $localname : ''), (($is_system_role) ? t('System role - not editable') : '') , '', (($is_system_role) ? 'disabled' : '')],
'$perms' => $perms,
'$inherited' => t('inherited'),
- '$notself' => 0,
- '$self' => 1,
- '$permlbl' => t('Individual Permissions'),
- '$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'),
- '$submit' => t('Submit')
+ '$is_system_role' => $is_system_role,
+ '$permlbl' => t('Role Permissions'),
+ '$permnote' => t('Some permissions may be inherited from your <a href="settings">channel role</a>, which have higher priority than contact role settings.'),
+ '$submit' => t('Submit'),
+ '$return_path' => argv(1),
+ '$group_select' => $group_select,
+
));
return $o;
}
diff --git a/Zotlabs/Module/Profiles.php b/Zotlabs/Module/Profiles.php
index 1512148b1..ca0ca4f1a 100644
--- a/Zotlabs/Module/Profiles.php
+++ b/Zotlabs/Module/Profiles.php
@@ -316,8 +316,6 @@ class Profiles extends \Zotlabs\Web\Controller {
$work = fix_mce_lf(escape_tags(trim($_POST['work'])));
$education = fix_mce_lf(escape_tags(trim($_POST['education'])));
- $hide_friends = ((intval($_POST['hide_friends'])) ? 1: 0);
-
// start fresh and create a new vcard. TODO: preserve the original guid or whatever else needs saving
// $orig_vcard = (($orig[0]['profile_vcard']) ? \Sabre\VObject\Reader::read($orig[0]['profile_vcard']) : null);
@@ -513,6 +511,16 @@ class Profiles extends \Zotlabs\Web\Controller {
$value = $locality . $comma1 . $region . $comma2 . $country_name;
}
+ $hide_friends = ((intval($_POST['hide_friends'])) ? 1: 0);
+
+ $suggestme = ((x($_POST, 'suggestme')) ? intval($_POST['suggestme']) : 0);
+ set_pconfig(local_channel(), 'system', 'suggestme', $suggestme);
+
+ $show_presence = (((x($_POST, 'show_presence')) && (intval($_POST['show_presence']) == 1)) ? 1 : 0);
+ set_pconfig(local_channel(), 'system', 'show_online_status', $show_presence);
+
+ $publish = ((x($_POST, 'profile_in_directory') && (intval($_POST['profile_in_directory']) == 1)) ? 1 : 0);
+
profile_activity($changes,$value);
}
@@ -551,7 +559,8 @@ class Profiles extends \Zotlabs\Web\Controller {
employment = '%s',
education = '%s',
hide_friends = %d,
- profile_vcard = '%s'
+ profile_vcard = '%s',
+ publish = %d
WHERE id = %d AND uid = %d",
dbesc($profile_name),
dbesc($name),
@@ -587,6 +596,7 @@ class Profiles extends \Zotlabs\Web\Controller {
dbesc($education),
intval($hide_friends),
dbesc($profile_vcard),
+ intval($publish),
intval(argv(1)),
intval(local_channel())
);
@@ -675,13 +685,43 @@ class Profiles extends \Zotlabs\Web\Controller {
else
$fields = $profile_fields_basic;
- $hide_friends = array(
- 'hide_friends',
- t('Hide your connections list from viewers of this profile'),
- $r[0]['hide_friends'],
- '',
- array(t('No'),t('Yes'))
- );
+ $show_presence = [];
+ $profile_in_dir = '';
+ $suggestme = '';
+ $hide_friends = [];
+ $is_default = (($r[0]['is_default']) ? 1 : 0);
+
+ if ($is_default) {
+
+ $hide_friends = array(
+ 'hide_friends',
+ t('Hide my connections from viewers of this profile'),
+ $r[0]['hide_friends'],
+ '',
+ [t('No'), t('Yes')]
+ );
+
+
+ $opt_tpl = get_markup_template("field_checkbox.tpl");
+ if (get_config('system', 'publish_all')) {
+ $profile_in_dir = '<input type="hidden" name="profile_in_directory" value="1" />';
+ }
+ else {
+ $profile_in_dir = replace_macros($opt_tpl, [
+ '$field' => ['profile_in_directory', t('Publish my default profile in the network directory'), $r[0]['publish'], '', [t('No'), t('Yes')]],
+ ]);
+ }
+
+ $suggestme = get_pconfig(local_channel(), 'system', 'suggestme');
+ $suggestme = (($suggestme === false) ? '0' : $suggestme); // default if not set: 0
+
+ $suggestme = replace_macros($opt_tpl, [
+ '$field' => ['suggestme', t('Suggest me as a potential contact to new members'), $suggestme, '', [t('No'), t('Yes')]],
+ ]);
+
+ $show_presence_val = intval(get_pconfig(local_channel(), 'system', 'show_online_status'));
+ $show_presence = ['show_presence', t('Reveal my online status'), $show_presence_val, '', [t('No'), t('Yes')]];
+ }
$q = q("select * from profdef where true");
if($q) {
@@ -710,7 +750,7 @@ class Profiles extends \Zotlabs\Web\Controller {
if(! $f)
$f = 'ymd';
- $is_default = (($r[0]['is_default']) ? 1 : 0);
+
$tpl = get_markup_template("profile_edit.tpl");
$o .= replace_macros($tpl,array(
@@ -724,7 +764,7 @@ class Profiles extends \Zotlabs\Web\Controller {
'$banner' => t('Edit Profile Details'),
'$submit' => t('Submit'),
'$viewprof' => t('View this profile'),
- '$editvis' => t('Edit visibility'),
+ '$editvis' => t('Edit visibility'),
'$tools_label' => t('Profile Tools'),
'$coverpic' => t('Change cover photo'),
'$profpic' => t('Change profile photo'),
@@ -732,7 +772,7 @@ class Profiles extends \Zotlabs\Web\Controller {
'$cl_prof' => t('Clone this profile'),
'$del_prof' => t('Delete this profile'),
'$addthing' => t('Add profile things'),
- '$personal' => t('Personal'),
+ '$basic' => t('Basic'),
'$location' => t('Location'),
'$relation' => t('Relationship'),
'$miscellaneous'=> t('Miscellaneous'),
@@ -801,6 +841,11 @@ class Profiles extends \Zotlabs\Web\Controller {
'$update' => t('Update'),
'$delete' => t('Delete'),
'$cancel' => t('Cancel'),
+
+ '$show_presence' => $show_presence,
+ '$suggestme' => $suggestme,
+ '$profile_in_dir' => $profile_in_dir,
+
));
$arr = array('profile' => $r[0], 'entry' => $o);
diff --git a/Zotlabs/Module/Regate.php b/Zotlabs/Module/Regate.php
index 462c997ff..33bb8d957 100644
--- a/Zotlabs/Module/Regate.php
+++ b/Zotlabs/Module/Regate.php
@@ -196,7 +196,7 @@ class Regate extends \Zotlabs\Web\Controller {
if ($invite_channel) {
$f = Connect::connect($new_channel['channel'], $invite_channel['xchan_addr']);
if ($f['success']) {
- $can_view_stream = their_perms_contains($channel_id, $f['abook']['abook_xchan'], 'view_stream');
+ $can_view_stream = intval(get_abconfig($channel_id, $f['abook']['abook_xchan'], 'their_perms', 'view_stream'));
// If we can view their stream, pull in some posts
if ($can_view_stream) {
Master::Summon(['Onepoll', $f['abook']['abook_id']]);
diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php
index e95752338..914523960 100644
--- a/Zotlabs/Module/Settings/Channel.php
+++ b/Zotlabs/Module/Settings/Channel.php
@@ -2,6 +2,10 @@
namespace Zotlabs\Module\Settings;
+use App;
+use Zotlabs\Access\PermissionLimits;
+use Zotlabs\Access\PermissionRoles;
+use Zotlabs\Daemon\Master;
use Zotlabs\Lib\Apps;
use Zotlabs\Lib\Libsync;
@@ -10,602 +14,266 @@ require_once('include/selectors.php');
class Channel {
-
function post() {
- $channel = \App::get_channel();
-
check_form_security_token_redirectOnErr('/settings', 'settings');
-
call_hooks('settings_post', $_POST);
- $set_perms = '';
-
- $role = ((x($_POST,'permissions_role')) ? notags(trim($_POST['permissions_role'])) : '');
- $oldrole = get_pconfig(local_channel(),'system','permissions_role');
-
- // This mapping can be removed after 3.4 release
- if($oldrole === 'social_party') {
- $oldrole = 'social_federation';
- }
-
- if(($role != $oldrole) || ($role === 'custom')) {
-
- if($role === 'custom') {
- $hide_presence = (((x($_POST,'hide_presence')) && (intval($_POST['hide_presence']) == 1)) ? 1: 0);
- $publish = (((x($_POST,'profile_in_directory')) && (intval($_POST['profile_in_directory']) == 1)) ? 1: 0);
- $def_group = ((x($_POST,'group-selection')) ? notags(trim($_POST['group-selection'])) : '');
- $r = q("update channel set channel_default_group = '%s' where channel_id = %d",
- dbesc($def_group),
- intval(local_channel())
- );
-
- $global_perms = \Zotlabs\Access\Permissions::Perms();
-
- foreach($global_perms as $k => $v) {
- \Zotlabs\Access\PermissionLimits::Set(local_channel(),$k,intval($_POST[$k]));
- }
- $acl = new \Zotlabs\Access\AccessList($channel);
- $acl->set_from_array($_POST);
- $x = $acl->get();
-
- $r = q("update channel set channel_allow_cid = '%s', channel_allow_gid = '%s',
- channel_deny_cid = '%s', channel_deny_gid = '%s' where channel_id = %d",
- dbesc($x['allow_cid']),
- dbesc($x['allow_gid']),
- dbesc($x['deny_cid']),
- dbesc($x['deny_gid']),
- intval(local_channel())
- );
- }
- else {
- $role_permissions = \Zotlabs\Access\PermissionRoles::role_perms($_POST['permissions_role']);
- if(! $role_permissions) {
- notice('Permissions category could not be found.');
- return;
- }
- $hide_presence = 1 - (intval($role_permissions['online']));
- if($role_permissions['default_collection']) {
- $r = q("select hash from pgrp where uid = %d and gname = '%s' limit 1",
- intval(local_channel()),
- dbesc( t('Friends') )
- );
- if(! $r) {
- require_once('include/group.php');
- group_add(local_channel(), t('Friends'));
- group_add_member(local_channel(),t('Friends'),$channel['channel_hash']);
- $r = q("select hash from pgrp where uid = %d and gname = '%s' limit 1",
- intval(local_channel()),
- dbesc( t('Friends') )
- );
- }
- if($r) {
- q("update channel set channel_default_group = '%s', channel_allow_gid = '%s', channel_allow_cid = '', channel_deny_gid = '', channel_deny_cid = '' where channel_id = %d",
- dbesc($r[0]['hash']),
- dbesc('<' . $r[0]['hash'] . '>'),
- intval(local_channel())
- );
- }
- else {
- notice( sprintf('Default privacy group \'%s\' not found. Please create and re-submit permission change.', t('Friends')) . EOL);
- return;
- }
- }
- // no default collection
- else {
- q("update channel set channel_default_group = '', channel_allow_gid = '', channel_allow_cid = '', channel_deny_gid = '',
- channel_deny_cid = '' where channel_id = %d",
- intval(local_channel())
- );
- }
-
- if($role_permissions['perms_connect']) {
- $x = \Zotlabs\Access\Permissions::FilledPerms($role_permissions['perms_connect']);
- foreach($x as $k => $v) {
- set_abconfig(local_channel(),$channel['channel_hash'],'my_perms',$k, $v);
- if($role_permissions['perms_auto']) {
- set_pconfig(local_channel(),'autoperms',$k,$v);
- }
- else {
- del_pconfig(local_channel(),'autoperms',$k);
- }
- }
- }
-
- if($role_permissions['limits']) {
- foreach($role_permissions['limits'] as $k => $v) {
- \Zotlabs\Access\PermissionLimits::Set(local_channel(),$k,$v);
- }
- }
- if(array_key_exists('directory_publish',$role_permissions)) {
- $publish = intval($role_permissions['directory_publish']);
- }
- }
-
- set_pconfig(local_channel(),'system','hide_online_status',$hide_presence);
- set_pconfig(local_channel(),'system','permissions_role',$role);
- }
-
- $username = ((x($_POST,'username')) ? notags(trim($_POST['username'])) : '');
- $timezone = ((x($_POST,'timezone_select')) ? notags(trim($_POST['timezone_select'])) : '');
- $defloc = ((x($_POST,'defloc')) ? notags(trim($_POST['defloc'])) : '');
- $openid = ((x($_POST,'openid_url')) ? notags(trim($_POST['openid_url'])) : '');
- $maxreq = ((x($_POST,'maxreq')) ? intval($_POST['maxreq']) : 0);
- $expire = ((x($_POST,'expire')) ? intval($_POST['expire']) : 0);
- $evdays = ((x($_POST,'evdays')) ? intval($_POST['evdays']) : 3);
- $photo_path = ((x($_POST,'photo_path')) ? escape_tags(trim($_POST['photo_path'])) : '');
- $attach_path = ((x($_POST,'attach_path')) ? escape_tags(trim($_POST['attach_path'])) : '');
-
- $expire_items = ((x($_POST,'expire_items')) ? intval($_POST['expire_items']) : 0);
- $expire_starred = ((x($_POST,'expire_starred')) ? intval($_POST['expire_starred']) : 0);
- $expire_photos = ((x($_POST,'expire_photos'))? intval($_POST['expire_photos']) : 0);
- $expire_network_only = ((x($_POST,'expire_network_only'))? intval($_POST['expire_network_only']) : 0);
-
- $allow_location = (((x($_POST,'allow_location')) && (intval($_POST['allow_location']) == 1)) ? 1: 0);
-
- $blocktags = (((x($_POST,'blocktags')) && (intval($_POST['blocktags']) == 1)) ? 0: 1); // this setting is inverted!
- $unkmail = (((x($_POST,'unkmail')) && (intval($_POST['unkmail']) == 1)) ? 1: 0);
- $cntunkmail = ((x($_POST,'cntunkmail')) ? intval($_POST['cntunkmail']) : 0);
- $suggestme = ((x($_POST,'suggestme')) ? intval($_POST['suggestme']) : 0);
- $autoperms = ((x($_POST,'autoperms')) ? intval($_POST['autoperms']) : 0);
-
- $post_newfriend = (($_POST['post_newfriend'] == 1) ? 1: 0);
- $post_joingroup = (($_POST['post_joingroup'] == 1) ? 1: 0);
- $post_profilechange = (($_POST['post_profilechange'] == 1) ? 1: 0);
- $adult = (($_POST['adult'] == 1) ? 1 : 0);
- $defpermcat = ((x($_POST,'defpermcat')) ? notags(trim($_POST['defpermcat'])) : 'default');
-
- $mailhost = ((array_key_exists('mailhost',$_POST)) ? notags(trim($_POST['mailhost'])) : '');
-
- $pageflags = $channel['channel_pageflags'];
- $existing_adult = (($pageflags & PAGE_ADULT) ? 1 : 0);
- if($adult != $existing_adult)
+ $channel = App::get_channel();
+ $role = ((x($_POST, 'permissions_role')) ? notags(trim($_POST['permissions_role'])) : '');
+ $timezone = ((x($_POST, 'timezone_select')) ? notags(trim($_POST['timezone_select'])) : '');
+ $defloc = ((x($_POST, 'defloc')) ? notags(trim($_POST['defloc'])) : '');
+ $evdays = ((x($_POST, 'evdays')) ? intval($_POST['evdays']) : 3);
+ $photo_path = ((x($_POST, 'photo_path')) ? escape_tags(trim($_POST['photo_path'])) : '');
+ $attach_path = ((x($_POST, 'attach_path')) ? escape_tags(trim($_POST['attach_path'])) : '');
+ $allow_location = (((x($_POST, 'allow_location')) && (intval($_POST['allow_location']) == 1)) ? 1 : 0);
+ $post_newfriend = (($_POST['post_newfriend'] == 1) ? 1 : 0);
+ $post_joingroup = (($_POST['post_joingroup'] == 1) ? 1 : 0);
+ $post_profilechange = (($_POST['post_profilechange'] == 1) ? 1 : 0);
+ $adult = (($_POST['adult'] == 1) ? 1 : 0);
+ $mailhost = ((array_key_exists('mailhost', $_POST)) ? notags(trim($_POST['mailhost'])) : '');
+ $pageflags = $channel['channel_pageflags'];
+ $existing_adult = (($pageflags & PAGE_ADULT) ? 1 : 0);
+ $expire = ((x($_POST, 'expire')) ? intval($_POST['expire']) : 0);
+
+ if ($adult != $existing_adult) {
$pageflags = ($pageflags ^ PAGE_ADULT);
-
+ }
$notify = 0;
-
- if(x($_POST,'notify1'))
+ if (x($_POST, 'notify1'))
$notify += intval($_POST['notify1']);
- if(x($_POST,'notify2'))
+ if (x($_POST, 'notify2'))
$notify += intval($_POST['notify2']);
- if(x($_POST,'notify3'))
+ if (x($_POST, 'notify3'))
$notify += intval($_POST['notify3']);
- if(x($_POST,'notify4'))
+ if (x($_POST, 'notify4'))
$notify += intval($_POST['notify4']);
- if(x($_POST,'notify5'))
+ if (x($_POST, 'notify5'))
$notify += intval($_POST['notify5']);
- if(x($_POST,'notify6'))
+ if (x($_POST, 'notify6'))
$notify += intval($_POST['notify6']);
- if(x($_POST,'notify7'))
+ if (x($_POST, 'notify7'))
$notify += intval($_POST['notify7']);
- if(x($_POST,'notify8'))
+ if (x($_POST, 'notify8'))
$notify += intval($_POST['notify8']);
$vnotify = 0;
-
- if(x($_POST,'vnotify1'))
+ if (x($_POST, 'vnotify1'))
$vnotify += intval($_POST['vnotify1']);
- if(x($_POST,'vnotify2'))
+ if (x($_POST, 'vnotify2'))
$vnotify += intval($_POST['vnotify2']);
- if(x($_POST,'vnotify3'))
+ if (x($_POST, 'vnotify3'))
$vnotify += intval($_POST['vnotify3']);
- if(x($_POST,'vnotify4'))
+ if (x($_POST, 'vnotify4'))
$vnotify += intval($_POST['vnotify4']);
- if(x($_POST,'vnotify5'))
+ if (x($_POST, 'vnotify5'))
$vnotify += intval($_POST['vnotify5']);
- if(x($_POST,'vnotify6'))
+ if (x($_POST, 'vnotify6'))
$vnotify += intval($_POST['vnotify6']);
- if(x($_POST,'vnotify7'))
+ if (x($_POST, 'vnotify7'))
$vnotify += intval($_POST['vnotify7']);
- if(x($_POST,'vnotify8'))
+ if (x($_POST, 'vnotify8'))
$vnotify += intval($_POST['vnotify8']);
- if(x($_POST,'vnotify9'))
+ if (x($_POST, 'vnotify9'))
$vnotify += intval($_POST['vnotify9']);
- if(x($_POST,'vnotify10'))
+ if (x($_POST, 'vnotify10'))
$vnotify += intval($_POST['vnotify10']);
- if(x($_POST,'vnotify11') && is_site_admin())
+ if (x($_POST, 'vnotify11') && is_site_admin())
$vnotify += intval($_POST['vnotify11']);
- if(x($_POST,'vnotify12'))
+ if (x($_POST, 'vnotify12'))
$vnotify += intval($_POST['vnotify12']);
- if(x($_POST,'vnotify13'))
+ if (x($_POST, 'vnotify13'))
$vnotify += intval($_POST['vnotify13']);
- if(x($_POST,'vnotify14'))
+ if (x($_POST, 'vnotify14'))
$vnotify += intval($_POST['vnotify14']);
- if(x($_POST,'vnotify15'))
+ if (x($_POST, 'vnotify15'))
$vnotify += intval($_POST['vnotify15']);
- $always_show_in_notices = x($_POST, 'always_show_in_notices') ? 1 : 0;
- $update_notices_per_parent = x($_POST, 'update_notices_per_parent') ? 1 : 0;
+ $always_show_in_notices = ((x($_POST, 'always_show_in_notices')) ? 1 : 0);
+ $update_notices_per_parent = ((x($_POST, 'update_notices_per_parent')) ? 1 : 0);
- $err = '';
+ if ($timezone !== $channel['channel_timezone']) {
+ if (strlen($timezone))
+ date_default_timezone_set($timezone);
+ }
- $name_change = false;
+ if ($role !== get_pconfig(local_channel(), 'system', 'permissions_role')) {
+ $role_permissions = PermissionRoles::role_perms($_POST['permissions_role']);
- if($username != $channel['channel_name']) {
- $name_change = true;
- require_once('include/channel.php');
- $err = validate_channelname($username);
- if($err) {
- notice($err);
- return;
+ if (isset($role_permissions['limits'])) {
+ foreach ($role_permissions['limits'] as $k => $v) {
+ PermissionLimits::Set(local_channel(), $k, $v);
+ }
}
- }
- if($timezone != $channel['channel_timezone']) {
- if(strlen($timezone))
- date_default_timezone_set($timezone);
+ set_pconfig(local_channel(), 'system', 'group_actor', 0);
+ if (isset($role_permissions['channel_type']) && $role_permissions['channel_type'] === 'group') {
+ set_pconfig(local_channel(), 'system', 'group_actor', 1);
+ }
}
- set_pconfig(local_channel(),'system','use_browser_location',$allow_location);
- set_pconfig(local_channel(),'system','suggestme', $suggestme);
- set_pconfig(local_channel(),'system','post_newfriend', $post_newfriend);
- set_pconfig(local_channel(),'system','post_joingroup', $post_joingroup);
- set_pconfig(local_channel(),'system','post_profilechange', $post_profilechange);
- set_pconfig(local_channel(),'system','blocktags',$blocktags);
- set_pconfig(local_channel(),'system','vnotify',$vnotify);
- set_pconfig(local_channel(),'system','always_show_in_notices',$always_show_in_notices);
- set_pconfig(local_channel(),'system','update_notices_per_parent',$update_notices_per_parent);
- set_pconfig(local_channel(),'system','evdays',$evdays);
- set_pconfig(local_channel(),'system','photo_path',$photo_path);
- set_pconfig(local_channel(),'system','attach_path',$attach_path);
- set_pconfig(local_channel(),'system','default_permcat',$defpermcat);
- set_pconfig(local_channel(),'system','email_notify_host',$mailhost);
- set_pconfig(local_channel(),'system','autoperms',$autoperms);
-
- $r = q("update channel set channel_name = '%s', channel_pageflags = %d, channel_timezone = '%s', channel_location = '%s', channel_notifyflags = %d, channel_max_anon_mail = %d, channel_max_friend_req = %d, channel_expire_days = %d $set_perms where channel_id = %d",
- dbesc($username),
+ set_pconfig(local_channel(), 'system', 'permissions_role', $role);
+ set_pconfig(local_channel(), 'system', 'use_browser_location', $allow_location);
+ set_pconfig(local_channel(), 'system', 'post_newfriend', $post_newfriend);
+ set_pconfig(local_channel(), 'system', 'post_joingroup', $post_joingroup);
+ set_pconfig(local_channel(), 'system', 'post_profilechange', $post_profilechange);
+ set_pconfig(local_channel(), 'system', 'vnotify', $vnotify);
+ set_pconfig(local_channel(), 'system', 'always_show_in_notices', $always_show_in_notices);
+ set_pconfig(local_channel(), 'system', 'update_notices_per_parent', $update_notices_per_parent);
+ set_pconfig(local_channel(), 'system', 'evdays', $evdays);
+ set_pconfig(local_channel(), 'system', 'photo_path', $photo_path);
+ set_pconfig(local_channel(), 'system', 'attach_path', $attach_path);
+ set_pconfig(local_channel(), 'system', 'email_notify_host', $mailhost);
+
+ $r = q("update channel set channel_pageflags = %d, channel_timezone = '%s',
+ channel_location = '%s', channel_notifyflags = %d, channel_expire_days = %d
+ where channel_id = %d",
intval($pageflags),
dbesc($timezone),
dbesc($defloc),
intval($notify),
- intval($unkmail),
- intval($maxreq),
intval($expire),
intval(local_channel())
);
- if($r)
- info( t('Settings updated.') . EOL);
-
- if(! is_null($publish)) {
- $r = q("UPDATE profile SET publish = %d WHERE is_default = 1 AND uid = %d",
- intval($publish),
- intval(local_channel())
- );
- }
-
- if($name_change) {
- // change name on all associated xchans by matching the url
- $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s' where xchan_url = '%s'",
- dbesc($username),
- dbesc(datetime_convert()),
- dbesc(z_root() . '/channel/' . $channel['channel_address'])
- );
- $r = q("update profile set fullname = '%s' where uid = %d and is_default = 1",
- dbesc($username),
- intval($channel['channel_id'])
- );
- }
-
- \Zotlabs\Daemon\Master::Summon(array('Directory',local_channel()));
+ if ($r)
+ info(t('Settings updated.') . EOL);
+ Master::Summon(['Directory', local_channel()]);
Libsync::build_sync_packet();
-
- if($email_changed && \App::$config['system']['register_policy'] == REGISTER_VERIFY) {
+ if ($email_changed && App::$config['system']['register_policy'] == REGISTER_VERIFY) {
// FIXME - set to un-verified, blocked and redirect to logout
// Q: Why? Are we verifying people or email addresses?
// A: the policy is to verify email addresses
}
- goaway(z_root() . '/settings' );
+ goaway(z_root() . '/settings');
return; // NOTREACHED
}
function get() {
- require_once('include/acl_selectors.php');
- require_once('include/permissions.php');
-
-
- $yes_no = array(t('No'),t('Yes'));
-
-
- $p = q("SELECT * FROM profile WHERE is_default = 1 AND uid = %d LIMIT 1",
- intval(local_channel())
- );
- if(count($p))
- $profile = $p[0];
-
- load_pconfig(local_channel(),'expire');
-
- $channel = \App::get_channel();
-
- $global_perms = \Zotlabs\Access\Permissions::Perms();
-
- $permiss = array();
-
- $perm_opts = array(
- array( t('Nobody except yourself'), 0),
- array( t('Only those you specifically allow'), PERMS_SPECIFIC),
- array( t('Approved connections'), PERMS_CONTACTS),
- array( t('Any connections'), PERMS_PENDING),
- array( t('Anybody on this website'), PERMS_SITE),
- array( t('Anybody in this network'), PERMS_NETWORK),
- array( t('Anybody authenticated'), PERMS_AUTHED),
- array( t('Anybody on the internet'), PERMS_PUBLIC)
- );
-
- $limits = \Zotlabs\Access\PermissionLimits::Get(local_channel());
- $anon_comments = get_config('system','anonymous_comments',true);
-
- foreach($global_perms as $k => $perm) {
- $options = array();
- $can_be_public = ((strstr($k,'view') || ($k === 'post_comments' && $anon_comments)) ? true : false);
- foreach($perm_opts as $opt) {
- if($opt[1] == PERMS_PUBLIC && (! $can_be_public))
- continue;
- $options[$opt[1]] = $opt[0];
- }
- $permiss[] = array($k,$perm,$limits[$k],'',$options);
- }
-
- // logger('permiss: ' . print_r($permiss,true));
-
- $username = $channel['channel_name'];
- $nickname = $channel['channel_address'];
- $timezone = $channel['channel_timezone'];
- $notify = $channel['channel_notifyflags'];
- $defloc = $channel['channel_location'];
-
- $maxreq = $channel['channel_max_friend_req'];
- $expire = $channel['channel_expire_days'];
- $adult_flag = intval($channel['channel_pageflags'] & PAGE_ADULT);
- $sys_expire = get_config('system','default_expire_days');
-
-// $unkmail = \App::$user['unkmail'];
-// $cntunkmail = \App::$user['cntunkmail'];
-
- $hide_presence = intval(get_pconfig(local_channel(), 'system','hide_online_status'));
-
-
- $expire_items = get_pconfig(local_channel(), 'expire','items');
- $expire_items = (($expire_items===false)? '1' : $expire_items); // default if not set: 1
-
- $expire_notes = get_pconfig(local_channel(), 'expire','notes');
- $expire_notes = (($expire_notes===false)? '1' : $expire_notes); // default if not set: 1
-
- $expire_starred = get_pconfig(local_channel(), 'expire','starred');
- $expire_starred = (($expire_starred===false)? '1' : $expire_starred); // default if not set: 1
-
- $expire_photos = get_pconfig(local_channel(), 'expire','photos');
- $expire_photos = (($expire_photos===false)? '0' : $expire_photos); // default if not set: 0
-
- $expire_network_only = get_pconfig(local_channel(), 'expire','network_only');
- $expire_network_only = (($expire_network_only===false)? '0' : $expire_network_only); // default if not set: 0
-
-
- $suggestme = get_pconfig(local_channel(), 'system','suggestme');
- $suggestme = (($suggestme===false)? '0': $suggestme); // default if not set: 0
-
- $post_newfriend = get_pconfig(local_channel(), 'system','post_newfriend');
- $post_newfriend = (($post_newfriend===false)? '0': $post_newfriend); // default if not set: 0
-
- $post_joingroup = get_pconfig(local_channel(), 'system','post_joingroup');
- $post_joingroup = (($post_joingroup===false)? '0': $post_joingroup); // default if not set: 0
-
- $post_profilechange = get_pconfig(local_channel(), 'system','post_profilechange');
- $post_profilechange = (($post_profilechange===false)? '0': $post_profilechange); // default if not set: 0
-
- $blocktags = get_pconfig(local_channel(),'system','blocktags');
- $blocktags = (($blocktags===false) ? '0' : $blocktags);
-
- $timezone = date_default_timezone_get();
-
- $opt_tpl = get_markup_template("field_checkbox.tpl");
- if(get_config('system','publish_all')) {
- $profile_in_dir = '<input type="hidden" name="profile_in_directory" value="1" />';
- }
- else {
- $profile_in_dir = replace_macros($opt_tpl,array(
- '$field' => array('profile_in_directory', t('Publish your default profile in the network directory'), $profile['publish'], '', $yes_no),
- ));
- }
-
- $suggestme = replace_macros($opt_tpl,array(
- '$field' => array('suggestme', t('Allow us to suggest you as a potential friend to new members?'), $suggestme, '', $yes_no),
-
- ));
-
- $subdir = ((strlen(\App::get_path())) ? '<br />' . t('or') . ' ' . z_root() . '/channel/' . $nickname : '');
-
- $webbie = $nickname . '@' . \App::get_hostname();
- $intl_nickname = unpunify($nickname) . '@' . unpunify(\App::get_hostname());
-
-
- $tpl_addr = get_markup_template("settings_nick_set.tpl");
-
- $prof_addr = replace_macros($tpl_addr,array(
- '$desc' => t('Your channel address is'),
+ load_pconfig(local_channel());
+
+ $channel = App::get_channel();
+ $nickname = $channel['channel_address'];
+ $timezone = $channel['channel_timezone'];
+ $notify = $channel['channel_notifyflags'];
+ $defloc = $channel['channel_location'];
+ $adult_flag = intval($channel['channel_pageflags'] & PAGE_ADULT);
+ $post_newfriend = get_pconfig(local_channel(), 'system', 'post_newfriend');
+ $post_newfriend = (($post_newfriend === false) ? '0' : $post_newfriend); // default if not set: 0
+ $post_joingroup = get_pconfig(local_channel(), 'system', 'post_joingroup');
+ $post_joingroup = (($post_joingroup === false) ? '0' : $post_joingroup); // default if not set: 0
+ $post_profilechange = get_pconfig(local_channel(), 'system', 'post_profilechange');
+ $post_profilechange = (($post_profilechange === false) ? '0' : $post_profilechange); // default if not set: 0
+ $subdir = ((strlen(App::get_path())) ? '<br />' . t('or') . ' ' . z_root() . '/channel/' . $nickname : '');
+ $webbie = $nickname . '@' . App::get_hostname();
+ $intl_nickname = unpunify($nickname) . '@' . unpunify(App::get_hostname());
+ $disable_discover_tab = intval(get_config('system', 'disable_discover_tab', 1)) == 1;
+ $site_firehose = intval(get_config('system', 'site_firehose', 0)) == 1;
+
+ $expire = $channel['channel_expire_days'];
+ $sys_expire = get_config('system', 'default_expire_days');
+
+ $tpl_addr = get_markup_template("settings_nick_set.tpl");
+ $prof_addr = replace_macros($tpl_addr, [
+ '$desc' => t('Your channel address is'),
'$nickname' => (($intl_nickname === $webbie) ? $webbie : $intl_nickname . '&nbsp;(' . $webbie . ')'),
- '$subdir' => $subdir,
- '$davdesc' => t('Your files/photos are accessible via WebDAV at'),
- '$davpath' => z_root() . '/dav/' . $nickname,
- '$basepath' => \App::get_hostname()
- ));
-
-
-
- $pcat = new \Zotlabs\Lib\Permcat(local_channel());
- $pcatlist = $pcat->listing();
- $permcats = [];
- if($pcatlist) {
- foreach($pcatlist as $pc) {
- $permcats[$pc['name']] = $pc['localname'];
- }
- }
-
- $default_permcat = get_pconfig(local_channel(),'system','default_permcat','default');
-
-
- $stpl = get_markup_template('settings.tpl');
-
- $acl = new \Zotlabs\Access\AccessList($channel);
- $perm_defaults = $acl->get();
-
- require_once('include/group.php');
- $group_select = mini_group_select(local_channel(),$channel['channel_default_group']);
-
- $evdays = get_pconfig(local_channel(),'system','evdays');
- if(! $evdays)
+ '$subdir' => $subdir,
+ '$davdesc' => t('Your files/photos are accessible via WebDAV at'),
+ '$davpath' => z_root() . '/dav/' . $nickname,
+ '$basepath' => App::get_hostname()
+ ]);
+
+ $evdays = get_pconfig(local_channel(), 'system', 'evdays');
+ if (!$evdays)
$evdays = 3;
- $permissions_role = get_pconfig(local_channel(),'system','permissions_role');
- if(! $permissions_role)
- $permissions_role = 'custom';
- // compatibility mapping - can be removed after 3.4 release
- if($permissions_role === 'social_party')
- $permissions_role = 'social_federation';
+ $always_show_in_notices = get_pconfig(local_channel(), 'system', 'always_show_in_notices');
+ $update_notices_per_parent = get_pconfig(local_channel(), 'system', 'update_notices_per_parent', 1);
- if(in_array($permissions_role,['forum','repository']))
- $autoperms = replace_macros(get_markup_template('field_checkbox.tpl'), [
- '$field' => [ 'autoperms',t('Automatic membership approval'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('If enabled, connection requests will be approved without your interaction'), $yes_no ]]);
- else
- $autoperms = '<input type="hidden" name="autoperms" value="' . intval(get_pconfig(local_channel(),'system','autoperms')) . '" />';
+ $vnotify = get_pconfig(local_channel(), 'system', 'vnotify');
+ if ($vnotify === false)
+ $vnotify = (-1);
- $permissions_set = (($permissions_role != 'custom') ? true : false);
+ $permissions_role = get_pconfig(local_channel(), 'system', 'permissions_role');
+ if (!$permissions_role) {
+ $permissions_role = 'custom';
+ }
- $perm_roles = \Zotlabs\Access\PermissionRoles::roles();
+ $perm_roles = PermissionRoles::channel_roles();
- $always_show_in_notices = get_pconfig(local_channel(),'system','always_show_in_notices');
- $update_notices_per_parent = get_pconfig(local_channel(), 'system', 'update_notices_per_parent', 1);
- $vnotify = get_pconfig(local_channel(),'system','vnotify');
+ $plugin = ['basic' => '', 'notify' => ''];
+ call_hooks('channel_settings', $plugin);
- if($vnotify === false)
- $vnotify = (-1);
+ $yes_no = [t('No'), t('Yes')];
- $plugin = [ 'basic' => '', 'security' => '', 'notify' => '' ];
- call_hooks('channel_settings',$plugin);
-
- $disable_discover_tab = intval(get_config('system','disable_discover_tab',1)) == 1;
- $site_firehose = intval(get_config('system','site_firehose',0)) == 1;
-
-
- $o .= replace_macros($stpl,array(
- '$ptitle' => t('Channel Settings'),
-
- '$submit' => t('Submit'),
- '$baseurl' => z_root(),
- '$uid' => local_channel(),
- '$form_security_token' => get_form_security_token("settings"),
- '$nickname_block' => $prof_addr,
- '$h_basic' => t('Basic Settings'),
- '$username' => array('username', t('Full Name:'), $username,''),
- '$email' => array('email', t('Email Address:'), $email, ''),
- '$timezone' => array('timezone_select' , t('Your Timezone:'), $timezone, '', get_timezones()),
- '$defloc' => array('defloc', t('Default Post Location:'), $defloc, t('Geographical location to display on your posts')),
- '$allowloc' => array('allow_location', t('Use Browser Location:'), ((get_pconfig(local_channel(),'system','use_browser_location')) ? 1 : ''), '', $yes_no),
-
- '$adult' => array('adult', t('Adult Content'), $adult_flag, t('This channel frequently or regularly publishes adult content. (Please tag any adult material and/or nudity with #NSFW)'), $yes_no),
-
- '$h_prv' => t('Security and Privacy Settings'),
- '$permissions_set' => $permissions_set,
- '$perms_set_msg' => t('Your permissions are already configured. Click to view/adjust'),
-
- '$hide_presence' => array('hide_presence', t('Hide my online presence'),$hide_presence, t('Prevents displaying in your profile that you are online'), $yes_no),
-
- '$lbl_pmacro' => t('Simple Privacy Settings:'),
- '$pmacro3' => t('Very Public - <em>extremely permissive (should be used with caution)</em>'),
- '$pmacro2' => t('Typical - <em>default public, privacy when desired (similar to social network permissions but with improved privacy)</em>'),
- '$pmacro1' => t('Private - <em>default private, never open or public</em>'),
- '$pmacro0' => t('Blocked - <em>default blocked to/from everybody</em>'),
- '$permiss_arr' => $permiss,
- '$blocktags' => array('blocktags',t('Allow others to tag your posts'), 1-$blocktags, t('Often used by the community to retro-actively flag inappropriate content'), $yes_no),
-
- '$lbl_p2macro' => t('Channel Permission Limits'),
-
- '$expire' => array('expire',t('Expire other channel content after this many days'),$expire, t('0 or blank to use the website limit.') . ' ' . ((intval($sys_expire)) ? sprintf( t('This website expires after %d days.'),intval($sys_expire)) : t('This website does not expire imported content.')) . ' ' . t('The website limit takes precedence if lower than your limit.')),
- '$maxreq' => array('maxreq', t('Maximum Friend Requests/Day:'), intval($channel['channel_max_friend_req']) , t('May reduce spam activity')),
- '$permissions' => t('Default Privacy Group'),
- '$permdesc' => t("\x28click to open/close\x29"),
- '$aclselect' => populate_acl($perm_defaults, false, \Zotlabs\Lib\PermissionDescription::fromDescription(t('Use my default audience setting for the type of object published'))),
-
- '$allow_cid' => acl2json($perm_defaults['allow_cid']),
- '$allow_gid' => acl2json($perm_defaults['allow_gid']),
- '$deny_cid' => acl2json($perm_defaults['deny_cid']),
- '$deny_gid' => acl2json($perm_defaults['deny_gid']),
- '$suggestme' => $suggestme,
- '$group_select' => $group_select,
- '$role' => array('permissions_role' , t('Channel role and privacy'), $permissions_role, '', $perm_roles),
- '$defpermcat' => [ 'defpermcat', t('Default permissions category'), $default_permcat, '', $permcats ],
- '$permcat_enable' => Apps::system_app_installed(local_channel(), 'Permission Categories'),
- '$profile_in_dir' => $profile_in_dir,
- '$hide_friends' => $hide_friends,
- '$hide_wall' => $hide_wall,
- '$unkmail' => $unkmail,
- '$cntunkmail' => array('cntunkmail', t('Maximum private messages per day from unknown people:'), intval($channel['channel_max_anon_mail']) ,t("Useful to reduce spamming")),
-
- '$autoperms' => $autoperms,
- '$h_not' => t('Notification Settings'),
- '$activity_options' => t('By default post a status message when:'),
- '$post_newfriend' => array('post_newfriend', t('accepting a friend request'), $post_newfriend, '', $yes_no),
- '$post_joingroup' => array('post_joingroup', t('joining a forum/community'), $post_joingroup, '', $yes_no),
- '$post_profilechange' => array('post_profilechange', t('making an <em>interesting</em> profile change'), $post_profilechange, '', $yes_no),
- '$lbl_not' => t('Send a notification email when:'),
- '$notify1' => array('notify1', t('You receive a connection request'), ($notify & NOTIFY_INTRO), NOTIFY_INTRO, '', $yes_no),
- '$notify2' => array('notify2', t('Your connections are confirmed'), ($notify & NOTIFY_CONFIRM), NOTIFY_CONFIRM, '', $yes_no),
- '$notify3' => array('notify3', t('Someone writes on your profile wall'), ($notify & NOTIFY_WALL), NOTIFY_WALL, '', $yes_no),
- '$notify4' => array('notify4', t('Someone writes a followup comment'), ($notify & NOTIFY_COMMENT), NOTIFY_COMMENT, '', $yes_no),
- '$notify5' => array('notify5', t('You receive a private message'), ($notify & NOTIFY_MAIL), NOTIFY_MAIL, '', $yes_no),
- '$notify6' => array('notify6', t('You receive a friend suggestion'), ($notify & NOTIFY_SUGGEST), NOTIFY_SUGGEST, '', $yes_no),
- '$notify7' => array('notify7', t('You are tagged in a post'), ($notify & NOTIFY_TAGSELF), NOTIFY_TAGSELF, '', $yes_no),
- '$notify8' => array('notify8', t('You are poked/prodded/etc. in a post'), ($notify & NOTIFY_POKE), NOTIFY_POKE, '', $yes_no),
-
- '$notify9' => array('notify9', t('Someone likes your post/comment'), ($notify & NOTIFY_LIKE), NOTIFY_LIKE, '', $yes_no),
-
-
- '$lbl_vnot' => t('Show visual notifications including:'),
-
- '$vnotify1' => array('vnotify1', t('Unseen stream activity'), ($vnotify & VNOTIFY_NETWORK), VNOTIFY_NETWORK, '', $yes_no),
- '$vnotify2' => array('vnotify2', t('Unseen channel activity'), ($vnotify & VNOTIFY_CHANNEL), VNOTIFY_CHANNEL, '', $yes_no),
- '$vnotify3' => array('vnotify3', t('Unseen private messages'), ($vnotify & VNOTIFY_MAIL), VNOTIFY_MAIL, t('Recommended'), $yes_no),
- '$vnotify4' => array('vnotify4', t('Upcoming events'), ($vnotify & VNOTIFY_EVENT), VNOTIFY_EVENT, '', $yes_no),
- '$vnotify5' => array('vnotify5', t('Events today'), ($vnotify & VNOTIFY_EVENTTODAY), VNOTIFY_EVENTTODAY, '', $yes_no),
- '$vnotify6' => array('vnotify6', t('Upcoming birthdays'), ($vnotify & VNOTIFY_BIRTHDAY), VNOTIFY_BIRTHDAY, t('Not available in all themes'), $yes_no),
- '$vnotify7' => array('vnotify7', t('System (personal) notifications'), ($vnotify & VNOTIFY_SYSTEM), VNOTIFY_SYSTEM, '', $yes_no),
- '$vnotify8' => array('vnotify8', t('System info messages'), ($vnotify & VNOTIFY_INFO), VNOTIFY_INFO, t('Recommended'), $yes_no),
- '$vnotify9' => array('vnotify9', t('System critical alerts'), ($vnotify & VNOTIFY_ALERT), VNOTIFY_ALERT, t('Recommended'), $yes_no),
- '$vnotify10' => array('vnotify10', t('New connections'), ($vnotify & VNOTIFY_INTRO), VNOTIFY_INTRO, t('Recommended'), $yes_no),
- '$vnotify11' => ((is_site_admin()) ? array('vnotify11', t('System Registrations'), ($vnotify & VNOTIFY_REGISTER), VNOTIFY_REGISTER, '', $yes_no) : array()),
- '$vnotify12' => array('vnotify12', t('Unseen shared files'), ($vnotify & VNOTIFY_FILES), VNOTIFY_FILES, '', $yes_no),
- '$vnotify13' => ((($disable_discover_tab && !$site_firehose) || !Apps::system_app_installed(local_channel(), 'Public Stream')) ? array() : array('vnotify13', t('Unseen public stream activity'), ($vnotify & VNOTIFY_PUBS), VNOTIFY_PUBS, '', $yes_no)),
- '$vnotify14' => array('vnotify14', t('Unseen likes and dislikes'), ($vnotify & VNOTIFY_LIKE), VNOTIFY_LIKE, '', $yes_no),
- '$vnotify15' => array('vnotify15', t('Unseen forum posts'), ($vnotify & VNOTIFY_FORUMS), VNOTIFY_FORUMS, '', $yes_no),
- '$mailhost' => [ 'mailhost', t('Email notification hub (hostname)'), get_pconfig(local_channel(),'system','email_notify_host',\App::get_hostname()), sprintf( t('If your channel is mirrored to multiple hubs, set this to your preferred location. This will prevent duplicate email notifications. Example: %s'),\App::get_hostname()) ],
- '$always_show_in_notices' => array('always_show_in_notices', t('Show new wall posts, private messages and connections under Notices'), $always_show_in_notices, 1, '', $yes_no),
- '$update_notices_per_parent' => array('update_notices_per_parent', t('Mark all notices of the thread read if a notice is clicked'), $update_notices_per_parent, 1, t('If no, only the clicked notice will be marked read'), $yes_no),
- '$desktop_notifications_info' => t('Desktop notifications are unavailable because the required browser permission has not been granted'),
+ $stpl = get_markup_template('settings.tpl');
+ $o = replace_macros($stpl, [
+ '$ptitle' => t('Channel Settings'),
+ '$submit' => t('Submit'),
+ '$baseurl' => z_root(),
+ '$uid' => local_channel(),
+ '$form_security_token' => get_form_security_token("settings"),
+ '$role' => ['permissions_role', t('Channel role'), $permissions_role, '', $perm_roles],
+ '$nickname_block' => $prof_addr,
+ '$h_basic' => t('Basic Settings'),
+ '$timezone' => ['timezone_select', t('Channel timezone:'), $timezone, '', get_timezones()],
+ '$defloc' => ['defloc', t('Default post location:'), $defloc, t('Geographical location to display on your posts')],
+ '$allowloc' => ['allow_location', t('Use browser location:'), ((get_pconfig(local_channel(), 'system', 'use_browser_location')) ? 1 : ''), '', $yes_no],
+ '$adult' => ['adult', t('Adult Content'), $adult_flag, t('This channel frequently or regularly publishes adult content')],
+ '$maxreq' => ['maxreq', t('Maximum Friend Requests/Day:'), intval($channel['channel_max_friend_req']), t('May reduce spam activity')],
+ '$h_not' => t('Notification Settings'),
+ '$activity_options' => t('By default post a status message when:'),
+ '$post_newfriend' => ['post_newfriend', t('accepting a friend request'), $post_newfriend, '', $yes_no],
+ '$post_joingroup' => ['post_joingroup', t('joining a forum/community'), $post_joingroup, '', $yes_no],
+ '$post_profilechange' => ['post_profilechange', t('making an <em>interesting</em> profile change'), $post_profilechange, '', $yes_no],
+ '$lbl_not' => t('Send a notification email when:'),
+ '$notify1' => ['notify1', t('You receive a connection request'), ($notify & NOTIFY_INTRO), NOTIFY_INTRO, '', $yes_no],
+ '$notify2' => ['notify2', t('Your connections are confirmed'), ($notify & NOTIFY_CONFIRM), NOTIFY_CONFIRM, '', $yes_no],
+ '$notify3' => ['notify3', t('Someone writes on your profile wall'), ($notify & NOTIFY_WALL), NOTIFY_WALL, '', $yes_no],
+ '$notify4' => ['notify4', t('Someone writes a followup comment'), ($notify & NOTIFY_COMMENT), NOTIFY_COMMENT, '', $yes_no],
+ '$notify5' => ['notify5', t('You receive a private message'), ($notify & NOTIFY_MAIL), NOTIFY_MAIL, '', $yes_no],
+ '$notify6' => ['notify6', t('You receive a friend suggestion'), ($notify & NOTIFY_SUGGEST), NOTIFY_SUGGEST, '', $yes_no],
+ '$notify7' => ['notify7', t('You are tagged in a post'), ($notify & NOTIFY_TAGSELF), NOTIFY_TAGSELF, '', $yes_no],
+ '$notify8' => ['notify8', t('You are poked/prodded/etc. in a post'), ($notify & NOTIFY_POKE), NOTIFY_POKE, '', $yes_no],
+ '$notify9' => ['notify9', t('Someone likes your post/comment'), ($notify & NOTIFY_LIKE), NOTIFY_LIKE, '', $yes_no],
+ '$lbl_vnot' => t('Show visual notifications including:'),
+ '$vnotify1' => ['vnotify1', t('Unseen stream activity'), ($vnotify & VNOTIFY_NETWORK), VNOTIFY_NETWORK, '', $yes_no],
+ '$vnotify2' => ['vnotify2', t('Unseen channel activity'), ($vnotify & VNOTIFY_CHANNEL), VNOTIFY_CHANNEL, '', $yes_no],
+ '$vnotify3' => ['vnotify3', t('Unseen private messages'), ($vnotify & VNOTIFY_MAIL), VNOTIFY_MAIL, t('Recommended'), $yes_no],
+ '$vnotify4' => ['vnotify4', t('Upcoming events'), ($vnotify & VNOTIFY_EVENT), VNOTIFY_EVENT, '', $yes_no],
+ '$vnotify5' => ['vnotify5', t('Events today'), ($vnotify & VNOTIFY_EVENTTODAY), VNOTIFY_EVENTTODAY, '', $yes_no],
+ '$vnotify6' => ['vnotify6', t('Upcoming birthdays'), ($vnotify & VNOTIFY_BIRTHDAY), VNOTIFY_BIRTHDAY, t('Not available in all themes'), $yes_no],
+ '$vnotify7' => ['vnotify7', t('System (personal) notifications'), ($vnotify & VNOTIFY_SYSTEM), VNOTIFY_SYSTEM, '', $yes_no],
+ '$vnotify8' => ['vnotify8', t('System info messages'), ($vnotify & VNOTIFY_INFO), VNOTIFY_INFO, t('Recommended'), $yes_no],
+ '$vnotify9' => ['vnotify9', t('System critical alerts'), ($vnotify & VNOTIFY_ALERT), VNOTIFY_ALERT, t('Recommended'), $yes_no],
+ '$vnotify10' => ['vnotify10', t('New connections'), ($vnotify & VNOTIFY_INTRO), VNOTIFY_INTRO, t('Recommended'), $yes_no],
+ '$vnotify11' => ((is_site_admin()) ? ['vnotify11', t('System Registrations'), ($vnotify & VNOTIFY_REGISTER), VNOTIFY_REGISTER, '', $yes_no] : []),
+ '$vnotify12' => ['vnotify12', t('Unseen shared files'), ($vnotify & VNOTIFY_FILES), VNOTIFY_FILES, '', $yes_no],
+ '$vnotify13' => ((($disable_discover_tab && !$site_firehose) || !Apps::system_app_installed(local_channel(), 'Public Stream')) ? [] : ['vnotify13', t('Unseen public stream activity'), ($vnotify & VNOTIFY_PUBS), VNOTIFY_PUBS, '', $yes_no]),
+ '$vnotify14' => ['vnotify14', t('Unseen likes and dislikes'), ($vnotify & VNOTIFY_LIKE), VNOTIFY_LIKE, '', $yes_no],
+ '$vnotify15' => ['vnotify15', t('Unseen forum posts'), ($vnotify & VNOTIFY_FORUMS), VNOTIFY_FORUMS, '', $yes_no],
+ '$mailhost' => ['mailhost', t('Email notification hub (hostname)'), get_pconfig(local_channel(), 'system', 'email_notify_host', App::get_hostname()), sprintf(t('If your channel is mirrored to multiple hubs, set this to your preferred location. This will prevent duplicate email notifications. Example: %s'), App::get_hostname())],
+ '$always_show_in_notices' => ['always_show_in_notices', t('Show new wall posts, private messages and connections under Notices'), $always_show_in_notices, 1, '', $yes_no],
+ '$update_notices_per_parent' => ['update_notices_per_parent', t('Mark all notices of the thread read if a notice is clicked'), $update_notices_per_parent, 1, t('If no, only the clicked notice will be marked read'), $yes_no],
+ '$desktop_notifications_info' => t('Desktop notifications are unavailable because the required browser permission has not been granted'),
'$desktop_notifications_request' => t('Grant permission'),
- '$evdays' => array('evdays', t('Notify me of events this many days in advance'), $evdays, t('Must be greater than 0')),
- '$basic_addon' => $plugin['basic'],
- '$sec_addon' => $plugin['security'],
- '$notify_addon' => $plugin['notify'],
-
- '$h_advn' => t('Advanced Account/Page Type Settings'),
- '$h_descadvn' => t('Change the behaviour of this account for special situations'),
- '$pagetype' => $pagetype,
- '$lbl_misc' => t('Miscellaneous Settings'),
- '$photo_path' => array('photo_path', t('Default photo upload folder'), get_pconfig(local_channel(),'system','photo_path'), t('%Y - current year, %m - current month')),
- '$attach_path' => array('attach_path', t('Default file upload folder'), get_pconfig(local_channel(),'system','attach_path'), t('%Y - current year, %m - current month')),
- '$removeme' => t('Remove Channel'),
- '$removechannel' => t('Remove this channel.'),
- ));
-
- call_hooks('settings_form',$o);
-
- //$o .= '</form>' . "\r\n";
+ '$evdays' => ['evdays', t('Notify me of events this many days in advance'), $evdays, t('Must be greater than 0')],
+ '$basic_addon' => $plugin['basic'],
+ '$notify_addon' => $plugin['notify'],
+ '$photo_path' => ['photo_path', t('Default photo upload folder'), get_pconfig(local_channel(), 'system', 'photo_path'), t('%Y - current year, %m - current month')],
+ '$attach_path' => ['attach_path', t('Default file upload folder'), get_pconfig(local_channel(), 'system', 'attach_path'), t('%Y - current year, %m - current month')],
+ '$removeme' => t('Remove Channel'),
+ '$removechannel' => t('Remove this channel.'),
+ '$expire' => ['expire', t('Expire other channel content after this many days'), $expire, t('0 or blank to use the website limit.') . ' ' . ((intval($sys_expire)) ? sprintf(t('This website expires after %d days.'), intval($sys_expire)) : t('This website does not expire imported content.')) . ' ' . t('The website limit takes precedence if lower than your limit.')],
+ ]);
+
+ call_hooks('settings_form', $o);
return $o;
}
diff --git a/Zotlabs/Module/Settings/Privacy.php b/Zotlabs/Module/Settings/Privacy.php
new file mode 100644
index 000000000..fbda78a6f
--- /dev/null
+++ b/Zotlabs/Module/Settings/Privacy.php
@@ -0,0 +1,127 @@
+<?php
+
+namespace Zotlabs\Module\Settings;
+
+use App;
+use Zotlabs\Access\PermissionLimits;
+use Zotlabs\Access\Permissions;
+use Zotlabs\Daemon\Master;
+use Zotlabs\Lib\Group;
+use Zotlabs\Lib\Libsync;
+
+class Privacy {
+
+ function post() {
+
+ check_form_security_token_redirectOnErr('/settings/privacy', 'settings');
+ call_hooks('settings_post', $_POST);
+
+ $index_opt_out = (((x($_POST, 'index_opt_out')) && (intval($_POST['index_opt_out']) == 1)) ? 1 : 0);
+ set_pconfig(local_channel(), 'system', 'index_opt_out', $index_opt_out);
+
+ $autoperms = (((x($_POST, 'autoperms')) && (intval($_POST['autoperms']) == 1)) ? 1 : 0);
+ set_pconfig(local_channel(), 'system', 'autoperms', $autoperms);
+
+ $role = get_pconfig(local_channel(), 'system', 'permissions_role');
+ if ($role === 'custom') {
+
+ $global_perms = Permissions::Perms();
+
+ foreach ($global_perms as $k => $v) {
+ PermissionLimits::Set(local_channel(), $k, intval($_POST[$k]));
+ }
+
+ $group_actor = (((x($_POST, 'group_actor')) && (intval($_POST['group_actor']) == 1)) ? 1 : 0);
+ set_pconfig(local_channel(), 'system', 'group_actor', $group_actor);
+
+ }
+
+ info(t('Privacy settings updated.') . EOL);
+ Master::Summon(['Directory', local_channel()]);
+ Libsync::build_sync_packet();
+
+ goaway(z_root() . '/settings/privacy');
+ return; // NOTREACHED
+ }
+
+ function get() {
+
+ load_pconfig(local_channel());
+
+ $channel = App::get_channel();
+ $global_perms = Permissions::Perms();
+ $permiss = [];
+
+ $perm_opts = [
+ [t('Only me'), 0],
+ [t('Only those you specifically allow'), PERMS_SPECIFIC],
+ [t('Approved connections'), PERMS_CONTACTS],
+ [t('Any connections'), PERMS_PENDING],
+ [t('Anybody on this website'), PERMS_SITE],
+ [t('Anybody in this network'), PERMS_NETWORK],
+ [t('Anybody authenticated'), PERMS_AUTHED],
+ [t('Anybody on the internet'), PERMS_PUBLIC]
+ ];
+
+ $help = [
+ 'view_stream',
+ 'view_wiki',
+ 'view_pages',
+ 'view_storage'
+ ];
+
+ $help_txt = t('Advise: set to "Anybody on the internet" and use privacy groups to restrict access');
+ $limits = PermissionLimits::Get(local_channel());
+ $anon_comments = get_config('system', 'anonymous_comments', true);
+
+ foreach ($global_perms as $k => $perm) {
+ $options = [];
+ $can_be_public = (strstr($k, 'view') || ($k === 'post_comments' && $anon_comments));
+
+ foreach ($perm_opts as $opt) {
+ if ($opt[1] == PERMS_PUBLIC && (!$can_be_public))
+ continue;
+
+ $options[$opt[1]] = $opt[0];
+ }
+
+ $permiss[] = [
+ $k,
+ $perm,
+ $limits[$k],
+ ((in_array($k, $help)) ? $help_txt : ''),
+ $options
+ ];
+ }
+
+ //logger('permiss: ' . print_r($permiss,true));
+
+ $autoperms = get_pconfig(local_channel(), 'system', 'autoperms');
+ $index_opt_out = get_pconfig(local_channel(), 'system', 'index_opt_out');
+ $group_actor = get_pconfig(local_channel(), 'system', 'group_actor');
+
+ $permissions_role = get_pconfig(local_channel(), 'system', 'permissions_role', 'custom');
+ $permission_limits = ($permissions_role === 'custom');
+
+ $stpl = get_markup_template('settings_privacy.tpl');
+
+ $o = replace_macros($stpl, [
+ '$ptitle' => t('Privacy Settings'),
+ '$submit' => t('Submit'),
+ '$form_security_token' => get_form_security_token("settings"),
+ '$permission_limits' => $permission_limits,
+ '$permiss_arr' => $permiss,
+ '$permission_limits_label' => t('Advanced configuration'),
+ '$permission_limits_warning' => [
+ t('Proceed with caution'),
+ t('Changing advanced configuration settings can impact your, and your contacts channels functionality and security.'),
+ t('Accept the risk and continue')
+ ],
+ '$autoperms' => ['autoperms', t('Automatically approve new contacts'), $autoperms, '', [t('No'), t('Yes')]],
+ '$index_opt_out' => ['index_opt_out', t('Opt-out of search engine indexing'), $index_opt_out, '', [t('No'), t('Yes')]],
+ '$group_actor' => ['group_actor', t('Group actor'), $group_actor, t('Allow this channel to act as a forum'), [t('No'), t('Yes')]],
+ ]);
+
+ return $o;
+ }
+}
diff --git a/Zotlabs/Module/Uexport.php b/Zotlabs/Module/Uexport.php
index 8116f616b..870c42802 100644
--- a/Zotlabs/Module/Uexport.php
+++ b/Zotlabs/Module/Uexport.php
@@ -143,6 +143,10 @@ class Uexport extends Controller {
function get() {
+ if(! local_channel()) {
+ return;
+ }
+
if(! Apps::system_app_installed(local_channel(), 'Channel Export')) {
//Do not display any associated widgets at this point
App::$pdl = '';
diff --git a/Zotlabs/Update/_1249.php b/Zotlabs/Update/_1249.php
new file mode 100644
index 000000000..6d72c4de4
--- /dev/null
+++ b/Zotlabs/Update/_1249.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Zotlabs\Update;
+
+class _1249 {
+
+ function run() {
+
+ dbq("START TRANSACTION");
+
+ if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
+ $r1 = dbq("ALTER TABLE abook ADD abook_role TEXT NOT NULL DEFAULT ''");
+ $r2 = dbq("CREATE INDEX \"abook_role\" ON abook (\"abook_role\")");
+ $r = ($r1 && $r2);
+ }
+ else {
+ $r = dbq("ALTER TABLE `abook` ADD `abook_role` CHAR(191) NOT NULL DEFAULT '' ,
+ ADD INDEX `abook_role` (`abook_role`)");
+ }
+
+ if($r) {
+ dbq("COMMIT");
+ return UPDATE_SUCCESS;
+ }
+
+ dbq("ROLLBACK");
+ return UPDATE_FAILED;
+
+ }
+
+}
diff --git a/Zotlabs/Widget/Collections.php b/Zotlabs/Widget/Collections.php
index bc9c812c6..774878540 100644
--- a/Zotlabs/Widget/Collections.php
+++ b/Zotlabs/Widget/Collections.php
@@ -1,8 +1,8 @@
<?php
namespace Zotlabs\Widget;
-
-require_once('include/group.php');
+
+use Zotlabs\Lib\AccessList;
class Collections {
@@ -49,6 +49,6 @@ class Collections {
break;
}
- return group_side($every, $each, $edit, $current, $abook_id, $wmode);
+ return AccessList::widget($every, $each, $edit, $current, $abook_id, $wmode);
}
}
diff --git a/Zotlabs/Widget/Messages.php b/Zotlabs/Widget/Messages.php
index c0fef9f75..71f4bd310 100644
--- a/Zotlabs/Widget/Messages.php
+++ b/Zotlabs/Widget/Messages.php
@@ -219,7 +219,7 @@ class Messages {
$entries[$i]['info'] = '';
$entries[$i]['created'] = datetime_convert('UTC', date_default_timezone_get(), $notice['created']);
$entries[$i]['summary'] = $summary;
- $entries[$i]['b64mid'] = basename($notice['link']);
+ $entries[$i]['b64mid'] = (($notice['ntype'] & NOTIFY_INTRO) ? '' : basename($notice['link']));
$entries[$i]['href'] = (($notice['ntype'] & NOTIFY_INTRO) ? $notice['link'] : z_root() . '/hq/' . basename($notice['link']));
$entries[$i]['icon'] = (($notice['ntype'] & NOTIFY_INTRO) ? '<i class="fa fa-user-plus"></i>' : '');
diff --git a/Zotlabs/Widget/Permcats.php b/Zotlabs/Widget/Permcats.php
new file mode 100644
index 000000000..72c80ca0c
--- /dev/null
+++ b/Zotlabs/Widget/Permcats.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace Zotlabs\Widget;
+
+use Zotlabs\Lib\Permcat;
+use Zotlabs\Access\PermissionLimits;
+
+class Permcats {
+
+ function widget($arr) {
+ $pcat = new Permcat(local_channel());
+ $pcatlist = $pcat->listing();
+
+ $list = '<b>Roles:</b><br>';
+ $active = '';
+ $active_role = '';
+
+ if($pcatlist) {
+ $i = 0;
+ foreach($pcatlist as $pc) {
+ if(argc() > 1) {
+ if($pc['name'] == hex2bin(argv(1))) {
+ $active = $i;
+ $active_role = $pc['name'];
+ }
+ }
+
+ $list .= '<a href="permcats/' . bin2hex($pc['name']) . '">' . $pc['localname'] . '</a><br>';
+ $i++;
+ }
+ }
+
+ if(argc() > 1) {
+
+/* get role members based on permissions
+ $test = $pcatlist[$active]['perms'];
+
+ $role_sql = '';
+ $count = 0;
+ foreach ($test as $t) {
+ $checkinherited = PermissionLimits::Get(local_channel(),$t['name']);
+
+ if($checkinherited & PERMS_SPECIFIC) {
+ $role_sql .= "( abconfig.k = '" . dbesc($t['name']) . "' AND abconfig.v = '" . intval($t['value']) . "' ) OR ";
+ $count++;
+ }
+ }
+
+ $role_sql = rtrim($role_sql, ' OR ');
+
+ $r = q("SELECT abconfig.xchan, xchan.xchan_name, abook.abook_id FROM abconfig LEFT JOIN xchan on abconfig.xchan = xchan.xchan_hash LEFT JOIN abook ON abconfig.xchan = abook.abook_xchan WHERE xchan.xchan_deleted = 0 and abconfig.chan = %d AND abconfig.cat = 'my_perms' AND ( $role_sql ) GROUP BY abconfig.xchan HAVING count(abconfig.xchan) = %d ORDER BY xchan.xchan_name",
+ intval(local_channel()),
+ intval($count)
+ );
+*/
+
+ // get role members based on abook_role
+
+ $r = q("SELECT abook.abook_id, abook.abook_role, xchan.xchan_name, xchan.xchan_addr, xchan.xchan_url, xchan.xchan_photo_s FROM abook
+ LEFT JOIN xchan on abook.abook_xchan = xchan.xchan_hash
+ WHERE abook.abook_channel = %d AND abook.abook_role = '%s' AND abook_self = 0 AND xchan_deleted = 0
+ ORDER BY xchan.xchan_name",
+ intval(local_channel()),
+ dbesc($active_role)
+ );
+
+ $members = '<b>Role members:</b><br>';
+ $members .= '<div class="border rounded" style="height: 20rem; overflow: auto;">';
+
+ foreach ($r as $rr) {
+ $addr = (($rr['xchan_addr']) ? $rr['xchan_addr'] : $rr['xchan_url']);
+ $members .= '<a href="connections#' . $rr['abook_id'] . '" class="lh-sm border-bottom p-2 d-block text-truncate"><img src="' . $rr['xchan_photo_s'] . '" class="float-start rounded me-2" style="height: 2.2rem; width: 2.2rem;" loading="lazy">' . $rr['xchan_name'] . '<br><span class="text-muted small">' . $addr . '</span></a>';
+ }
+ $members .= '</div>';
+ }
+ return $list . '<br>' . $members. '<br>' . $others;
+
+ }
+}
diff --git a/Zotlabs/Widget/Profile.php b/Zotlabs/Widget/Profile.php
index 8bd624c0f..0e5444a56 100644
--- a/Zotlabs/Widget/Profile.php
+++ b/Zotlabs/Widget/Profile.php
@@ -2,12 +2,16 @@
namespace Zotlabs\Widget;
+use App;
class Profile {
-
function widget($args) {
+ if(!App::$profile['profile_uid']) {
+ return;
+ }
+
$block = observer_prohibited();
- return profile_sidebar(\App::$profile, $block, true, false);
- }
+ return profile_sidebar(App::$profile, $block, true, false);
+ }
}
diff --git a/Zotlabs/Widget/Settings_menu.php b/Zotlabs/Widget/Settings_menu.php
index 25b80a4b4..4d0f1d2dd 100644
--- a/Zotlabs/Widget/Settings_menu.php
+++ b/Zotlabs/Widget/Settings_menu.php
@@ -40,6 +40,11 @@ class Settings_menu {
'selected' => ((argv(1) === 'channel') ? 'active' : ''),
),
+ array(
+ 'label' => t('Privacy settings'),
+ 'url' => z_root().'/settings/privacy',
+ 'selected' => ((argv(1) === 'privacy') ? 'active' : '')
+ )
);
$tabs[] = array(
diff --git a/app/group.apd b/app/group.apd
index d026ed23d..bf3ddf4a1 100644
--- a/app/group.apd
+++ b/app/group.apd
@@ -1,7 +1,7 @@
-version: 3
+version: 4
url: $baseurl/group
requires: local_channel
name: Privacy Groups
-photo: icon:users
+photo: icon:lock
categories: Networking
desc: A tool to create and manage privacy groups.
diff --git a/boot.php b/boot.php
index 607d64e60..120383d7c 100644
--- a/boot.php
+++ b/boot.php
@@ -55,10 +55,10 @@ require_once('include/bbcode.php');
require_once('include/items.php');
define ( 'PLATFORM_NAME', 'hubzilla' );
-define ( 'STD_VERSION', '6.5.1' );
+define ( 'STD_VERSION', '6.5.9' );
define ( 'ZOT_REVISION', '6.0' );
-define ( 'DB_UPDATE_VERSION', 1248 );
+define ( 'DB_UPDATE_VERSION', 1249 );
define ( 'PROJECT_BASE', __DIR__ );
@@ -484,7 +484,7 @@ define ( 'NAMESPACE_YMEDIA', 'http://search.yahoo.com/mrss/' );
define ( 'ACTIVITYSTREAMS_JSONLD_REV', 'https://www.w3.org/ns/activitystreams' );
-define ( 'ZOT_APSCHEMA_REV', '/apschema/v1.9' );
+define ( 'ZOT_APSCHEMA_REV', '/apschema/v1.10' );
/**
* activity stream defines
*/
@@ -860,7 +860,7 @@ class App {
private static $baseurl;
- private static $meta;
+ public static $meta;
/**
* App constructor.
diff --git a/include/attach.php b/include/attach.php
index 067da21ae..2109b84f1 100644
--- a/include/attach.php
+++ b/include/attach.php
@@ -15,10 +15,10 @@ use Zotlabs\Lib\Libsync;
use Zotlabs\Lib\Activity;
use Zotlabs\Access\PermissionLimits;
use Zotlabs\Daemon\Master;
+use Zotlabs\Lib\AccessList;
require_once('include/permissions.php');
require_once('include/security.php');
-require_once('include/group.php');
/**
* @brief Guess the mimetype from file ending.
@@ -2208,7 +2208,7 @@ function attach_recursive_perms($arr_allow_cid, $arr_allow_gid, $arr_deny_cid, $
//lookup all channels in sharee group and add them to sharee $arr_allow_cid
if($arr_allow_gid) {
- $in_group = expand_groups($arr_allow_gid);
+ $in_group = AccessList::expand($arr_allow_gid);
$arr_allow_cid = array_unique(array_merge($arr_allow_cid, $in_group));
}
@@ -2280,7 +2280,7 @@ function attach_recursive_perms($arr_allow_cid, $arr_allow_gid, $arr_deny_cid, $
//check sharee arr_allow_cid against members of allow_gid of all parent folders
foreach($parent_arr['allow_gid'] as $folder_arr_allow_gid) {
//get the group members
- $folder_arr_allow_cid = expand_groups($folder_arr_allow_gid);
+ $folder_arr_allow_cid = AccessList::expand($folder_arr_allow_gid);
foreach($folder_arr_allow_cid as $ac_hash) {
$count_values[$ac_hash]++;
}
diff --git a/include/channel.php b/include/channel.php
index 102a03489..00d973738 100644
--- a/include/channel.php
+++ b/include/channel.php
@@ -15,6 +15,7 @@ use Zotlabs\Render\Comanche;
use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\Connect;
use Zotlabs\Lib\Libsync;
+use Zotlabs\Lib\AccessList;
require_once('include/crypto.php');
require_once('include/menu.php');
@@ -240,7 +241,7 @@ function create_identity($arr) {
// Force a few things on the short term until we can provide a theme or app with choice
- $publish = 1;
+ $publish = 0;
if(array_key_exists('publish', $arr))
$publish = intval($arr['publish']);
@@ -325,6 +326,12 @@ function create_identity($arr) {
if($role_permissions && array_key_exists('perms_auto',$role_permissions))
set_pconfig($r[0]['channel_id'],'system','autoperms',intval($role_permissions['perms_auto']));
+ $group_actor = false;
+ if($role_permissions && array_key_exists('channel_type', $role_permissions) && $role_permissions['channel_type'] === 'group') {
+ set_pconfig($r[0]['channel_id'], 'system', 'group_actor', 1);
+ $group_actor = true;
+ }
+
$ret['channel'] = $r[0];
if(intval($arr['account_id']))
@@ -374,7 +381,8 @@ function create_identity($arr) {
'xchan_network' => 'zot6',
'xchan_photo_date' => datetime_convert(),
'xchan_name_date' => datetime_convert(),
- 'xchan_system' => $system
+ 'xchan_system' => $system,
+ 'xchan_pubforum' => $group_actor
]
);
if(! $r)
@@ -399,14 +407,6 @@ function create_identity($arr) {
]
);
- if($role_permissions) {
- $myperms = ((array_key_exists('perms_connect',$role_permissions)) ? $role_permissions['perms_connect'] : array());
- }
- else {
- $x = PermissionRoles::role_perms('social');
- $myperms = $x['perms_connect'];
- }
-
$r = abook_store_lowlevel(
[
'abook_account' => intval($ret['channel']['channel_account_id']),
@@ -419,19 +419,18 @@ function create_identity($arr) {
]
);
- $x = Permissions::FilledPerms($myperms);
- foreach($x as $k => $v) {
- set_abconfig($newuid,$hash,'my_perms',$k,$v);
- }
-
if(intval($ret['channel']['channel_account_id'])) {
- // Save our permissions role so we can perhaps call it up and modify it later.
+
+ // Set the default permcat
+ set_pconfig($newuid,'system','default_permcat','default');
if($role_permissions) {
+ // Save our permissions role so we can perhaps call it up and modify it later.
set_pconfig($newuid,'system','permissions_role',$arr['permissions_role']);
+
if(array_key_exists('online',$role_permissions))
- set_pconfig($newuid,'system','hide_presence',1-intval($role_permissions['online']));
+ set_pconfig($newuid,'system','show_online_status', intval($role_permissions['online']));
if(array_key_exists('perms_auto',$role_permissions)) {
$autoperms = intval($role_permissions['perms_auto']);
set_pconfig($newuid,'system','autoperms',$autoperms);
@@ -453,11 +452,10 @@ function create_identity($arr) {
// Create a group with yourself as a member. This allows somebody to use it
// right away as a default group for new contacts.
- require_once('include/group.php');
- $group_hash = group_add($newuid, t('Friends'));
+ $group_hash = AccessList::add($newuid, t('Friends'));
if($group_hash) {
- group_add_member($newuid,t('Friends'),$ret['channel']['channel_hash']);
+ AccessList::member_add($newuid,t('Friends'),$ret['channel']['channel_hash']);
$default_collection_str = '';
// if our role_permissions indicate that we're using a default collection ACL, add it.
@@ -496,8 +494,7 @@ function create_identity($arr) {
if($acct) {
$f = connect_and_sync($ret['channel'], $acct);
if($f['success']) {
- $can_view_stream = their_perms_contains($ret['channel']['channel_id'],$f['abook']['abook_xchan'],'view_stream');
-
+ $can_view_stream = intval(get_abconfig($ret['channel']['channel_id'], $f['abook']['abook_xchan'], 'their_perms', 'view_stream'));
// If we can view their stream, pull in some posts
if(($can_view_stream) || ($f['abook']['xchan_network'] === 'rss')) {
Master::Summon([ 'Onepoll',$f['abook']['abook_id'] ]);
@@ -1488,6 +1485,7 @@ function profile_load($nickname, $profile = '') {
if($can_view_profile) {
$online = get_online_status($nickname);
+
App::$profile['online_status'] = $online['result'];
}
@@ -2060,11 +2058,12 @@ function get_online_status($nick) {
return $ret;
$r = q("select channel_id, channel_hash from channel where channel_address = '%s' limit 1",
- dbesc(argv(1))
+ dbesc($nick)
);
+
if($r) {
- $hide = get_pconfig($r[0]['channel_id'],'system','hide_online_status');
- if($hide)
+ $show = get_pconfig($r[0]['channel_id'],'system','show_online_status');
+ if(!$show)
return $ret;
$x = q("select cp_status from chatpresence where cp_xchan = '%s' and cp_room = 0 limit 1",
diff --git a/include/connections.php b/include/connections.php
index 0611377ab..11264e6d8 100644
--- a/include/connections.php
+++ b/include/connections.php
@@ -27,7 +27,8 @@ function abook_store_lowlevel($arr) {
'abook_profile' => ((array_key_exists('abook_profile',$arr)) ? $arr['abook_profile'] : ''),
'abook_incl' => ((array_key_exists('abook_incl',$arr)) ? $arr['abook_incl'] : ''),
'abook_excl' => ((array_key_exists('abook_excl',$arr)) ? $arr['abook_excl'] : ''),
- 'abook_instance' => ((array_key_exists('abook_instance',$arr)) ? $arr['abook_instance'] : '')
+ 'abook_instance' => ((array_key_exists('abook_instance',$arr)) ? $arr['abook_instance'] : ''),
+ 'abook_role' => ((array_key_exists('abook_role',$arr)) ? $arr['abook_role'] : '')
];
return create_table_from_array('abook',$store);
diff --git a/include/conversation.php b/include/conversation.php
index a7dfa6b73..d12151fcc 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -1070,7 +1070,7 @@ function thread_author_menu($item, $mode = '') {
if($contact) {
$poke_link = ((Apps::system_app_installed($local_channel, 'Poke')) ? z_root() . '/poke/?f=&c=' . $contact['abook_id'] : '');
if (! intval($contact['abook_self']))
- $contact_url = z_root() . '/connedit/' . $contact['abook_id'];
+ $contact_url = z_root() . '/connections#' . $contact['abook_id'];
$posts_link = z_root() . '/network/?cid=' . $contact['abook_id'];
$clean_url = normalise_link($item['author-link']);
@@ -1086,7 +1086,9 @@ function thread_author_menu($item, $mode = '') {
'title' => t('View Profile'),
'icon' => 'fw',
'action' => '',
- 'href' => $profile_link
+ 'href' => $profile_link,
+ 'data' => '',
+ 'class' => ''
];
}
@@ -1096,7 +1098,9 @@ function thread_author_menu($item, $mode = '') {
'title' => t('Recent Activity'),
'icon' => 'fw',
'action' => '',
- 'href' => $posts_link
+ 'href' => $posts_link,
+ 'data' => '',
+ 'class' => ''
];
}
@@ -1107,6 +1111,8 @@ function thread_author_menu($item, $mode = '') {
'icon' => 'fw',
'action' => 'doFollowAuthor(\'' . $follow_url . '\'); return false;',
'href' => '#',
+ 'data' => '',
+ 'class' => ''
];
}
@@ -1116,7 +1122,9 @@ function thread_author_menu($item, $mode = '') {
'title' => t('Edit Connection'),
'icon' => 'fw',
'action' => '',
- 'href' => $contact_url
+ 'href' => $contact_url,
+ 'data' => 'data-id="' . $contact['abook_id'] . '"',
+ 'class' => 'contact-edit'
];
}
@@ -1126,7 +1134,9 @@ function thread_author_menu($item, $mode = '') {
'title' => t('Message'),
'icon' => 'fw',
'action' => '',
- 'href' => $pm_url
+ 'href' => $pm_url,
+ 'data' => '',
+ 'class' => ''
];
}
@@ -1136,7 +1146,9 @@ function thread_author_menu($item, $mode = '') {
'title' => t('Ratings'),
'icon' => 'fw',
'action' => '',
- 'href' => $ratings_url
+ 'href' => $ratings_url,
+ 'data' => '',
+ 'class' => ''
];
}
@@ -1146,7 +1158,9 @@ function thread_author_menu($item, $mode = '') {
'title' => t('Poke'),
'icon' => 'fw',
'action' => '',
- 'href' => $poke_link
+ 'href' => $poke_link,
+ 'data' => '',
+ 'class' => ''
];
}
diff --git a/include/group.php b/include/group.php
index bb1ed5ed8..4e1472900 100644
--- a/include/group.php
+++ b/include/group.php
@@ -326,7 +326,7 @@ function group_side($every="connections",$each="group",$edit = false, $group_id
$o = replace_macros($tpl, array(
'$title' => t('Privacy Groups'),
'$edittext' => t('Edit group'),
- '$createtext' => t('Add privacy group'),
+ '$createtext' => ((argv(1) == 'new' ) ? '' : t('Manage privacy groups')),
'$ungrouped' => (($every === 'contacts') ? t('Channels not in any privacy group') : ''),
'$groups' => $groups,
'$add' => t('add'),
diff --git a/include/items.php b/include/items.php
index 2ee870c2f..a66703e6e 100644
--- a/include/items.php
+++ b/include/items.php
@@ -13,9 +13,10 @@ use Zotlabs\Lib\IConfig;
use Zotlabs\Lib\Activity;
use Zotlabs\Lib\Libsync;
use Zotlabs\Lib\Libzot;
+use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Access\PermissionLimits;
use Zotlabs\Access\PermissionRoles;
-use Zotlabs\Access\AccessList;
+use Zotlabs\Lib\AccessList;
use Zotlabs\Daemon\Master;
require_once('include/bbcode.php');
@@ -35,8 +36,6 @@ require_once('include/permissions.php');
*/
function collect_recipients($item, &$private_envelope,$include_groups = true) {
- require_once('include/group.php');
-
$private_envelope = ((intval($item['item_private'])) ? true : false);
$recipients = array();
@@ -47,7 +46,7 @@ function collect_recipients($item, &$private_envelope,$include_groups = true) {
$allow_people = expand_acl($item['allow_cid']);
if($include_groups) {
- $allow_groups = expand_groups(expand_acl($item['allow_gid']));
+ $allow_groups = AccessList::expand(expand_acl($item['allow_gid']));
}
else {
$allow_groups = [];
@@ -72,7 +71,7 @@ function collect_recipients($item, &$private_envelope,$include_groups = true) {
}
$deny_people = expand_acl($item['deny_cid']);
- $deny_groups = expand_groups(expand_acl($item['deny_gid']));
+ $deny_groups = AccessList::expand(expand_acl($item['deny_gid']));
$deny = array_unique(array_merge($deny_people,$deny_groups));
@@ -344,6 +343,7 @@ function can_comment_on_post($observer_xchan, $item) {
return true;
break;
case 'any connections':
+ case 'specific':
case 'contacts':
case '':
if(local_channel() && get_abconfig(local_channel(),$item['owner_xchan'],'their_perms','post_comments')) {
@@ -1226,6 +1226,9 @@ function map_scope($scope, $strip = false) {
return 'site: ' . App::get_hostname();
case PERMS_PENDING:
return 'any connections';
+// uncomment after Hubzilla version 7.0 is running on the majority of active hubs
+// case PERMS_SPECIFIC:
+// return 'specific';
case PERMS_CONTACTS:
default:
return 'contacts';
@@ -2537,12 +2540,7 @@ function get_item_contact($item,$contacts) {
*/
function tag_deliver($uid, $item_id) {
- $role = get_pconfig($uid,'system','permissions_role');
- $rolesettings = PermissionRoles::role_perms($role);
- $channel_type = isset($rolesettings['channel_type']) ? $rolesettings['channel_type'] : 'normal';
-
- $is_group = (($channel_type === 'group') ? true : false);
-
+ $is_group = get_pconfig($uid, 'system', 'group_actor');
$mention = false;
/*
@@ -2579,15 +2577,18 @@ function tag_deliver($uid, $item_id) {
}
if ($is_group && intval($item['item_private']) === 2 && intval($item['item_thread_top'])) {
-
// do not turn the groups own direkt messages into group items
if($item['item_wall'] && $item['author_xchan'] === $u[0]['channel_hash'])
return;
// group delivery via DM
- if(perm_is_allowed($uid,$item['owner_xchan'],'post_wall') || perm_is_allowed($uid,$item['owner_xchan'],'tag_deliver')) {
+ if(perm_is_allowed($uid,$item['owner_xchan'],'post_wall')) {
logger('group DM delivery for ' . $u[0]['channel_address']);
start_delivery_chain($u[0], $item, $item_id, 0, true, (($item['edited'] != $item['created']) || $item['item_deleted']));
+ q("update item set item_blocked = %d where id = %d",
+ intval(ITEM_HIDDEN),
+ intval($item_id)
+ );
}
return;
}
@@ -2600,13 +2601,6 @@ function tag_deliver($uid, $item_id) {
return;
}
- /* this should not be required anymore due to the check above
- if (strpos($item['body'],'[/share]')) {
- logger('W2W post already shared');
- return;
- }
- */
-
// group delivery via W2W
logger('rewriting W2W post for ' . $u[0]['channel_address']);
start_delivery_chain($u[0], $item, $item_id, 0, true, (($item['edited'] != $item['created']) || $item['item_deleted']));
@@ -2677,9 +2671,37 @@ function tag_deliver($uid, $item_id) {
intval($uid)
);
- if(($x) && intval($x[0]['item_uplink'])) {
- start_delivery_chain($u[0],$item,$item_id,$x[0]);
+ if ($x) {
+
+ // group comments don't normally require a second delivery chain
+ // but we create a linked Announce so they will show up in the home timeline
+ // on microblog platforms and this creates a second delivery chain
+
+ if ($is_group && intval($x[0]['item_wall'])) {
+ // don't let the forked delivery chain recurse
+ if ($item['verb'] === 'Announce' && $item['author_xchan'] === $u['channel_hash']) {
+ return;
+ }
+ // don't announce moderated content until it has been approved
+ if (intval($item['item_blocked']) === ITEM_MODERATED) {
+ return;
+ }
+
+ // don't boost likes and other response activities as it is likely that
+ // few platforms will handle this in an elegant way
+
+ if (ActivityStreams::is_response_activity($item['verb'])) {
+ return;
+ }
+ logger('group_comment');
+ start_delivery_chain($u[0], $item, $item_id, $x[0], true, (($item['edited'] != $item['created']) || $item['item_deleted']));
+
+ }
+ elseif (intval($x[0]['item_uplink'])) {
+ start_delivery_chain($u,$item,$item_id,$x[0]);
+ }
}
+
}
@@ -2920,13 +2942,7 @@ function item_community_tag($channel,$item) {
*/
function tgroup_check($uid, $item) {
-
- $role = get_pconfig($uid,'system','permissions_role');
- $rolesettings = PermissionRoles::role_perms($role);
- $channel_type = isset($rolesettings['channel_type']) ? $rolesettings['channel_type'] : 'normal';
-
- $is_group = (($channel_type === 'group') ? true : false);
-
+ $is_group = get_pconfig($uid, 'system', 'group_actor');
$mention = false;
// check that the message originated elsewhere and is a top-level post
@@ -3125,6 +3141,10 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $group = false
$arr = [];
+ q("update item set item_hidden = 1 where id = %d",
+ intval($item_id)
+ );
+
if ($edit) {
// process edit or delete action
@@ -3155,7 +3175,7 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $group = false
}
else {
$arr['uuid'] = item_message_id();
- $arr['mid'] = z_root() . '/activity/' . $arr['uuid'];
+ $arr['mid'] = z_root() . '/item/' . $arr['uuid'];
$arr['parent_mid'] = $arr['mid'];
}
@@ -3173,6 +3193,10 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $group = false
$arr['item_private'] = (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
|| $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 1 : 0);
+ if ($channel['channel_allow_cid'] && empty($channel['channel_allow_gid'])) {
+ $arr['item_private'] = 2;
+ }
+
$arr['item_origin'] = 1;
$arr['item_wall'] = 1;
$arr['item_thread_top'] = 1;
@@ -3192,6 +3216,29 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $group = false
$bb .= "[/share]";
$arr['body'] = $bb;
+ // Conversational objects shouldn't be copied, but other objects should.
+ if (in_array($item['obj_type'], [ 'Image', 'Event', 'Question' ])) {
+ $arr['obj'] = $item['obj'];
+ $t = json_decode($arr['obj'],true);
+
+ if ($t !== NULL) {
+ $arr['obj'] = $t;
+ }
+ $arr['obj']['content'] = bbcode($bb);
+ $arr['obj']['source']['content'] = $bb;
+ $arr['obj']['id'] = $arr['mid'];
+
+ if (! array_path_exists('obj/source/mediaType',$arr)) {
+ $arr['obj']['source']['mediaType'] = 'text/bbcode';
+ }
+
+ $arr['obj']['directMessage'] = (intval($arr['item_private']) === 2);
+
+ }
+
+ $arr['tgt_type'] = $item['tgt_type'];
+ $arr['target'] = $item['target'];
+
$arr['term'] = $item['term'];
$arr['author_xchan'] = $channel['channel_hash'];
@@ -3222,6 +3269,92 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $group = false
}
+ if ($group && $parent) {
+ logger('comment arrived in group', LOGGER_DEBUG);
+ $arr = [];
+
+ // don't let this recurse. We checked for this before calling, but this ensures
+ // it doesn't sneak through another way because recursion is nasty.
+
+ if ($item['verb'] === 'Announce' && $item['author_xchan'] === $channel['channel_hash']) {
+ return;
+ }
+
+ // Don't send Announce activities for poll responses.
+
+ if ($item['obj_type'] === 'Answer') {
+ return;
+ }
+
+ if ($edit) {
+ if (intval($item['item_deleted'])) {
+ drop_item($item['id'],false,DROPITEM_PHASE1);
+ Master::Summon([ 'Notifier','drop',$item['id'] ]);
+ return;
+ }
+ return;
+ }
+ else {
+ $arr['uuid'] = item_message_id();
+ $arr['mid'] = z_root() . '/activity/' . $arr['uuid'];
+ $arr['parent_mid'] = $item['parent_mid'];
+ //IConfig::Set($arr,'activitypub','context', str_replace('/item/','/conversation/',$item['parent_mid']));
+ }
+ $arr['aid'] = $channel['channel_account_id'];
+ $arr['uid'] = $channel['channel_id'];
+
+ $arr['verb'] = 'Announce';
+
+ if (is_array($item['obj'])) {
+ $arr['obj'] = $item['obj'];
+ }
+ elseif (is_string($item['obj']) && strlen($item['obj'])) {
+ $arr['obj'] = json_decode($item['obj'],true);
+ }
+
+ if (! $arr['obj']) {
+ $arr['obj'] = $item['mid'];
+ }
+
+ if (is_array($arr['obj'])) {
+ $obj_actor = ((isset($arr['obj']['actor'])) ? ((is_array($arr['obj']['actor'])) ? $arr['obj']['actor']['id'] : $arr['obj']['actor']) : $arr['obj']['attributedTo']);
+ $mention = Activity::get_actor_bbmention($obj_actor);
+ $arr['body'] = sprintf( t('&#x1f501; Repeated %1$s\'s %2$s'), $mention, $arr['obj']['type']);
+ }
+
+ $arr['author_xchan'] = $channel['channel_hash'];
+
+ $arr['item_wall'] = 1;
+
+ $arr['item_private'] = (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 1 : 0);
+
+ $arr['item_origin'] = 1;
+ $arr['item_notshown'] = 1;
+
+ $arr['item_thread_top'] = 0;
+
+ $arr['allow_cid'] = $channel['channel_allow_cid'];
+ $arr['allow_gid'] = $channel['channel_allow_gid'];
+ $arr['deny_cid'] = $channel['channel_deny_cid'];
+ $arr['deny_gid'] = $channel['channel_deny_gid'];
+ $arr['comment_policy'] = map_scope(PermissionLimits::Get($channel['channel_id'],'post_comments'));
+
+ $post = item_store($arr);
+ $post_id = $post['item_id'];
+
+ if ($post_id) {
+ Master::Summon([ 'Notifier','tgroup',$post_id ]);
+ }
+
+ q("update channel set channel_lastpost = '%s' where channel_id = %d",
+ dbesc(datetime_convert()),
+ intval($channel['channel_id'])
+ );
+
+ return;
+ }
+
+
// Change this copy of the post to a forum head message and deliver to all the tgroup members
// also reset all the privacy bits to the forum default permissions
@@ -3510,12 +3643,11 @@ function compare_permissions($obj1,$obj2) {
* @return array
*/
function enumerate_permissions($obj) {
- require_once('include/group.php');
$allow_people = expand_acl($obj['allow_cid']);
- $allow_groups = expand_groups(expand_acl($obj['allow_gid']));
+ $allow_groups = AccessList::expand(expand_acl($obj['allow_gid']));
$deny_people = expand_acl($obj['deny_cid']);
- $deny_groups = expand_groups(expand_acl($obj['deny_gid']));
+ $deny_groups = AccessList::expand(expand_acl($obj['deny_gid']));
$recipients = array_unique(array_merge($allow_people,$allow_groups));
$deny = array_unique(array_merge($deny_people,$deny_groups));
$recipients = array_diff($recipients,$deny);
@@ -4252,7 +4384,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
$contact_str = '';
- $contacts = group_get_members($r[0]['id']);
+ $contacts = AccessList::members($uid, $r[0]['id']);
if ($contacts) {
foreach($contacts as $c) {
if($contact_str)
@@ -4268,7 +4400,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
$sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND (( author_xchan IN ( $contact_str ) OR owner_xchan in ( $contact_str)) or allow_gid like '" . protect_sprintf('%<' . dbesc($r[0]['hash']) . '>%') . "' ) and id = parent $item_normal ) ";
- $x = group_rec_byhash($uid,$r[0]['hash']);
+ $x = AccessList::by_hash($uid, $r[0]['hash']);
$result['headline'] = sprintf( t('Privacy group: %s'),$x['gname']);
}
elseif($arr['cid'] && $uid) {
diff --git a/include/nav.php b/include/nav.php
index 7cc64ab1b..9278c1587 100644
--- a/include/nav.php
+++ b/include/nav.php
@@ -26,7 +26,7 @@ function nav($template = 'default') {
intval($channel['channel_id'])
);
- if (empty($_SESSION['delegate'])) {
+ if (empty($_SESSION['delegate']) && feature_enabled(local_channel(), 'nav_channel_select')) {
$chans = q("select channel_name, channel_id from channel where channel_account_id = %d and channel_removed = 0 order by channel_name ",
intval(get_account_id())
);
@@ -97,13 +97,11 @@ function nav($template = 'default') {
if (empty($_SESSION['delegate'])) {
$nav['manage'] = ['manage', t('Channels'), "", t('Manage your channels'), 'manage_nav_btn'];
}
- if (Apps::system_app_installed(local_channel(), 'Privacy Groups'))
- $nav['group'] = ['group', t('Privacy Groups'), "", t('Manage your privacy groups'), 'group_nav_btn'];
$nav['settings'] = ['settings', t('Settings'), "", t('Account/Channel Settings'), 'settings_nav_btn'];
- if ($chans && count($chans) > 1 && feature_enabled(local_channel(), 'nav_channel_select'))
+ if ($chans && count($chans) > 1)
$nav['channels'] = $chans;
$nav['logout'] = ['logout', t('Logout'), "", t('End this session'), 'logout_nav_btn'];
diff --git a/include/permissions.php b/include/permissions.php
index d94b70da6..bbd13ed58 100644
--- a/include/permissions.php
+++ b/include/permissions.php
@@ -21,7 +21,7 @@ require_once('include/security.php');
* @param bool $default_ignored (default true)
* if false, lie and pretend the ignored person has permissions you are ignoring (used in channel discovery)
*
- * @returns array of all permissions, key is permission name, value is true or false
+ * @returns array of all permissions, key is permission name, value is 1 or 0
*/
function get_all_perms($uid, $observer_xchan, $check_siteblock = true, $default_ignored = true) {
@@ -61,7 +61,7 @@ function get_all_perms($uid, $observer_xchan, $check_siteblock = true, $default_
// The uid provided doesn't exist. This would be a big fail.
if(! $r) {
- $ret[$perm_name] = false;
+ $ret[$perm_name] = 0;
continue;
}
@@ -70,7 +70,7 @@ function get_all_perms($uid, $observer_xchan, $check_siteblock = true, $default_
if($observer_xchan) {
if($channel_perm & PERMS_AUTHED) {
- $ret[$perm_name] = true;
+ $ret[$perm_name] = 1;
continue;
}
@@ -104,7 +104,7 @@ function get_all_perms($uid, $observer_xchan, $check_siteblock = true, $default_
// If they're blocked - they can't read or write
if(($x) && intval($x[0]['abook_blocked'])) {
- $ret[$perm_name] = false;
+ $ret[$perm_name] = 0;
continue;
}
@@ -115,7 +115,7 @@ function get_all_perms($uid, $observer_xchan, $check_siteblock = true, $default_
if(($x) && ($default_ignored) && in_array($perm_name,$blocked_anon_perms) && intval($x[0]['abook_ignored'])) {
- $ret[$perm_name] = false;
+ $ret[$perm_name] = 0;
continue;
}
}
@@ -123,7 +123,7 @@ function get_all_perms($uid, $observer_xchan, $check_siteblock = true, $default_
// system is blocked to anybody who is not authenticated
if(($check_siteblock) && (! $observer_xchan) && intval(get_config('system', 'block_public'))) {
- $ret[$perm_name] = false;
+ $ret[$perm_name] = 0;
continue;
}
@@ -133,16 +133,16 @@ function get_all_perms($uid, $observer_xchan, $check_siteblock = true, $default_
if(($observer_xchan) && ($r[0]['channel_hash'] === $observer_xchan)) {
if($r[0]['channel_moved'] && (in_array($perm_name,$blocked_anon_perms)))
- $ret[$perm_name] = false;
+ $ret[$perm_name] = 0;
else
- $ret[$perm_name] = true;
+ $ret[$perm_name] = 1;
continue;
}
// Anybody at all (that wasn't blocked or ignored). They have permission.
if($channel_perm & PERMS_PUBLIC) {
- $ret[$perm_name] = true;
+ $ret[$perm_name] = 1;
continue;
}
@@ -150,7 +150,7 @@ function get_all_perms($uid, $observer_xchan, $check_siteblock = true, $default_
// out, permission is denied.
if(! $observer_xchan) {
- $ret[$perm_name] = false;
+ $ret[$perm_name] = 0;
continue;
}
@@ -158,7 +158,7 @@ function get_all_perms($uid, $observer_xchan, $check_siteblock = true, $default_
if($channel_perm & PERMS_NETWORK) {
if($x && $x[0]['xchan_network'] === 'zot6') {
- $ret[$perm_name] = true;
+ $ret[$perm_name] = 1;
continue;
}
}
@@ -175,9 +175,9 @@ function get_all_perms($uid, $observer_xchan, $check_siteblock = true, $default_
}
if($c)
- $ret[$perm_name] = true;
+ $ret[$perm_name] = 1;
else
- $ret[$perm_name] = false;
+ $ret[$perm_name] = 0;
continue;
}
@@ -186,19 +186,19 @@ function get_all_perms($uid, $observer_xchan, $check_siteblock = true, $default_
// handle whether we're allowing any, approved or specific ones
if(! $x) {
- $ret[$perm_name] = false;
+ $ret[$perm_name] = 0;
continue;
}
// They are in your address book, but haven't been approved
if($channel_perm & PERMS_PENDING && (! intval($x[0]['abook_pseudo']))) {
- $ret[$perm_name] = true;
+ $ret[$perm_name] = 1;
continue;
}
if(intval($x[0]['abook_pending'])) {
- $ret[$perm_name] = false;
+ $ret[$perm_name] = 0;
continue;
}
@@ -207,11 +207,11 @@ function get_all_perms($uid, $observer_xchan, $check_siteblock = true, $default_
if($channel_perm & PERMS_CONTACTS) {
// it was a fake abook entry, not really a connection
if(array_key_exists('abook_pseudo',$x[0]) && intval($x[0]['abook_pseudo'])) {
- $ret[$perm_name] = false;
+ $ret[$perm_name] = 0;
continue;
}
- $ret[$perm_name] = true;
+ $ret[$perm_name] = 1;
continue;
}
@@ -221,7 +221,7 @@ function get_all_perms($uid, $observer_xchan, $check_siteblock = true, $default_
if($abperms) {
foreach($abperms as $ab) {
if(($ab['cat'] == 'my_perms') && ($ab['k'] == $perm_name)) {
- $ret[$perm_name] = (intval($ab['v']) ? true : false);
+ $ret[$perm_name] = (intval($ab['v']) ? 1 : 0);
break;
}
}
@@ -231,7 +231,7 @@ function get_all_perms($uid, $observer_xchan, $check_siteblock = true, $default_
// No permissions allowed.
- $ret[$perm_name] = false;
+ $ret[$perm_name] = 0;
continue;
}
diff --git a/include/selectors.php b/include/selectors.php
index 71e2a387d..d58ef1085 100644
--- a/include/selectors.php
+++ b/include/selectors.php
@@ -15,7 +15,7 @@ function contact_profile_assign($current) {
$select = [
'profile_assign',
- t('Profile to assign new connections'),
+ t('Select a profile to assign to this contact'),
$current,
'',
$options
@@ -70,7 +70,7 @@ function gender_selector($current="",$suffix="") {
}
$o .= '</select>';
return $o;
-}
+}
function gender_selector_min($current="",$suffix="") {
$o = '';
@@ -87,7 +87,7 @@ function gender_selector_min($current="",$suffix="") {
}
$o .= '</select>';
return $o;
-}
+}
@@ -107,7 +107,7 @@ function sexpref_selector($current="",$suffix="") {
}
$o .= '</select>';
return $o;
-}
+}
function sexpref_selector_min($current="",$suffix="") {
@@ -125,7 +125,7 @@ function sexpref_selector_min($current="",$suffix="") {
}
$o .= '</select>';
return $o;
-}
+}
@@ -144,7 +144,7 @@ function marital_selector($current="",$suffix="") {
}
$o .= '</select>';
return $o;
-}
+}
function marital_selector_min($current="",$suffix="") {
$o = '';
@@ -161,5 +161,5 @@ function marital_selector_min($current="",$suffix="") {
}
$o .= '</select>';
return $o;
-}
+}
diff --git a/include/text.php b/include/text.php
index d46c089b5..b2b3fce6e 100644
--- a/include/text.php
+++ b/include/text.php
@@ -12,6 +12,7 @@ use Ramsey\Uuid\Exception\UnableToBuildUuidException;
use Zotlabs\Lib\Crypto;
use Zotlabs\Lib\SvgSanitizer;
use Zotlabs\Lib\Libzot;
+use Zotlabs\Lib\AccessList;
require_once("include/bbcode.php");
@@ -1753,6 +1754,7 @@ function prepare_body(&$item,$attach = false,$opts = false) {
}
}
+
$poll = (($item['obj_type'] === 'Question' && in_array($item['verb'],[ ACTIVITY_POST, ACTIVITY_UPDATE, ACTIVITY_SHARE ])) ? format_poll($item, $s, $opts) : false);
if ($poll) {
$s = $poll;
@@ -1854,11 +1856,16 @@ function format_poll($item,$s,$opts) {
return EMPTY_STR;
}
- $commentable = can_comment_on_post(((local_channel()) ? get_observer_hash() : EMPTY_STR),$item);
+ $commentable = can_comment_on_post(((local_channel()) ? get_observer_hash() : EMPTY_STR), $item);
+
+ $activated = ((local_channel() && local_channel() == $item['uid'] && get_observer_hash() !== $item['owner_xchan']) ? true : false);
+ $output = $s;
+
+ if (strpos($item['body'], '[/share]') !== false) {
+ $output = substr($output, 0, -12);
+ }
- //logger('format_poll: ' . print_r($item,true));
- $activated = ((local_channel() && local_channel() == $item['uid']) ? true : false);
- $output = $s . EOL. EOL;
+ $output .= EOL . EOL;
if ($act['type'] === 'Question') {
if ($activated and $commentable) {
@@ -1884,6 +1891,12 @@ function format_poll($item,$s,$opts) {
}
}
if (array_key_exists('oneOf',$act) && is_array($act['oneOf'])) {
+ $totalResponses = 0;
+ foreach ($act['oneOf'] as $poll) {
+ if (array_path_exists('replies/totalItems',$poll)) {
+ $totalResponses += intval($poll['replies']['totalItems']);
+ }
+ }
foreach ($act['oneOf'] as $poll) {
if (array_key_exists('name',$poll) && $poll['name']) {
$text = html2plain(purify_html($poll['name']),256);
@@ -1894,29 +1907,48 @@ function format_poll($item,$s,$opts) {
$total = 0;
}
if ($activated && $commentable) {
- $output .= '<input type="radio" name="answer" value="' . htmlspecialchars($text) . '"> ' . $text . '</input>' . ' (' . $total . ')' . EOL;
+ $output .= '<input type="radio" name="answer" value="' . htmlspecialchars($text) . '">&nbsp;&nbsp;<strong>' . $text . '</strong>' . EOL;
+ $output .= '<div class="progress bg-secondary bg-opacity-25" style="height: 3px;">';
+ $output .= '<div class="progress-bar bg-info" role="progressbar" style="width: ' . (($totalResponses) ? intval($total / $totalResponses * 100) : 0). '%;" aria-valuenow="" aria-valuemin="0" aria-valuemax="100"></div>';
+ $output .= '</div>';
+ $output .= '<div class="text-muted"><small>' . sprintf(tt('%d Vote', '%d Votes', $total, 'noun'), $total) . '&nbsp;|&nbsp;' . (($totalResponses) ? intval($total / $totalResponses * 100) . '%' : '0%') . '</small></div>';
+ $output .= EOL;
}
+
else {
- $output .= '( ) ' . $text . ' (' . $total . ')' . EOL;
+ $output .= '<input type="radio" name="answer" value="' . htmlspecialchars($text) . '" disabled="disabled">&nbsp;&nbsp;<strong>' . $text . '</strong>' . EOL;
+ $output .= '<div class="progress bg-secondary bg-opacity-25" style="height: 3px;">';
+ $output .= '<div class="progress-bar bg-info" role="progressbar" style="width: ' . (($totalResponses) ? intval($total / $totalResponses * 100) : 0) . '%;" aria-valuenow="" aria-valuemin="0" aria-valuemax="100"></div>';
+ $output .= '</div>';
+ $output .= '<div class="text-muted"><small>' . sprintf(tt('%d Vote', '%d Votes', $total, 'noun'), $total) . '&nbsp;|&nbsp;' . (($totalResponses) ? intval($total / $totalResponses * 100) . '%' : '0%') . '</small></div>';
+ $output .= EOL;
}
}
}
}
+
+ $message = (($totalResponses) ? sprintf(tt('%d Vote in total', '%d Votes in total', $totalResponses, 'noun'), $totalResponses) . EOL : '');
+
if ($item['comments_closed'] > NULL_DATE) {
$t = datetime_convert('UTC',date_default_timezone_get(), $item['comments_closed'], 'Y-m-d H:i');
$closed = ((datetime_convert() > $item['comments_closed']) ? true : false);
if ($closed) {
- $message = t('Poll has ended.');
+ $message .= t('Poll has ended');
}
else {
- $message = sprintf(t('Poll ends: %s'),$t);
+ $message .= sprintf(t('Poll ends in %s'), '<span class="autotime" title="' . $t . '"></span>');
}
- $output .= EOL . '<div>' . $message . '</div>';
}
- if ($activated and $commentable) {
- $output .= EOL . '<input type="button" class="btn btn-std btn-success" name="vote" value="' . t("Vote") . '" onclick="submitPoll(' . $item['id'] . '); return false;">'. '</form>';
+
+ $output .= '<div class="mb-3">' . $message . '</div>';
+
+ if ($activated && $commentable && !$closed) {
+ $output .= '<input type="button" class="btn btn-std btn-success" name="vote" value="' . t("Vote") . '" onclick="submitPoll(' . $item['id'] . '); return false;">'. '</form>';
}
+ if (strpos($item['body'], '[/share]') !== false) {
+ $output .= '</div></div>';
+ }
}
return $output;
}
@@ -2989,7 +3021,7 @@ function handle_tag(&$body, &$str_tags, $profile_uid, $tag, $in_network = true)
// weird - as all the other tags are linked to something.
if(local_channel() && local_channel() == $profile_uid) {
- $grp = group_byname($profile_uid,$name);
+ $grp = AccessList::byname($profile_uid,$name);
if($grp) {
$g = q("select hash from pgrp where id = %d and visible = 1 limit 1",
@@ -3692,6 +3724,13 @@ function get_forum_channels($uid) {
if(! $uid)
return;
+ $r = q("select abook_id, xchan_pubforum, xchan_hash, xchan_network, xchan_name, xchan_url, xchan_photo_s from abook left join xchan on abook_xchan = xchan_hash where xchan_deleted = 0 and abook_channel = %d and abook_pending = 0 and abook_ignored = 0 and abook_blocked = 0 and abook_archived = 0 and abook_self = 0 and xchan_pubforum = 1 order by xchan_name",
+ intval($uid)
+ );
+
+
+/*
+
if(isset(App::$data['forum_channels']))
return App::$data['forum_channels'];
@@ -3763,6 +3802,7 @@ function get_forum_channels($uid) {
}
App::$data['forum_channels'] = $r;
+*/
return $r;
diff --git a/tests/unit/Access/PermissionLimitsTest.php b/tests/unit/Access/PermissionLimitsTest.php
index 57ad42a19..0a90d11df 100644
--- a/tests/unit/Access/PermissionLimitsTest.php
+++ b/tests/unit/Access/PermissionLimitsTest.php
@@ -45,8 +45,8 @@ class PermissionLimitsTest extends UnitTestCase {
* @uses ::call_hooks
*/
public function testStd_Limits() {
- // There are 18 default perms
- $permsCount = 18;
+ // There are 17 default perms
+ $permsCount = 17;
// Create a stub for global function t() with expectation
$t = $this->getFunctionMock('Zotlabs\Access', 't');
@@ -69,10 +69,9 @@ class PermissionLimitsTest extends UnitTestCase {
$this->assertEquals(PERMS_SPECIFIC, $stdlimits['post_comments']);
$this->assertEquals(PERMS_SPECIFIC, $stdlimits['post_mail']);
$this->assertEquals(PERMS_SPECIFIC, $stdlimits['post_like']);
- $this->assertEquals(PERMS_SPECIFIC, $stdlimits['tag_deliver']);
$this->assertEquals(PERMS_SPECIFIC, $stdlimits['chat']);
$this->assertEquals(PERMS_SPECIFIC, $stdlimits['republish']);
$this->assertEquals(PERMS_SPECIFIC, $stdlimits['delegate']);
}
-} \ No newline at end of file
+}
diff --git a/tests/unit/Access/PermissionRolesTest.php b/tests/unit/Access/PermissionRolesTest.php
index dd55eb6e2..3d3cbbae5 100644
--- a/tests/unit/Access/PermissionRolesTest.php
+++ b/tests/unit/Access/PermissionRolesTest.php
@@ -40,7 +40,7 @@ class PermissionRolesTest extends UnitTestCase {
use PHPMock;
public function testVersion() {
- $expectedVersion = 2;
+ $expectedVersion = 3;
$this->assertEquals($expectedVersion, PermissionRoles::version());
@@ -58,23 +58,12 @@ class PermissionRolesTest extends UnitTestCase {
}
);
- $roles = PermissionRoles::roles();
+ $roles = PermissionRoles::channel_roles();
$r = new PermissionRoles();
- $this->assertEquals($roles, $r->roles());
+ $this->assertEquals($roles, $r->channel_roles());
- $socialNetworking = [
- 'social_federation' => 'Social - Federation',
- 'social' => 'Social - Mostly Public',
- 'social_restricted' => 'Social - Restricted',
- 'social_private' => 'Social - Private'
- ];
+ $this->assertCount(4, $roles, 'There should be 4 channel roles.');
- Assert::assertArraySubset(['Social Networking' => $socialNetworking], $roles);
- $this->assertEquals($socialNetworking, $roles['Social Networking']);
-
- $this->assertCount(5, $roles, 'There should be 5 permission groups.');
-
- $this->assertCount(1, $roles['Other'], "In the 'Other' group should be just one permission role");
}
@@ -88,12 +77,9 @@ class PermissionRolesTest extends UnitTestCase {
$t = $this->getFunctionMock('Zotlabs\Access', 't');
$t = $this->getFunctionMock('Zotlabs\Access', 'get_config');
- $rp_social = PermissionRoles::role_perms('social');
- $this->assertEquals('social', $rp_social['role']);
-
+ $rp_social = PermissionRoles::role_perms('personal');
+ $this->assertEquals('personal', $rp_social['role']);
- $rp_custom = PermissionRoles::role_perms('custom');
- $this->assertEquals(['role' => 'custom'], $rp_custom);
$rp_nonexistent = PermissionRoles::role_perms('nonexistent');
$this->assertEquals(['role' => 'nonexistent'], $rp_nonexistent);
diff --git a/tests/unit/Access/PermissionsTest.php b/tests/unit/Access/PermissionsTest.php
index 40724fff8..3ab567ad0 100644
--- a/tests/unit/Access/PermissionsTest.php
+++ b/tests/unit/Access/PermissionsTest.php
@@ -37,7 +37,7 @@ class PermissionsTest extends UnitTestCase {
use PHPMock;
public function testVersion() {
- $expectedVersion = 2;
+ $expectedVersion = 3;
// static call
$this->assertEquals($expectedVersion, Permissions::version());
@@ -60,8 +60,8 @@ class PermissionsTest extends UnitTestCase {
* @uses ::call_hooks
*/
public function testPerms() {
- // There are 18 default perms
- $permsCount = 18;
+ // There are 17 default perms
+ $permsCount = 17;
// Create a stub for global function t() with expectation
$t = $this->getFunctionMock('Zotlabs\Access', 't');
@@ -94,8 +94,8 @@ class PermissionsTest extends UnitTestCase {
* @uses ::call_hooks
*/
public function testPermsFilter() {
- // There are 18 default perms
- $permsCount = 18;
+ // There are 17 default perms
+ $permsCount = 17;
// Create a stub for global function t() with expectation
$t = $this->getFunctionMock('Zotlabs\Access', 't');
@@ -154,7 +154,6 @@ class PermissionsTest extends UnitTestCase {
'post_comments' => 0,
'post_mail' => 0,
'post_like' => 0,
- 'tag_deliver' => 0,
'chat' => 0,
'republish' => 0,
'delegate' => 0
@@ -177,7 +176,6 @@ class PermissionsTest extends UnitTestCase {
'post_comments' => 0,
'post_mail' => 0,
'post_like' => 0,
- 'tag_deliver' => 0,
'chat' => 0,
'republish' => 0,
'delegate' => 0
@@ -200,7 +198,6 @@ class PermissionsTest extends UnitTestCase {
'post_comments' => 0,
'post_mail' => 0,
'post_like' => 0,
- 'tag_deliver' => 0,
'chat' => 0,
'republish' => 0,
'delegate' => 0
@@ -234,7 +231,6 @@ class PermissionsTest extends UnitTestCase {
'post_comments' => 0,
'post_mail' => 0,
'post_like' => 0,
- 'tag_deliver' => 0,
'chat' => 0,
'republish' => 0,
'delegate' => 0
diff --git a/view/css/mod_connections.css b/view/css/mod_connections.css
index 4c26193b4..6a83367b8 100644
--- a/view/css/mod_connections.css
+++ b/view/css/mod_connections.css
@@ -1,17 +1,8 @@
+#contacts-follow-form,
#contacts-search-form {
display: none;
}
-.section-subtitle-wrapper .btn-xs {
- margin-top: -2px;
-}
-
-.contact-search {
- height: 22px;
- border-top-right-radius: 0px;
- border-bottom-right-radius: 0px;
-}
-
.directory-photo-img.archived {
opacity: 0.3;
filter:alpha(opacity=30);
@@ -39,7 +30,8 @@
}
.contact-photo-wrapper .oneway-overlay {
- margin-top: -25px;
- margin-left: 53px;
- font-size: 20px;
+ margin-top: -18px;
+ margin-left: 62px;
+ font-size: 1.2rem;
+ display: inherit; /* this is required for chromium */
}
diff --git a/view/css/widgets.css b/view/css/widgets.css
index df77940dd..0a091272c 100644
--- a/view/css/widgets.css
+++ b/view/css/widgets.css
@@ -244,9 +244,8 @@ a.wikilist {
/* contact block */
.contact-block-div .oneway-overlay {
font-size: .9rem;
- margin-left: -1.2rem;
- margin-top: 2rem;
- opacity: 0.8;
+ margin-left: -1rem;
+ margin-top: 1.9rem;
}
#cid-filter-wrapper {
diff --git a/view/js/main.js b/view/js/main.js
index 0e16809e4..f4f641e33 100644
--- a/view/js/main.js
+++ b/view/js/main.js
@@ -525,11 +525,14 @@ function showHideComments(id) {
}
}
-function openClose(theID) {
- if(document.getElementById(theID).style.display == "block") {
+function openClose(theID, display) {
+ if (typeof display == typeof undefined)
+ display = 'block';
+
+ if(document.getElementById(theID).style.display == display) {
document.getElementById(theID).style.display = "none";
} else {
- document.getElementById(theID).style.display = "block";
+ document.getElementById(theID).style.display = display;
}
}
@@ -541,9 +544,11 @@ function openCloseTR(theID) {
}
}
-function closeOpen(theID) {
+function closeOpen(theID, display) {
+ if (typeof display == typeof undefined)
+ display = 'block';
if(document.getElementById(theID).style.display == "none") {
- document.getElementById(theID).style.display = "block";
+ document.getElementById(theID).style.display = display;
} else {
document.getElementById(theID).style.display = "none";
}
diff --git a/view/js/mod_connections.js b/view/js/mod_connections.js
index db18e078d..848e9ed9f 100644
--- a/view/js/mod_connections.js
+++ b/view/js/mod_connections.js
@@ -1,5 +1,5 @@
$(document).ready(function() {
$("#contacts-search").contact_autocomplete(baseurl + '/acl', 'a', true);
$(".autotime").timeago();
-});
+});
diff --git a/view/pdl/mod_chat.pdl b/view/pdl/mod_chat.pdl
index 808ba3d5a..8a79b4b12 100644
--- a/view/pdl/mod_chat.pdl
+++ b/view/pdl/mod_chat.pdl
@@ -1,5 +1,5 @@
[region=aside]
-[widget=vcard][/widget]
+[widget=profile][/widget]
[widget=chatroom_list][/widget]
[widget=bookmarkedchats][/widget]
[widget=suggestedchats][/widget]
diff --git a/view/pdl/mod_connections.pdl b/view/pdl/mod_connections.pdl
index b777cada5..3c3dfd313 100644
--- a/view/pdl/mod_connections.pdl
+++ b/view/pdl/mod_connections.pdl
@@ -1,7 +1,4 @@
[region=aside]
-[widget=follow][/widget]
-[widget=collections][var=mode][connections[/arg][/widget]
-[widget=suggestions][/widget]
[widget=findpeople][/widget]
[/region]
[region=right_aside]
diff --git a/view/pdl/mod_connedit.pdl b/view/pdl/mod_connedit.pdl
index 4bdadb5e8..fa2f2969b 100644
--- a/view/pdl/mod_connedit.pdl
+++ b/view/pdl/mod_connedit.pdl
@@ -1,8 +1,6 @@
[region=aside]
[widget=vcard][/widget]
[widget=collections][var=mode]abook[/var][/widget]
-[widget=suggestions][/widget]
-[widget=findpeople][/widget]
[/region]
[region=right_aside]
[widget=notifications][/widget]
diff --git a/view/pdl/mod_import_items.pdl b/view/pdl/mod_import_items.pdl
new file mode 100644
index 000000000..e657fa88b
--- /dev/null
+++ b/view/pdl/mod_import_items.pdl
@@ -0,0 +1,3 @@
+[region=right_aside]
+[widget=notifications][/widget]
+[/region]
diff --git a/view/pdl/mod_permcats.pdl b/view/pdl/mod_permcats.pdl
new file mode 100644
index 000000000..bc6c89920
--- /dev/null
+++ b/view/pdl/mod_permcats.pdl
@@ -0,0 +1,7 @@
+[region=aside]
+[widget=permcats][/widget]
+[/region]
+[region=right_aside]
+[widget=notifications][/widget]
+[widget=newmember][/widget]
+[/region]
diff --git a/view/pdl/mod_profperm.pdl b/view/pdl/mod_profperm.pdl
index 7e15fc869..d7e5d29f3 100644
--- a/view/pdl/mod_profperm.pdl
+++ b/view/pdl/mod_profperm.pdl
@@ -1,5 +1,5 @@
[region=aside]
-[widget=fullprofile][/widget]
+[widget=profile][/widget]
[/region]
[region=right_aside]
[widget=notifications][/widget]
diff --git a/view/pdl/mod_viewconnections.pdl b/view/pdl/mod_viewconnections.pdl
index 7e15fc869..d7e5d29f3 100644
--- a/view/pdl/mod_viewconnections.pdl
+++ b/view/pdl/mod_viewconnections.pdl
@@ -1,5 +1,5 @@
[region=aside]
-[widget=fullprofile][/widget]
+[widget=profile][/widget]
[/region]
[region=right_aside]
[widget=notifications][/widget]
diff --git a/view/theme/redbasic/css/style.css b/view/theme/redbasic/css/style.css
index ac5b6a80a..542940404 100644
--- a/view/theme/redbasic/css/style.css
+++ b/view/theme/redbasic/css/style.css
@@ -418,11 +418,6 @@ footer {
filter:alpha(opacity=100);
}
-#profile-photo-wrapper img {
- width: 100%;
- height: 100%;
-}
-
#hide-friends-yes-label,
#hide-friends-no-label {
margin-left: 125px;
@@ -1223,24 +1218,24 @@ img.mail-conv-sender-photo {
}
.menu-img-3 {
- width: 3.3em;
- height: 3.3em;
+ width: 2.7rem;
+ height: 2.7rem;
margin-right: 5px;
border-radius: $radius;
float: left;
}
.menu-img-2 {
- height: 2.2em;
- width: 2.2em;
+ height: 1.8rem;
+ width: 1.8rem;
margin-right: 5px;
border-radius: $radius;
float: left;
}
.menu-img-1 {
- height: 1.28571429em;
- width: 1.28571429em;
+ height: 1.1rem;
+ width: 1.1rem;
border-radius: $radius;
}
@@ -1784,7 +1779,7 @@ dl.bb-dl > dd > li {
.oneway-overlay {
position: absolute;
- text-shadow: -2px 0 1px #fff, 0 2px 1px#fff, 2px 0 1px #fff, 0 -2px 1px #fff;
+ text-shadow: -1px 0 1px #fff, 0 1px 1px#fff, 1px 0 1px #fff, 0 -1px 1px #fff;
}
.cover-photo-review {
diff --git a/view/theme/redbasic/schema/Focus-Boxy.css b/view/theme/redbasic/schema/Focus-Boxy.css
index b9b259796..90fd51b02 100644
--- a/view/theme/redbasic/schema/Focus-Boxy.css
+++ b/view/theme/redbasic/schema/Focus-Boxy.css
@@ -3,13 +3,31 @@
}
.wall-item-content-wrapper.comment {
- border-bottom: 1px solid #dee2e6;
+ border-bottom: 1px solid rgba(0,0,0,.125);
}
.widget {
- border: 1px solid #dee2e6;
+ border: 1px solid rgba(0,0,0,.125);
}
#note-text {
border: 1px solid transparent;
}
+
+.vcard-card {
+ border: 1px solid rgba(0,0,0,.125);
+ border-bottom: 0;
+}
+
+.vcard-card .card {
+ border-top: 0;
+ border-right: 0;
+ border-left: 0;
+}
+
+.vcard-card .vcard {
+ border: 1px solid rgba(0,0,0,.125);
+ border-top: 0;
+ border-right: 0;
+ border-left: 0;
+}
diff --git a/view/tpl/abook_edit.tpl b/view/tpl/abook_edit.tpl
index 686b40a54..28631ed68 100644
--- a/view/tpl/abook_edit.tpl
+++ b/view/tpl/abook_edit.tpl
@@ -24,6 +24,7 @@
{{if $abook_prev || $abook_next}}
<div class="btn-group">
<a href="connedit/{{$abook_prev}}{{if $section}}?f=&section={{$section}}{{/if}}" class="btn btn-outline-secondary btn-sm{{if ! $abook_prev}} disabled{{/if}}" ><i class="fa fa-backward"></i></a>
+ {{if $sections}}
<div class="btn-group" >
<button class="btn btn-outline-secondary btn-sm{{if $is_pending}} disabled{{/if}}" type="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-bars"></i></button>
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="dLabel">
@@ -32,6 +33,7 @@
{{/foreach}}
</div>
</div>
+ {{/if}}
<a href="connedit/{{$abook_next}}{{if $section}}?f=&section={{$section}}{{/if}}" class="btn btn-outline-secondary btn-sm{{if ! $abook_next}} disabled{{/if}}" ><i class="fa fa-forward"></i></a>
</div>
{{/if}}
@@ -40,6 +42,65 @@
<h2>{{$header}}</h2>
</div>
<div class="section-content-wrapper-np">
+ <form id="abook-edit-form" action="connedit/{{$contact_id}}" method="post" >
+
+ <input type="hidden" name="contact_id" value="{{$contact_id}}">
+ <input type="hidden" name="section" value="{{$section}}">
+
+ <div class="section-content-wrapper">
+ <a href="permcats/{{$permcat_value}}" class="float-end"><i class="fa fa-external-link"></i>&nbsp;{{$permcat_new}}</a>
+ {{include file="field_select.tpl" field=$permcat}}
+ <button type="button" class="btn btn-outline-secondary float-end" data-bs-toggle="modal" data-bs-target="#perms_modal">Permissions</button>
+ <button type="submit" name="done" value="{{$submit}}" class="btn btn-primary">{{$submit}}</button>
+ <div class="modal" id="perms_modal" tabindex="-1" aria-labelledby="perms_modal_label" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <div class="modal-title h3" id="perms_modal_label">Permissions Overview</div>
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
+ </div>
+ <div class="modal-body">
+
+ <table class="table table-hover table-sm">
+ <thead>
+ <tr>
+ <th scope="col">Permission</th>
+ <th scope="col">{{$them}}</th>
+ <th scope="col">{{$me}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{foreach $perms as $perm}}
+ <tr>
+ <td>{{$perm.1}}</td>
+ <td>
+ {{if $perm.2}}
+ <i class="fa fa-check text-success"></i>
+ {{else}}
+ <i class="fa fa-times text-danger"></i>
+ {{/if}}
+ </td>
+ <td>
+ {{if $perm.3}}
+ <i class="fa fa-check text-success"></i>
+ {{else}}
+ <i class="fa fa-times text-danger"></i>
+ {{/if}}
+ </td>
+ </tr>
+ {{/foreach}}
+
+ </tbody>
+ </table>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
{{if $notself}}
{{foreach $tools as $tool}}
{{if $tool.info}}
@@ -73,33 +134,9 @@
</div>
{{/if}}
- <form id="abook-edit-form" action="connedit/{{$contact_id}}" method="post" >
-
- <input type="hidden" name="contact_id" value="{{$contact_id}}">
- <input type="hidden" name="section" value="{{$section}}">
-
<div class="panel-group" id="contact-edit-tools" role="tablist" aria-multiselectable="true">
{{if $notself}}
- {{if $is_pending}}
- <div class="panel">
- <div class="section-subtitle-wrapper" role="tab" id="pending-tool">
- <h3>
- <a data-bs-toggle="collapse" data-bs-parent="#contact-edit-tools" href="#pending-tool-collapse" aria-expanded="true" aria-controls="pending-tool-collapse">
- {{$pending_label}}
- </a>
- </h3>
- </div>
- <div id="pending-tool-collapse" class="panel-collapse collapse show" role="tabpanel" aria-labelledby="pending-tool">
- <div class="section-content-tools-wrapper">
- {{include file="field_checkbox.tpl" field=$unapproved}}
- <div class="settings-submit-wrapper" >
- <button type="submit" name="done" value="{{$submit}}" class="btn btn-primary">{{$submit}}</button>
- </div>
- </div>
- </div>
- </div>
- {{/if}}
{{if ! $is_pending}}
<div id="template-form-vcard-org" class="mb-3 form-vcard-org">
<div class="mb-3 form-vcard-org">
@@ -438,85 +475,6 @@
<input type="hidden" name="{{$excl.0}}" value="{{$excl.2}}" />
{{/if}}
- {{if $rating}}
- <div class="panel">
- <div class="section-subtitle-wrapper" role="tab" id="rating-tool">
- <h3>
- <a data-bs-toggle="collapse" data-bs-parent="#contact-edit-tools" href="#rating-tool-collapse" aria-expanded="true" aria-controls="rating-tool-collapse">
- {{$lbl_rating}}
- </a>
- </h3>
- </div>
- <div id="rating-tool-collapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="rating-tool">
- <div class="section-content-tools-wrapper">
- <div class="section-content-warning-wrapper">
- {{$rating_info}}
- </div>
- <div class="mb-3"><strong>{{$lbl_rating_label}}</strong></div>
- {{$rating}}
- {{include file="field_textarea.tpl" field=$rating_text}}
- <input id="contact-rating-mirror" type="hidden" name="rating" value="{{$rating_val}}" />
- <div class="settings-submit-wrapper" >
- <button type="submit" name="done" value="{{$submit}}" class="btn btn-primary">{{$submit}}</button>
- </div>
- </div>
- </div>
- </div>
- {{/if}}
-
- {{/if}}
-
- {{if ! $is_pending}}
- <div class="panel">
- {{if $notself}}
- <div class="section-subtitle-wrapper" role="tab" id="perms-tool">
- <h3>
- <a data-bs-toggle="collapse" data-bs-parent="#contact-edit-tools" href="#perms-tool-collapse" aria-expanded="true" aria-controls="perms-tool-collapse">
- {{$permlbl}}
- </a>
- </h3>
- </div>
- {{/if}}
- <div id="perms-tool-collapse" class="panel-collapse collapse{{if $self || $section === 'perms'}} show{{/if}}" role="tabpanel" aria-labelledby="perms-tool">
- <div class="section-content-tools-wrapper">
- <div class="section-content-warning-wrapper">
- {{if $notself}}{{$permnote}}{{/if}}
- {{if $self}}{{$permnote_self}}{{/if}}
- </div>
-
- {{if $permcat_enable}}
- <a href="permcats" class="float-end"><i class="fa fa-plus"></i>&nbsp;{{$permcat_new}}</a>
- {{include file="field_select.tpl" field=$permcat}}
- {{/if}}
-
- <table id="perms-tool-table" class=mb-3>
- <tr>
- <td></td>
- {{if $notself}}
- <td class="abook-them">{{$them}}</td>
- {{/if}}
- <td colspan="2" class="abook-me">{{$me}}</td>
- </tr>
- {{foreach $perms as $prm}}
- {{include file="field_acheckbox.tpl" field=$prm}}
- {{/foreach}}
- </table>
-
- {{if $self}}
- <div>
- <div class="section-content-info-wrapper">
- {{$autolbl}}
- </div>
- {{include file="field_checkbox.tpl" field=$autoperms}}
- </div>
- {{/if}}
-
- <div class="settings-submit-wrapper" >
- <button type="submit" name="done" value="{{$submit}}" class="btn btn-primary">{{$submit}}</button>
- </div>
- </div>
- </div>
- </div>
{{/if}}
</div>
</form>
diff --git a/view/tpl/admin_site.tpl b/view/tpl/admin_site.tpl
index 6882c3b8a..fa942baff 100644
--- a/view/tpl/admin_site.tpl
+++ b/view/tpl/admin_site.tpl
@@ -31,7 +31,7 @@
<h3>{{$registration}}</h3>
{{include file="field_input.tpl" field=$register_text}}
- {{include file="field_select_grouped.tpl" field=$role}}
+ {{include file="field_select.tpl" field=$role}}
{{include file="field_select.tpl" field=$register_policy}}
{{** include file="field_checkbox.tpl" field=$register_wo_email **}}
{{include file="register_duty.tpl" field=$register_duty}}
diff --git a/view/tpl/connection_template.tpl b/view/tpl/connection_template.tpl
index e7ab559cb..5c1542111 100644
--- a/view/tpl/connection_template.tpl
+++ b/view/tpl/connection_template.tpl
@@ -1,23 +1,12 @@
<div id="contact-entry-wrapper-{{$contact.id}}">
<div class="section-subtitle-wrapper clearfix">
<div class="float-end">
- {{if $contact.approve && $contact.ignore}}
- <form action="connedit/{{$contact.id}}" method="post" >
- <button type="submit" class="btn btn-success btn-sm" name="pending" value="1" title="{{$contact.approve_hover}}"><i class="fa fa-check"></i> {{$contact.approve}}</button>
-
- <a href="connedit/{{$contact.id}}/ignore" class="btn btn-warning btn-sm" title="{{$contact.ignore_hover}}"><i class="fa fa-ban"></i> {{$contact.ignore}}</a>
-
- {{/if}}
- {{if $contact.connect}}
- <a href="{{$contact.follow}}" class="btn btn-success btn-sm" title="{{$contact.connect_hover}}"><i class="fa fa-plus"></i> {{$contact.connect}}</a>
- {{/if}}
- <a href="#" class="btn btn-danger btn-sm contact-delete-btn" title="{{$contact.delete_hover}}" onclick="dropItem('{{$contact.deletelink}}', '#contact-entry-wrapper-{{$contact.id}}'); return false;"><i class="fa fa-trash-o"></i> {{$contact.delete}}</a>
- <a href="{{$contact.link}}" class="btn btn-outline-secondary btn-sm" title="{{$contact.edit_hover}}"><i class="fa fa-pencil"></i> {{$contact.edit}}</a>
- {{if $contact.approve}}
- </form>
- {{/if}}
+ <span id="contact-role-{{$contact.id}}" class="badge rounded-pill bg-warning text-dark me-1" title="{{$role_label}}">{{$contact.role}}</span>
+ <button type="button" class="btn btn-outline-secondary btn-sm contact-edit" title="{{$contact.edit_hover}}" data-id="{{$contact.id}}">
+ <i class="fa fa-pencil"></i> {{$contact.edit}}
+ </button>
</div>
- <h3>{{if $contact.public_forum}}<i class="fa fa-comments-o"></i>&nbsp;{{/if}}<a href="{{$contact.url}}" title="{{$contact.img_hover}}" >{{$contact.name}}</a>{{if $contact.phone}}&nbsp;<a class="btn btn-outline-secondary btn-sm" href="tel:{{$contact.phone}}" title="{{$contact.call}}"><i class="fa fa-phone connphone"></i></a>{{/if}}</h3>
+ <h3>{{if $contact.public_forum}}<i class="fa fa-comments-o" title="{{$group_label}}"></i>&nbsp;{{/if}}<a href="{{$contact.url}}" title="{{$contact.img_hover}}" >{{$contact.name}}</a>{{if $contact.phone}}&nbsp;<a class="btn btn-outline-secondary btn-sm" href="tel:{{$contact.phone}}" title="{{$contact.call}}"><i class="fa fa-phone connphone"></i></a>{{/if}}</h3>
</div>
<div class="section-content-tools-wrapper">
<div class="contact-photo-wrapper" >
diff --git a/view/tpl/connections.tpl b/view/tpl/connections.tpl
index 1719a6522..5fec38a84 100644
--- a/view/tpl/connections.tpl
+++ b/view/tpl/connections.tpl
@@ -1,7 +1,10 @@
<div class="generic-content-wrapper">
<div class="section-title-wrapper clearfix">
<div class="dropdown float-end">
- <button type="button" class="btn btn-primary btn-sm" onclick="openClose('contacts-search-form'); $('#contacts-search').focus();">
+ <button type="button" class="btn btn-success btn-sm" onclick="openClose('contacts-follow-form'); closeMenu('contacts-search-form'); $('#contacts-follow').focus();">
+ <i class="fa fa-plus"></i>&nbsp;Add
+ </button>
+ <button type="button" class="btn btn-primary btn-sm" onclick="openClose('contacts-search-form'); closeMenu('contacts-follow-form'); $('#contacts-search').focus();">
<i class="fa fa-search"></i>&nbsp;{{$label}}
</button>
<button type="button" class="btn btn-outline-secondary btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="{{$sort}}">
@@ -16,10 +19,23 @@
{{if $finding}}<h2>{{$finding}}</h2>{{else}}<h2>{{$header}}{{if $total}} ({{$total}}){{/if}}</h2>{{/if}}
</div>
<div id="contacts-search-form" class="section-content-tools-wrapper">
- <form action="{{$cmd}}" method="get" id="mimimi" name="contacts-search-form">
+ <form action="{{$cmd}}" method="get" name="contacts-search-form">
<div class="input-group mb-3">
<input type="text" name="search" id="contacts-search" class="form-control" onfocus="this.select();" value="{{$search}}" placeholder="{{$desc}}" />
- <button id="contacts-search-submit" class="btn btn-outline-secondary" type="submit"><i class="fa fa-fw fa-search"></i></button>
+ <button id="contacts-search-submit" class="btn btn-primary" type="submit"><i class="fa fa-fw fa-search"></i></button>
+ </div>
+ </form>
+ </div>
+ <div id="contacts-follow-form" class="section-content-tools-wrapper">
+ {{if $abook_usage_message}}
+ <div class="section-conten-info-wrapper">
+ {{$abook_usage_message}}
+ </div>
+ {{/if}}
+ <form action="follow" method="post">
+ <div class="input-group mb-3">
+ <input class="form-control" id="contacts-follow" type="text" name="url" title="Examples: bob@example.com, https://example.com/barbara" placeholder="Enter channel address">
+ <button class="btn btn-success" type="submit" name="submit" value="Connect" title="Connect"><i class="fa fa-fw fa-plus"></i></button>
</div>
</form>
</div>
@@ -34,3 +50,5 @@
<div id="page-spinner" class="spinner-wrapper">
<div class="spinner m"></div>
</div>
+{{include file="contact_edit_modal.tpl"}}
+
diff --git a/view/tpl/connstatus.tpl b/view/tpl/connstatus.tpl
index 869345682..30f450820 100644
--- a/view/tpl/connstatus.tpl
+++ b/view/tpl/connstatus.tpl
@@ -1 +1 @@
-<i class="fa fa-comments oneway-overlay text-{{if $perminfo.connpermcount == 3}}success{{elseif $perminfo.connpermcount > 0}}warning{{else}}danger{{/if}}" title="{{$perminfo.connperms}}"></i>
+<i class="fa fa-circle oneway-overlay text-{{if $perminfo.connpermcount == 3}}success{{elseif $perminfo.connpermcount > 0}}warning{{else}}danger{{/if}}" title="{{$perminfo.connperms}}"></i>
diff --git a/view/tpl/contact_edit.tpl b/view/tpl/contact_edit.tpl
new file mode 100644
index 000000000..3c4ed2ffe
--- /dev/null
+++ b/view/tpl/contact_edit.tpl
@@ -0,0 +1,133 @@
+<form id="contact-edit-form" action="contactedit/{{$contact_id}}" method="post" >
+ <div id="contact-edit-tools" class="panel-group" role="tablist" >
+ <div class="panel">
+ <div class="section-subtitle-wrapper" role="tab" id="roles-tool">
+ <h3>
+ <a class="section" data-bs-toggle="collapse" data-bs-target="#roles-tool-collapse" href="#" aria-expanded="true" aria-controls="roles-tool-collapse" data-section="roles">
+ Roles
+ </a>
+ </h3>
+ </div>
+ <div id="roles-tool-collapse" class="panel-collapse collapse{{if $section == 'roles'}} show{{/if}}" role="tabpanel" aria-labelledby="roles-tool" data-bs-parent="#contact-edit-tools">
+ <div class="section-content-tools-wrapper">
+ {{include file="field_select.tpl" field=$permcat}}
+ <button class="btn btn-outline-secondary btn-sm float-end sub_section{{if $sub_section == 'perms'}} sub_section_active{{/if}}" type="button" onclick="openClose('perms-table', 'table')" data-section="perms">
+ Compare permissions
+ </button>
+ <a href="permcats/{{$permcat_value}}" class="btn btn-sm btn-outline-primary">
+ <i class="fa fa-external-link"></i>&nbsp;{{$permcat_new}}
+ </a>
+ <table id="perms-table" class="table table-hover table-sm mt-3" style="display: {{if $sub_section == 'perms'}}table{{else}}none{{/if}};">
+ <thead>
+ <tr class="w-100">
+ <th scope="col">Permission</th>
+ <th scope="col">{{$them}}</th>
+ <th scope="col">{{$me}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{foreach $perms as $perm}}
+ <tr>
+ <td>{{$perm.1}}</td>
+ <td>
+ {{if $perm.2}}
+ <i class="fa fa-check text-success"></i>
+ {{else}}
+ <i class="fa fa-times text-danger"></i>
+ {{/if}}
+ </td>
+ <td>
+ {{if $perm.3}}
+ <i class="fa fa-check text-success"></i>
+ {{else}}
+ <i class="fa fa-times text-danger"></i>
+ {{/if}}
+ </td>
+ </tr>
+ {{/foreach}}
+
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ {{if $groups}}
+ <div class="panel">
+ <div class="section-subtitle-wrapper" role="tab" id="group-tool">
+ <h3>
+ <a class="section" data-bs-toggle="collapse" data-bs-target="#group-tool-collapse" href="#" aria-expanded="true" aria-controls="group-tool-collapse" data-section="group">
+ Privacy groups
+ </a>
+ </h3>
+ </div>
+ <div id="group-tool-collapse" class="panel-collapse collapse{{if $section == 'group'}} show{{/if}}" role="tabpanel" aria-labelledby="group-tool" data-bs-parent="#contact-edit-tools">
+ <div class="section-content-tools-wrapper clearfix">
+ {{foreach $groups as $group}}
+ {{include file="field_checkbox.tpl" field=$group}}
+ {{/foreach}}
+ <a href="group/new" class="btn btn-sm btn-outline-primary">
+ <i class="fa fa-external-link"></i>&nbsp;Privacy groups
+ </a>
+ </div>
+ </div>
+ </div>
+ {{/if}}
+ {{if $multiprofs}}
+ <div class="panel">
+ <div class="section-subtitle-wrapper" role="tab" id="profile-tool">
+ <h3>
+ <a class="section" data-bs-toggle="collapse" data-bs-target="#profile-tool-collapse" href="#" aria-expanded="true" aria-controls="profile-tool-collapse" data-section="profile">
+ Profiles
+ </a>
+ </h3>
+ </div>
+ <div id="profile-tool-collapse" class="panel-collapse collapse{{if $section == 'profile'}} show{{/if}}" role="tabpanel" aria-labelledby="profile-tool" data-bs-parent="#contact-edit-tools">
+ <div class="section-content-tools-wrapper">
+ {{$profile_select}}
+ <a href="profiles" class="btn btn-sm btn-outline-primary">
+ <i class="fa fa-external-link"></i>&nbsp;Profiles
+ </a>
+ </div>
+ </div>
+ </div>
+ {{/if}}
+ {{if $slide}}
+ <div class="panel">
+ <div class="section-subtitle-wrapper" role="tab" id="affinity-tool">
+ <h3>
+ <a class="section" data-bs-toggle="collapse" data-bs-target="#affinity-tool-collapse" href="#" aria-expanded="true" aria-controls="affinity-tool-collapse" data-section="affinity">
+ Affinity
+ </a>
+ </h3>
+ </div>
+ <div id="affinity-tool-collapse" class="panel-collapse collapse{{if $section == 'affinity'}} show{{/if}}" role="tabpanel" aria-labelledby="affinity-tool" data-bs-parent="#contact-edit-tools">
+ <div class="section-content-tools-wrapper">
+ <div class="mb-2"><label>{{$lbl_slider}}</label></div>
+ {{$slide}}
+ <input id="contact-closeness-mirror" type="hidden" name="closeness" value="{{$close}}" />
+ </div>
+ </div>
+ </div>
+ {{/if}}
+ {{if $connfilter}}
+ <div class="panel">
+ <div class="section-subtitle-wrapper" role="tab" id="filter-tool">
+ <h3>
+ <a class="section" data-bs-toggle="collapse" data-bs-target="#filter-tool-collapse" href="#" aria-expanded="true" aria-controls="filter-tool-collapse" data-section="filter">
+ Content filter
+ </a>
+ </h3>
+ </div>
+ <div id="filter-tool-collapse" class="panel-collapse collapse{{if $section == 'filter'}} show{{/if}}" role="tabpanel" aria-labelledby="filter-tool" data-bs-parent="#contact-edit-tools">
+ <div class="section-content-tools-wrapper">
+ {{include file="field_textarea.tpl" field=$incl}}
+ {{include file="field_textarea.tpl" field=$excl}}
+ </div>
+ </div>
+ </div>
+ {{else}}
+ <input type="hidden" name="{{$incl.0}}" value="{{$incl.2}}" />
+ <input type="hidden" name="{{$excl.0}}" value="{{$excl.2}}" />
+ {{/if}}
+ </div>
+</form>
diff --git a/view/tpl/contact_edit_header.tpl b/view/tpl/contact_edit_header.tpl
new file mode 100644
index 000000000..997d294bd
--- /dev/null
+++ b/view/tpl/contact_edit_header.tpl
@@ -0,0 +1,9 @@
+<div class="float-start me-2">
+ <a href="{{$href}}" title="{{$link_label}}" target="_blank">
+ <img src="{{$img_src}}" class="rounded" style="width: 3rem; height: 3rem;" />
+ </a>
+</div>
+<div class="m-1">
+ <div class="text-truncate h3 m-0"><strong>{{if $is_group}}<i class="fa fa-comments-o" title="{{$group_label}}"></i> {{/if}}{{$name}}</strong></div>
+ <div class="text-truncate text-muted">{{$addr}}</div>
+</div>
diff --git a/view/tpl/contact_edit_modal.tpl b/view/tpl/contact_edit_modal.tpl
new file mode 100644
index 000000000..be290c403
--- /dev/null
+++ b/view/tpl/contact_edit_modal.tpl
@@ -0,0 +1,152 @@
+<div id="edit-modal" class="modal" tabindex="-1">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <div id="edit-modal-title" class="modal-title w-75">
+ <div class="placeholder-wave">
+ <span class="placeholder placeholder-lg" style="width: 200px;"></span>
+ </div>
+ </div>
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
+ </div>
+ <div id="edit-modal-body" class="modal-body">
+ <div class="placeholder-wave">
+ <span class="placeholder placeholder-lg w-100 mb-4"></span>
+ <span class="placeholder placeholder-lg w-100 mb-4"></span>
+ <span class="placeholder placeholder-lg w-100 mb-4"></span>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <div id="edit-modal-tools" class="me-auto"></div>
+ <button id="contact-save" type="button" class="btn btn-primary"></button>
+ </div>
+ </div>
+ </div>
+</div>
+<script>
+ let poi;
+ let section = 'roles';
+ let sub_section;
+
+
+ $('#edit-modal').on('hidden.bs.modal', function (e) {
+ if (window.location.hash) {
+ history.replaceState(null, '', 'connections');
+ }
+ })
+
+ if (window.location.hash) {
+ poi = window.location.hash.substr(1);
+ init_contact_edit(poi);
+ }
+
+ window.onhashchange = function() {
+ if (window.location.hash) {
+ poi = window.location.hash.substr(1);
+ init_contact_edit(poi);
+ }
+ };
+
+
+ $(document).on('click', '.contact-edit', function (e) {
+ e.preventDefault();
+ poi = this.dataset.id
+ init_contact_edit(poi);
+ });
+
+ $(document).on('click', '#contact-save', function () {
+ let form_data = $('#contact-edit-form').serialize() + '&section=' + section + '&sub_section=' + sub_section;
+
+ $.post('contactedit/' + poi, form_data, function(data) {
+ if (!data.success) {
+ $.jGrowl(data.message, {sticky: false, theme: 'notice', life: 10000});
+ return;
+ }
+ activate(data);
+ $.jGrowl(data.message, {sticky: false, theme: ((data.success) ? 'info' : 'notice'), life: ((data.success) ? 3000 : 10000)});
+ // $('#edit-modal').modal('hide');
+ });
+
+ });
+
+ $(document).on('click', '.contact-tool', function (e) {
+ e.preventDefault();
+ let cmd = this.dataset.cmd;
+
+ $.get('contactedit/' + poi + '/' + cmd, function(data) {
+ $('#edit-modal-tools').html(data.tools);
+ $.jGrowl(data.message, {sticky: false, theme: ((data.success) ? 'info' : 'notice'), life: ((data.success) ? 3000 : 10000)});
+ if (cmd === 'drop') {
+ if ($('#contact-entry-wrapper-' + poi).length) {
+ $('#contact-entry-wrapper-' + poi).fadeOut();
+ }
+ $('#edit-modal').modal('hide');
+ }
+ });
+ });
+
+ $(document).on('click', '.section', function () {
+ section = this.dataset.section;
+ sub_section = '';
+ });
+
+ $(document).on('click', '.sub_section', function () {
+ if ($(this).hasClass('sub_section_active')) {
+ $(this).removeClass('sub_section_active');
+ sub_section = '';
+ }
+ else {
+ $(this).addClass('sub_section_active');
+ sub_section = this.dataset.section;
+ }
+ });
+
+ function init_contact_edit(poi) {
+ if (!poi)
+ return
+ $.get('contactedit/' + poi, function(data) {
+ if (!data.success) {
+ $.jGrowl(data.message, {sticky: false, theme: 'notice', life: 10000});
+ return;
+ }
+ $('#edit-modal').modal('show');
+ activate(data);
+ });
+ }
+
+ function activate(data) {
+ $('#edit-modal-title').css('filter', 'blur(0px)');
+ $('#edit-modal-body').css('filter', 'blur(0px)');
+ $('#contact-save').removeClass('disabled');
+ $('#contact-tools').removeClass('disabled');
+
+ if (data.title) {
+ $('#edit-modal-title').html(data.title);
+ }
+
+ if (data.body) {
+ $('#edit-modal-body').html(data.body);
+ }
+
+ if (data.tools) {
+ $('#edit-modal-tools').html(data.tools);
+ }
+
+ if (data.submit) {
+ $('#contact-save').html(data.submit);
+ }
+
+ if (data.role && $('#contact-role-' + poi).length) {
+ $('#contact-role-' + poi).html(data.role);
+ }
+
+ if (data.pending) {
+ $('#contact-save').removeClass('btn-primary');
+ $('#contact-save').addClass('btn-success');
+ }
+ else {
+ $('#contact-save').addClass('btn-primary');
+ $('#contact-save').removeClass('btn-success');
+ }
+ }
+</script>
diff --git a/view/tpl/contact_edit_tools.tpl b/view/tpl/contact_edit_tools.tpl
new file mode 100644
index 000000000..565b9df86
--- /dev/null
+++ b/view/tpl/contact_edit_tools.tpl
@@ -0,0 +1,14 @@
+<button id="contact-tools" class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+ <i class="fa fa-cog"></i>&nbsp;{{$tools_label}}
+</button>
+<div class="dropdown-menu">
+ <a class="dropdown-item contact-tool" href="#" title="{{$tools.refresh.title}}" data-cmd="refresh">{{$tools.refresh.label}}</a>
+ <a class="dropdown-item contact-tool" href="#" title="{{$tools.rephoto.title}}" data-cmd="resetphoto">{{$tools.rephoto.label}}</a>
+ <div class="dropdown-divider"></div>
+ <a class="dropdown-item contact-tool" href="#" title="{{$tools.block.title}}" data-cmd="block">{{$tools.block.label}}</a>
+ <a class="dropdown-item contact-tool" href="#" title="{{$tools.ignore.title}}" data-cmd="ignore">{{$tools.ignore.label}}</a>
+ <a class="dropdown-item contact-tool" href="#" title="{{$tools.archive.title}}" data-cmd="archive">{{$tools.archive.label}}</a>
+ <a class="dropdown-item contact-tool" href="#" title="{{$tools.hide.title}}" data-cmd="hide">{{$tools.hide.label}}</a>
+ <div class="dropdown-divider"></div>
+ <a class="dropdown-item contact-tool" href="#" title="{{$tools.delete.title}}" data-cmd="drop">{{$tools.delete.label}}</a>
+</div>
diff --git a/view/tpl/conv_frame.tpl b/view/tpl/conv_frame.tpl
index c28bb732a..4237c671b 100644
--- a/view/tpl/conv_frame.tpl
+++ b/view/tpl/conv_frame.tpl
@@ -18,3 +18,4 @@
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
+{{include file="contact_edit_modal.tpl"}}
diff --git a/view/tpl/conv_item.tpl b/view/tpl/conv_item.tpl
index 7c3505410..0a07319c8 100644
--- a/view/tpl/conv_item.tpl
+++ b/view/tpl/conv_item.tpl
@@ -40,7 +40,7 @@
<i class="fa fa-caret-down wall-item-photo-caret cursor-pointer" data-bs-toggle="dropdown"></i>
<div class="dropdown-menu">
{{foreach $item.thread_author_menu as $mitem}}
- <a class="dropdown-item" {{if $mitem.href}}href="{{$mitem.href}}"{{/if}} {{if $mitem.action}}onclick="{{$mitem.action}}"{{/if}} {{if $mitem.title}}title="{{$mitem.title}}"{{/if}} >{{$mitem.title}}</a>
+ <a class="dropdown-item{{if $mitem.class}} {{$mitem.class}}{{/if}}" {{if $mitem.href}}href="{{$mitem.href}}"{{/if}} {{if $mitem.action}}onclick="{{$mitem.action}}"{{/if}} {{if $mitem.title}}title="{{$mitem.title}}"{{/if}}{{if $mitem.data}} {{$mitem.data}}{{/if}}>{{$mitem.title}}</a>
{{/foreach}}
</div>
{{/if}}
@@ -48,7 +48,7 @@
</div>
{{if $item.lock}}
<div class="wall-item-lock dropdown">
- <i class="fa {{if $item.locktype == 2}}fa-envelope-o{{else}}fa-lock{{/if}} lockview{{if $item.privacy_warning}} text-danger{{/if}}" data-bs-toggle="dropdown" title="{{$item.lock}}" onclick="lockview('item',{{$item.id}});" ></i>&nbsp;
+ <i class="fa {{if $item.locktype == 2}}fa-envelope-o{{else if $item.locktype == 1}}fa-lock{{else}}fa-unlock{{/if}} lockview{{if $item.privacy_warning}} text-danger{{/if}}" data-bs-toggle="dropdown" title="{{$item.lock}}" onclick="lockview('item',{{$item.id}});" ></i>&nbsp;
<div id="panel-{{$item.id}}" class="dropdown-menu"></div>
</div>
{{/if}}
diff --git a/view/tpl/conv_list.tpl b/view/tpl/conv_list.tpl
index a20a6de8d..b4071ba16 100644
--- a/view/tpl/conv_list.tpl
+++ b/view/tpl/conv_list.tpl
@@ -43,7 +43,7 @@
</div>
{{if $item.lock}}
<div class="wall-item-lock dropdown">
- <i class="fa {{if $item.locktype == 2}}fa-envelope-o{{else}}fa-lock{{/if}} lockview" data-bs-toggle="dropdown" title="{{$item.lock}}" onclick="lockview('item',{{$item.id}});" ></i>&nbsp;
+ <i class="fa {{if $item.locktype == 2}}fa-envelope-o{{else if $item.locktype == 1}}fa-lock{{else}}fa-unlock{{/if}} lockview{{if $item.privacy_warning}} text-danger{{/if}}" data-bs-toggle="dropdown" title="{{$item.lock}}" onclick="lockview('item',{{$item.id}});" ></i>&nbsp;
<div id="panel-{{$item.id}}" class="dropdown-menu"></div>
</div>
{{/if}}
diff --git a/view/tpl/conversation.tpl b/view/tpl/conversation.tpl
index 82c7be922..6729cf55c 100644
--- a/view/tpl/conversation.tpl
+++ b/view/tpl/conversation.tpl
@@ -9,10 +9,10 @@
<div id="collapsed-comments-{{$thread.id}}" class="collapsed-comments" style="display: none;">
{{/if}}
{{if $item.comment_lastcollapsed}}</div>{{/if}}
-
+
{{include file="{{$item.template}}"}}
-
-
+
+
{{/foreach}}
</div>
{{/foreach}}
diff --git a/view/tpl/field_acheckbox.tpl b/view/tpl/field_acheckbox.tpl
index 4c8b62f36..44f65fefd 100644
--- a/view/tpl/field_acheckbox.tpl
+++ b/view/tpl/field_acheckbox.tpl
@@ -1,24 +1,31 @@
-<tr class="highlight">
+<tr>
<td>
- <label class="mainlabel" for='me_id_{{$field.0}}'>{{$field.1}}</label><br>
- <span class='field_abook_help'>{{$field.6}}</span>
+ <label class="mainlabel" for="me_id_{{$field.0}}">{{$field.1}}</label>
+ <span class="field_abook_help">{{$field.6}}</span>
</td>
- {{if $notself}}
- <td class="abook-them">
- {{if $field.2 == 1}}<i class="fa fa-check-square-o"></i>{{/if}}
- {{if $field.2 == 0}}<i class="fa fa-square-o"></i>{{/if}}
- </td>
- {{/if}}
- <td class="abook-me">
- {{if $self || !$field.5 }}
- <input type="checkbox" name='{{$field.0}}' class='abook-edit-me' id='me_id_{{$field.0}}' value="{{$field.4}}" {{if $field.3}}checked="checked"{{/if}} />
- {{/if}}
- {{if $notself && $field.5}}
- <input type="hidden" name='{{$field.0}}' value="{{if $field.7}}1{{else}}0{{/if}}" />
- {{if $field.3}}<i class="fa fa-check-square-o"></i>{{else}}<i class="fa fa-square-o"></i>{{/if}}
+ <td>
+ {{if $field.5}}
+ <span class="text-nowrap text-danger">
+ {{$inherited}}
+ {{if $field.7}}
+ <i class="fa fa-check-square-o"></i>
+ {{else}}
+ <i class="fa fa-square-o"></i>
+ {{/if}}
+ </span>
{{/if}}
</td>
<td>
- {{if $field.5}}<span class="permission-inherited">{{$inherited}}{{if $self}}{{if $field.7}} <i class="fa fa-check-square-o"></i>{{else}} <i class="fa fa-square-o"></i>{{/if}}{{/if}}</span>{{/if}}
+ {{if $is_system_role}}
+ {{if $field.3}}
+ <i class="fa fa-check-square-o"></i>
+ {{else}}
+ <i class="fa fa-square-o"></i>
+ {{/if}}
+ {{else}}
+ <input type="checkbox" name="{{$field.0}}" value="{{$field.4}}" {{if $field.3}}checked="checked"{{/if}} />
+ {{/if}}
+
</td>
+
</tr>
diff --git a/view/tpl/field_checkbox.tpl b/view/tpl/field_checkbox.tpl
index a1ab42d5e..670bb7e29 100644
--- a/view/tpl/field_checkbox.tpl
+++ b/view/tpl/field_checkbox.tpl
@@ -1,6 +1,6 @@
<div id="{{$field.0}}_container" class="clearfix onoffswitch checkbox mb-3">
<label for="id_{{$field.0}}">{{$field.1}}{{if $field.6}}<sup class="required zuiqmid"> {{$field.6}}</sup>{{/if}}</label>
- <div class="float-end"><input type="checkbox" name='{{$field.0}}' id='id_{{$field.0}}' value="1" {{if $field.2}}checked="checked"{{/if}} {{if $field.5}}{{$field.5}}{{/if}} /><label class="switchlabel" for='id_{{$field.0}}'> <span class="onoffswitch-inner" data-on='{{if $field.4}}{{$field.4.1}}{{/if}}' data-off='{{if $field.4}}{{$field.4.0}}{{/if}}'></span><span class="onoffswitch-switch"></span></label></div>
+ <div class="float-end"><input type="checkbox" name="{{$field.0}}" id="id_{{$field.0}}" value="1" {{if $field.2}}checked="checked"{{/if}} {{if $field.5}}{{$field.5}}{{/if}} /><label class="switchlabel" for='id_{{$field.0}}'> <span class="onoffswitch-inner" data-on='{{if $field.4}}{{$field.4.1}}{{/if}}' data-off='{{if $field.4}}{{$field.4.0}}{{/if}}'></span><span class="onoffswitch-switch"></span></label></div>
<small class="form-text text-muted">{{$field.3}}</small>
</div>
{{*
diff --git a/view/tpl/group_edit.tpl b/view/tpl/group_edit.tpl
index 5568179af..61203ab10 100644
--- a/view/tpl/group_edit.tpl
+++ b/view/tpl/group_edit.tpl
@@ -13,6 +13,8 @@
<input type='hidden' name='form_security_token' value='{{$form_security_token_edit}}'>
{{include file="field_input.tpl" field=$gname}}
{{include file="field_checkbox.tpl" field=$public}}
+ {{include file="field_checkbox.tpl" field=$is_default_acl}}
+ {{include file="field_checkbox.tpl" field=$is_default_group}}
{{$pgrp_extras}}
<a href="group/drop/{{$gid}}?t={{$form_security_token_drop}}" onclick="return confirmDelete();" class="btn btn-sm btn-danger">
{{$delete}}
diff --git a/view/tpl/group_selection.tpl b/view/tpl/group_selection.tpl
index a91658464..7db80e06f 100644
--- a/view/tpl/group_selection.tpl
+++ b/view/tpl/group_selection.tpl
@@ -1,8 +1,8 @@
<div class="mb-3 field custom">
-<label for="group-selection" id="group-selection-lbl">{{$label}}</label>
-<select class="form-control" name="group-selection" id="group-selection" >
-{{foreach $groups as $group}}
-<option value="{{$group.id}}" {{if $group.selected}}selected="selected"{{/if}} >{{$group.name}}</option>
-{{/foreach}}
-</select>
+ <label for="id_{{$form_id}}">{{$label}}</label>
+ <select class="form-control" name="{{$form_id}}" id="{{$form_id}}" >
+ {{foreach $groups as $group}}
+ <option value="{{$group.id}}" {{if $group.selected}}selected="selected"{{/if}} >{{$group.name}}</option>
+ {{/foreach}}
+ </select>
</div>
diff --git a/view/tpl/group_side.tpl b/view/tpl/group_side.tpl
index 14f714ae9..979d20aa5 100644
--- a/view/tpl/group_side.tpl
+++ b/view/tpl/group_side.tpl
@@ -13,9 +13,11 @@
<a class="nav-link{{if $group.selected}} active{{/if}}" href="{{$group.href}}">{{$group.text}}</a>
</li>
{{/foreach}}
+ {{if $createtext}}
<li class="nav-item">
- <a class="nav-link" href="group/new" title="{{$createtext}}" ><i class="fa fa-plus-circle"></i> {{$createtext}}</a>
+ <a class="nav-link" href="group/new" title="{{$createtext}}" ><i class="fa fa-external-link"></i> {{$createtext}}</a>
</li>
+ {{/if}}
</ul>
</div>
diff --git a/view/tpl/micropro_card.tpl b/view/tpl/micropro_card.tpl
index 058bfc14c..40a7967c5 100644
--- a/view/tpl/micropro_card.tpl
+++ b/view/tpl/micropro_card.tpl
@@ -1,5 +1,5 @@
<a class="list-group-item{{if $class}} {{$class}}{{/if}} fakelink" href="{{if $click}}#{{else}}{{$url}}{{/if}}" {{if $click}}onclick="{{$click}}"{{/if}}>
- <img class="menu-img-3" src="{{$photo}}" title="{{$title}}" alt="" />{{if $perminfo}}{{include "connstatus.tpl"}}{{/if}}
+ <img class="menu-img-3" src="{{$photo}}" title="{{$title}}" alt="" loading="lazy" />{{if $perminfo}}{{include "connstatus.tpl"}}{{/if}}
<span class="contactname">{{$name}}</span>
<span class="dropdown-sub-text">{{$addr}}<br>{{$network}}</span>
</a>
diff --git a/view/tpl/new_channel.tpl b/view/tpl/new_channel.tpl
index 8d72df55b..f11a4291f 100644
--- a/view/tpl/new_channel.tpl
+++ b/view/tpl/new_channel.tpl
@@ -18,17 +18,17 @@
{{if $default_role}}
<input type="hidden" name="permissions_role" value="{{$default_role}}" />
{{else}}
- {{include file="field_select_grouped.tpl" field=$role}}
+ {{include file="field_select.tpl" field=$role}}
{{/if}}
-
+
{{include file="field_input.tpl" field=$name}}
-
+
{{include file="field_input.tpl" field=$nickname}}
<button class="btn btn-primary" type="submit" id="newchannel-submit-button">{{$submit}}</button>
-
-
+
+
<div id="newchannel-submit-end" class="clear"></div>
-
+
<div id="newchannel-import-link" class="descriptive-paragraph" >{{$label_import}}</div>
<div id="newchannel-import-end" class="clear"></div>
</form>
diff --git a/view/tpl/notes.tpl b/view/tpl/notes.tpl
index 902691fae..24c3ec53c 100644
--- a/view/tpl/notes.tpl
+++ b/view/tpl/notes.tpl
@@ -8,7 +8,7 @@
{{else}}
<div id="personal-notes" class="widget{{if $hidden}} d-none{{/if}}">
<div class="float-end rounded border border-secondary mb-1 ps-1 pe-1 text-muted small note-mode" title="Double click note for edit mode">{{$strings.read}}</div>
- <h3 class="float-start">{{$banner}}</h3>
+ <h3 class="float-start">{{$strings.title}}</h3>
{{/if}}
<textarea name="note_text" id="note-text" class="form-control{{if $app}} border-0{{else}} p-1{{/if}}" style="display: none;">{{$text}}</textarea>
<div id="note-text-html" class="{{if !$app}}border rounded p-1{{/if}}">{{$html}}</div>
diff --git a/view/tpl/permcats.tpl b/view/tpl/permcats.tpl
index 5b2d811d7..279903048 100644
--- a/view/tpl/permcats.tpl
+++ b/view/tpl/permcats.tpl
@@ -4,49 +4,37 @@
<div class="clear"></div>
</div>
<div class="section-content-tools-wrapper">
- <div class="section-content-info-wrapper">
- {{$desc}}
- </div>
-
<form action="permcats" id="settings-permcats-form" method="post" autocomplete="off" >
- <input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
- {{include file="field_input.tpl" field=$name}}
+ <input type="hidden" name="form_security_token" value="{{$form_security_token}}">
+ <input type="hidden" name="return_path" value="{{$return_path}}">
- <div class="settings-submit-wrapper mb-3">
- <button type="submit" name="submit" class="btn btn-primary">{{$submit}}</button>
- </div>
- </div>
+ {{if $is_system_role}}
+ <input type="hidden" name="is_system_role" value="1">
+ <input type="hidden" name="name" value="{{$is_system_role}}">
+ {{/if}}
- <div class="panel" id="permission-settings">
- <div class="section-subtitle-wrapper" role="tab" id="perms-tool">
- <h3>
- <a data-bs-toggle="collapse" data-bs-parent="#permission-settings" href="#perms-tool-collapse" aria-expanded="true" aria-controls="perms-tool-collapse">
- {{$permlbl}}
- </a>
- </h3>
- </div>
- <div id="perms-tool-collapse" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="perms-tool">
- <div class="section-content-tools-wrapper">
- <div class="section-content-warning-wrapper">
- {{$permnote}}
- </div>
+ {{include file="field_input.tpl" field=$name}}
+ {{include file="field_checkbox.tpl" field=$default_role}}
- <table id="perms-tool-table" class=mb-3>
- <tr>
- <td></td><td colspan="2" class="abook-me">{{$me}}</td>
- </tr>
- {{foreach $perms as $prm}}
- {{include file="field_acheckbox.tpl" field=$prm}}
- {{/foreach}}
- </table>
+ {{$group_select}}
- <div class="settings-submit-wrapper" >
- <button type="submit" name="submit" class="btn btn-primary">{{$submit}}</button>
- </div>
+ <div class="section-subtitle-wrapper" id="perms-tool">
+ <h3>
+ {{$permlbl}}
+ </h3>
</div>
- </div>
- {{if $permcats}}
- <div class="section-content-wrapper-np">
+ <div class="section-content-warning-wrapper">
+ {{$permnote}}
+ </div>
+ <table id="" class="table table-hover">
+ {{foreach $perms as $prm}}
+ {{include file="field_acheckbox.tpl" field=$prm}}
+ {{/foreach}}
+ </table>
+ <div class="settings-submit-wrapper" >
+ <button type="submit" name="submit" class="btn btn-primary">{{$submit}}</button>
+ </div>
+ {{**if $permcats}}
<table id="permcat-index">
{{foreach $permcats as $k => $v}}
<tr class="permcat-row-{{$k}}">
@@ -55,10 +43,8 @@
</tr>
{{/foreach}}
</table>
- </div>
- {{/if}}
+ {{/if**}}
+ </form>
</div>
- </form>
-
</div>
diff --git a/view/tpl/privacy_groups.tpl b/view/tpl/privacy_groups.tpl
index c06f5b0ca..0bbc998a1 100644
--- a/view/tpl/privacy_groups.tpl
+++ b/view/tpl/privacy_groups.tpl
@@ -8,6 +8,8 @@
<input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
{{include file="field_input.tpl" field=$gname}}
{{include file="field_checkbox.tpl" field=$public}}
+ {{include file="field_checkbox.tpl" field=$is_default_acl}}
+ {{include file="field_checkbox.tpl" field=$is_default_group}}
{{$pgrp_extras}}
<button type="submit" name="submit" class="btn btn-sm btn-primary float-end">{{$submit}}</button>
</form>
diff --git a/view/tpl/profile_edit.tpl b/view/tpl/profile_edit.tpl
index 95346b3a8..3f5814c4a 100644
--- a/view/tpl/profile_edit.tpl
+++ b/view/tpl/profile_edit.tpl
@@ -50,7 +50,7 @@
<div class="section-subtitle-wrapper" role="tab" id="personal">
<h3>
<a data-bs-toggle="collapse" data-bs-target="#personal-collapse" href="#" aria-expanded="true" aria-controls="personal-collapse">
- {{$personal}}
+ {{$basic}}
</a>
</h3>
</div>
@@ -84,7 +84,17 @@
{{$dob}}
{{/if}}
+ {{$profile_in_dir}}
+
+ {{$suggestme}}
+
+ {{if $show_presence}}
+ {{include file="field_checkbox.tpl" field=$show_presence}}
+ {{/if}}
+
+ {{if $hide_friends}}
{{include file="field_checkbox.tpl" field=$hide_friends}}
+ {{/if}}
<div class="mb-3" >
<button type="submit" name="submit" class="btn btn-primary" value="{{$submit}}">{{$submit}}</button>
diff --git a/view/tpl/profile_vcard.tpl b/view/tpl/profile_vcard.tpl
index 8ebc9a311..9002d3742 100644
--- a/view/tpl/profile_vcard.tpl
+++ b/view/tpl/profile_vcard.tpl
@@ -1,5 +1,5 @@
-<div class="rounded mb-3 vcard-card h-card">
- <div class="card">
+<div class="rounded mb-3 vcard-card h-card">
+ <div class="card mb-2">
<div class="row">
<div class="col-4" style="width: 7rem;">
{{if $editmenu}}
@@ -49,10 +49,10 @@
{{if $details}}
<div class="vcard ps-2 pe-2">
{{if $profile.pdesc}}
- <div class="pb-3 pt-2">{{$profile.pdesc}}</div>
+ <div class="mb-2">{{$profile.pdesc}}</div>
{{/if}}
{{if $location}}
- <dl class="">
+ <dl class="mb-0 pb-1">
<dt class="location-label">{{$location}}</dt>
<dd class="adr h-adr">
{{if $profile.address}}
@@ -72,25 +72,25 @@
</dl>
{{/if}}
{{if $hometown}}
- <dl class="">
+ <dl class="mb-0 pb-1">
<dt class="hometown-label">{{$hometown}}</dt>
<dd class="p-hometown">{{$profile.hometown}}</dd>
</dl>
{{/if}}
{{if $gender}}
- <dl class="">
+ <dl class="mb-0 pb-1">
<dt class="gender-label">{{$gender}}</dt>
<dd class="p-gender">{{if $profile.gender_icon}}<i class="fa fa-{{$profile.gender_icon}}"></i>&nbsp;{{/if}}{{$profile.gender}}</dd>
</dl>
{{/if}}
{{if $marital}}
- <dl class="">
+ <dl class="mb-0 pb-1">
<dt class="marital-label"><span class="heart"><i class="fa fa-heart"></i>&nbsp;</span>{{$marital}}</dt>
<dd class="marital-text">{{$profile.marital}}</dd>
</dl>
{{/if}}
{{if $homepage}}
- <dl class="pb-2">
+ <dl class="mb-0 pb-1">
<dt class="homepage-label">{{$homepage}}</dt>
<dd class="homepage-url u-url">{{$profile.homepage}}</dd>
</dl>
diff --git a/view/tpl/search_item.tpl b/view/tpl/search_item.tpl
index ee89973a8..f3d0a8d03 100644
--- a/view/tpl/search_item.tpl
+++ b/view/tpl/search_item.tpl
@@ -36,7 +36,7 @@
</div>
{{if $item.lock}}
<div class="wall-item-lock dropdown">
- <i class="fa {{if $item.locktype == 2}}fa-envelope-o{{else}}fa-lock{{/if}} lockview" data-bs-toggle="dropdown" title="{{$item.lock}}" onclick="lockview('item',{{$item.id}});" ></i><ul id="panel-{{$item.id}}" class="lockview-panel dropdown-menu"></ul>&nbsp;
+ <i class="fa {{if $item.locktype == 2}}fa-envelope-o{{else if $item.locktype == 1}}fa-lock{{else}}fa-unlock{{/if}} lockview{{if $item.privacy_warning}} text-danger{{/if}}" data-bs-toggle="dropdown" title="{{$item.lock}}" onclick="lockview('item',{{$item.id}});" ></i>&nbsp;
</div>
{{/if}}
<div class="wall-item-author">
diff --git a/view/tpl/settings.tpl b/view/tpl/settings.tpl
index 353da9c2b..9b23d7d82 100644
--- a/view/tpl/settings.tpl
+++ b/view/tpl/settings.tpl
@@ -18,13 +18,14 @@
</div>
<div id="basic-settings-collapse" class="collapse show" role="tabpanel" aria-labelledby="basic-settings" data-bs-parent="#settings">
<div class="section-content-tools-wrapper">
- {{include file="field_input.tpl" field=$username}}
+ {{include file="field_select.tpl" field=$role}}
{{include file="field_select_grouped.tpl" field=$timezone}}
{{include file="field_input.tpl" field=$defloc}}
{{include file="field_checkbox.tpl" field=$allowloc}}
{{include file="field_checkbox.tpl" field=$adult}}
{{include file="field_input.tpl" field=$photo_path}}
{{include file="field_input.tpl" field=$attach_path}}
+ {{include file="field_input.tpl" field=$expire}}
{{if $basic_addon}}
{{$basic_addon}}
{{/if}}
@@ -35,66 +36,6 @@
</div>
</div>
<div class="panel">
- <div class="section-subtitle-wrapper" role="tab" id="privacy-settings">
- <h3>
- <a data-bs-toggle="collapse" data-bs-target="#privacy-settings-collapse" href="#">
- {{$h_prv}}
- </a>
- </h3>
- </div>
- <div id="privacy-settings-collapse" class="collapse" role="tabpanel" aria-labelledby="privacy-settings" data-bs-parent="#settings">
- <div class="section-content-tools-wrapper">
- {{include file="field_select_grouped.tpl" field=$role}}
- {{$autoperms}}
- <div id="advanced-perm" style="display:{{if $permissions_set}}none{{else}}block{{/if}};">
- <div class="mb-3">
- <button type="button" class="btn btn-outline-secondary" data-bs-toggle="modal" data-bs-target="#apsModal">{{$lbl_p2macro}}</button>
- </div>
- <div class="modal" id="apsModal">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <h4 class="modal-title">{{$lbl_p2macro}}</h4>
- <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
- </div>
- <div class="modal-body">
- {{foreach $permiss_arr as $permit}}
- {{include file="field_select.tpl" field=$permit}}
- {{/foreach}}
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Close</button>
- </div>
- </div><!-- /.modal-content -->
- </div><!-- /.modal-dialog -->
- </div><!-- /.modal -->
-
- <div id="settings-default-perms" class="mb-3" >
- <button type="button" class="btn btn-outline-secondary" data-bs-toggle="modal" data-bs-target="#aclModal"><i id="jot-perms-icon" class="fa"></i>&nbsp;{{$permissions}}</button>
- </div>
- {{$group_select}}
- {{include file="field_checkbox.tpl" field=$hide_presence}}
- {{$profile_in_dir}}
- </div>
- <div class="settings-common-perms">
- {{$suggestme}}
- {{include file="field_checkbox.tpl" field=$blocktags}}
- {{include file="field_input.tpl" field=$expire}}
- </div>
- {{if $permcat_enable}}
- {{include file="field_select.tpl" field=$defpermcat}}
- {{/if}}
-
- {{if $sec_addon}}
- {{$sec_addon}}
- {{/if}}
- <div class="settings-submit-wrapper" >
- <button type="submit" name="submit" class="btn btn-primary">{{$submit}}</button>
- </div>
- </div>
- </div>
- </div>
- <div class="panel">
<div class="section-subtitle-wrapper" role="tab" id="notification-settings">
<h3>
<a data-bs-toggle="collapse" data-bs-target="#notification-settings-collapse" href="#">
diff --git a/view/tpl/settings_privacy.tpl b/view/tpl/settings_privacy.tpl
new file mode 100644
index 000000000..aff9619c3
--- /dev/null
+++ b/view/tpl/settings_privacy.tpl
@@ -0,0 +1,56 @@
+<div class="generic-content-wrapper">
+ <div class="section-title-wrapper">
+ <h2>{{$ptitle}}</h2>
+ </div>
+ {{$nickname_block}}
+ <form action="settings/privacy" id="settings-form" method="post" autocomplete="off">
+ <input type='hidden' name='form_security_token' value='{{$form_security_token}}' />
+
+ <div class="section-content-tools-wrapper">
+
+ {{include file="field_checkbox.tpl" field=$autoperms}}
+ {{include file="field_checkbox.tpl" field=$index_opt_out}}
+
+ {{if $sec_addon}}
+ {{$sec_addon}}
+ {{/if}}
+ {{if $permission_limits}}
+ <div id="permission-limits">
+ <div class="modal" id="apsModal">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <div class="modal-title h3">{{$permission_limits_label}}</div>
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
+ </div>
+ <div class="modal-body">
+ <div class="multi-collapse collapse show">
+ <h2 class="text-danger mb-3"><i class="fa fa-warning"></i> {{$permission_limits_warning.0}}</h2>
+ <h3 class="mb-3">{{$permission_limits_warning.1}}</h3>
+ <button type="button" class="btn btn-primary" data-bs-toggle="collapse" data-bs-target=".multi-collapse" aria-expanded="false" aria-controls="collapseExample">{{$permission_limits_warning.2}}</button>
+ </div>
+ <div class="multi-collapse collapse">
+ {{foreach $permiss_arr as $permit}}
+ {{include file="field_select.tpl" field=$permit}}
+ {{/foreach}}
+ {{include file="field_checkbox.tpl" field=$group_actor}}
+ </div>
+
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Close</button>
+ </div>
+ </div><!-- /.modal-content -->
+ </div><!-- /.modal-dialog -->
+ </div><!-- /.modal -->
+ </div>
+ <div class="float-end">
+ <button type="button" class="btn btn-outline-secondary" data-bs-toggle="modal" data-bs-target="#apsModal">{{$permission_limits_label}}</button>
+ </div>
+ {{/if}}
+ <div class="settings-submit-wrapper" >
+ <button type="submit" name="submit" class="btn btn-primary">{{$submit}}</button>
+ </div>
+ </div>
+ </form>
+</div>