aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Zotlabs/Access/AccessList.php56
-rw-r--r--Zotlabs/Lib/ThreadItem.php2
-rw-r--r--Zotlabs/Module/Chat.php2
-rw-r--r--Zotlabs/Module/Sse_bs.php24
-rw-r--r--Zotlabs/Widget/Messages.php6
-rw-r--r--boot.php2
-rw-r--r--tests/unit/Access/AccessListTest.php36
-rw-r--r--view/js/main.js29
8 files changed, 108 insertions, 49 deletions
diff --git a/Zotlabs/Access/AccessList.php b/Zotlabs/Access/AccessList.php
index 790ef4745..3f5271e87 100644
--- a/Zotlabs/Access/AccessList.php
+++ b/Zotlabs/Access/AccessList.php
@@ -2,6 +2,7 @@
namespace Zotlabs\Access;
+
/**
* @brief AccessList class which represents individual content ACLs.
*
@@ -17,29 +18,48 @@ class AccessList {
* @brief Allow contacts
* @var string
*/
- private $allow_cid;
+ private ?string $allow_cid;
/**
* @brief Allow groups
* @var string
*/
- private $allow_gid;
+ private ?string $allow_gid;
/**
* @brief Deny contacts
* @var string
*/
- private $deny_cid;
+ private ?string $deny_cid;
/**
* @brief Deny groups
* @var string
*/
- private $deny_gid;
+ private ?string $deny_gid;
/**
* @brief Indicates if we are using the default constructor values or
* values that have been set explicitly.
* @var boolean
*/
- private $explicit;
+ private bool $explicit;
+
+ /**
+ * @brief Keys required by the constructor if the channel array is given.
+ */
+ private const REQUIRED_KEYS_CONSTRUCTOR = [
+ 'channel_allow_cid',
+ 'channel_allow_gid',
+ 'channel_deny_cid',
+ 'channel_deny_gid'
+ ];
+ /**
+ * @brief Keys required by the set method.
+ */
+ private const REQUIRED_KEYS_SET = [
+ 'allow_cid',
+ 'allow_gid',
+ 'deny_cid',
+ 'deny_gid'
+ ];
/**
* @brief Constructor for AccessList class.
@@ -53,8 +73,9 @@ class AccessList {
* * \e string \b channel_deny_cid => string of denied cids
* * \e string \b channel_deny_gid => string of denied gids
*/
- function __construct($channel) {
+ function __construct(array $channel) {
if ($channel) {
+ $this->validate_input_array($channel, self::REQUIRED_KEYS_CONSTRUCTOR);
$this->allow_cid = $channel['channel_allow_cid'];
$this->allow_gid = $channel['channel_allow_gid'];
$this->deny_cid = $channel['channel_deny_cid'];
@@ -70,13 +91,24 @@ class AccessList {
$this->explicit = false;
}
+ private function validate_input_array(array $arr, array $required_keys) : void {
+ $missing_keys = array_diff($required_keys, array_keys($arr));
+
+ if (!empty($missing_keys)) {
+ throw new \Exception(
+ 'Invalid AccessList object: Expected array with keys: '
+ . implode(', ', $missing_keys)
+ );
+ }
+ }
+
/**
* @brief Get if we are using the default constructor values
* or values that have been set explicitly.
*
* @return boolean
*/
- function get_explicit() {
+ function get_explicit() : bool {
return $this->explicit;
}
@@ -94,7 +126,9 @@ class AccessList {
* * \e string \b deny_gid => string of denied gids
* @param boolean $explicit (optional) default true
*/
- function set($arr, $explicit = true) {
+ function set(array $arr, bool $explicit = true) : void {
+ $this->validate_input_array($arr, self::REQUIRED_KEYS_SET);
+
$this->allow_cid = $arr['allow_cid'];
$this->allow_gid = $arr['allow_gid'];
$this->deny_cid = $arr['deny_cid'];
@@ -112,7 +146,7 @@ class AccessList {
* * \e string \b deny_cid => string of denied cids
* * \e string \b deny_gid => string of denied gids
*/
- function get() {
+ function get() : array {
return [
'allow_cid' => $this->allow_cid,
'allow_gid' => $this->allow_gid,
@@ -138,7 +172,7 @@ class AccessList {
* * \e array|string \b group_deny => array with gids or comma-seperated string
* @param boolean $explicit (optional) default true
*/
- function set_from_array($arr, $explicit = true) {
+ function set_from_array(array $arr, bool $explicit = true) : void {
$arr['contact_allow'] = $arr['contact_allow'] ?? [];
$arr['group_allow'] = $arr['group_allow'] ?? [];
$arr['contact_deny'] = $arr['contact_deny'] ?? [];
@@ -161,7 +195,7 @@ class AccessList {
*
* @return boolean Return true if any of allow_* deny_* values is set.
*/
- function is_private() {
+ function is_private() : bool {
return (($this->allow_cid || $this->allow_gid || $this->deny_cid || $this->deny_gid) ? true : false);
}
diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php
index 7fa621470..7d2bcde56 100644
--- a/Zotlabs/Lib/ThreadItem.php
+++ b/Zotlabs/Lib/ThreadItem.php
@@ -101,7 +101,7 @@ class ThreadItem {
$conv = $this->get_conversation();
$observer = $conv->get_observer();
- $acl = new AccessList(false);
+ $acl = new AccessList([]);
$acl->set($item);
$lock = ((intval($item['item_private']) || ($item['uid'] == local_channel() && $acl->is_private()))
diff --git a/Zotlabs/Module/Chat.php b/Zotlabs/Module/Chat.php
index fc74016ab..2d36e022a 100644
--- a/Zotlabs/Module/Chat.php
+++ b/Zotlabs/Module/Chat.php
@@ -181,7 +181,7 @@ class Chat extends Controller {
);
if($x) {
- $acl = new AccessList(false);
+ $acl = new AccessList([]);
$acl->set($x[0]);
$private = $acl->is_private();
diff --git a/Zotlabs/Module/Sse_bs.php b/Zotlabs/Module/Sse_bs.php
index 970c482a9..a3a3afd23 100644
--- a/Zotlabs/Module/Sse_bs.php
+++ b/Zotlabs/Module/Sse_bs.php
@@ -169,12 +169,12 @@ class Sse_bs extends Controller {
$sql_extra2 = '';
if(self::$xchans)
- $sql_extra2 = " AND CASE WHEN verb = '" . ACTIVITY_SHARE . "' THEN owner_xchan ELSE author_xchan END IN (" . self::$xchans . ") ";
+ $sql_extra2 = " AND CASE WHEN verb = '" . dbesc(ACTIVITY_SHARE) . "' THEN owner_xchan ELSE author_xchan END IN (" . self::$xchans . ") ";
$item_normal = item_normal();
- // FEP-5624 filter approvals for comments
- $approvals = " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject') ";
+ // Filter FEP-5624 approvals for comments and internal follow activities
+ $item_normal .= " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
if ($notifications) {
$items = q("SELECT * FROM item
@@ -184,7 +184,6 @@ class Sse_bs extends Controller {
AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image')
AND author_xchan != '%s'
$item_normal
- $approvals
$sql_extra
$sql_extra2
ORDER BY created DESC LIMIT $limit OFFSET $offset",
@@ -258,8 +257,8 @@ class Sse_bs extends Controller {
$item_normal = item_normal();
- // FEP-5624 filter approvals for comments
- $approvals = " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject') ";
+ // Filter FEP-5624 approvals for comments and internal follow activities
+ $item_normal .= " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
if ($notifications) {
$items = q("SELECT * FROM item
@@ -269,7 +268,6 @@ class Sse_bs extends Controller {
AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image')
AND author_xchan != '%s'
$item_normal
- $approvals
$sql_extra
$sql_extra2
ORDER BY created DESC LIMIT $limit OFFSET $offset",
@@ -343,8 +341,8 @@ class Sse_bs extends Controller {
$item_normal = item_normal();
- // FEP-5624 filter approvals for comments
- $approvals = " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject') ";
+ // Filter FEP-5624 approvals for comments and internal follow activities
+ $item_normal .= " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
if ($notifications) {
$items = q("SELECT * FROM item
@@ -445,8 +443,8 @@ class Sse_bs extends Controller {
$item_normal = item_normal();
- // FEP-5624 filter approvals for comments
- $approvals = " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject') ";
+ // Filter FEP-5624 approvals for comments and internal follow activities
+ $item_normal .= " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
if ($notifications) {
$items = q("SELECT * FROM item
@@ -641,6 +639,10 @@ class Sse_bs extends Controller {
$item_normal = item_normal();
+ // Filter FEP-5624 approvals for comments and internal follow activities
+ $item_normal .= " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
+
+
$r = q("SELECT * FROM item
WHERE verb = '%s'
AND obj_type IN ('Document', 'Video', 'Audio', 'Image')
diff --git a/Zotlabs/Widget/Messages.php b/Zotlabs/Widget/Messages.php
index 0a8900c4f..cdd889121 100644
--- a/Zotlabs/Widget/Messages.php
+++ b/Zotlabs/Widget/Messages.php
@@ -60,8 +60,10 @@ class Messages {
}
$channel = App::get_channel();
- $item_normal_i = str_replace('item.', 'i.', item_normal());
- $item_normal_c = str_replace('item.', 'c.', item_normal());
+ $item_normal = item_normal();
+ $item_normal .= " and item.verb != '" . ACTIVITY_FOLLOW . "'";
+ $item_normal_i = str_replace('item.', 'i.', $item_normal);
+ $item_normal_c = str_replace('item.', 'c.', $item_normal);
$entries = [];
$limit = 30;
$dummy_order_sql = '';
diff --git a/boot.php b/boot.php
index 2b438c048..95726d9f6 100644
--- a/boot.php
+++ b/boot.php
@@ -60,7 +60,7 @@ require_once('include/bbcode.php');
require_once('include/items.php');
define('PLATFORM_NAME', 'hubzilla');
-define('STD_VERSION', '8.7');
+define('STD_VERSION', '8.7.1');
define('ZOT_REVISION', '6.0');
define('DB_UPDATE_VERSION', 1258);
diff --git a/tests/unit/Access/AccessListTest.php b/tests/unit/Access/AccessListTest.php
index 2f185db17..635f09930 100644
--- a/tests/unit/Access/AccessListTest.php
+++ b/tests/unit/Access/AccessListTest.php
@@ -60,14 +60,24 @@ class AccessListTest extends UnitTestCase {
}
/**
- * @expectedException PHPUnit\Framework\Error\Error
+ * AccessList constructor should throw an exception if input is not
+ * an array.
*/
-/*
- public function testPHPErrorOnInvalidConstructor() {
+ public function testConstructorThrowsOnInvalidInputType() {
+ $this->expectException("TypeError");
$accessList = new AccessList('invalid');
- // Causes: "Illegal string offset 'channel_allow_cid'"
}
-*/
+
+ /**
+ * AccessList constructor should throw an exception on
+ * invalid input.
+ */
+ public function testConstructorThrowsOnMissingKeysInArray() {
+ $this->expectException("Exception");
+ $this->expectExceptionMessage("Invalid AccessList object");
+ $accessList = new AccessList(['something_else' => 'should_this_fail?']);
+ }
+
/**
* Test that the defaults are as expected when constructed with
* an empty array.
@@ -111,16 +121,22 @@ class AccessListTest extends UnitTestCase {
}
/**
- * @expectedException PHPUnit\Framework\Error\Error
+ * The set method should throw an exception if input is not an array.
*/
-/*
- public function testPHPErrorOnInvalidSet() {
+ public function testSetThrowsOnInvalidInputType() {
+ $this->expectException('TypeError');
$accessList = new AccessList([]);
$accessList->set('invalid');
- // Causes: "Illegal string offset 'allow_cid'"
}
-*/
+
+ public function testSetThrowsOnMissingKeysInArray() {
+ $this->expectException('Exception');
+ $this->expectExceptionMessage('Invalid AccessList object');
+
+ $accessList = new AccessList([]);
+ $accessList->set(['something_else' => 'should_this_fail?']);
+ }
/**
* The set_from_array() function calls some other functions, too which are
diff --git a/view/js/main.js b/view/js/main.js
index 9c2480795..c463b1f59 100644
--- a/view/js/main.js
+++ b/view/js/main.js
@@ -646,7 +646,8 @@ function updatePageItems(mode, data) {
function updateConvItems(mode,data) {
- var scroll_position = $(window).scrollTop();
+ let scroll_position = $(window).scrollTop();
+ let b64mids = [];
if(mode !== 'update')
$(document).trigger('hz:updateConvItems');
@@ -660,12 +661,12 @@ function updateConvItems(mode,data) {
$('.thread-wrapper', data).each(function() {
if(this.classList.contains('toplevel_item')) {
- var ident = this.id;
- var convId = ident.replace('thread-wrapper-','');
- var commentWrap = $('#'+ident+' .collapsed-comments').attr('id');
+ let ident = this.id;
+ let convId = ident.replace('thread-wrapper-','');
+ let commentWrap = $('#'+ident+' .collapsed-comments').attr('id');
- var itmId = 0;
- var isVisible = false;
+ let itmId = 0;
+ let isVisible = false;
// figure out the comment state
if(typeof commentWrap !== 'undefined')
@@ -695,7 +696,7 @@ function updateConvItems(mode,data) {
if(isVisible)
showHideComments(itmId);
- var commentBody = localStorage.getItem("comment_body-" + convId);
+ let commentBody = localStorage.getItem("comment_body-" + convId);
if(commentBody) {
var commentElm = $('#comment-edit-text-' + convId);
@@ -723,7 +724,7 @@ function updateConvItems(mode,data) {
if(mode === 'replace') {
if (window.location.search.indexOf("mid=") != -1 || window.location.pathname.indexOf("display") != -1) {
- var title = $(".wall-item-title").text();
+ let title = $(".wall-item-title").text();
title.replace(/^\s+/, '');
title.replace(/\s+$/, '');
if (title) {
@@ -734,10 +735,14 @@ function updateConvItems(mode,data) {
}
}
- $(document).trigger('hz:sse_setNotificationsStatus', [$(this).data('b64mids')]);
+ $(this).data('b64mids').forEach((b64mid) => {
+ b64mids.push(b64mid);
+ });
});
+ $(document).trigger('hz:sse_setNotificationsStatus', [b64mids]);
+
$(window).scrollTop(scroll_position);
if(followUpPageLoad) {
@@ -802,7 +807,7 @@ function updateConvItems(mode,data) {
}
// reset rotators and cursors we may have set before reaching this place
- $('.like-rotator').hide();
+
$("#page-spinner").hide();
$("#profile-jot-text-loading").hide();
@@ -837,8 +842,7 @@ function scrollToItem() {
}
function collapseHeight() {
-
- $(".wall-item-content, .directory-collapse").each(function() {
+ $(".wall-item-content:not('.divmore_checked'), .directory-collapse:not('.divmore_checked')").each(function(i) {
var orgHeight = $(this).outerHeight(true);
var id = $(this).attr('id')
var open = ((expanded_items.indexOf($(this).attr('id')) === -1) ? false : true);
@@ -866,6 +870,7 @@ function collapseHeight() {
$(this).addClass('divmore');
}
}
+ $(this).addClass('divmore_checked');
});
}