From e609de295742fa1de70279206d6bea91900350ba Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 6 Feb 2018 12:40:22 +0000 Subject: [PATCH 1/3] Many item calls are now isolated in a single function --- include/api.php | 10 +-- include/event.php | 15 +--- include/items.php | 4 +- include/text.php | 20 +---- mod/admin.php | 2 +- mod/contacts.php | 3 - mod/events.php | 2 +- mod/item.php | 2 +- mod/network.php | 3 +- mod/photos.php | 54 ++------------ mod/poke.php | 5 -- mod/profile.php | 3 +- mod/starred.php | 8 +- mod/subthread.php | 7 +- mod/tagger.php | 24 +----- mod/tagrm.php | 20 ++--- mod/videos.php | 20 +---- src/Model/Item.php | 149 +++++++++++++++++++++++--------------- src/Model/Term.php | 29 -------- src/Protocol/DFRN.php | 137 ++++++----------------------------- src/Protocol/Diaspora.php | 18 +---- src/Protocol/OStatus.php | 11 +-- src/Worker/OnePoll.php | 2 +- 23 files changed, 161 insertions(+), 387 deletions(-) diff --git a/include/api.php b/include/api.php index e50bc92a8..1e8ba13d4 100644 --- a/include/api.php +++ b/include/api.php @@ -2218,7 +2218,7 @@ function api_statuses_destroy($type) $ret = api_statuses_show($type); - Item::delete($id); + Item::deleteById($id); return $ret; } @@ -2459,9 +2459,7 @@ function api_favorites_create_destroy($type) throw new BadRequestException("Invalid action ".$action); } - $r = q("UPDATE item SET starred=%d WHERE id=%d AND uid=%d", $item[0]['starred'], $itemid, api_user()); - - q("UPDATE thread SET starred=%d WHERE iid=%d AND uid=%d", $item[0]['starred'], $itemid, api_user()); + Item::update(['starred' => $item[0]['starred']], ['id' => $itemid]); if ($r === false) { throw new InternalServerErrorException("DB error"); @@ -3991,7 +3989,7 @@ function api_fr_photoalbum_delete($type) if (!DBM::is_result($photo_item)) { throw new InternalServerErrorException("problem with deleting items occured"); } - Item::delete($photo_item[0]['id']); + Item::deleteById($photo_item[0]['id']); } // now let's delete all photos from the album @@ -4294,7 +4292,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::delete($photo_item[0]['id']); + Item::deleteById($photo_item[0]['id']); $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/event.php b/include/event.php index 30ba1cfde..cce2a98cc 100644 --- a/include/event.php +++ b/include/event.php @@ -318,13 +318,8 @@ function event_store($arr) { $object .= '' . xmlify(format_event_bbcode($arr)) . ''; $object .= '' . "\n"; - q("UPDATE `item` SET `body` = '%s', `object` = '%s', `edited` = '%s' WHERE `id` = %d AND `uid` = %d", - dbesc(format_event_bbcode($arr)), - dbesc($object), - dbesc($arr['edited']), - intval($r[0]['id']), - intval($arr['uid']) - ); + $fields = ['body' => format_event_bbcode($arr), 'object' => $object, 'edited' => $arr['edited']]; + Item::update($fields, ['id' => $r[0]['id']]); $item_id = $r[0]['id']; } else { @@ -402,11 +397,7 @@ function event_store($arr) { $item_id = Item::insert($item_arr); if ($item_id) { - q("UPDATE `item` SET `event-id` = %d WHERE `uid` = %d AND `id` = %d", - intval($event['id']), - intval($arr['uid']), - intval($item_id) - ); + Item::update(['event-id' => $event['id']], ['id' => $item_id]); } Addon::callHooks("event_created", $event['id']); diff --git a/include/items.php b/include/items.php index 6d7391257..c3da8f0cc 100644 --- a/include/items.php +++ b/include/items.php @@ -322,7 +322,7 @@ function drop_items($items) { if (count($items)) { foreach ($items as $item) { - $owner = Item::delete($item); + $owner = Item::deleteById($item); if ($owner && !$uid) $uid = $owner; } @@ -394,7 +394,7 @@ function drop_item($id) { } // delete the item - Item::delete($item['id']); + Item::deleteById($item['id']); goaway(System::baseUrl() . '/' . $_SESSION['return_url']); //NOTREACHED diff --git a/include/text.php b/include/text.php index 05575887a..bc53f2d7b 100644 --- a/include/text.php +++ b/include/text.php @@ -1897,15 +1897,8 @@ function file_tag_save_file($uid, $item, $file) intval($uid) ); if (DBM::is_result($r)) { - if (! stristr($r[0]['file'],'[' . file_tag_encode($file) . ']')) { - q("UPDATE `item` SET `file` = '%s' WHERE `id` = %d AND `uid` = %d", - dbesc($r[0]['file'] . '[' . file_tag_encode($file) . ']'), - intval($item), - intval($uid) - ); - } - - Term::insertFromFileFieldByItemId($item); + $fields = ['file' => $r[0]['file'] . '[' . file_tag_encode($file) . ']']; + Item::update($fields, ['id' => $item]); $saved = PConfig::get($uid, 'system', 'filetags'); if (!strlen($saved) || !stristr($saved, '[' . file_tag_encode($file) . ']')) { @@ -1938,13 +1931,8 @@ function file_tag_unsave_file($uid, $item, $file, $cat = false) return false; } - q("UPDATE `item` SET `file` = '%s' WHERE `id` = %d AND `uid` = %d", - dbesc(str_replace($pattern,'',$r[0]['file'])), - intval($item), - intval($uid) - ); - - Term::insertFromFileFieldByItemId($item); + $fields = ['file' => str_replace($pattern,'',$r[0]['file'])]; + Item::update($fields, ['id' => $item]); $r = q("SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d", dbesc($file), diff --git a/mod/admin.php b/mod/admin.php index 5625bb98d..468c72da7 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -505,7 +505,7 @@ function admin_page_deleteitem_post(App $a) // associated threads. $r = dba::select('item', ['id'], ['guid' => $guid]); while ($row = dba::fetch($r)) { - Item::delete($row['id']); + Item::deleteById($row['id']); } dba::close($r); } diff --git a/mod/contacts.php b/mod/contacts.php index c37c4f3d5..3f7eb342b 100644 --- a/mod/contacts.php +++ b/mod/contacts.php @@ -348,9 +348,6 @@ function _contact_archive($contact_id, $orig_record) intval($contact_id), intval(local_user()) ); - if ($archived) { - q("UPDATE `item` SET `private` = 2 WHERE `contact-id` = %d AND `uid` = %d", intval($contact_id), intval(local_user())); - } return DBM::is_result($r); } diff --git a/mod/events.php b/mod/events.php index 0b8938631..5f6fb2c68 100644 --- a/mod/events.php +++ b/mod/events.php @@ -550,7 +550,7 @@ function events_content(App $a) { // Delete only real events (no birthdays) if (DBM::is_result($ev) && $ev[0]['type'] == 'event') { - $del = Item::delete($ev[0]['itemid']); + $del = Item::deleteById($ev[0]['itemid']); } if ($del == 0) { diff --git a/mod/item.php b/mod/item.php index 57f83ea5e..548996416 100644 --- a/mod/item.php +++ b/mod/item.php @@ -876,7 +876,7 @@ function item_content(App $a) { $o = ''; if (($a->argc == 3) && ($a->argv[1] === 'drop') && intval($a->argv[2])) { if (is_ajax()) { - $o = Item::delete($a->argv[2]); + $o = Item::deleteById($a->argv[2]); } else { $o = drop_item($a->argv[2]); } diff --git a/mod/network.php b/mod/network.php index c2f05fd8e..1121b14da 100644 --- a/mod/network.php +++ b/mod/network.php @@ -17,6 +17,7 @@ use Friendica\Core\System; use Friendica\Database\DBM; use Friendica\Model\Contact; use Friendica\Model\Group; +use Friendica\Model\Item; use Friendica\Model\Profile; use Friendica\Module\Login; use Friendica\Util\DateTimeFormat; @@ -326,7 +327,7 @@ function networkSetSeen($condition) $unseen = dba::exists('item', $condition); if ($unseen) { - $r = dba::update('item', ['unseen' => false], $condition); + $r = Item::update(['unseen' => false], $condition); } } diff --git a/mod/photos.php b/mod/photos.php index 7260bae9e..9515d1795 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -285,25 +285,12 @@ function photos_post(App $a) ); // find and delete the corresponding item with all the comments and likes/dislikes - $r = q("SELECT `id`, `parent-uri`, `visible` FROM `item` WHERE `resource-id` IN ( $str_res ) AND `uid` = %d", + $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) { - q("UPDATE `item` SET `deleted` = 1, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d", - dbesc(DateTimeFormat::utcNow()), - dbesc($rr['parent-uri']), - intval($page_owner_uid) - ); - Term::insertFromTagFieldByItemUri($rr['parent-uri'], $page_owner_uid); - Item::deleteThreadByUri($rr['parent-uri'], $page_owner_uid); - - $drop_id = intval($rr['id']); - - // send the notification upstream/downstream as the case may be - if ($rr['visible']) { - Worker::add(PRIORITY_HIGH, "Notifier", "drop", $drop_id); - } + Item::deleteById($rr['id']); } } @@ -358,29 +345,15 @@ function photos_post(App $a) intval($page_owner_uid), dbesc($r[0]['resource-id']) ); - $i = q("SELECT `id`, `uri`, `visible` FROM `item` WHERE `resource-id` = '%s' AND `uid` = %d LIMIT 1", + $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)) { - q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d", - dbesc(DateTimeFormat::utcNow()), - dbesc(DateTimeFormat::utcNow()), - dbesc($i[0]['uri']), - intval($page_owner_uid) - ); - Term::insertFromTagFieldByItemUri($i[0]['uri'], $page_owner_uid); - Item::deleteThreadByUri($i[0]['uri'], $page_owner_uid); - - $url = System::baseUrl(); - $drop_id = intval($i[0]['id']); + Item::deleteById($i[0]['id']); // Update the photo albums cache Photo::clearAlbumCache($page_owner_uid); - - if ($i[0]['visible']) { - Worker::add(PRIORITY_HIGH, "Notifier", "drop", $drop_id); - } } } @@ -646,16 +619,9 @@ function photos_post(App $a) } $newinform .= $inform; - $r = q("UPDATE `item` SET `tag` = '%s', `inform` = '%s', `edited` = '%s', `changed` = '%s' WHERE `id` = %d AND `uid` = %d", - dbesc($newtag), - dbesc($newinform), - dbesc(DateTimeFormat::utcNow()), - dbesc(DateTimeFormat::utcNow()), - intval($item_id), - intval($page_owner_uid) - ); - Term::insertFromTagFieldByItemId($item_id); - Item::updateThread($item_id); + $fields = ['tag' => $newtag, 'inform' => $newinform, 'edited' => DateTimeFormat::utcNow(), 'changed' => DateTimeFormat::utcNow()]; + $condition = ['id' => $item_id]; + Item::update($fields, $condition); $best = 0; foreach ($p as $scales) { @@ -1427,11 +1393,7 @@ function photos_content(App $a) ); if (local_user() && (local_user() == $link_item['uid'])) { - q("UPDATE `item` SET `unseen` = 0 WHERE `parent` = %d and `uid` = %d", - intval($link_item['parent']), - intval(local_user()) - ); - Item::updateThread($link_item['parent']); + Item::update(['unseen' => false], ['parent' => $link_item['parent']]); } if ($link_item['coord']) { diff --git a/mod/poke.php b/mod/poke.php index f5df4d5f8..1e6c53e17 100644 --- a/mod/poke.php +++ b/mod/poke.php @@ -135,11 +135,6 @@ function poke_init(App $a) { $item_id = Item::insert($arr); if($item_id) { - //q("UPDATE `item` SET `plink` = '%s' WHERE `uid` = %d AND `id` = %d", - // dbesc(System::baseUrl() . '/display/' . $poster['nickname'] . '/' . $item_id), - // intval($uid), - // intval($item_id) - //); Worker::add(PRIORITY_HIGH, "Notifier", "tag", $item_id); } diff --git a/mod/profile.php b/mod/profile.php index 6602c4057..a7c39ab33 100644 --- a/mod/profile.php +++ b/mod/profile.php @@ -13,6 +13,7 @@ use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Database\DBM; use Friendica\Model\Group; +use Friendica\Model\Item; use Friendica\Model\Profile; use Friendica\Module\Login; use Friendica\Protocol\DFRN; @@ -359,7 +360,7 @@ function profile_content(App $a, $update = 0) if ($is_owner) { $unseen = dba::exists('item', ['wall' => true, 'unseen' => true, 'uid' => local_user()]); if ($unseen) { - $r = dba::update('item', ['unseen' => false], + $r = Item::update(['unseen' => false], ['wall' => true, 'unseen' => true, 'uid' => local_user()]); } } diff --git a/mod/starred.php b/mod/starred.php index 5338b6c1d..5e00cd9cc 100644 --- a/mod/starred.php +++ b/mod/starred.php @@ -32,13 +32,7 @@ function starred_init(App $a) { $starred = 1; } - $r = q("UPDATE `item` SET `starred` = %d WHERE `uid` = %d AND `id` = %d", - intval($starred), - intval(local_user()), - intval($message_id) - ); - - Item::updateThread($message_id); + Item::update(['starred' => $starred], ['id' => $message_id]); // See if we've been passed a return path to redirect to $return_path = ((x($_REQUEST,'return')) ? $_REQUEST['return'] : ''); diff --git a/mod/subthread.php b/mod/subthread.php index dc8dcc1a9..562e189be 100644 --- a/mod/subthread.php +++ b/mod/subthread.php @@ -152,11 +152,8 @@ EOT; $post_id = Item::insert($arr); - if (! $item['visible']) { - $r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d AND `uid` = %d", - intval($item['id']), - intval($owner_uid) - ); + if (!$item['visible']) { + Item::update(['visible' => true], ['id' => $item['id']]); } $arr['id'] = $post_id; diff --git a/mod/tagger.php b/mod/tagger.php index 050e532f3..6016d443b 100644 --- a/mod/tagger.php +++ b/mod/tagger.php @@ -148,24 +148,16 @@ EOT; $post_id = Item::insert($arr); - if(! $item['visible']) { - $r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d AND `uid` = %d", - intval($item['id']), - intval($owner_uid) - ); + if (!$item['visible']) { + Item::update(['visible' => true], ['id' => $item['id']]); } - $term_objtype = (($item['resource-id']) ? TERM_OBJ_PHOTO : TERM_OBJ_POST ); + $term_objtype = ($item['resource-id'] ? TERM_OBJ_PHOTO : TERM_OBJ_POST); $t = q("SELECT count(tid) as tcount FROM term WHERE oid=%d AND term='%s'", intval($item['id']), dbesc($term) ); if((! $blocktags) && $t[0]['tcount']==0 ) { - /*q("update item set tag = '%s' where id = %d", - dbesc($item['tag'] . (strlen($item['tag']) ? ',' : '') . '#[url=' . System::baseUrl() . '/search?tag=' . $term . ']'. $term . '[/url]'), - intval($item['id']) - );*/ - q("INSERT INTO term (oid, otype, type, term, url, uid) VALUE (%d, %d, %d, '%s', '%s', %d)", intval($item['id']), $term_objtype, @@ -199,14 +191,6 @@ EOT; intval($owner_uid) ); } - - /*if(count($x) && !$x[0]['blocktags'] && (! stristr($r[0]['tag'], ']' . $term . '['))) { - q("update item set tag = '%s' where id = %d", - dbesc($r[0]['tag'] . (strlen($r[0]['tag']) ? ',' : '') . '#[url=' . System::baseUrl() . '/search?tag=' . $term . ']'. $term . '[/url]'), - intval($r[0]['id']) - ); - }*/ - } @@ -219,6 +203,4 @@ EOT; killme(); return; // NOTREACHED - - } diff --git a/mod/tagrm.php b/mod/tagrm.php index fbbf3a7bb..2a829932e 100644 --- a/mod/tagrm.php +++ b/mod/tagrm.php @@ -6,12 +6,13 @@ use Friendica\App; use Friendica\Core\L10n; use Friendica\Core\System; use Friendica\Database\DBM; +use Friendica\Model\Item; require_once 'include/bbcode.php'; function tagrm_post(App $a) { - if (! local_user()) { + if (!local_user()) { goaway(System::baseUrl() . '/' . $_SESSION['photo_return']); } @@ -27,7 +28,7 @@ function tagrm_post(App $a) { intval(local_user()) ); - if (! DBM::is_result($r)) { + if (!DBM::is_result($r)) { goaway(System::baseUrl() . '/' . $_SESSION['photo_return']); } @@ -41,17 +42,12 @@ function tagrm_post(App $a) { $tag_str = implode(',',$arr); - q("UPDATE `item` SET `tag` = '%s' WHERE `id` = %d AND `uid` = %d", - dbesc($tag_str), - intval($item), - intval(local_user()) - ); + Item::update(['tag' => $tag_str], ['id' => $item]); info(L10n::t('Tag removed') . EOL ); goaway(System::baseUrl() . '/' . $_SESSION['photo_return']); // NOTREACHED - } @@ -60,13 +56,13 @@ function tagrm_content(App $a) { $o = ''; - if (! local_user()) { + if (!local_user()) { goaway(System::baseUrl() . '/' . $_SESSION['photo_return']); // NOTREACHED } $item = (($a->argc > 1) ? intval($a->argv[1]) : 0); - if (! $item) { + if (!$item) { goaway(System::baseUrl() . '/' . $_SESSION['photo_return']); // NOTREACHED } @@ -76,13 +72,13 @@ function tagrm_content(App $a) { intval(local_user()) ); - if (! DBM::is_result($r)) { + if (!DBM::is_result($r)) { goaway(System::baseUrl() . '/' . $_SESSION['photo_return']); } $arr = explode(',', $r[0]['tag']); - if (! count($arr)) { + if (!count($arr)) { goaway(System::baseUrl() . '/' . $_SESSION['photo_return']); } diff --git a/mod/videos.php b/mod/videos.php index 26a4e4cce..65dda1b49 100644 --- a/mod/videos.php +++ b/mod/videos.php @@ -165,27 +165,13 @@ function videos_post(App $a) { intval(local_user()), dbesc($video_id) ); - $i = q("SELECT * FROM `item` WHERE `attach` like '%%attach/%s%%' AND `uid` = %d LIMIT 1", + $i = q("SELECT `id` FROM `item` WHERE `attach` like '%%attach/%s%%' AND `uid` = %d LIMIT 1", dbesc($video_id), intval(local_user()) ); - //echo "
"; var_dump($i); killme();
+
 			if (DBM::is_result($i)) {
-				q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d",
-					dbesc(DateTimeFormat::utcNow()),
-					dbesc(DateTimeFormat::utcNow()),
-					dbesc($i[0]['uri']),
-					intval(local_user())
-				);
-				Term::insertFromTagFieldByItemUri($i[0]['uri'], local_user());
-				Item::deleteThreadByUri($i[0]['uri'], local_user());
-
-				$url = System::baseUrl();
-				$drop_id = intval($i[0]['id']);
-
-				if ($i[0]['visible']) {
-					Worker::add(PRIORITY_HIGH, "Notifier", "drop", $drop_id);
-				}
+				Item::deleteById($i[0]['id']);
 			}
 		}
 
