From bdbc51229aa647154dae57d7b3d00f7ff5d7324e Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 26 May 2018 18:07:27 +0000 Subject: [PATCH 01/10] Fix for not being able to delete items --- boot.php | 2 +- database.sql | 12 +++++++++++- include/api.php | 8 ++++---- include/conversation.php | 23 ++++++++++++++--------- mod/display.php | 2 +- mod/network.php | 10 ++++++++-- mod/notes.php | 6 +++--- mod/profile.php | 2 +- mod/search.php | 4 ++-- src/Database/DBStructure.php | 11 +++++++++++ src/Model/Contact.php | 2 +- src/Model/Item.php | 8 ++++++++ 12 files changed, 65 insertions(+), 25 deletions(-) diff --git a/boot.php b/boot.php index 78bd68f3e4..66e44677b7 100644 --- a/boot.php +++ b/boot.php @@ -41,7 +41,7 @@ define('FRIENDICA_PLATFORM', 'Friendica'); define('FRIENDICA_CODENAME', 'The Tazmans Flax-lily'); define('FRIENDICA_VERSION', '2018.05-rc'); define('DFRN_PROTOCOL_VERSION', '2.23'); -define('DB_UPDATE_VERSION', 1265); +define('DB_UPDATE_VERSION', 1266); define('NEW_UPDATE_ROUTINE_VERSION', 1170); /** diff --git a/database.sql b/database.sql index 64ac656fd9..7c0a593795 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2018.05-rc (The Tazmans Flax-lily) --- DB_UPDATE_VERSION 1265 +-- DB_UPDATE_VERSION 1266 -- ------------------------------------------ @@ -1076,6 +1076,16 @@ CREATE TABLE IF NOT EXISTS `userd` ( INDEX `username` (`username`(32)) ) DEFAULT COLLATE utf8mb4_general_ci; +-- +-- TABLE user-item +-- +CREATE TABLE IF NOT EXISTS `user-item` ( + `iid` int unsigned NOT NULL DEFAULT 0 COMMENT 'Item id', + `uid` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'User id', + `hidden` boolean NOT NULL DEFAULT '0' COMMENT 'Hidden marker', + PRIMARY KEY(`uid`,`iid`) +) DEFAULT COLLATE utf8mb4_general_ci; + -- -- TABLE workerqueue -- diff --git a/include/api.php b/include/api.php index 628b86c649..e25d12c40a 100644 --- a/include/api.php +++ b/include/api.php @@ -1663,7 +1663,7 @@ function api_search($type) $r = dba::p( "SELECT ".item_fieldlists()." - FROM `item` ".item_joins()." + FROM `item` ".item_joins(api_user())." WHERE ".item_condition()." AND (`item`.`uid` = 0 OR (`item`.`uid` = ? AND NOT `item`.`global`)) AND `item`.`body` LIKE CONCAT('%',?,'%') $sql_extra @@ -1827,7 +1827,7 @@ function api_statuses_public_timeline($type) "SELECT " . item_fieldlists() . " FROM `thread` STRAIGHT_JOIN `item` ON `item`.`id` = `thread`.`iid` - " . item_joins() . " + " . item_joins(api_user()) . " STRAIGHT_JOIN `user` ON `user`.`uid` = `thread`.`uid` AND NOT `user`.`hidewall` AND `verb` = ? @@ -1856,7 +1856,7 @@ function api_statuses_public_timeline($type) $r = dba::p( "SELECT " . item_fieldlists() . " FROM `item` - " . item_joins() . " + " . item_joins(api_user()) . " STRAIGHT_JOIN `user` ON `user`.`uid` = `item`.`uid` AND NOT `user`.`hidewall` AND `verb` = ? @@ -1930,7 +1930,7 @@ function api_statuses_networkpublic_timeline($type) "SELECT " . item_fieldlists() . " FROM `thread` STRAIGHT_JOIN `item` ON `item`.`id` = `thread`.`iid` - " . item_joins() . " + " . item_joins(api_user()) . " WHERE `thread`.`uid` = 0 AND `verb` = ? AND NOT `thread`.`private` diff --git a/include/conversation.php b/include/conversation.php index 324b53b5a8..fb485baf12 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -405,10 +405,12 @@ function visible_activity($item) { /** * @brief SQL query for items + * + * @param int $uid user id */ -function item_query() { +function item_query($uid = 0) { return "SELECT " . item_fieldlists() . " FROM `item` " . - item_joins() . " WHERE " . item_condition(); + item_joins($uid) . " WHERE " . item_condition(); } /** @@ -467,16 +469,19 @@ These Fields are not added below (yet). They are here to for bug search. /** * @brief SQL join for contacts that are needed for displaying items + * + * @param int $uid user id */ -function item_joins() { +function item_joins($uid = 0) { return sprintf("STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND NOT `contact`.`blocked` AND ((NOT `contact`.`readonly` AND NOT `contact`.`pending` AND (`contact`.`rel` IN (%s, %s))) OR `contact`.`self` OR (`item`.`id` != `item`.`parent`) OR `contact`.`uid` = 0) INNER JOIN `contact` AS `author` ON `author`.`id`=`item`.`author-id` AND NOT `author`.`blocked` INNER JOIN `contact` AS `owner` ON `owner`.`id`=`item`.`owner-id` AND NOT `owner`.`blocked` + LEFT JOIN `user-item` ON `user-item`.`iid` = `item`.`id` AND `user-item`.`uid` = %d LEFT JOIN `event` ON `event-id` = `event`.`id`", - CONTACT_IS_SHARING, CONTACT_IS_FRIEND + CONTACT_IS_SHARING, CONTACT_IS_FRIEND, intval($uid) ); } @@ -484,7 +489,7 @@ function item_joins() { * @brief SQL condition for items that are needed for displaying items */ function item_condition() { - return "`item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`"; + return "`item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated` AND (`user-item`.`hidden` IS NULL OR NOT `user-item`.`hidden`) "; } /** @@ -497,7 +502,7 @@ function item_condition() { * that are based on unique features of the calling module. * */ -function conversation(App $a, $items, $mode, $update, $preview = false, $order = 'commented') { +function conversation(App $a, $items, $mode, $update, $preview = false, $order = 'commented', $uid = 0) { require_once 'mod/proxy.php'; $ssl_state = ((local_user()) ? true : false); @@ -521,7 +526,7 @@ function conversation(App $a, $items, $mode, $update, $preview = false, $order = $previewing = (($preview) ? ' preview ' : ''); if ($mode === 'network') { - $items = conversation_add_children($items, false, $order); + $items = conversation_add_children($items, false, $order, $uid); $profile_owner = local_user(); if (!$update) { /* @@ -885,7 +890,7 @@ function conversation(App $a, $items, $mode, $update, $preview = false, $order = * * @return array items with parents and comments */ -function conversation_add_children($parents, $block_authors, $order) { +function conversation_add_children($parents, $block_authors, $order, $uid = 0) { $max_comments = Config::get('system', 'max_comments', 100); if ($max_comments > 0) { @@ -899,7 +904,7 @@ function conversation_add_children($parents, $block_authors, $order) { $block_sql = $block_authors ? "AND NOT `author`.`hidden` AND NOT `author`.`blocked`" : ""; foreach ($parents AS $parent) { - $thread_items = dba::p(item_query()."AND `item`.`parent-uri` = ? + $thread_items = dba::p(item_query(local_user())."AND `item`.`parent-uri` = ? AND `item`.`uid` IN (0, ?) $block_sql ORDER BY `item`.`uid` ASC, `item`.`commented` DESC" . $limit, $parent['uri'], local_user()); diff --git a/mod/display.php b/mod/display.php index ef5704c736..80e913d204 100644 --- a/mod/display.php +++ b/mod/display.php @@ -346,7 +346,7 @@ function display_content(App $a, $update = false, $update_uid = 0) { return ''; } - $r = dba::p(item_query()."AND `item`.`parent-uri` = (SELECT `parent-uri` FROM `item` WHERE `id` = ?) + $r = dba::p(item_query(local_user())."AND `item`.`parent-uri` = (SELECT `parent-uri` FROM `item` WHERE `id` = ?) AND `item`.`uid` IN (0, ?) $sql_extra ORDER BY `item`.`uid` ASC, `parent` DESC, `gravity` ASC, `id` ASC", $item_id, local_user() diff --git a/mod/network.php b/mod/network.php index 87594a77c4..2e7ae12e0b 100644 --- a/mod/network.php +++ b/mod/network.php @@ -345,7 +345,7 @@ function networkConversation($a, $items, $mode, $update, $ordering = '') // Set this so that the conversation function can find out contact info for our wall-wall items $a->page_contact = $a->contact; - $o = conversation($a, $items, $mode, $update, false, $ordering); + $o = conversation($a, $items, $mode, $update, false, $ordering, local_user()); if (!$update) { if (PConfig::get(local_user(), 'system', 'infinite_scroll')) { @@ -456,7 +456,7 @@ function networkFlatView(App $a, $update = 0) $items = q("SELECT %s FROM `item` $sql_post_table %s WHERE %s AND `item`.`uid` = %d ORDER BY `item`.`id` DESC $pager_sql ", - item_fieldlists(), item_joins(), item_condition(), + item_fieldlists(), item_joins($_SESSION['uid']), item_condition(), intval($_SESSION['uid']) ); @@ -774,12 +774,15 @@ function networkThreadedView(App $a, $update, $parent) AND (`item`.`parent-uri` != `item`.`uri` OR `contact`.`uid` = `item`.`uid` AND `contact`.`self` OR `contact`.`rel` IN (%d, %d) AND NOT `contact`.`readonly`) + LEFT JOIN `user-item` ON `user-item`.`iid` = `item`.`id` AND `user-item`.`uid` = %d WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`deleted` + AND (`user-item`.`hidden` IS NULL OR NOT `user-item`.`hidden`) AND NOT `item`.`moderated` AND $sql_extra4 $sql_extra3 $sql_extra $sql_range $sql_nets ORDER BY `order_date` DESC LIMIT 100", intval(CONTACT_IS_SHARING), intval(CONTACT_IS_FRIEND), + intval(local_user()), intval(local_user()) ); } else { @@ -791,12 +794,15 @@ function networkThreadedView(App $a, $update, $parent) AND (`item`.`parent-uri` != `item`.`uri` OR `contact`.`uid` = `item`.`uid` AND `contact`.`self` OR `contact`.`rel` IN (%d, %d) AND NOT `contact`.`readonly`) + LEFT JOIN `user-item` ON `user-item`.`iid` = `item`.`id` AND `user-item`.`uid` = %d WHERE `thread`.`uid` = %d AND `thread`.`visible` AND NOT `thread`.`deleted` AND NOT `thread`.`moderated` + AND (`user-item`.`hidden` IS NULL OR NOT `user-item`.`hidden`) $sql_extra2 $sql_extra3 $sql_range $sql_extra $sql_nets ORDER BY `order_date` DESC $pager_sql", intval(CONTACT_IS_SHARING), intval(CONTACT_IS_FRIEND), + intval(local_user()), intval(local_user()) ); } diff --git a/mod/notes.php b/mod/notes.php index aa239fb0e0..96a2826089 100644 --- a/mod/notes.php +++ b/mod/notes.php @@ -82,7 +82,7 @@ function notes_content(App $a, $update = false) WHERE %s AND `item`.`uid` = %d AND `item`.`type` = 'note' AND `contact`.`self` AND `item`.`id` = `item`.`parent` AND NOT `item`.`wall` $sql_extra ", - item_joins(), + item_joins(local_user()), item_condition(), intval(local_user()) ); @@ -97,7 +97,7 @@ function notes_content(App $a, $update = false) AND `item`.`id` = `item`.`parent` AND NOT `item`.`wall` $sql_extra ORDER BY `item`.`created` DESC LIMIT %d ,%d ", - item_joins(), + item_joins(local_user()), item_condition(), intval(local_user()), intval($a->pager['start']), @@ -119,7 +119,7 @@ function notes_content(App $a, $update = false) $sql_extra ORDER BY `parent` DESC, `gravity` ASC, `item`.`id` ASC ", item_fieldlists(), - item_joins(), + item_joins(local_user()), item_condition(), intval(local_user()), dbesc($parents_str) diff --git a/mod/profile.php b/mod/profile.php index 2856cdd177..2af2845f27 100644 --- a/mod/profile.php +++ b/mod/profile.php @@ -339,7 +339,7 @@ function profile_content(App $a, $update = 0) $parents_str = implode(', ', $parents_arr); - $items = q(item_query() . " AND `item`.`uid` = %d + $items = q(item_query($a->profile['profile_uid']) . " AND `item`.`uid` = %d AND `item`.`parent` IN (%s) $sql_extra ", intval($a->profile['profile_uid']), diff --git a/mod/search.php b/mod/search.php index be0f943d07..4c461e4183 100644 --- a/mod/search.php +++ b/mod/search.php @@ -204,7 +204,7 @@ function search_content(App $a) { AND `term`.`otype` = %d AND `term`.`type` = %d AND `term`.`term` = '%s' AND `item`.`verb` = '%s' AND NOT `author`.`blocked` AND NOT `author`.`hidden` ORDER BY term.created DESC LIMIT %d , %d ", - item_fieldlists(), item_joins(), item_condition(), + item_fieldlists(), item_joins(local_user()), item_condition(), intval(local_user()), intval(TERM_OBJ_POST), intval(TERM_HASHTAG), dbesc(protect_sprintf($search)), dbesc(ACTIVITY_POST), intval($a->pager['start']), intval($a->pager['itemspage'])); @@ -219,7 +219,7 @@ function search_content(App $a) { AND NOT `author`.`blocked` AND NOT `author`.`hidden` $sql_extra GROUP BY `item`.`uri`, `item`.`id` ORDER BY `item`.`id` DESC LIMIT %d , %d", - item_fieldlists(), item_joins(), item_condition(), + item_fieldlists(), item_joins(local_user()), item_condition(), intval(local_user()), intval($a->pager['start']), intval($a->pager['itemspage'])); } diff --git a/src/Database/DBStructure.php b/src/Database/DBStructure.php index 6db786dfc8..41543d89cc 100644 --- a/src/Database/DBStructure.php +++ b/src/Database/DBStructure.php @@ -1786,6 +1786,17 @@ class DBStructure "username" => ["username(32)"], ] ]; + $database["user-item"] = [ + "comment" => "User specific item data", + "fields" => [ + "iid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "primary" => "1", "relation" => ["item" => "id"], "comment" => "Item id"], + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "primary" => "1", "relation" => ["user" => "uid"], "comment" => "User id"], + "hidden" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Hidden marker"], + ], + "indexes" => [ + "PRIMARY" => ["uid", "iid"], + ] + ]; $database["workerqueue"] = [ "comment" => "Background tasks queue entries", "fields" => [ diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 03f5a36db1..bbfb399238 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -1049,7 +1049,7 @@ class Contact extends BaseObject $contact = ($r[0]["contact-type"] == ACCOUNT_TYPE_COMMUNITY ? 'owner-id' : 'author-id'); - $r = q(item_query() . " AND `item`.`" . $contact . "` = %d AND " . $sql . + $r = q(item_query(local_user()) . " AND `item`.`" . $contact . "` = %d AND " . $sql . " AND `item`.`verb` = '%s' ORDER BY `item`.`created` DESC LIMIT %d, %d", intval($author_id), intval(local_user()), dbesc(ACTIVITY_POST), intval($a->pager['start']), intval($a->pager['itemspage']) diff --git a/src/Model/Item.php b/src/Model/Item.php index 309ddd858d..91c889a1ed 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -201,8 +201,16 @@ class Item extends BaseObject // send the notification upstream/downstream Worker::add(['priority' => $priority, 'dont_fork' => true], "Notifier", "drop", intval($item['id'])); + } elseif ($item['uid'] != 0) { + + // When we delete just our local user copy of an item, we have to set an marker to hide it + $global_item = dba::selectFirst('item', ['id'], ['uri' => $item['uri'], 'uid' => 0, 'deleted' => false]); + if (DBM::is_result($global_item)) { + dba::update('user-item', ['hidden' => true], ['iid' => $global_item['id'], 'uid' => $item['uid']], true); + } } + logger('Item with ID ' . $item_id . " has been deleted.", LOGGER_DEBUG); return true; From 4c36109f02c8135b2b88d7e0231ab5a61d61e3d6 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 26 May 2018 20:03:30 +0000 Subject: [PATCH 02/10] Some more places to add the user id --- include/conversation.php | 4 ++-- mod/community.php | 2 +- mod/display.php | 2 +- mod/profile.php | 2 +- mod/search.php | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/conversation.php b/include/conversation.php index fb485baf12..290d68bf3d 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -587,7 +587,7 @@ function conversation(App $a, $items, $mode, $update, $preview = false, $order = . " var profile_page = 1; "; } } elseif ($mode === 'community') { - $items = conversation_add_children($items, true, $order); + $items = conversation_add_children($items, true, $order, $uid); $profile_owner = 0; if (!$update) { $live_update_div = '
' . "\r\n" @@ -890,7 +890,7 @@ function conversation(App $a, $items, $mode, $update, $preview = false, $order = * * @return array items with parents and comments */ -function conversation_add_children($parents, $block_authors, $order, $uid = 0) { +function conversation_add_children($parents, $block_authors, $order, $uid) { $max_comments = Config::get('system', 'max_comments', 100); if ($max_comments > 0) { diff --git a/mod/community.php b/mod/community.php index 876339dea1..59be7487bd 100644 --- a/mod/community.php +++ b/mod/community.php @@ -171,7 +171,7 @@ function community_content(App $a, $update = 0) $s = $r; } - $o .= conversation($a, $s, 'community', $update); + $o .= conversation($a, $s, 'community', $update, false, 'commented', local_user()); if (!$update) { $o .= alt_pager($a, count($r)); diff --git a/mod/display.php b/mod/display.php index 80e913d204..6286569a54 100644 --- a/mod/display.php +++ b/mod/display.php @@ -369,7 +369,7 @@ function display_content(App $a, $update = false, $update_uid = 0) { if (!$update) { $o .= ""; } - $o .= conversation($a, $items, 'display', $update_uid); + $o .= conversation($a, $items, 'display', $update_uid, false, 'commented', local_user()); // Preparing the meta header $description = trim(HTML::toPlaintext(BBCode::convert($s[0]["body"], false), 0, true)); diff --git a/mod/profile.php b/mod/profile.php index 2af2845f27..2fb947a836 100644 --- a/mod/profile.php +++ b/mod/profile.php @@ -365,7 +365,7 @@ function profile_content(App $a, $update = 0) } } - $o .= conversation($a, $items, 'profile', $update); + $o .= conversation($a, $items, 'profile', $update, false, 'commented', local_user()); if (!$update) { $o .= alt_pager($a, count($items)); diff --git a/mod/search.php b/mod/search.php index 4c461e4183..a600965e46 100644 --- a/mod/search.php +++ b/mod/search.php @@ -241,7 +241,7 @@ function search_content(App $a) { ]); logger("Start Conversation for '".$search."'", LOGGER_DEBUG); - $o .= conversation($a,$r,'search',false); + $o .= conversation($a, $r, 'search', false, false, 'commented', local_user()); $o .= alt_pager($a,count($r)); From a50805c37103fc6c44ce2f1562dee4fc91479b89 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 26 May 2018 20:07:30 +0000 Subject: [PATCH 03/10] Grammar fix --- src/Model/Item.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Model/Item.php b/src/Model/Item.php index 91c889a1ed..4e67083f99 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -203,7 +203,7 @@ class Item extends BaseObject Worker::add(['priority' => $priority, 'dont_fork' => true], "Notifier", "drop", intval($item['id'])); } elseif ($item['uid'] != 0) { - // When we delete just our local user copy of an item, we have to set an marker to hide it + // When we delete just our local user copy of an item, we have to set a marker to hide it $global_item = dba::selectFirst('item', ['id'], ['uri' => $item['uri'], 'uid' => 0, 'deleted' => false]); if (DBM::is_result($global_item)) { dba::update('user-item', ['hidden' => true], ['iid' => $global_item['id'], 'uid' => $item['uid']], true); From a6396dde557215c1434563ab244e2b87dd399e48 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 26 May 2018 20:08:42 +0000 Subject: [PATCH 04/10] Removed useless line --- src/Model/Item.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Model/Item.php b/src/Model/Item.php index 4e67083f99..6effb393a2 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -210,7 +210,6 @@ class Item extends BaseObject } } - logger('Item with ID ' . $item_id . " has been deleted.", LOGGER_DEBUG); return true; From 708ddf2b02cfde465169d533a2c04200fb9eec15 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 26 May 2018 20:23:49 +0000 Subject: [PATCH 05/10] Preparation for new deletion functionality --- src/Model/Item.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Model/Item.php b/src/Model/Item.php index 6effb393a2..ea866152bb 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -92,12 +92,13 @@ class Item extends BaseObject * * @param array $condition The condition for finding the item entries * @param integer $priority Priority for the notification + * @param integer $uid User who wants to delete the item */ - public static function delete($condition, $priority = PRIORITY_HIGH) + public static function delete($condition, $priority = PRIORITY_HIGH, $uid = 0) { $items = dba::select('item', ['id'], $condition); while ($item = dba::fetch($items)) { - self::deleteById($item['id'], $priority); + self::deleteById($item['id'], $priority, $uid); } dba::close($items); } @@ -107,10 +108,11 @@ class Item extends BaseObject * * @param integer $item_id Item ID that should be delete * @param integer $priority Priority for the notification + * @param integer $uid User who wants to delete the item * * @return boolean success */ - public static function deleteById($item_id, $priority = PRIORITY_HIGH) + public static function deleteById($item_id, $priority = PRIORITY_HIGH, $uid = 0) { // locate item to be deleted $fields = ['id', 'uri', 'uid', 'parent', 'parent-uri', 'origin', @@ -132,6 +134,12 @@ class Item extends BaseObject $parent = ['origin' => false]; } + // "Deleting" global items just means hiding them + if (($item['uid'] == 0) && ($uid != 0)) { + dba::update('user-item', ['hidden' => true], ['iid' => $item_id, 'uid' => $uid], true); + return true; + } + // clean up categories and tags so they don't end up as orphans $matches = false; From 54136f3a74b2df925449c9017cd4908eef2b8b76 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 26 May 2018 21:38:45 +0000 Subject: [PATCH 06/10] Added the new parameter to the delete function. --- include/api.php | 6 +++--- include/items.php | 4 ++-- mod/events.php | 2 +- mod/item.php | 2 +- mod/photos.php | 4 ++-- mod/videos.php | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/api.php b/include/api.php index e25d12c40a..3832257784 100644 --- a/include/api.php +++ b/include/api.php @@ -2256,7 +2256,7 @@ function api_statuses_destroy($type) $ret = api_statuses_show($type); - Item::deleteById($id); + Item::deleteById($id, PRIORITY_HIGH, api_user()); return $ret; } @@ -4148,7 +4148,7 @@ function api_fr_photoalbum_delete($type) if (!DBM::is_result($photo_item)) { throw new InternalServerErrorException("problem with deleting items occured"); } - Item::deleteById($photo_item[0]['id']); + Item::deleteById($photo_item[0]['id'], PRIORITY_HIGH, api_user()); } // now let's delete all photos from the album @@ -4441,7 +4441,7 @@ function api_fr_photo_delete($type) } // function for setting the items to "deleted = 1" which ensures that comments, likes etc. are not shown anymore // to the user and the contacts of the users (drop_items() do all the necessary magic to avoid orphans in database and federate deletion) - Item::deleteById($photo_item[0]['id']); + Item::deleteById($photo_item[0]['id'], PRIORITY_HIGH, api_user()); $answer = ['result' => 'deleted', 'message' => 'photo with id `' . $photo_id . '` has been deleted from server.']; return api_format_data("photo_delete", $type, ['$result' => $answer]); diff --git a/include/items.php b/include/items.php index c04bef01c3..b84ac701a6 100644 --- a/include/items.php +++ b/include/items.php @@ -321,7 +321,7 @@ function drop_items($items) { if (count($items)) { foreach ($items as $item) { - $owner = Item::deleteById($item); + $owner = Item::deleteById($item, PRIORITY_HIGH, local_user()); if ($owner && !$uid) $uid = $owner; } @@ -393,7 +393,7 @@ function drop_item($id) { } // delete the item - Item::deleteById($item['id']); + Item::deleteById($item['id'], PRIORITY_HIGH, local_user()); goaway(System::baseUrl() . '/' . $_SESSION['return_url']); //NOTREACHED diff --git a/mod/events.php b/mod/events.php index cad440f164..e40e69f500 100644 --- a/mod/events.php +++ b/mod/events.php @@ -545,7 +545,7 @@ function events_content(App $a) { // Delete only real events (no birthdays) if (DBM::is_result($ev) && $ev[0]['type'] == 'event') { - $del = Item::deleteById($ev[0]['itemid']); + $del = Item::deleteById($ev[0]['itemid'], PRIORITY_HIGH, local_user()); } if ($del == 0) { diff --git a/mod/item.php b/mod/item.php index a3ed63cd97..ca79a64028 100644 --- a/mod/item.php +++ b/mod/item.php @@ -877,7 +877,7 @@ function item_content(App $a) { $o = ''; if (($a->argc == 3) && ($a->argv[1] === 'drop') && intval($a->argv[2])) { if (is_ajax()) { - $o = Item::deleteById($a->argv[2]); + $o = Item::deleteById($a->argv[2], PRIORITY_HIGH, local_user()); } else { $o = drop_item($a->argv[2]); } diff --git a/mod/photos.php b/mod/photos.php index c8dad750d1..3d38be5037 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -289,7 +289,7 @@ function photos_post(App $a) ); if (DBM::is_result($r)) { foreach ($r as $rr) { - Item::deleteById($rr['id']); + Item::deleteById($rr['id'], PRIORITY_HIGH, $page_owner_uid); } } @@ -349,7 +349,7 @@ function photos_post(App $a) intval($page_owner_uid) ); if (DBM::is_result($i)) { - Item::deleteById($i[0]['id']); + Item::deleteById($i[0]['id'], PRIORITY_HIGH, $page_owner_uid); // Update the photo albums cache Photo::clearAlbumCache($page_owner_uid); diff --git a/mod/videos.php b/mod/videos.php index f4b8c46b1b..6dee4586aa 100644 --- a/mod/videos.php +++ b/mod/videos.php @@ -169,7 +169,7 @@ function videos_post(App $a) { ); if (DBM::is_result($i)) { - Item::deleteById($i[0]['id']); + Item::deleteById($i[0]['id'], PRIORITY_HIGH, local_user()); } } From deb015be12dadf2b2f10df4cc97911dedf3a0405 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 27 May 2018 10:42:47 +0000 Subject: [PATCH 07/10] Changed documentation --- src/Database/DBStructure.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Database/DBStructure.php b/src/Database/DBStructure.php index 41543d89cc..847449b754 100644 --- a/src/Database/DBStructure.php +++ b/src/Database/DBStructure.php @@ -1791,7 +1791,7 @@ class DBStructure "fields" => [ "iid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "primary" => "1", "relation" => ["item" => "id"], "comment" => "Item id"], "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "primary" => "1", "relation" => ["user" => "uid"], "comment" => "User id"], - "hidden" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Hidden marker"], + "hidden" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Marker to hide an item from the user"], ], "indexes" => [ "PRIMARY" => ["uid", "iid"], From 8329705ebab61159b114b274e794bf6c3d6a6a95 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 29 May 2018 05:22:57 +0000 Subject: [PATCH 08/10] New function to delete items for users --- include/api.php | 6 +++--- include/items.php | 4 ++-- mod/admin.php | 9 ++------- mod/events.php | 2 +- mod/item.php | 2 +- mod/photos.php | 22 +++++---------------- mod/videos.php | 2 +- src/Model/Item.php | 40 ++++++++++++++++++++++++++++----------- src/Protocol/DFRN.php | 10 ++++------ src/Protocol/Diaspora.php | 4 ++-- src/Protocol/OStatus.php | 7 +++---- 11 files changed, 53 insertions(+), 55 deletions(-) diff --git a/include/api.php b/include/api.php index 3832257784..a70c18f3ca 100644 --- a/include/api.php +++ b/include/api.php @@ -2256,7 +2256,7 @@ function api_statuses_destroy($type) $ret = api_statuses_show($type); - Item::deleteById($id, PRIORITY_HIGH, api_user()); + Item::deleteForUser(['id' => $id], api_user()); return $ret; } @@ -4148,7 +4148,7 @@ function api_fr_photoalbum_delete($type) if (!DBM::is_result($photo_item)) { throw new InternalServerErrorException("problem with deleting items occured"); } - Item::deleteById($photo_item[0]['id'], PRIORITY_HIGH, api_user()); + Item::deleteForUser(['id' => $photo_item[0]['id']], api_user()); } // now let's delete all photos from the album @@ -4441,7 +4441,7 @@ function api_fr_photo_delete($type) } // function for setting the items to "deleted = 1" which ensures that comments, likes etc. are not shown anymore // to the user and the contacts of the users (drop_items() do all the necessary magic to avoid orphans in database and federate deletion) - Item::deleteById($photo_item[0]['id'], PRIORITY_HIGH, api_user()); + Item::deleteForUser(['id' => $photo_item[0]['id']], api_user()); $answer = ['result' => 'deleted', 'message' => 'photo with id `' . $photo_id . '` has been deleted from server.']; return api_format_data("photo_delete", $type, ['$result' => $answer]); diff --git a/include/items.php b/include/items.php index b84ac701a6..4533b6077e 100644 --- a/include/items.php +++ b/include/items.php @@ -321,7 +321,7 @@ function drop_items($items) { if (count($items)) { foreach ($items as $item) { - $owner = Item::deleteById($item, PRIORITY_HIGH, local_user()); + $owner = Item::deleteForUser(['id' => $item], local_user()); if ($owner && !$uid) $uid = $owner; } @@ -393,7 +393,7 @@ function drop_item($id) { } // delete the item - Item::deleteById($item['id'], PRIORITY_HIGH, local_user()); + Item::deleteForUser(['id' => $item['id']], local_user()); goaway(System::baseUrl() . '/' . $_SESSION['return_url']); //NOTREACHED diff --git a/mod/admin.php b/mod/admin.php index e374201fff..83dafcfd97 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -555,14 +555,9 @@ function admin_page_deleteitem_post(App $a) if (strpos($guid, '/')) { $guid = substr($guid, strrpos($guid, '/') + 1); } - // Now that we have the GUID get all IDs of the associated entries in the - // item table of the DB and drop those items, which will also delete the + // Now that we have the GUID, drop those items, which will also delete the // associated threads. - $r = dba::select('item', ['id'], ['guid' => $guid]); - while ($row = dba::fetch($r)) { - Item::deleteById($row['id']); - } - dba::close($r); + Item::delete(['guid' => $guid]); } info(L10n::t('Item marked for deletion.') . EOL); diff --git a/mod/events.php b/mod/events.php index e40e69f500..87c358a99e 100644 --- a/mod/events.php +++ b/mod/events.php @@ -545,7 +545,7 @@ function events_content(App $a) { // Delete only real events (no birthdays) if (DBM::is_result($ev) && $ev[0]['type'] == 'event') { - $del = Item::deleteById($ev[0]['itemid'], PRIORITY_HIGH, local_user()); + $del = Item::deleteForUser(['id' => $ev[0]['itemid']], local_user()); } if ($del == 0) { diff --git a/mod/item.php b/mod/item.php index ca79a64028..823350874b 100644 --- a/mod/item.php +++ b/mod/item.php @@ -877,7 +877,7 @@ function item_content(App $a) { $o = ''; if (($a->argc == 3) && ($a->argv[1] === 'drop') && intval($a->argv[2])) { if (is_ajax()) { - $o = Item::deleteById($a->argv[2], PRIORITY_HIGH, local_user()); + $o = Item::deleteForUser(['id' => $a->argv[2]], local_user()); } else { $o = drop_item($a->argv[2]); } diff --git a/mod/photos.php b/mod/photos.php index 3d38be5037..30d3728d36 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -284,14 +284,7 @@ function photos_post(App $a) ); // find and delete the corresponding item with all the comments and likes/dislikes - $r = q("SELECT `id` FROM `item` WHERE `resource-id` IN ( $str_res ) AND `uid` = %d", - intval($page_owner_uid) - ); - if (DBM::is_result($r)) { - foreach ($r as $rr) { - Item::deleteById($rr['id'], PRIORITY_HIGH, $page_owner_uid); - } - } + Item::deleteForUser(['resource-id' => $res, 'uid' => $page_owner_uid], $page_owner_uid); // Update the photo albums cache Photo::clearAlbumCache($page_owner_uid); @@ -344,16 +337,11 @@ function photos_post(App $a) intval($page_owner_uid), dbesc($r[0]['resource-id']) ); - $i = q("SELECT `id` FROM `item` WHERE `resource-id` = '%s' AND `uid` = %d LIMIT 1", - dbesc($r[0]['resource-id']), - intval($page_owner_uid) - ); - if (DBM::is_result($i)) { - Item::deleteById($i[0]['id'], PRIORITY_HIGH, $page_owner_uid); - // Update the photo albums cache - Photo::clearAlbumCache($page_owner_uid); - } + Item::deleteForUser(['resource-id' => $r[0]['resource-id'], 'uid' => $page_owner_uid], $page_owner_uid); + + // Update the photo albums cache + Photo::clearAlbumCache($page_owner_uid); } goaway('photos/' . $a->data['user']['nickname']); diff --git a/mod/videos.php b/mod/videos.php index 6dee4586aa..0dd653e914 100644 --- a/mod/videos.php +++ b/mod/videos.php @@ -169,7 +169,7 @@ function videos_post(App $a) { ); if (DBM::is_result($i)) { - Item::deleteById($i[0]['id'], PRIORITY_HIGH, local_user()); + Item::deleteForUser(['id' => $i[0]['id']], local_user()); } } diff --git a/src/Model/Item.php b/src/Model/Item.php index ea866152bb..0bac3210d7 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -92,13 +92,38 @@ class Item extends BaseObject * * @param array $condition The condition for finding the item entries * @param integer $priority Priority for the notification - * @param integer $uid User who wants to delete the item */ - public static function delete($condition, $priority = PRIORITY_HIGH, $uid = 0) + public static function delete($condition, $priority = PRIORITY_HIGH) { $items = dba::select('item', ['id'], $condition); while ($item = dba::fetch($items)) { - self::deleteById($item['id'], $priority, $uid); + self::deleteById($item['id'], $priority); + } + dba::close($items); + } + + /** + * @brief Delete an item for an user and notify others about it - if it was ours + * + * @param array $condition The condition for finding the item entries + * @param integer $uid User who wants to delete this item + */ + public static function deleteForUser($condition, $uid) + { + if ($uid == 0) { + return; + } + + $items = dba::select('item', ['id', 'uid'], $condition); + while ($item = dba::fetch($items)) { + // "Deleting" global items just means hiding them + if ($item['uid'] == 0) { + dba::update('user-item', ['hidden' => true], ['iid' => $item['id'], 'uid' => $uid], true); + } elseif ($item['uid'] == $uid) { + self::deleteById($item['id'], PRIORITY_HIGH); + } else { + logger('Wrong ownership. Not deleting item ' . $item['id']); + } } dba::close($items); } @@ -108,11 +133,10 @@ class Item extends BaseObject * * @param integer $item_id Item ID that should be delete * @param integer $priority Priority for the notification - * @param integer $uid User who wants to delete the item * * @return boolean success */ - public static function deleteById($item_id, $priority = PRIORITY_HIGH, $uid = 0) + private static function deleteById($item_id, $priority = PRIORITY_HIGH) { // locate item to be deleted $fields = ['id', 'uri', 'uid', 'parent', 'parent-uri', 'origin', @@ -134,12 +158,6 @@ class Item extends BaseObject $parent = ['origin' => false]; } - // "Deleting" global items just means hiding them - if (($item['uid'] == 0) && ($uid != 0)) { - dba::update('user-item', ['hidden' => true], ['iid' => $item_id, 'uid' => $uid], true); - return true; - } - // clean up categories and tags so they don't end up as orphans $matches = false; diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 5efcfb80b5..bf943f1a15 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -2807,15 +2807,13 @@ class DFRN } } - $entrytype = self::getEntryType($importer, $item); - - if (!$item["deleted"]) { - logger('deleting item '.$item["id"].' uri='.$uri, LOGGER_DEBUG); - } else { + if ($item["deleted"]) { return; } - Item::deleteById($item["id"]); + logger('deleting item '.$item["id"].' uri='.$uri, LOGGER_DEBUG); + + Item::delete(['id' => $item["id"]]); } /** diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index d2a7995d86..f3aa672a21 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -2785,7 +2785,7 @@ class Diaspora while ($item = dba::fetch($r)) { // Fetch the parent item - $parent = dba::selectFirst('item', ['author-link', 'origin'], ['id' => $item["parent"]]); + $parent = dba::selectFirst('item', ['author-link'], ['id' => $item["parent"]]); // Only delete it if the parent author really fits if (!link_compare($parent["author-link"], $contact["url"]) && !link_compare($item["author-link"], $contact["url"])) { @@ -2793,7 +2793,7 @@ class Diaspora continue; } - Item::deleteById($item["id"]); + Item::delete(['id' => $item["id"]]); logger("Deleted target ".$target_guid." (".$item["id"].") from user ".$item["uid"]." parent: ".$item["parent"], LOGGER_DEBUG); } diff --git a/src/Protocol/OStatus.php b/src/Protocol/OStatus.php index 8b69392144..e91d81f58e 100644 --- a/src/Protocol/OStatus.php +++ b/src/Protocol/OStatus.php @@ -537,13 +537,12 @@ class OStatus private static function deleteNotice($item) { $condition = ['uid' => $item['uid'], 'author-link' => $item['author-link'], 'uri' => $item['uri']]; - $deleted = dba::selectFirst('item', ['id', 'parent-uri'], $condition); - if (!DBM::is_result($deleted)) { - logger('Item from '.$item['author-link'].' with uri '.$item['uri'].' for user '.$item['uid']." wasn't found. We don't delete it. "); + if (!dba::exists('item', $condition)) { + logger('Item from '.$item['author-link'].' with uri '.$item['uri'].' for user '.$item['uid']." wasn't found. We don't delete it."); return; } - Item::deleteById($deleted["id"]); + Item::delete($condition); logger('Deleted item with uri '.$item['uri'].' for user '.$item['uid']); } From 5bcb9daa43e3a50185a9ffc973d72107ba30572c Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 29 May 2018 18:57:32 +0000 Subject: [PATCH 09/10] Use local_user instead --- mod/network.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mod/network.php b/mod/network.php index 2e7ae12e0b..23835c8d5f 100644 --- a/mod/network.php +++ b/mod/network.php @@ -456,8 +456,8 @@ function networkFlatView(App $a, $update = 0) $items = q("SELECT %s FROM `item` $sql_post_table %s WHERE %s AND `item`.`uid` = %d ORDER BY `item`.`id` DESC $pager_sql ", - item_fieldlists(), item_joins($_SESSION['uid']), item_condition(), - intval($_SESSION['uid']) + item_fieldlists(), item_joins(local_user()), item_condition(), + intval(local_user()) ); $condition = ['unseen' => true, 'uid' => local_user()]; @@ -610,7 +610,7 @@ function networkThreadedView(App $a, $update, $parent) $sql_tag_nets = (($nets) ? sprintf(" AND `item`.`network` = '%s' ", dbesc($nets)) : ''); if ($gid) { - $group = dba::selectFirst('group', ['name'], ['id' => $gid, 'uid' => $_SESSION['uid']]); + $group = dba::selectFirst('group', ['name'], ['id' => $gid, 'uid' => local_user()]); if (!DBM::is_result($group)) { if ($update) { killme(); @@ -626,7 +626,7 @@ function networkThreadedView(App $a, $update, $parent) $contact_str_self = ''; $contact_str = implode(',', $contacts); - $self = dba::selectFirst('contact', ['id'], ['uid' => $_SESSION['uid'], 'self' => true]); + $self = dba::selectFirst('contact', ['id'], ['uid' => local_user(), 'self' => true]); if (DBM::is_result($self)) { $contact_str_self = $self['id']; } From c86111d19353cab8874553aba48dd9af389121c2 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 29 May 2018 19:00:26 +0000 Subject: [PATCH 10/10] Coding standards --- src/Protocol/DFRN.php | 4 ++-- src/Protocol/Diaspora.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index bf943f1a15..ac147a7626 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -2811,9 +2811,9 @@ class DFRN return; } - logger('deleting item '.$item["id"].' uri='.$uri, LOGGER_DEBUG); + logger('deleting item '.$item['id'].' uri='.$uri, LOGGER_DEBUG); - Item::delete(['id' => $item["id"]]); + Item::delete(['id' => $item['id']]); } /** diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index f3aa672a21..2bb8461340 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -2793,7 +2793,7 @@ class Diaspora continue; } - Item::delete(['id' => $item["id"]]); + Item::delete(['id' => $item['id']]); logger("Deleted target ".$target_guid." (".$item["id"].") from user ".$item["uid"]." parent: ".$item["parent"], LOGGER_DEBUG); }