diff --git a/include/text.php b/include/text.php
index 7bed8b4994..3d6bf6a563 100644
--- a/include/text.php
+++ b/include/text.php
@@ -4,11 +4,11 @@
*/
use Friendica\App;
-use Friendica\Content\Smilies;
use Friendica\Content\Text\BBCode;
use Friendica\Core\Protocol;
use Friendica\Model\Contact;
use Friendica\Model\FileTag;
+use Friendica\Model\Group;
use Friendica\Util\Strings;
/**
@@ -20,18 +20,9 @@ use Friendica\Util\Strings;
function expand_acl($s) {
// turn string array of angle-bracketed elements into numeric array
// e.g. "<1><2><3>" => array(1,2,3);
- $ret = [];
+ preg_match_all('/<(' . Group::FOLLOWERS . '|'. Group::MUTUALS . '|[0-9]+)>/', $s, $matches, PREG_PATTERN_ORDER);
- if (strlen($s)) {
- $t = str_replace('<', '', $s);
- $a = explode('>', $t);
- foreach ($a as $aa) {
- if (intval($aa)) {
- $ret[] = intval($aa);
- }
- }
- }
- return $ret;
+ return $matches[1];
}
@@ -42,6 +33,8 @@ function expand_acl($s) {
function sanitise_acl(&$item) {
if (intval($item)) {
$item = '<' . intval(Strings::escapeTags(trim($item))) . '>';
+ } elseif (in_array($item, [Group::FOLLOWERS, Group::MUTUALS])) {
+ $item = '<' . $item . '>';
} else {
unset($item);
}
diff --git a/mod/lockview.php b/mod/lockview.php
index 35c4b04332..eede1b6a0d 100644
--- a/mod/lockview.php
+++ b/mod/lockview.php
@@ -6,6 +6,7 @@ use Friendica\App;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Database\DBA;
+use Friendica\Model\Group;
use Friendica\Model\Item;
function lockview_content(App $a)
@@ -67,6 +68,19 @@ function lockview_content(App $a)
$l = [];
if (count($allowed_groups)) {
+ $key = array_search(Group::FOLLOWERS, $allowed_groups);
+ if ($key !== false) {
+ $l[] = '' . L10n::t('Followers') . '';
+ unset($allowed_groups[$key]);
+ }
+
+ $key = array_search(Group::MUTUALS, $allowed_groups);
+ if ($key !== false) {
+ $l[] = '' . L10n::t('Mutuals') . '';
+ unset($allowed_groups[$key]);
+ }
+
+
$r = q("SELECT `name` FROM `group` WHERE `id` IN ( %s )",
DBA::escape(implode(', ', $allowed_groups))
);
@@ -89,6 +103,18 @@ function lockview_content(App $a)
}
if (count($deny_groups)) {
+ $key = array_search(Group::FOLLOWERS, $deny_groups);
+ if ($key !== false) {
+ $l[] = '' . L10n::t('Followers') . '';
+ unset($deny_groups[$key]);
+ }
+
+ $key = array_search(Group::MUTUALS, $deny_groups);
+ if ($key !== false) {
+ $l[] = '' . L10n::t('Mutuals') . '';
+ unset($deny_groups[$key]);
+ }
+
$r = q("SELECT `name` FROM `group` WHERE `id` IN ( %s )",
DBA::escape(implode(', ', $deny_groups))
);
diff --git a/mod/network.php b/mod/network.php
index 7354667200..fddec60c8d 100644
--- a/mod/network.php
+++ b/mod/network.php
@@ -643,7 +643,7 @@ function networkThreadedView(App $a, $update, $parent)
// NOTREACHED
}
- $contacts = Group::expand([$gid]);
+ $contacts = Group::expand(local_user(), [$gid]);
if ((is_array($contacts)) && count($contacts)) {
$contact_str_self = '';
diff --git a/src/Model/Group.php b/src/Model/Group.php
index feff4661ab..5c587ee2a6 100644
--- a/src/Model/Group.php
+++ b/src/Model/Group.php
@@ -16,9 +16,25 @@ use Friendica\Database\DBA;
*/
class Group extends BaseObject
{
+ const FOLLOWERS = '~';
+ const MUTUALS = '&';
+
+ public static function getByUserId($uid, $includesDeleted = false)
+ {
+ $DB = self::getApp()->getDatabase();
+
+ $conditions = ['uid' => $uid];
+
+ if (!$includesDeleted) {
+ $conditions['deleted'] = false;
+ }
+
+ $groupsStmt = $DB->select('group', [], $conditions);
+
+ return $DB->toArray($groupsStmt);
+ }
+
/**
- *
- *
* @param int $group_id
* @return bool
* @throws \Exception
@@ -300,20 +316,43 @@ class Group extends BaseObject
/**
* @brief Returns the combined list of contact ids from a group id list
*
+ * @param int $uid
* @param array $group_ids
* @param boolean $check_dead
* @return array
* @throws \Exception
*/
- public static function expand($group_ids, $check_dead = false)
+ public static function expand($uid, array $group_ids, $check_dead = false)
{
if (!is_array($group_ids) || !count($group_ids)) {
return [];
}
- $stmt = DBA::select('group_member', ['contact-id'], ['gid' => $group_ids]);
-
$return = [];
+
+ $key = array_search(self::FOLLOWERS, $group_ids);
+ if ($key !== false) {
+ $followersStmt = Contact::select(['id'], ['uid' => $uid, 'rel' => [Contact::FOLLOWER, Contact::FRIEND]]);
+
+ while($follower = DBA::fetch($followersStmt)) {
+ $return[] = $follower['id'];
+ }
+
+ unset($group_ids[$key]);
+ }
+
+ $key = array_search(self::MUTUALS, $group_ids);
+ if ($key !== false) {
+ $mutualsStmt = Contact::select(['id'], ['uid' => $uid, 'rel' => [Contact::FRIEND]]);
+
+ while($mutual = DBA::fetch($mutualsStmt)) {
+ $return[] = $mutual['id'];
+ }
+
+ unset($group_ids[$key]);
+ }
+
+ $stmt = DBA::select('group_member', ['contact-id'], ['gid' => $group_ids]);
while($group_member = DBA::fetch($stmt)) {
$return[] = $group_member['contact-id'];
}
@@ -332,7 +371,7 @@ class Group extends BaseObject
* @param int $gid An optional pre-selected group
* @param string $label An optional label of the list
* @return string
- * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+ * @throws \Exception
*/
public static function displayGroupSelection($uid, $gid = 0, $label = '')
{
@@ -377,7 +416,7 @@ class Group extends BaseObject
* @param string $group_id
* @param int $cid
* @return string
- * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+ * @throws \Exception
*/
public static function sidebarWidget($every = 'contact', $each = 'group', $editmode = 'standard', $group_id = '', $cid = 0)
{
diff --git a/src/Model/Item.php b/src/Model/Item.php
index 28f7b436d9..e54dadba5d 100644
--- a/src/Model/Item.php
+++ b/src/Model/Item.php
@@ -2799,12 +2799,12 @@ class Item extends BaseObject
*/
if (self::hasPermissions($photo)) {
if ($cid) {
- $recips = self::enumeratePermissions($photo);
+ $recips = self::enumeratePermissions($uid, $photo);
if (in_array($cid, $recips)) {
$replace = true;
}
} elseif ($item) {
- if (self::samePermissions($item, $photo)) {
+ if (self::samePermissions($uid, $item, $photo)) {
$replace = true;
}
}
@@ -2854,7 +2854,7 @@ class Item extends BaseObject
!empty($obj['deny_cid']) || !empty($obj['deny_gid']);
}
- private static function samePermissions($obj1, $obj2)
+ private static function samePermissions($uid, $obj1, $obj2)
{
// first part is easy. Check that these are exactly the same.
if (($obj1['allow_cid'] == $obj2['allow_cid'])
@@ -2865,8 +2865,8 @@ class Item extends BaseObject
}
// This is harder. Parse all the permissions and compare the resulting set.
- $recipients1 = self::enumeratePermissions($obj1);
- $recipients2 = self::enumeratePermissions($obj2);
+ $recipients1 = self::enumeratePermissions($uid, $obj1);
+ $recipients2 = self::enumeratePermissions($uid, $obj2);
sort($recipients1);
sort($recipients2);
@@ -2875,12 +2875,12 @@ class Item extends BaseObject
}
// returns an array of contact-ids that are allowed to see this object
- public static function enumeratePermissions($obj)
+ public static function enumeratePermissions($uid, array $obj)
{
$allow_people = expand_acl($obj['allow_cid']);
- $allow_groups = Group::expand(expand_acl($obj['allow_gid']));
+ $allow_groups = Group::expand($uid, expand_acl($obj['allow_gid']));
$deny_people = expand_acl($obj['deny_cid']);
- $deny_groups = Group::expand(expand_acl($obj['deny_gid']));
+ $deny_groups = Group::expand($uid, 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);
diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php
index b64e746e79..9d8c9de90a 100644
--- a/src/Protocol/ActivityPub/Transmitter.php
+++ b/src/Protocol/ActivityPub/Transmitter.php
@@ -386,7 +386,7 @@ class Transmitter
}
}
} else {
- $receiver_list = Item::enumeratePermissions($item);
+ $receiver_list = Item::enumeratePermissions($item['uid'], $item);
foreach ($terms as $term) {
$cid = Contact::getIdForURL($term['url'], $item['uid']);
diff --git a/src/Worker/Notifier.php b/src/Worker/Notifier.php
index 42ad0afb6d..4efd3e9126 100644
--- a/src/Worker/Notifier.php
+++ b/src/Worker/Notifier.php
@@ -271,9 +271,9 @@ class Notifier
}
$allow_people = expand_acl($parent['allow_cid']);
- $allow_groups = Group::expand(expand_acl($parent['allow_gid']),true);
+ $allow_groups = Group::expand($uid, expand_acl($parent['allow_gid']),true);
$deny_people = expand_acl($parent['deny_cid']);
- $deny_groups = Group::expand(expand_acl($parent['deny_gid']));
+ $deny_groups = Group::expand($uid, expand_acl($parent['deny_gid']));
// if our parent is a public forum (forum_mode == 1), uplink to the origional author causing
// a delivery fork. private groups (forum_mode == 2) do not uplink