diff --git a/src/Model/Item.php b/src/Model/Item.php
index 01edf8d95..88efb6aa6 100644
--- a/src/Model/Item.php
+++ b/src/Model/Item.php
@@ -29,6 +29,7 @@ use Text_LanguageDetect;
 require_once 'boot.php';
 require_once 'include/items.php';
 require_once 'include/text.php';
+require_once 'include/event.php';
 
 class Item extends BaseObject
 {
@@ -78,17 +79,35 @@ class Item extends BaseObject
 		return $rows;
 	}
 
+	/**
+	 * @brief Delete an item and notify others about it - if it was ours
+	 *
+	 * @param array $condition The condition for finding the item entries
+	 * @param integer $priority Priority for the notification
+	 */
+	public static function delete($condition, $priority = PRIORITY_HIGH)
+	{
+		$items = dba::select('item', ['id'], $condition);
+		while ($item = dba::fetch($items)) {
+			self::deleteById($item['id'], $priority);
+		}
+		dba::close($items);
+	}
+
 	/**
 	 * @brief Delete an item and notify others about it - if it was ours
 	 *
 	 * @param integer $item_id Item ID that should be delete
+	 * @param integer $priority Priority for the notification
 	 *
 	 * @return $boolean success
 	 */
-	public static function delete($item_id, $priority = PRIORITY_HIGH)
+	public static function deleteById($item_id, $priority = PRIORITY_HIGH)
 	{
 		// locate item to be deleted
-		$fields = ['id', 'uid', 'parent', 'parent-uri', 'origin', 'deleted', 'file', 'resource-id', 'event-id', 'attach'];
+		$fields = ['id', 'uid', 'parent', 'parent-uri', 'origin', 'deleted',
+			'file', 'resource-id', 'event-id', 'attach',
+			'verb', 'object-type', 'object', 'target', 'contact-id'];
 		$item = dba::selectFirst('item', $fields, ['id' => $item_id]);
 		if (!DBM::is_result($item)) {
 			return false;
@@ -134,9 +153,9 @@ class Item extends BaseObject
 			dba::delete('photo', ['resource-id' => $item['resource-id'], 'uid' => $item['uid']]);
 		}
 
-		// If item is a link to an event, nuke the event record.
+		// If item is a link to an event, delete the event.
 		if (intval($item['event-id'])) {
-			dba::delete('event', ['id' => $item['event-id'], 'uid' => $item['uid']]);
+			event_delete($item['event-id']);
 		}
 
 		// If item has attachments, drop them
@@ -145,6 +164,9 @@ class Item extends BaseObject
 			dba::delete('attach', ['id' => $matches[1], 'uid' => $item['uid']]);
 		}
 
