From 8c2f91573aff1850b7f2856aa2f8c2f469560100 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 27 Jun 2018 18:09:13 +0000 Subject: [PATCH 1/9] Fix mail import --- src/Worker/OnePoll.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Worker/OnePoll.php b/src/Worker/OnePoll.php index 43526a372b..f3784d3ffa 100644 --- a/src/Worker/OnePoll.php +++ b/src/Worker/OnePoll.php @@ -389,7 +389,7 @@ class OnePoll // Have we seen it before? $fields = ['deleted', 'id']; $condition = ['uid' => $importer_uid, 'uri' => $datarray['uri']]; - $item = dba::selectFirst('item', $fields, $condition); + $item = Item::selectFirst($fields, $condition); if (DBM::is_result($item)) { logger("Mail: Seen before ".$msg_uid." for ".$mailconf['user']." UID: ".$importer_uid." URI: ".$datarray['uri'],LOGGER_DEBUG); @@ -435,13 +435,17 @@ class OnePoll $refs_arr = explode(' ', $raw_refs); if (count($refs_arr)) { for ($x = 0; $x < count($refs_arr); $x ++) { - $refs_arr[$x] = "'" . Email::msgid2iri(str_replace(['<', '>', ' '],['', '', ''],dbesc($refs_arr[$x]))) . "'"; +// $refs_arr[$x] = "'" . Email::msgid2iri(str_replace(['<', '>', ' '],['', '', ''],dbesc($refs_arr[$x]))) . "'"; + $refs_arr[$x] = Email::msgid2iri(str_replace(['<', '>', ' '],['', '', ''], $refs_arr[$x])); } } $condition = ['uri' => $refs_arr, 'uid' => $importer_uid]; $parent = Item::selectFirst(['parent-uri'], $condition); if (DBM::is_result($parent)) { + logger('Parent found with matching uri. ' . json_encode($refs_arr), LOGGER_DEBUG); $datarray['parent-uri'] = $parent['parent-uri']; // Set the parent as the top-level item + } else { + logger('No parent found with matching uri. ' . json_encode($refs_arr), LOGGER_DEBUG); } } @@ -474,7 +478,10 @@ class OnePoll $params = ['order' => ['created' => true]]; $parent = Item::selectFirst(['parent-uri'], $condition, $params); if (DBM::is_result($parent)) { + logger('Parent found with matching title. ' . $datarray['title'], LOGGER_DEBUG); $datarray['parent-uri'] = $parent['parent-uri']; + } else { + logger('No parent found with matching title. ' . $datarray['title'], LOGGER_DEBUG); } } From 76dab3b2d7b8fb2609d54ab55c8b3114d8da661f Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 27 Jun 2018 18:09:33 +0000 Subject: [PATCH 2/9] Use gravity instead of verb --- boot.php | 3 ++- include/api.php | 55 ++++++++++++++++++++------------------- include/enotify.php | 4 +-- mod/item.php | 2 +- mod/network.php | 2 +- mod/photos.php | 1 + mod/profile.php | 13 ++++----- mod/subthread.php | 2 +- mod/tagger.php | 2 +- src/Model/Contact.php | 4 +-- src/Model/Item.php | 21 ++++++++------- src/Protocol/DFRN.php | 2 +- src/Protocol/Diaspora.php | 2 +- src/Protocol/OStatus.php | 2 +- 14 files changed, 59 insertions(+), 56 deletions(-) diff --git a/boot.php b/boot.php index ac21d108a3..64abdddca3 100644 --- a/boot.php +++ b/boot.php @@ -451,8 +451,9 @@ define('ACTIVITY_OBJ_QUESTION', 'http://activityschema.org/object/question'); * @{ */ define('GRAVITY_PARENT', 0); -define('GRAVITY_LIKE', 3); +define('GRAVITY_ACTIVITY', 3); define('GRAVITY_COMMENT', 6); +define('GRAVITY_UNKNOWN', 9); /* @}*/ /** diff --git a/include/api.php b/include/api.php index 819d2c75a0..2eaabd8242 100644 --- a/include/api.php +++ b/include/api.php @@ -1270,8 +1270,8 @@ function api_status_show($type) } // get last public wall message - $condition = ["`owner-id` = ? AND `uid` = ? AND `type` != 'activity' ".$privacy_sql, - $user_info['pid'], api_user()]; + $condition = ['owner-id' => $user_info['pid'], 'uid' => api_user(), + 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT]]; $lastwall = dba::selectFirst('item', [], $condition, ['order' => ['id' => true]]); if (DBM::is_result($lastwall)) { @@ -1355,8 +1355,8 @@ function api_users_show($type) $user_info = api_get_user($a); - $condition = ["`owner-id` = ? AND `uid` = ? AND `verb` = ? AND `type` != 'activity' AND NOT `private`", - $user_info['pid'], api_user(), ACTIVITY_POST]; + $condition = ['owner-id' => $user_info['pid'], 'uid' => api_user(), + 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT], 'private' => false]; $lastwall = dba::selectFirst('item', [], $condition, ['order' => ['id' => true]]); if (DBM::is_result($lastwall)) { @@ -1534,10 +1534,10 @@ function api_search($type) $start = $page * $count; - $condition = ["`verb` = ? AND `item`.`id` > ? + $condition = ["`gravity` IN (?, ?) AND `item`.`id` > ? AND (`item`.`uid` = 0 OR (`item`.`uid` = ? AND NOT `item`.`global`)) AND `item`.`body` LIKE CONCAT('%',?,'%')", - ACTIVITY_POST, $since_id, api_user(), $_REQUEST['q']]; + GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, api_user(), $_REQUEST['q']]; if ($max_id > 0) { $condition[0] .= " AND `item`.`id` <= ?"; @@ -1597,7 +1597,8 @@ function api_statuses_home_timeline($type) $start = $page * $count; - $condition = ["`uid` = ? AND `verb` = ? AND `item`.`id` > ?", api_user(), ACTIVITY_POST, $since_id]; + $condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `item`.`id` > ?", + api_user(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id]; if ($max_id > 0) { $condition[0] .= " AND `item`.`id` <= ?"; @@ -1680,8 +1681,8 @@ function api_statuses_public_timeline($type) $sql_extra = ''; if ($exclude_replies && !$conversation_id) { - $condition = ["`verb` = ? AND `iid` > ? AND NOT `private` AND `wall` AND NOT `user`.`hidewall`", - ACTIVITY_POST, $since_id]; + $condition = ["`gravity` IN (?, ?) AND `iid` > ? AND NOT `private` AND `wall` AND NOT `user`.`hidewall`", + GRAVITY_PARENT, GRAVITY_COMMENT, $since_id]; if ($max_id > 0) { $condition[0] .= " AND `thread`.`iid` <= ?"; @@ -1693,8 +1694,8 @@ function api_statuses_public_timeline($type) $r = Item::inArray($statuses); } else { - $condition = ["`verb` = ? AND `id` > ? AND NOT `private` AND `wall` AND NOT `user`.`hidewall` AND `item`.`origin`", - ACTIVITY_POST, $since_id]; + $condition = ["`gravity` IN (?, ?) AND `id` > ? AND NOT `private` AND `wall` AND NOT `user`.`hidewall` AND `item`.`origin`", + GRAVITY_PARENT, GRAVITY_COMMENT, $since_id]; if ($max_id > 0) { $condition[0] .= " AND `item`.`id` <= ?"; @@ -1756,8 +1757,8 @@ function api_statuses_networkpublic_timeline($type) } $start = ($page - 1) * $count; - $condition = ["`uid` = 0 AND `verb` = ? AND `thread`.`iid` > ? AND NOT `private`", - ACTIVITY_POST, $since_id]; + $condition = ["`uid` = 0 AND `gravity` IN (?, ?) AND `thread`.`iid` > ? AND NOT `private`", + GRAVITY_PARENT, GRAVITY_COMMENT, $since_id]; if ($max_id > 0) { $condition[0] .= " AND `thread`.`iid` <= ?"; @@ -1829,10 +1830,10 @@ function api_statuses_show($type) $id = $item['id']; if ($conversation) { - $condition = ['parent' => $id, 'verb' => ACTIVITY_POST]; + $condition = ['parent' => $id, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT]]; $params = ['order' => ['id' => true]]; } else { - $condition = ['id' => $id, 'verb' => ACTIVITY_POST]; + $condition = ['id' => $id, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT]]; $params = []; } @@ -1908,8 +1909,8 @@ function api_conversation_show($type) $id = $parent['id']; - $condition = ["`parent` = ? AND `uid` IN (0, ?) AND `verb` = ? AND `item`.`id` > ?", - $id, api_user(), ACTIVITY_POST, $since_id]; + $condition = ["`parent` = ? AND `uid` IN (0, ?) AND `gravity` IN (?, ?) AND `item`.`id` > ?", + $id, api_user(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id]; if ($max_id > 0) { $condition[0] .= " AND `item`.`id` <= ?"; @@ -2077,9 +2078,9 @@ function api_statuses_mentions($type) $start = ($page - 1) * $count; - $condition = ["`uid` = ? AND `verb` = ? AND `item`.`id` > ? AND `author-id` != ? + $condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `item`.`id` > ? AND `author-id` != ? AND `item`.`parent` IN (SELECT `iid` FROM `thread` WHERE `thread`.`uid` = ? AND `thread`.`mention` AND NOT `thread`.`ignored`)", - api_user(), ACTIVITY_POST, $since_id, $user_info['pid'], api_user()]; + api_user(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, $user_info['pid'], api_user()]; if ($max_id > 0) { $condition[0] .= " AND `item`.`id` <= ?"; @@ -2145,8 +2146,8 @@ function api_statuses_user_timeline($type) } $start = ($page - 1) * $count; - $condition = ["`uid` = ? AND `verb` = ? AND `item`.`id` > ? AND `item`.`contact-id` = ?", - api_user(), ACTIVITY_POST, $since_id, $user_info['cid']]; + $condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `item`.`id` > ? AND `item`.`contact-id` = ?", + api_user(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, $user_info['cid']]; if ($user_info['self'] == 1) { $condition[0] .= ' AND `item`.`wall` '; @@ -2299,8 +2300,8 @@ function api_favorites($type) $start = $page*$count; - $condition = ["`uid` = ? AND `verb` = ? AND `id` > ? AND `starred`", - api_user(), ACTIVITY_POST, $since_id]; + $condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `id` > ? AND `starred`", + api_user(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id]; $params = ['order' => ['id' => true], 'limit' => [$start, $count]]; @@ -3099,8 +3100,8 @@ function api_lists_statuses($type) $start = $page * $count; - $condition = ["`uid` = ? AND `verb` = ? AND `id` > ? AND `group_member`.`gid` = ?", - api_user(), ACTIVITY_POST, $since_id, $_REQUEST['list_id']]; + $condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `id` > ? AND `group_member`.`gid` = ?", + api_user(), GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, $_REQUEST['list_id']]; if ($max_id > 0) { $condition[0] .= " AND `item`.`id` <= ?"; @@ -4630,8 +4631,8 @@ function prepare_photo_data($type, $scale, $photo_id) $data['photo']['friendica_activities'] = api_format_items_activities($item, $type); // retrieve comments on photo - $condition = ["`parent` = ? AND `uid` = ? AND (`verb` = ? OR `type`='photo')", - $item[0]['parent'], api_user(), ACTIVITY_POST]; + $condition = ["`parent` = ? AND `uid` = ? AND (`gravity` IN (?, ?) OR `type`='photo')", + $item[0]['parent'], api_user(), GRAVITY_PARENT, GRAVITY_COMMENT]; $statuses = Item::selectForUser(api_user(), [], $condition); diff --git a/include/enotify.php b/include/enotify.php index 00459ac5c0..be9468dd8f 100644 --- a/include/enotify.php +++ b/include/enotify.php @@ -740,9 +740,9 @@ function check_item_notification($itemid, $uid, $defaulttype = "") { // We need the additional check for the "local_profile" because of mixed situations on connector networks $item = q("SELECT `id`, `mention`, `tag`,`parent`, `title`, `body`, `author-id`, `guid`, `parent-uri`, `uri`, `contact-id`, `network` - FROM `item` WHERE `id` = %d AND `verb` IN ('%s', '') AND `type` != 'activity' AND + FROM `item` WHERE `id` = %d AND `gravity` IN (%d, %d) AND NOT (`author-id` IN ($contact_list)) LIMIT 1", - intval($itemid), dbesc(ACTIVITY_POST)); + intval($itemid), intval(GRAVITY_PARENT), intval(GRAVITY_COMMENT)); if (!$item) return false; diff --git a/mod/item.php b/mod/item.php index 2830cae2c9..0a3c3e2fa4 100644 --- a/mod/item.php +++ b/mod/item.php @@ -567,7 +567,7 @@ function item_post(App $a) { $network = NETWORK_DFRN; } - $gravity = ($parent ? 6 : 0); + $gravity = ($parent ? GRAVITY_COMMENT : GRAVITY_PARENT); // even if the post arrived via API we are considering that it // originated on this site by default for determining relayability. diff --git a/mod/network.php b/mod/network.php index 61e4e779ed..442ae669ba 100644 --- a/mod/network.php +++ b/mod/network.php @@ -756,7 +756,7 @@ function networkThreadedView(App $a, $update, $parent) // Load all unseen items $sql_extra4 = "`item`.`unseen`"; if (Config::get("system", "like_no_comment")) { - $sql_extra4 .= " AND `item`.`verb` = '".ACTIVITY_POST."'"; + $sql_extra4 .= " AND `item`.`gravity` IN (" . GRAVITY_PARENT . "," . GRAVITY_COMMENT . ")"; } if ($order === 'post') { // Only show toplevel posts when updating posts in this order mode diff --git a/mod/photos.php b/mod/photos.php index f54bc62444..c0e1c7477a 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -640,6 +640,7 @@ function photos_post(App $a) $arr['deny_gid'] = $p[0]['deny_gid']; $arr['visible'] = 1; $arr['verb'] = ACTIVITY_TAG; + $arr["gravity"] = GRAVITY_PARENT; $arr['object-type'] = ACTIVITY_OBJ_PERSON; $arr['target-type'] = ACTIVITY_OBJ_IMAGE; $arr['tag'] = $tagged[4]; diff --git a/mod/profile.php b/mod/profile.php index a6075b01cf..8d156cbd64 100644 --- a/mod/profile.php +++ b/mod/profile.php @@ -243,17 +243,14 @@ function profile_content(App $a, $update = 0) $r = q("SELECT distinct(parent) AS `item_id`, `item`.`network` AS `item_network`, `item`.`created` FROM `item` INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id` - AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0 - WHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND - (`item`.`deleted` = 0 OR item.verb = '" . ACTIVITY_LIKE . "' - OR item.verb = '" . ACTIVITY_DISLIKE . "' OR item.verb = '" . ACTIVITY_ATTEND . "' - OR item.verb = '" . ACTIVITY_ATTENDNO . "' OR item.verb = '" . ACTIVITY_ATTENDMAYBE . "') - AND `item`.`moderated` = 0 - AND `item`.`wall` = 1 + AND NOT `contact`.`blocked` AND NOT `contact`.`pending` + WHERE `item`.`uid` = %d AND `item`.`visible` AND + (NOT `item`.`deleted` OR `item`.`gravity` = %d) + AND NOT `item`.`moderated` AND `item`.`wall` $sql_extra4 $sql_extra ORDER BY `item`.`created` DESC", - intval($a->profile['profile_uid']) + intval($a->profile['profile_uid']), intval(GRAVITY_ACTIVITY) ); if (!DBM::is_result($r)) { diff --git a/mod/subthread.php b/mod/subthread.php index 0b6f4ecaaa..e05aa5fec8 100644 --- a/mod/subthread.php +++ b/mod/subthread.php @@ -125,7 +125,7 @@ EOT; $arr['type'] = 'activity'; $arr['wall'] = $item['wall']; $arr['origin'] = 1; - $arr['gravity'] = GRAVITY_LIKE; + $arr['gravity'] = GRAVITY_ACTIVITY; $arr['parent'] = $item['id']; $arr['parent-uri'] = $item['uri']; $arr['thr-parent'] = $item['uri']; diff --git a/mod/tagger.php b/mod/tagger.php index 717c094776..a5e9b3715b 100644 --- a/mod/tagger.php +++ b/mod/tagger.php @@ -121,7 +121,7 @@ EOT; $arr['contact-id'] = $contact['id']; $arr['type'] = 'activity'; $arr['wall'] = $item['wall']; - $arr['gravity'] = GRAVITY_COMMENT; + $arr['gravity'] = GRAVITY_ACTIVITY; $arr['parent'] = $item['id']; $arr['parent-uri'] = $item['uri']; $arr['owner-name'] = $item['author-name']; diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 973e5b5a21..fe9869c6f8 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -1064,8 +1064,8 @@ class Contact extends BaseObject $contact = ($r[0]["contact-type"] == ACCOUNT_TYPE_COMMUNITY ? 'owner-id' : 'author-id'); - $condition = ["`$contact` = ? AND `verb` = ? AND " . $sql, - $author_id, ACTIVITY_POST, local_user()]; + $condition = ["`$contact` = ? AND `gravity` IN (?, ?) AND " . $sql, + $author_id, GRAVITY_PARENT, GRAVITY_COMMENT, local_user()]; $params = ['order' => ['created' => true], 'limit' => [$a->pager['start'], $a->pager['itemspage']]]; $r = Item::selectForUser(local_user(), [], $condition, $params); diff --git a/src/Model/Item.php b/src/Model/Item.php index 6fe4a575dd..fe6dc5d1d4 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -953,18 +953,21 @@ class Item extends BaseObject $item['parent-uri'] = $item['thr-parent']; } - if (x($item, 'gravity')) { + $item['type'] = defaults($item, 'type', 'remote'); + + if (isset($item['gravity'])) { $item['gravity'] = intval($item['gravity']); } elseif ($item['parent-uri'] === $item['uri']) { - $item['gravity'] = 0; - } elseif (activity_match($item['verb'],ACTIVITY_POST)) { - $item['gravity'] = 6; + $item['gravity'] = GRAVITY_PARENT; + } elseif (activity_match($item['verb'], ACTIVITY_POST)) { + $item['gravity'] = GRAVITY_COMMENT; + } elseif ($item['type'] == 'activity') { + $item['gravity'] = GRAVITY_ACTIVITY; } else { - $item['gravity'] = 6; // extensible catchall + $item['gravity'] = GRAVITY_UNKNOWN; // Should not happen + logger('Unknown gravity for verb: ' . $item['verb'] . ' - type: ' . $item['type'], LOGGER_DEBUG); } - $item['type'] = defaults($item, 'type', 'remote'); - $uid = intval($item['uid']); // check for create date and expire time @@ -1219,7 +1222,7 @@ class Item extends BaseObject logger('$force_parent=true, reply converted to top-level post.'); $parent_id = 0; $item['parent-uri'] = $item['uri']; - $item['gravity'] = 0; + $item['gravity'] = GRAVITY_PARENT; } else { logger('item parent '.$item['parent-uri'].' for '.$item['uid'].' was not found - ignoring item'); return 0; @@ -2644,7 +2647,7 @@ EOT; 'type' => 'activity', 'wall' => $item['wall'], 'origin' => 1, - 'gravity' => GRAVITY_LIKE, + 'gravity' => GRAVITY_ACTIVITY, 'parent' => $item['id'], 'parent-uri' => $item['uri'], 'thr-parent' => $item['uri'], diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 1047ffdfe2..0b8cb73827 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -2310,7 +2310,7 @@ class DFRN ) { $is_like = true; $item["type"] = "activity"; - $item["gravity"] = GRAVITY_LIKE; + $item["gravity"] = GRAVITY_ACTIVITY; // only one like or dislike per person // splitted into two queries for performance issues $condition = ['uid' => $item["uid"], 'author-id' => $item["author-id"], diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index 29fb42a808..6ef529b7fe 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -2049,7 +2049,7 @@ class Diaspora $datarray["type"] = "activity"; $datarray["verb"] = $verb; - $datarray["gravity"] = GRAVITY_LIKE; + $datarray["gravity"] = GRAVITY_ACTIVITY; $datarray["parent-uri"] = $parent_item["uri"]; $datarray["object-type"] = ACTIVITY_OBJ_NOTE; diff --git a/src/Protocol/OStatus.php b/src/Protocol/OStatus.php index 2c826221e7..9aef0840c0 100644 --- a/src/Protocol/OStatus.php +++ b/src/Protocol/OStatus.php @@ -451,7 +451,7 @@ class OStatus $item["verb"] = ACTIVITY_LIKE; $item["parent-uri"] = $orig_uri; - $item["gravity"] = GRAVITY_LIKE; + $item["gravity"] = GRAVITY_ACTIVITY; } // http://activitystrea.ms/schema/1.0/rsvp-yes From 028c9f4da5190f6d9290117fb6503d5934e1034a Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 27 Jun 2018 19:37:13 +0000 Subject: [PATCH 3/9] We now store the verb in the item-content as well --- boot.php | 2 +- include/api.php | 2 +- src/Database/DBStructure.php | 1 + src/Model/Item.php | 90 ++++++++++++++++++++++-------------- src/Protocol/DFRN.php | 10 ++-- src/Protocol/OStatus.php | 12 ++--- 6 files changed, 70 insertions(+), 47 deletions(-) diff --git a/boot.php b/boot.php index 64abdddca3..864e7804c9 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.08-dev'); define('DFRN_PROTOCOL_VERSION', '2.23'); -define('DB_UPDATE_VERSION', 1271); +define('DB_UPDATE_VERSION', 1272); define('NEW_UPDATE_ROUTINE_VERSION', 1170); /** diff --git a/include/api.php b/include/api.php index 2eaabd8242..32fe6c651d 100644 --- a/include/api.php +++ b/include/api.php @@ -1626,7 +1626,7 @@ function api_statuses_home_timeline($type) } if (!empty($idarray)) { - $unseen = dba::exists('item', ['unseen' => true, 'id' => $idarray]); + $unseen = Item::exists(['unseen' => true, 'id' => $idarray]); if ($unseen) { Item::update(['unseen' => false], ['unseen' => true, 'id' => $idarray]); } diff --git a/src/Database/DBStructure.php b/src/Database/DBStructure.php index eaf54cee23..8fb2afddb2 100644 --- a/src/Database/DBStructure.php +++ b/src/Database/DBStructure.php @@ -1270,6 +1270,7 @@ class DBStructure "target-type" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => "ActivityStreams target type if applicable (URI)"], "target" => ["type" => "text", "comment" => "JSON encoded target structure if used"], "plink" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "permalink or URL to a displayable copy of the message at its source"], + "verb" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => "ActivityStreams verb"], ], "indexes" => [ "PRIMARY" => ["id"], diff --git a/src/Model/Item.php b/src/Model/Item.php index fe6dc5d1d4..2dac079b6f 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -58,7 +58,7 @@ class Item extends BaseObject // Field list for "item-content" table that is mixed with the item table const CONTENT_FIELDLIST = ['title', 'content-warning', 'body', 'location', - 'coord', 'app', 'rendered-hash', 'rendered-html', + 'coord', 'app', 'rendered-hash', 'rendered-html', 'verb', 'object-type', 'object', 'target-type', 'target']; // All fields in the item table @@ -143,6 +143,27 @@ class Item extends BaseObject return $data; } + /** + * @brief Check if item data exists + * + * @param array $condition array of fields for condition + * + * @return boolean Are there rows for that condition? + */ + public static function exists($condition) { + $stmt = self::select(['id'], $condition, ['limit' => 1]); + + if (is_bool($stmt)) { + $retval = $stmt; + } else { + $retval = (dba::num_rows($stmt) > 0); + } + + dba::close($stmt); + + return $retval; + } + /** * Retrieve a single record from the item table for a given user and returns it in an associative array * @@ -377,8 +398,8 @@ class Item extends BaseObject $fields['item'] = ['id', 'uid', 'parent', 'uri', 'parent-uri', 'thr-parent', 'guid', 'contact-id', 'owner-id', 'author-id', 'type', 'wall', 'gravity', 'extid', - 'created', 'edited', 'commented', 'received', 'changed', 'verb', - 'postopts', 'plink', 'resource-id', 'event-id', 'tag', 'attach', 'inform', + 'created', 'edited', 'commented', 'received', 'changed', 'postopts', + 'plink', 'resource-id', 'event-id', 'tag', 'attach', 'inform', 'file', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'private', 'pubmail', 'moderated', 'visible', 'starred', 'bookmark', 'unseen', 'deleted', 'origin', 'forum_mode', 'mention', 'global', @@ -728,15 +749,14 @@ class Item extends BaseObject self::deleteTagsFromItem($item); // Set the item to "deleted" - dba::update('item', ['deleted' => true, 'title' => '', 'body' => '', - 'edited' => DateTimeFormat::utcNow(), 'changed' => DateTimeFormat::utcNow()], + dba::update('item', ['deleted' => true, 'edited' => DateTimeFormat::utcNow(), 'changed' => DateTimeFormat::utcNow()], ['id' => $item['id']]); Term::insertFromTagFieldByItemId($item['id']); Term::insertFromFileFieldByItemId($item['id']); self::deleteThread($item['id'], $item['parent-uri']); - if (!dba::exists('item', ["`uri` = ? AND `uid` != 0 AND NOT `deleted`", $item['uri']])) { + if (!self::exists(["`uri` = ? AND `uid` != 0 AND NOT `deleted`", $item['uri']])) { self::delete(['uri' => $item['uri'], 'uid' => 0, 'deleted' => false], $priority); } @@ -1120,7 +1140,7 @@ class Item extends BaseObject // Checking if there is already an item with the same guid logger('Checking for an item for user '.$item['uid'].' on network '.$item['network'].' with the guid '.$item['guid'], LOGGER_DEBUG); $condition = ['guid' => $item['guid'], 'network' => $item['network'], 'uid' => $item['uid']]; - if (dba::exists('item', $condition)) { + if (self::exists($condition)) { logger('found item with guid '.$item['guid'].' for user '.$item['uid'].' on network '.$item['network'], LOGGER_DEBUG); return 0; } @@ -1234,7 +1254,7 @@ class Item extends BaseObject $condition = ["`uri` = ? AND `network` IN (?, ?) AND `uid` = ?", $item['uri'], $item['network'], NETWORK_DFRN, $item['uid']]; - if (dba::exists('item', $condition)) { + if (self::exists($condition)) { logger('duplicated item with the same uri found. '.print_r($item,true)); return 0; } @@ -1242,7 +1262,7 @@ class Item extends BaseObject // On Friendica and Diaspora the GUID is unique if (in_array($item['network'], [NETWORK_DFRN, NETWORK_DIASPORA])) { $condition = ['guid' => $item['guid'], 'uid' => $item['uid']]; - if (dba::exists('item', $condition)) { + if (self::exists($condition)) { logger('duplicated item with the same guid found. '.print_r($item,true)); return 0; } @@ -1250,7 +1270,7 @@ class Item extends BaseObject // Check for an existing post with the same content. There seems to be a problem with OStatus. $condition = ["`body` = ? AND `network` = ? AND `created` = ? AND `contact-id` = ? AND `uid` = ?", $item['body'], $item['network'], $item['created'], $item['contact-id'], $item['uid']]; - if (dba::exists('item', $condition)) { + if (self::exists($condition)) { logger('duplicated item with the same body found. '.print_r($item,true)); return 0; } @@ -1263,7 +1283,7 @@ class Item extends BaseObject // Set the global flag on all items if this was a global item entry dba::update('item', ['global' => true], ['uri' => $item["uri"]]); } else { - $item["global"] = dba::exists('item', ['uid' => 0, 'uri' => $item["uri"]]); + $item["global"] = self::exists(['uid' => 0, 'uri' => $item["uri"]]); } // ACL settings @@ -1304,7 +1324,7 @@ class Item extends BaseObject * An unique index would help - but the limitations of MySQL (maximum size of index values) prevent this. */ if ($item["uid"] == 0) { - if (dba::exists('item', ['uri' => trim($item['uri']), 'uid' => 0])) { + if (self::exists(['uri' => trim($item['uri']), 'uid' => 0])) { logger('Global item already stored. URI: '.$item['uri'].' on network '.$item['network'], LOGGER_DEBUG); return 0; } @@ -1671,7 +1691,7 @@ class Item extends BaseObject if (DBM::is_result($item) && ($item["allow_cid"] == '') && ($item["allow_gid"] == '') && ($item["deny_cid"] == '') && ($item["deny_gid"] == '')) { - if (!dba::exists('item', ['uri' => $item['uri'], 'uid' => 0])) { + if (!self::exists(['uri' => $item['uri'], 'uid' => 0])) { // Preparing public shadow (removing user specific data) $item['uid'] = 0; unset($item['id']); @@ -1725,12 +1745,12 @@ class Item extends BaseObject } // Is there a shadow parent? - if (!dba::exists('item', ['uri' => $item['parent-uri'], 'uid' => 0])) { + if (!self::exists(['uri' => $item['parent-uri'], 'uid' => 0])) { return; } // Is there already a shadow entry? - if (dba::exists('item', ['uri' => $item['uri'], 'uid' => 0])) { + if (self::exists(['uri' => $item['uri'], 'uid' => 0])) { return; } @@ -1760,7 +1780,7 @@ class Item extends BaseObject // If this was a comment to a Diaspora post we don't get our comment back. // This means that we have to distribute the comment by ourselves. - if ($origin && dba::exists('item', ['id' => $parent, 'network' => NETWORK_DIASPORA])) { + if ($origin && self::exists(['id' => $parent, 'network' => NETWORK_DIASPORA])) { self::distribute($public_shadow); } } @@ -2570,30 +2590,32 @@ class Item extends BaseObject // event participation are essentially radio toggles. If you make a subsequent choice, // we need to eradicate your first choice. if ($event_verb_flag) { - $verbs = "'" . dbesc(ACTIVITY_ATTEND) . "', '" . dbesc(ACTIVITY_ATTENDNO) . "', '" . dbesc(ACTIVITY_ATTENDMAYBE) . "'"; + $verbs = [ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE]; } else { - $verbs = "'".dbesc($activity)."'"; + $verbs = $activity; } - /// @todo This query is expected to be a performance eater due to the "OR" - it has to be changed totally - $existing_like = q("SELECT `id`, `guid`, `verb` FROM `item` - WHERE `verb` IN ($verbs) - AND `deleted` = 0 - AND `author-id` = %d - AND `uid` = %d - AND (`parent` = '%s' OR `parent-uri` = '%s' OR `thr-parent` = '%s') - LIMIT 1", - intval($author_contact['id']), - intval($item['uid']), - dbesc($item_id), dbesc($item_id), dbesc($item['uri']) - ); + $base_condition = ['verb' => $verbs, 'deleted' => false, 'gravity' => GRAVITY_ACTIVITY, + 'author-id' => $author_contact['id'], 'uid' => item['uid']]; + + $condition = array_merge($base_condition, ['parent' => $item_id]); + $like_item = self::selectFirst(['id', 'guid', 'verb'], $condition); + + if (!DBM::is_result($like_item)) { + $condition = array_merge($base_condition, ['parent-uri' => $item_id]); + $like_item = self::selectFirst(['id', 'guid', 'verb'], $condition); + } + + if (!DBM::is_result($like_item)) { + $condition = array_merge($base_condition, ['thr-parent' => $item_id]); + $like_item = self::selectFirst(['id', 'guid', 'verb'], $condition); + } // If it exists, mark it as deleted - if (DBM::is_result($existing_like)) { - $like_item = $existing_like[0]; - + if (DBM::is_result($like_item)) { // Already voted, undo it $fields = ['deleted' => true, 'unseen' => true, 'changed' => DateTimeFormat::utcNow()]; + /// @todo Consider using self::update - but before doing so, check the side effects dba::update('item', $fields, ['id' => $like_item['id']]); // Clean up the Diaspora signatures for this like @@ -2757,7 +2779,7 @@ EOT; if ($itemuri != "") { $condition = ["`uri` = ? AND NOT `deleted` AND NOT (`uid` IN (?, 0))", $itemuri, $item["uid"]]; - if (!dba::exists('item', $condition)) { + if (!self::exists($condition)) { dba::delete('item', ['uri' => $itemuri, 'uid' => 0]); logger("deleteThread: Deleted shadow for item ".$itemuri, LOGGER_DEBUG); } diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 0b8cb73827..c1e116f2f7 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -2313,15 +2313,15 @@ class DFRN $item["gravity"] = GRAVITY_ACTIVITY; // only one like or dislike per person // splitted into two queries for performance issues - $condition = ['uid' => $item["uid"], 'author-id' => $item["author-id"], + $condition = ['uid' => $item["uid"], 'author-id' => $item["author-id"], 'gravity' => GRAVITY_ACTIVITY, 'verb' => $item["verb"], 'parent-uri' => $item["parent-uri"]]; - if (dba::exists('item', $condition)) { + if (Item::exists($condition)) { return false; } - $condition = ['uid' => $item["uid"], 'author-id' => $item["author-id"], + $condition = ['uid' => $item["uid"], 'author-id' => $item["author-id"], 'gravity' => GRAVITY_ACTIVITY, 'verb' => $item["verb"], 'thr-parent' => $item["parent-uri"]]; - if (dba::exists('item', $condition)) { + if (Item::exists($condition)) { return false; } } else { @@ -2770,7 +2770,7 @@ class DFRN // Comments can be deleted by the thread owner or comment owner if (($item['id'] != $item['parent']) && ($item['contact-id'] != $importer["id"])) { $condition = ['id' => $item['parent'], 'contact-id' => $importer["id"]]; - if (!dba::exists('item', $condition)) { + if (!Item::exists($condition)) { logger("Item with uri " . $uri . " wasn't found or mustn't be deleted by contact " . $importer["id"] . " - ignoring deletion.", LOGGER_DEBUG); return; } diff --git a/src/Protocol/OStatus.php b/src/Protocol/OStatus.php index 9aef0840c0..4538d36dfa 100644 --- a/src/Protocol/OStatus.php +++ b/src/Protocol/OStatus.php @@ -416,7 +416,7 @@ class OStatus } // Deletions come with the same uri, so we check for duplicates after processing deletions - if (dba::exists('item', ['uid' => $importer["uid"], 'uri' => $item["uri"]])) { + if (Item::exists(['uid' => $importer["uid"], 'uri' => $item["uri"]])) { logger('Post with URI '.$item["uri"].' already existed for user '.$importer["uid"].'.', LOGGER_DEBUG); continue; } else { @@ -489,7 +489,7 @@ class OStatus } } else { // But we will only import complete threads - $valid = dba::exists('item', ['uid' => $importer["uid"], 'uri' => self::$itemlist[0]['parent-uri']]); + $valid = Item::exists(['uid' => $importer["uid"], 'uri' => self::$itemlist[0]['parent-uri']]); if ($valid) { logger("Item with uri ".self::$itemlist[0]["uri"]." belongs to parent ".self::$itemlist[0]['parent-uri']." of user ".$importer["uid"].". It will be imported.", LOGGER_DEBUG); } @@ -506,7 +506,7 @@ class OStatus } } foreach (self::$itemlist as $item) { - $found = dba::exists('item', ['uid' => $importer["uid"], 'uri' => $item["uri"]]); + $found = Item::exists(['uid' => $importer["uid"], 'uri' => $item["uri"]]); if ($found) { logger("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already exists.", LOGGER_DEBUG); } elseif ($item['contact-id'] < 0) { @@ -537,8 +537,8 @@ class OStatus */ private static function deleteNotice($item) { - $condition = ['uid' => $item['uid'], 'author-link' => $item['author-link'], 'uri' => $item['uri']]; - if (!dba::exists('item', $condition)) { + $condition = ['uid' => $item['uid'], 'author-id' => $item['author-id'], 'uri' => $item['uri']]; + if (!Item::exists($condition)) { logger('Item from '.$item['author-link'].' with uri '.$item['uri'].' for user '.$item['uid']." wasn't found. We don't delete it."); return; } @@ -674,7 +674,7 @@ class OStatus } if (isset($item["parent-uri"])) { - if (!dba::exists('item', ['uid' => $importer["uid"], 'uri' => $item['parent-uri']])) { + if (!Item::exists(['uid' => $importer["uid"], 'uri' => $item['parent-uri']])) { if ($related != '') { self::fetchRelated($related, $item["parent-uri"], $importer); } From 3918a31fc2a6677a420e8ba5cc09d22f22b40518 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 27 Jun 2018 20:08:02 +0000 Subject: [PATCH 4/9] Remove unneeded logging --- src/Worker/OnePoll.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Worker/OnePoll.php b/src/Worker/OnePoll.php index f3784d3ffa..423ce17414 100644 --- a/src/Worker/OnePoll.php +++ b/src/Worker/OnePoll.php @@ -442,10 +442,7 @@ class OnePoll $condition = ['uri' => $refs_arr, 'uid' => $importer_uid]; $parent = Item::selectFirst(['parent-uri'], $condition); if (DBM::is_result($parent)) { - logger('Parent found with matching uri. ' . json_encode($refs_arr), LOGGER_DEBUG); $datarray['parent-uri'] = $parent['parent-uri']; // Set the parent as the top-level item - } else { - logger('No parent found with matching uri. ' . json_encode($refs_arr), LOGGER_DEBUG); } } @@ -478,10 +475,7 @@ class OnePoll $params = ['order' => ['created' => true]]; $parent = Item::selectFirst(['parent-uri'], $condition, $params); if (DBM::is_result($parent)) { - logger('Parent found with matching title. ' . $datarray['title'], LOGGER_DEBUG); $datarray['parent-uri'] = $parent['parent-uri']; - } else { - logger('No parent found with matching title. ' . $datarray['title'], LOGGER_DEBUG); } } From b3abe148a6b918644a25c2ba17aaa7835d663d43 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 27 Jun 2018 20:11:09 +0000 Subject: [PATCH 5/9] Remove comment --- src/Worker/OnePoll.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Worker/OnePoll.php b/src/Worker/OnePoll.php index 423ce17414..eaef5f252d 100644 --- a/src/Worker/OnePoll.php +++ b/src/Worker/OnePoll.php @@ -435,7 +435,6 @@ class OnePoll $refs_arr = explode(' ', $raw_refs); if (count($refs_arr)) { for ($x = 0; $x < count($refs_arr); $x ++) { -// $refs_arr[$x] = "'" . Email::msgid2iri(str_replace(['<', '>', ' '],['', '', ''],dbesc($refs_arr[$x]))) . "'"; $refs_arr[$x] = Email::msgid2iri(str_replace(['<', '>', ' '],['', '', ''], $refs_arr[$x])); } } From 51a58ec2e2014cab48140a22ec2c42b233f1ec61 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 27 Jun 2018 20:25:24 +0000 Subject: [PATCH 6/9] Fix for fetching false fer... (sorry) verbs --- 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 2dac079b6f..9fafe26aa6 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -86,7 +86,7 @@ class Item extends BaseObject // Fetch data from the item-content table whenever there is content there foreach (self::CONTENT_FIELDLIST as $field) { - if (is_null($row[$field]) && !is_null($row['item-' . $field])) { + if (empty($row[$field]) && !empty($row['item-' . $field])) { $row[$field] = $row['item-' . $field]; } unset($row['item-' . $field]); @@ -403,7 +403,7 @@ class Item extends BaseObject 'file', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'private', 'pubmail', 'moderated', 'visible', 'starred', 'bookmark', 'unseen', 'deleted', 'origin', 'forum_mode', 'mention', 'global', - 'id' => 'item_id', 'network']; + 'id' => 'item_id', 'network', 'icid']; $fields['item-content'] = self::CONTENT_FIELDLIST; From b705a91ccdb574aeb99a2a4edb55fd549a14d3e8 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 28 Jun 2018 03:31:10 +0000 Subject: [PATCH 7/9] Standards and some more replace item calls --- mod/photos.php | 2 +- src/Model/Term.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mod/photos.php b/mod/photos.php index c0e1c7477a..34eea0c642 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -640,7 +640,7 @@ function photos_post(App $a) $arr['deny_gid'] = $p[0]['deny_gid']; $arr['visible'] = 1; $arr['verb'] = ACTIVITY_TAG; - $arr["gravity"] = GRAVITY_PARENT; + $arr['gravity'] = GRAVITY_PARENT; $arr['object-type'] = ACTIVITY_OBJ_PERSON; $arr['target-type'] = ACTIVITY_OBJ_IMAGE; $arr['tag'] = $tagged[4]; diff --git a/src/Model/Term.php b/src/Model/Term.php index b211e7d2eb..8587142092 100644 --- a/src/Model/Term.php +++ b/src/Model/Term.php @@ -24,7 +24,7 @@ class Term $profile_base_diaspora = $profile_data['host'] . $profile_path . '/u/'; $fields = ['guid', 'uid', 'id', 'edited', 'deleted', 'created', 'received', 'title', 'body', 'tag', 'parent']; - $message = dba::selectFirst('item', $fields, ['id' => $itemid]); + $message = Item::selectFirst($fields, ['id' => $itemid]); if (!DBM::is_result($message)) { return; } @@ -130,7 +130,7 @@ class Term */ public static function insertFromFileFieldByItemId($itemid) { - $message = dba::selectFirst('item', ['uid', 'deleted', 'file'], ['id' => $itemid]); + $message = Item::selectFirst(['uid', 'deleted', 'file'], ['id' => $itemid]); if (!DBM::is_result($message)) { return; } From bfe4842402287cbc9e987a61c4fcb91bb41be4bf Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 28 Jun 2018 03:51:57 +0000 Subject: [PATCH 8/9] Changed database structure --- database.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/database.sql b/database.sql index 9711ace803..1a08a5ba98 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2018.08-dev (The Tazmans Flax-lily) --- DB_UPDATE_VERSION 1271 +-- DB_UPDATE_VERSION 1272 -- ------------------------------------------ @@ -565,6 +565,7 @@ CREATE TABLE IF NOT EXISTS `item-content` ( `target-type` varchar(100) NOT NULL DEFAULT '' COMMENT 'ActivityStreams target type if applicable (URI)', `target` text COMMENT 'JSON encoded target structure if used', `plink` varchar(255) NOT NULL DEFAULT '' COMMENT 'permalink or URL to a displayable copy of the message at its source', + `verb` varchar(100) NOT NULL DEFAULT '' COMMENT 'ActivityStreams verb', PRIMARY KEY(`id`), UNIQUE INDEX `uri-plink-hash` (`uri-plink-hash`), INDEX `uri` (`uri`(191)) From dec1eaa2e868553b319b8c3b27b92b7956296058 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 28 Jun 2018 04:37:58 +0000 Subject: [PATCH 9/9] Tagging now is a comment --- mod/tagger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/tagger.php b/mod/tagger.php index a5e9b3715b..717c094776 100644 --- a/mod/tagger.php +++ b/mod/tagger.php @@ -121,7 +121,7 @@ EOT; $arr['contact-id'] = $contact['id']; $arr['type'] = 'activity'; $arr['wall'] = $item['wall']; - $arr['gravity'] = GRAVITY_ACTIVITY; + $arr['gravity'] = GRAVITY_COMMENT; $arr['parent'] = $item['id']; $arr['parent-uri'] = $item['uri']; $arr['owner-name'] = $item['author-name'];