+		// Delete tags that had been attached to other items
+		self::deleteTagsFromItem($item);
+
 		// Set the item to "deleted"
 		dba::update('item', ['deleted' => true, 'title' => '', 'body' => '',
 					'edited' => DateTimeFormat::utcNow(), 'changed' => DateTimeFormat::utcNow()],
@@ -156,10 +178,7 @@ class Item extends BaseObject
 
 		// If it's the parent of a comment thread, kill all the kids
 		if ($item['id'] == $item['parent']) {
-			$items = dba::select('item', ['id'], ['parent' => $item['parent']]);
-			while ($row = dba::fetch($items)) {
-				self::delete($row['id'], $priority);
-			}
+			self::delete(['parent' => $item['parent']]);
 		}
 
 		// send the notification upstream/downstream
@@ -170,6 +189,44 @@ class Item extends BaseObject
 		return true;
 	}
 
+	private static function deleteTagsFromItem($item)
+	{
+		if (($item["verb"] != ACTIVITY_TAG) || ($item["object-type"] != ACTIVITY_OBJ_TAGTERM)) {
+			return;
+		}
+
+		$xo = XML::parseString($item["object"], false);
+		$xt = XML::parseString($item["target"], false);
+
+		if ($xt->type != ACTIVITY_OBJ_NOTE) {
+			return;
+		}
+
+		$i = dba::selectFirst('item', ['id', 'contact-id', 'tag'], ['uri' => $xt->id, 'uid' => $item['uid']]);
+		if (!DBM::is_result($i)) {
+			return;
+		}
+
+		// For tags, the owner cannot remove the tag on the author's copy of the post.
+		$owner_remove = ($item["contact-id"] == $i["contact-id"]);
+		$author_copy = $item["origin"];
+
+		if (($owner_remove && $author_copy) || !$owner_remove) {
+			return;
+		}
+
+		$tags = explode(',', $i["tag"]);
+		$newtags = [];
+		if (count($tags)) {
+			foreach ($tags as $tag) {
+				if (trim($tag) !== trim($xo->body)) {
+				       $newtags[] = trim($tag);
+				}
+			}
+		}
+		self::update(['tag' => implode(',', $newtags)], ['id' => $i["id"]]);
+	}
+
 	public static function insert($arr, $force_parent = false, $notify = false, $dontcache = false)
 	{
 		$a = get_app();
@@ -1626,7 +1683,7 @@ class Item extends BaseObject
 				continue;
 			}
 
-			self::delete($item['id'], PRIORITY_LOW);
+			self::deleteByID($item['id'], PRIORITY_LOW);
 		}
 	}
 
@@ -1851,13 +1908,11 @@ EOT;
 			'unseen'        => 1,
 		];
 
-		$new_item_id = Item::insert($new_item);
+		$new_item_id = self::insert($new_item);
 
-		// @todo: Explain this block
-		if (! $item['visible']) {
-			q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d",
-				intval($item['id'])
-			);
+		// If the parent item isn't visible then set it to visible
+		if (!$item['visible']) {
+			self::update(['visible' => true], ['id' => $item['id']]);
 		}
 
 		// Save the author information for the like in case we need to relay to Diaspora
@@ -1878,69 +1933,58 @@ EOT;
 				`moderated`, `visible`, `spam`, `starred`, `bookmark`, `contact-id`, `gcontact-id`,
 				`deleted`, `origin`, `forum_mode`, `mention`, `network`, `author-id`, `owner-id`
 			FROM `item` WHERE `id` = %d AND (`parent` = %d OR `parent` = 0) LIMIT 1", intval($itemid), intval($itemid));
-	
+
 		if (!$items) {
 			return;
 		}
-	
+
 		$item = $items[0];
 		$item['iid'] = $itemid;
-	
+
 		if (!$onlyshadow) {
 			$result = dba::insert('thread', $item);
-	
+
 			logger("Add thread for item ".$itemid." - ".print_r($result, true), LOGGER_DEBUG);
 		}
 	}
 
-	public static function updateThreadByUri($itemuri, $uid)
-	{
-		$messages = dba::select('item', ['id'], ['uri' => $itemuri, 'uid' => $uid]);
-	
-		if (DBM::is_result($messages)) {
-			foreach ($messages as $message) {
-				self::updateThread($message["id"]);
-			}
-		}
-	}
-
-	public static function updateThread($itemid, $setmention = false)
+	private static function updateThread($itemid, $setmention = false)
 	{
 		$items = q("SELECT `uid`, `guid`, `title`, `body`, `created`, `edited`, `commented`, `received`, `changed`, `wall`, `private`, `pubmail`, `moderated`, `visible`, `spam`, `starred`, `bookmark`, `contact-id`, `gcontact-id`,
 				`deleted`, `origin`, `forum_mode`, `network`, `rendered-html`, `rendered-hash` FROM `item` WHERE `id` = %d AND (`parent` = %d OR `parent` = 0) LIMIT 1", intval($itemid), intval($itemid));
-	
+
 		if (!DBM::is_result($items)) {
 			return;
 		}
-	
+
 		$item = $items[0];
-	
+
 		if ($setmention) {
 			$item["mention"] = 1;
 		}
-	
+
 		$sql = "";
-	
+
 		foreach ($item as $field => $data)
 			if (!in_array($field, ["guid", "title", "body", "rendered-html", "rendered-hash"])) {
 				if ($sql != "") {
 					$sql .= ", ";
 				}
-	
+
 				$sql .= "`".$field."` = '".dbesc($data)."'";
 			}
-	
+
 		$result = q("UPDATE `thread` SET ".$sql." WHERE `iid` = %d", intval($itemid));
-	
+
 		logger("Update thread for item ".$itemid." - guid ".$item["guid"]." - ".print_r($result, true)." ".print_r($item, true), LOGGER_DEBUG);
-	
+
 		// Updating a shadow item entry
 		$items = dba::selectFirst('item', ['id'], ['guid' => $item['guid'], 'uid' => 0]);
-	
+
 		if (!DBM::is_result($items)) {
 			return;
 		}
-	
+
 		$result = dba::update(
 			'item',
 			['title' => $item['title'], 'body' => $item['body'], 'rendered-html' => $item['rendered-html'], 'rendered-hash' => $item['rendered-hash']],
@@ -1949,31 +1993,20 @@ EOT;
 
 		logger("Updating public shadow for post ".$items["id"]." - guid ".$item["guid"]." Result: ".print_r($result, true), LOGGER_DEBUG);
 	}
-	
-	public static function deleteThreadByUri($itemuri, $uid)
-	{
-		$messages = dba::select('item', ['id'], ['uri' => $itemuri, 'uid' => $uid]);
-	
-		if (DBM::is_result($messages)) {
-			foreach ($messages as $message) {
-				self::deleteThread($message["id"], $itemuri);
-			}
-		}
-	}
-	
-	public static function deleteThread($itemid, $itemuri = "")
+
+	private static function deleteThread($itemid, $itemuri = "")
 	{
 		$item = dba::selectFirst('thread', ['uid'], ['iid' => $itemid]);
 		if (!DBM::is_result($item)) {
 			logger('No thread found for id '.$itemid, LOGGER_DEBUG);
 			return;
 		}
-	
+
 		// Using dba::delete at this time could delete the associated item entries
 		$result = dba::e("DELETE FROM `thread` WHERE `iid` = ?", $itemid);
-	
+
 		logger("deleteThread: Deleted thread for item ".$itemid." - ".print_r($result, true), LOGGER_DEBUG);
-	
+
 		if ($itemuri != "") {
 			$r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND NOT `deleted` AND NOT (`uid` IN (%d, 0))",
 					dbesc($itemuri),
diff --git a/src/Model/Term.php b/src/Model/Term.php
index c730bf744..d950d1d5f 100644
--- a/src/Model/Term.php
+++ b/src/Model/Term.php
@@ -122,19 +122,6 @@ class Term
 		}
 	}
 
-	public static function insertFromTagFieldByItemUri($itemuri, $uid)
-	{
-		$messages = dba::select('item', ['id'], ['uri' => $itemuri, 'uid' => $uid]);
-
-		if (DBM::is_result($messages)) {
-			while ($message = dba::fetch($messages)) {
-				self::insertFromTagFieldByItemId($message['id']);
-			}
-			dba::close($messages);
-		}
-	}
-
-
 	/**
 	 * @param integer $itemid item id
 	 * @return void
@@ -181,20 +168,4 @@ class Term
 			}
 		}
 	}
-
-	/**
-	 * @param string  $itemuri item uri
-	 * @param integer $uid     uid
-	 * @return void
-	 */
-	public static function insertFromFileFieldByItemUri($itemuri, $uid)
-	{
-		$messages = q("SELECT `id` FROM `item` WHERE uri ='%s' AND uid=%d", dbesc($itemuri), intval($uid));
-
-		if (count($messages)) {
-			foreach ($messages as $message) {
-				self::insertFromFileFieldByItemId($message["id"]);
-			}
-		}
-	}
 }
diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php
index 2b3b9b0dc..6ec83151f 100644
--- a/src/Protocol/DFRN.php
+++ b/src/Protocol/DFRN.php
@@ -2088,10 +2088,7 @@ class DFRN
 					'edited' => DateTimeFormat::utc($item["edited"])];
 
 			$condition = ["`uri` = ? AND `uid` IN (0, ?)", $item["uri"], $importer["importer_uid"]];
-			dba::update('item', $fields, $condition);
-
-			Term::insertFromTagFieldByItemUri($item["uri"], $importer["importer_uid"]);
-			Item::updateThreadByUri($item["uri"], $importer["importer_uid"]);
+			Item::update($fields, $condition);
 
 			$changed = true;
 
@@ -2328,13 +2325,9 @@ class DFRN
 
 					// extract tag, if not duplicate, add to parent item
 					if ($xo->content) {
-						if (!(stristr($r[0]["tag"], trim($xo->content)))) {
-							q(
-								"UPDATE `item` SET `tag` = '%s' WHERE `id` = %d",
-								dbesc($r[0]["tag"] . (strlen($r[0]["tag"]) ? ',' : '') . '#[url=' . $xo->id . ']'. $xo->content . '[/url]'),
-								intval($r[0]["id"])
-							);
-							Term::insertFromTagFieldByItemId($r[0]["id"]);
+						if (!stristr($r[0]["tag"], trim($xo->content))) {
+							$tag = $r[0]["tag"] . (strlen($r[0]["tag"]) ? ',' : '') . '#[url=' . $xo->id . ']'. $xo->content . '[/url]';
+							Item::update(['tag' => $tag], ['id' => $r[0]["id"]]);
 						}
 					}
 				}
@@ -2746,121 +2739,35 @@ class DFRN
 			if ($attributes->name == "ref") {
 				$uri = $attributes->textContent;
 			}
-			if ($attributes->name == "when") {
-				$when = $attributes->textContent;
-			}
-		}
-		if ($when) {
-			$when = DateTimeFormat::utc($when);
-		} else {
-			$when = DateTimeFormat::utcNow();
 		}
 
 		if (!$uri || !$importer["id"]) {
 			return false;
 		}
 
-		/// @todo Only select the used fields
-		$r = q(
-			"SELECT `item`.*, `contact`.`self` FROM `item` INNER JOIN `contact` on `item`.`contact-id` = `contact`.`id`
-			WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d AND NOT `item`.`file` LIKE '%%[%%' LIMIT 1",
-			dbesc($uri),
-			intval($importer["uid"]),
-			intval($importer["id"])
-		);
-		if (!DBM::is_result($r)) {
+		$condition = ["`uri` = ? AND `uid` = ? AND `contact-id` = ? AND NOT `file` LIKE '%[%'",
+				$uri, $importer["uid"], $importer["id"]];
+		$item = dba::selectFirst('item', ['id'], $condition);
+		if (!DBM::is_result($item)) {
 			logger("Item with uri " . $uri . " from contact " . $importer["id"] . " for user " . $importer["uid"] . " wasn't found.", LOGGER_DEBUG);
 			return;
+		}
+
+		$entrytype = self::getEntryType($importer, $item);
+
+		if (!$item["deleted"]) {
+			logger('deleting item '.$item["id"].' uri='.$uri, LOGGER_DEBUG);
 		} else {
-			$item = $r[0];
+			return;
+		}
 
-			$entrytype = self::getEntryType($importer, $item);
+		Item::deleteById($item["id"]);
 
-			if (!$item["deleted"]) {
-				logger('deleting item '.$item["id"].' uri='.$uri, LOGGER_DEBUG);
-			} else {
-				return;
-			}
-
-			if ($item["object-type"] == ACTIVITY_OBJ_EVENT) {
-				logger("Deleting event ".$item["event-id"], LOGGER_DEBUG);
-				event_delete($item["event-id"]);
-			}
-
-			if (($item["verb"] == ACTIVITY_TAG) && ($item["object-type"] == ACTIVITY_OBJ_TAGTERM)) {
-				$xo = XML::parseString($item["object"], false);
-				$xt = XML::parseString($item["target"], false);
-
-				if ($xt->type == ACTIVITY_OBJ_NOTE) {
-					$i = q(
-						"SELECT `id`, `contact-id`, `tag` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-						dbesc($xt->id),
-						intval($importer["importer_uid"])
-					);
-					if (DBM::is_result($i)) {
-						// For tags, the owner cannot remove the tag on the author's copy of the post.
-
-						$owner_remove = (($item["contact-id"] == $i[0]["contact-id"]) ? true: false);
-						$author_remove = (($item["origin"] && $item["self"]) ? true : false);
-						$author_copy = (($item["origin"]) ? true : false);
-
-						if ($owner_remove && $author_copy) {
-							return;
-						}
-						if ($author_remove || $owner_remove) {
-							$tags = explode(',', $i[0]["tag"]);
-							$newtags = [];
-							if (count($tags)) {
-								foreach ($tags as $tag) {
-									if (trim($tag) !== trim($xo->body)) {
-										$newtags[] = trim($tag);
-									}
-								}
-							}
-							q(
-								"UPDATE `item` SET `tag` = '%s' WHERE `id` = %d",
-								dbesc(implode(',', $newtags)),
-								intval($i[0]["id"])
-							);
-							Term::insertFromTagFieldByItemId($i[0]["id"]);
-						}
-					}
-				}
-			}
-
-			if ($entrytype == DFRN_TOP_LEVEL) {
-				$r = q(
-					"UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',
-						`body` = '', `title` = ''
-					WHERE `parent-uri` = '%s' AND `uid` IN (0, %d)",
-					dbesc($when),
-					dbesc(DateTimeFormat::utcNow()),
-					dbesc($uri),
-					intval($importer["uid"])
-				);
-				Term::insertFromTagFieldByItemUri($uri, $importer["uid"]);
-				Term::insertFromFileFieldByItemUri($uri, $importer["uid"]);
-				Item::updateThreadByUri($uri, $importer["uid"]);
-			} else {
-				$r = q(
-					"UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',
-						`body` = '', `title` = ''
-					WHERE `uri` = '%s' AND `uid` IN (0, %d)",
-					dbesc($when),
-					dbesc(DateTimeFormat::utcNow()),
-					dbesc($uri),
-					intval($importer["uid"])
-				);
-				Term::insertFromTagFieldByItemUri($uri, $importer["uid"]);
-				Term::insertFromFileFieldByItemUri($uri, $importer["uid"]);
-				Item::updateThreadByUri($uri, $importer["importer_uid"]);
-
-				// if this is a relayed delete, propagate it to other recipients
-
-				if ($entrytype == DFRN_REPLY_RC) {
-					logger("Notifying followers about deletion of post " . $item["id"], LOGGER_DEBUG);
-					Worker::add(PRIORITY_HIGH, "Notifier", "drop", $item["id"]);
-				}
+		if ($entrytype != DFRN_TOP_LEVEL) {
+			// if this is a relayed delete, propagate it to other recipients
+			if ($entrytype == DFRN_REPLY_RC) {
+				logger("Notifying followers about deletion of post " . $item["id"], LOGGER_DEBUG);
+				Worker::add(PRIORITY_HIGH, "Notifier", "drop", $item["id"]);
 			}
 		}
 	}
diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php
index 2b5905c95..0f5c9c0c9 100644
--- a/src/Protocol/Diaspora.php
+++ b/src/Protocol/Diaspora.php
@@ -2842,23 +2842,7 @@ class Diaspora
 				continue;
 			}
 
-			// Currently we don't have a central deletion function that we could use in this case.
-			// The function "item_drop" doesn't work for that case
-			dba::update(
-				'item',
-				[
-					'deleted' => true,
-					'title' => '',
-					'body' => '',
-					'edited' => DateTimeFormat::utcNow(),
-					'changed' => DateTimeFormat::utcNow()],
-				['id' => $item["id"]]
-			);
-
-			// Delete the thread - if it is a starting post and not a comment
-			if ($target_type != 'Comment') {
-				Item::deleteThread($item["id"], $item["parent-uri"]);
-			}
+			Item::deleteById($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 8688b5a7f..1ff13c55d 100644
--- a/src/Protocol/OStatus.php
+++ b/src/Protocol/OStatus.php
@@ -552,16 +552,7 @@ class OStatus
 			return;
 		}
 
-		// Currently we don't have a central deletion function that we could use in this case
-		// The function "item_drop" doesn't work for that case
-		dba::update(
-			'item',
-			['deleted' => true, 'title' => '', 'body' => '',
-					'edited' => DateTimeFormat::utcNow(), 'changed' => DateTimeFormat::utcNow()],
-			['id' => $deleted["id"]]
-		);
-
-		Item::deleteThread($deleted["id"], $deleted["parent-uri"]);
+		Item::deleteById($deleted["id"]);
 
 		logger('Deleted item with uri '.$item['uri'].' for user '.$item['uid']);
 	}
diff --git a/src/Worker/OnePoll.php b/src/Worker/OnePoll.php
index 42c2774fa..377bda85f 100644
--- a/src/Worker/OnePoll.php
+++ b/src/Worker/OnePoll.php
@@ -395,7 +395,7 @@ class OnePoll
 								if (($mailconf['action'] != 1) && ($mailconf['action'] != 3))
 									if ($meta->deleted && ! $item['deleted']) {
 										$fields = ['deleted' => true, 'changed' => DateTimeFormat::utcNow()];
-										dba::update('item', $fields, ['id' => $item['id']]);
+										Item::update($fields, ['id' => $item['id']]);
 									}
 
 								switch ($mailconf['action']) {

From 7be59dbeabd8d14e613b3d3631320d58eb0e79fa Mon Sep 17 00:00:00 2001
From: Michael 
Date: Tue, 6 Feb 2018 16:32:00 +0000
Subject: [PATCH 2/3] Priority and capitalisation

---
 src/Model/Item.php | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/Model/Item.php b/src/Model/Item.php
index 88efb6aa6..cc42aafc6 100644
--- a/src/Model/Item.php
+++ b/src/Model/Item.php
@@ -178,7 +178,7 @@ class Item extends BaseObject
 
 		// If it's the parent of a comment thread, kill all the kids
 		if ($item['id'] == $item['parent']) {
-			self::delete(['parent' => $item['parent']]);
+			self::delete(['parent' => $item['parent']], $priority);
 		}
 
 		// send the notification upstream/downstream
@@ -1683,7 +1683,7 @@ class Item extends BaseObject
 				continue;
 			}
 
-			self::deleteByID($item['id'], PRIORITY_LOW);
+			self::deleteById($item['id'], PRIORITY_LOW);
 		}
 	}
 

From 1ec6359faacc64e1c994abeb37c2af8cbcfb571f Mon Sep 17 00:00:00 2001
From: Michael 
Date: Tue, 6 Feb 2018 16:44:48 +0000
Subject: [PATCH 3/3] Duplicate check

---
 include/text.php | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/include/text.php b/include/text.php
index bc53f2d7b..d40a1feef 100644
--- a/include/text.php
+++ b/include/text.php
@@ -1897,9 +1897,10 @@ function file_tag_save_file($uid, $item, $file)
 		intval($uid)
 	);
 	if (DBM::is_result($r)) {
-		$fields = ['file' => $r[0]['file'] . '[' . file_tag_encode($file) . ']'];
-		Item::update($fields, ['id' => $item]);
-
+		if (!stristr($r[0]['file'],'[' . file_tag_encode($file) . ']')) {
+			$fields = ['file' => $r[0]['file'] . '[' . file_tag_encode($file) . ']'];
+			Item::update($fields, ['id' => $item]);
+		}
 		$saved = PConfig::get($uid, 'system', 'filetags');
 		if (!strlen($saved) || !stristr($saved, '[' . file_tag_encode($file) . ']')) {
 			PConfig::set($uid, 'system', 'filetags', $saved . '[' . file_tag_encode($file) . ']');