X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FModel%2FItem.php;h=4018db9ff68a74acd4e27e6384aaf4c75ac884cc;hb=6e10de92847dd7ef1bf20f8eac05316fbe31e1e7;hp=01a0b7497cb6397f6762222c2e540d566c021066;hpb=d4e3f3f4bbc69d47dba7ca4296f0edbe55401d40;p=friendica.git diff --git a/src/Model/Item.php b/src/Model/Item.php index 01a0b7497c..4018db9ff6 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -33,6 +33,371 @@ require_once 'include/text.php'; class Item extends BaseObject { + // Field list that is used to display the items + const DISPLAY_FIELDLIST = ['uid', 'id', 'parent', 'uri', 'thr-parent', 'parent-uri', 'guid', + 'commented', 'created', 'edited', 'received', 'verb', 'object-type', 'postopts', 'plink', + 'wall', 'private', 'starred', 'origin', 'title', 'body', 'file', 'attach', + 'content-warning', 'location', 'coord', 'app', 'rendered-hash', 'rendered-html', 'object', + 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'item_id', 'item_network', + 'author-id', 'author-link', 'author-name', 'author-avatar', + 'owner-id', 'owner-link', 'owner-name', 'owner-avatar', + 'contact-id', 'contact-link', 'contact-name', 'contact-avatar', + 'network', 'url', 'name', 'writable', 'self', 'cid', 'alias', + 'event-id', 'event-created', 'event-edited', 'event-start', 'event-finish', + 'event-summary', 'event-desc', 'event-location', 'event-type', + 'event-nofinish', 'event-adjust', 'event-ignore', 'event-id']; + + // Field list that is used to deliver items via the protocols + const DELIVER_FIELDLIST = ['uid', 'id', 'parent', 'uri', 'thr-parent', 'parent-uri', 'guid', + 'created', 'edited', 'verb', 'object-type', 'object', 'target', + 'private', 'title', 'body', 'location', 'coord', 'app', + 'attach', 'tag', 'bookmark', 'deleted', 'extid', + 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', + 'author-id', 'author-link', 'owner-link', 'contact-uid', + 'signed_text', 'signature', 'signer']; + + /** + * Retrieve a single record from the item table for a given user and returns it in an associative array + * + * @brief Retrieve a single record from a table + * @param integer $uid User ID + * @param array $fields + * @param array $condition + * @param array $params + * @return bool|array + * @see dba::select + */ + public static function selectFirstForUser($uid, array $selected = [], array $condition = [], $params = []) + { + $params['uid'] = $uid; + + if (empty($selected)) { + $selected = Item::DISPLAY_FIELDLIST; + } + + return self::selectFirst($selected, $condition, $params); + } + + /** + * @brief Select rows from the item table for a given user + * + * @param integer $uid User ID + * @param array $selected Array of selected fields, empty for all + * @param array $condition Array of fields for condition + * @param array $params Array of several parameters + * + * @return boolean|object + */ + public static function selectForUser($uid, array $selected = [], array $condition = [], $params = []) + { + $params['uid'] = $uid; + + if (empty($selected)) { + $selected = Item::DISPLAY_FIELDLIST; + } + + return self::select($selected, $condition, $params); + } + + /** + * Retrieve a single record from the item table and returns it in an associative array + * + * @brief Retrieve a single record from a table + * @param array $fields + * @param array $condition + * @param array $params + * @return bool|array + * @see dba::select + */ + public static function selectFirst(array $fields = [], array $condition = [], $params = []) + { + $params['limit'] = 1; + + $result = self::select($fields, $condition, $params); + + if (is_bool($result)) { + return $result; + } else { + $row = dba::fetch($result); + dba::close($result); + return $row; + } + } + + /** + * @brief Select rows from the item table + * + * @param array $selected Array of selected fields, empty for all + * @param array $condition Array of fields for condition + * @param array $params Array of several parameters + * + * @return boolean|object + */ + public static function select(array $selected = [], array $condition = [], $params = []) + { + $uid = 0; + $usermode = false; + + if (isset($params['uid'])) { + $uid = $params['uid']; + $usermode = true; + } + + $fields = self::fieldlist($selected); + + $select_fields = self::constructSelectFields($fields, $selected); + + $condition_string = dba::buildCondition($condition); + + $condition_string = self::addTablesToFields($condition_string, $fields); + + if ($usermode) { + $condition_string = $condition_string . ' AND ' . self::condition(false); + } + + $param_string = self::addTablesToFields(dba::buildParameter($params), $fields); + + $table = "`item` " . self::constructJoins($uid, $select_fields . $condition_string . $param_string, false); + + $sql = "SELECT " . $select_fields . " FROM " . $table . $condition_string . $param_string; + + return dba::p($sql, $condition); + } + + /** + * Retrieve a single record from the starting post in the item table and returns it in an associative array + * + * @brief Retrieve a single record from a table + * @param integer $uid User ID + * @param array $fields + * @param array $condition + * @param array $params + * @return bool|array + * @see dba::select + */ + public static function selectFirstThreadForUser($uid, array $fields = [], array $condition = [], $params = []) + { + $params['limit'] = 1; + $result = self::selectThreadForUser($uid, $fields, $condition, $params); + + if (is_bool($result)) { + return $result; + } else { + $row = dba::fetch($result); + dba::close($result); + return $row; + } + } + + /** + * @brief Select rows from the starting post in the item table + * + * @param integer $uid User ID + * @param array $fields Array of selected fields, empty for all + * @param array $condition Array of fields for condition + * @param array $params Array of several parameters + * + * @return boolean|object + */ + public static function selectThreadForUser($uid, array $selected = [], array $condition = [], $params = []) + { + if (empty($selected)) { + $selected = Item::DISPLAY_FIELDLIST; + } + + $fields = self::fieldlist($selected); + + $threadfields = ['thread' => ['iid', 'uid', 'contact-id', 'owner-id', 'author-id', + 'created', 'edited', 'commented', 'received', 'changed', 'wall', 'private', + 'pubmail', 'moderated', 'visible', 'starred', 'ignored', 'bookmark', + 'unseen', 'deleted', 'origin', 'forum_mode', 'mention', 'network']]; + + $select_fields = self::constructSelectFields($fields, $selected); + + $condition_string = dba::buildCondition($condition); + + $condition_string = self::addTablesToFields($condition_string, $threadfields); + $condition_string = self::addTablesToFields($condition_string, $fields); + + $condition_string = $condition_string . ' AND ' . self::condition(true); + + $param_string = dba::buildParameter($params); + $param_string = self::addTablesToFields($param_string, $threadfields); + $param_string = self::addTablesToFields($param_string, $fields); + + $table = "`thread` " . self::constructJoins($uid, $select_fields . $condition_string . $param_string, true); + + $sql = "SELECT " . $select_fields . " FROM " . $table . $condition_string . $param_string; + + return dba::p($sql, $condition); + } + + /** + * @brief Returns a list of fields that are associated with the item table + * + * @return array field list + */ + private static function fieldlist($selected) + { + $item_fields = ['author-id', 'owner-id', 'contact-id', 'uid', 'id', 'parent', + 'uri', 'thr-parent', 'parent-uri', 'content-warning', + 'commented', 'created', 'edited', 'received', 'verb', 'object-type', 'postopts', 'plink', + 'guid', 'wall', 'private', 'starred', 'origin', 'title', 'body', 'file', 'event-id', + 'location', 'coord', 'app', 'attach', 'rendered-hash', 'rendered-html', 'object', + 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', + 'id' => 'item_id', 'network' => 'item_network', + 'type', 'extid', 'changed', 'moderated', 'target-type', 'target', + 'resource-id', 'tag', 'inform', 'pubmail', 'visible', 'bookmark', 'unseen', 'deleted', + 'forum_mode', 'mention', 'global', 'shadow']; + + $author_fields = ['url' => 'author-link', 'name' => 'author-name', 'thumb' => 'author-avatar']; + $owner_fields = ['url' => 'owner-link', 'name' => 'owner-name', 'thumb' => 'owner-avatar']; + $contact_fields = ['url' => 'contact-link', 'name' => 'contact-name', 'thumb' => 'contact-avatar', + 'network', 'url', 'name', 'writable', 'self', 'id' => 'cid', 'alias', 'uid' => 'contact-uid', + 'photo', 'name-date', 'uri-date', 'avatar-date', 'thumb', 'dfrn-id']; + + $event_fields = ['created' => 'event-created', 'edited' => 'event-edited', + 'start' => 'event-start','finish' => 'event-finish', + 'summary' => 'event-summary','desc' => 'event-desc', + 'location' => 'event-location', 'type' => 'event-type', + 'nofinish' => 'event-nofinish','adjust' => 'event-adjust', + 'ignore' => 'event-ignore', 'id' => 'event-id']; + + $fields = ['item' => $item_fields, 'author' => $author_fields, 'owner' => $owner_fields, + 'contact' => $contact_fields, 'event' => $event_fields]; + + $fields['parent-item'] = ['guid' => 'parent-guid']; + $fields['parent-item-author'] = ['url' => 'parent-author-link', 'name' => 'parent-author-name']; + $fields['sign'] = ['signed_text', 'signature', 'signer']; + + return $fields; + } + + /** + * @brief Returns SQL condition for the "select" functions + * + * @param boolean $thread_mode Called for the items (false) or for the threads (true) + * + * @return string SQL condition + */ + private static function condition($thread_mode) + { + if ($thread_mode) { + $master_table = "`thread`"; + } else { + $master_table = "`item`"; + } + return "$master_table.`visible` AND NOT $master_table.`deleted` AND NOT $master_table.`moderated` AND (`user-item`.`hidden` IS NULL OR NOT `user-item`.`hidden`) "; + } + + /** + * @brief Returns all needed "JOIN" commands for the "select" functions + * + * @param integer $uid User ID + * @param string $sql_commands The parts of the built SQL commands in the "select" functions + * @param boolean $thread_mode Called for the items (false) or for the threads (true) + * + * @return string The SQL joins for the "select" functions + */ + private static function constructJoins($uid, $sql_commands, $thread_mode) + { + if ($thread_mode) { + $master_table = "`thread`"; + $master_table_key = "`thread`.`iid`"; + $joins = "STRAIGHT_JOIN `item` ON `item`.`id` = `thread`.`iid` "; + } else { + $master_table = "`item`"; + $master_table_key = "`item`.`id`"; + $joins = ''; + } + + $joins .= sprintf("STRAIGHT_JOIN `contact` ON `contact`.`id` = $master_table.`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) + STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = $master_table.`author-id` AND NOT `author`.`blocked` + STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = $master_table.`owner-id` AND NOT `owner`.`blocked` + LEFT JOIN `user-item` ON `user-item`.`iid` = $master_table_key AND `user-item`.`uid` = %d", + CONTACT_IS_SHARING, CONTACT_IS_FRIEND, intval($uid)); + + if (strpos($sql_commands, "`group_member`.") !== false) { + $joins .= " STRAIGHT_JOIN `group_member` ON `group_member`.`contact-id` = $master_table.`contact-id`"; + } + + if (strpos($sql_commands, "`user`.") !== false) { + $joins .= " STRAIGHT_JOIN `user` ON `user`.`uid` = $master_table.`uid`"; + } + + if (strpos($sql_commands, "`event`.") !== false) { + $joins .= " LEFT JOIN `event` ON `event-id` = `event`.`id`"; + } + + if (strpos($sql_commands, "`sign`.") !== false) { + $joins .= " LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id`"; + } + + if ((strpos($sql_commands, "`parent-item`.") !== false) || (strpos($sql_commands, "`parent-author`.") !== false)) { + $joins .= " STRAIGHT_JOIN `item` AS `parent-item` ON `parent-item`.`id` = `item`.`parent`"; + } + + if (strpos($sql_commands, "`parent-item-author`.") !== false) { + $joins .= " STRAIGHT_JOIN `contact` AS `parent-item-author` ON `parent-item-author`.`id` = `parent-item`.`author-id`"; + } + + return $joins; + } + + /** + * @brief Add the field list for the "select" functions + * + * @param array $fields The field definition array + * @param array $selected The array with the selected fields from the "select" functions + * + * @return string The field list + */ + private static function constructSelectFields($fields, $selected) + { + $selection = []; + foreach ($fields as $table => $table_fields) { + foreach ($table_fields as $field => $select) { + if (empty($selected) || in_array($select, $selected)) { + if (is_int($field)) { + $selection[] = "`" . $table . "`.`".$select."`"; + } else { + $selection[] = "`" . $table . "`.`" . $field . "` AS `".$select ."`"; + } + } + } + } + return implode(", ", $selection); + } + + /** + * @brief add table definition to fields in an SQL query + * + * @param string $query SQL query + * @param array $fields The field definition array + * + * @return string the changed SQL query + */ + private static function addTablesToFields($query, $fields) + { + foreach ($fields as $table => $table_fields) { + foreach ($table_fields as $alias => $field) { + if (is_int($alias)) { + $replace_field = $field; + } else { + $replace_field = $alias; + } + + $search = "/([^\.])`" . $field . "`/i"; + $replace = "$1`" . $table . "`.`" . $replace_field . "`"; + $query = preg_replace($search, $replace, $query); + } + } + return $query; + } + /** * @brief Update existing item entries * @@ -75,8 +440,9 @@ class Item extends BaseObject Term::insertFromFileFieldByItemId($item['id']); self::updateThread($item['id']); - // We only need to notfiy others when it is an original entry from us - if ($item['origin']) { + // We only need to notfiy others when it is an original entry from us. + // Only call the notifier when the item has some content relevant change. + if ($item['origin'] && in_array('edited', array_keys($fields))) { Worker::add(PRIORITY_HIGH, "Notifier", 'edit_post', $item['id']); } } @@ -101,6 +467,32 @@ class Item extends BaseObject 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); + } + /** * @brief Delete an item and notify others about it - if it was ours * @@ -109,18 +501,20 @@ class Item extends BaseObject * * @return boolean success */ - public static function deleteById($item_id, $priority = PRIORITY_HIGH) + private 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', 'uri', '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)) { + logger('Item with ID ' . $item_id . " hasn't been found.", LOGGER_DEBUG); return false; } if ($item['deleted']) { + logger('Item with ID ' . $item_id . ' has already been deleted.', LOGGER_DEBUG); return false; } @@ -129,8 +523,6 @@ class Item extends BaseObject $parent = ['origin' => false]; } - logger('delete item: ' . $item['id'], LOGGER_DEBUG); - // clean up categories and tags so they don't end up as orphans $matches = false; @@ -183,16 +575,34 @@ class Item extends BaseObject Term::insertFromFileFieldByItemId($item['id']); self::deleteThread($item['id'], $item['parent-uri']); + if (!dba::exists('item', ["`uri` = ? AND `uid` != 0 AND NOT `deleted`", $item['uri']])) { + self::delete(['uri' => $item['uri'], 'uid' => 0, 'deleted' => false], $priority); + } + // If it's the parent of a comment thread, kill all the kids if ($item['id'] == $item['parent']) { - self::delete(['parent' => $item['parent']], $priority); + self::delete(['parent' => $item['parent'], 'deleted' => false], $priority); } - // send the notification upstream/downstream + // Is it our comment and/or our thread? if ($item['origin'] || $parent['origin']) { + + // When we delete the original post we will delete all existing copies on the server as well + self::delete(['uri' => $item['uri'], 'deleted' => false], $priority); + + // 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 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); + } } + logger('Item with ID ' . $item_id . " has been deleted.", LOGGER_DEBUG); + return true; } @@ -333,12 +743,18 @@ class Item extends BaseObject $item['origin'] = 1; $item['network'] = NETWORK_DFRN; $item['protocol'] = PROTOCOL_DFRN; + + if (is_int($notify)) { + $priority = $notify; + } else { + $priority = PRIORITY_HIGH; + } } else { $item['network'] = trim(defaults($item, 'network', NETWORK_PHANTOM)); } $item['guid'] = self::guid($item, $notify); - $item['uri'] = notags(trim(defaults($item, 'uri', item_new_uri($a->get_hostname(), $item['uid'], $item['guid'])))); + $item['uri'] = notags(trim(defaults($item, 'uri', self::newURI($item['uid'], $item['guid'])))); // Store conversation data $item = Conversation::insert($item); @@ -355,6 +771,13 @@ class Item extends BaseObject unset($item['dsprsig']); } + if (!empty($item['diaspora_signed_text'])) { + $diaspora_signed_text = $item['diaspora_signed_text']; + unset($item['diaspora_signed_text']); + } else { + $diaspora_signed_text = ''; + } + // Converting the plink /// @TODO Check if this is really still needed if ($item['network'] == NETWORK_OSTATUS) { @@ -508,6 +931,14 @@ class Item extends BaseObject return 0; } + //unset($item['author-link']); + unset($item['author-name']); + unset($item['author-avatar']); + + //unset($item['owner-link']); + unset($item['owner-name']); + unset($item['owner-avatar']); + if ($item['network'] == NETWORK_PHANTOM) { logger('Missing network. Called by: '.System::callstack(), LOGGER_DEBUG); @@ -553,7 +984,7 @@ class Item extends BaseObject $fields = ['uri', 'parent-uri', 'id', 'deleted', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', - 'wall', 'private', 'forum_mode']; + 'wall', 'private', 'forum_mode', 'origin']; $condition = ['uri' => $item['parent-uri'], 'uid' => $item['uid']]; $params = ['order' => ['id' => false]]; $parent = dba::selectFirst('item', $fields, $condition, $params); @@ -805,6 +1236,12 @@ class Item extends BaseObject 'signature' => $dsprsig->signature, 'signer' => $dsprsig->signer]); } + if (!empty($diaspora_signed_text)) { + // Formerly we stored the signed text, the signature and the author in different fields. + // We now store the raw data so that we are more flexible. + dba::insert('sign', ['iid' => $current_post, 'signed_text' => $diaspora_signed_text]); + } + $deleted = self::tagDeliver($item['uid'], $current_post); /* @@ -848,7 +1285,9 @@ class Item extends BaseObject check_user_notification($current_post); if ($notify) { - Worker::add(['priority' => PRIORITY_HIGH, 'dont_fork' => true], "Notifier", $notify_type, $current_post); + Worker::add(['priority' => $priority, 'dont_fork' => true], "Notifier", $notify_type, $current_post); + } elseif (!empty($parent) && $parent['origin']) { + Worker::add(['priority' => PRIORITY_HIGH, 'dont_fork' => true], "Notifier", "comment-import", $current_post); } return $current_post; @@ -857,9 +1296,10 @@ class Item extends BaseObject /** * @brief Distributes public items to the receivers * - * @param integer $itemid Item ID that should be added + * @param integer $itemid Item ID that should be added + * @param string $signed_text Original text (for Diaspora signatures), JSON encoded. */ - public static function distribute($itemid) + public static function distribute($itemid, $signed_text = '') { $condition = ["`id` IN (SELECT `parent` FROM `item` WHERE `id` = ?)", $itemid]; $parent = dba::selectFirst('item', ['owner-id'], $condition); @@ -894,14 +1334,22 @@ class Item extends BaseObject $users[$contact['uid']] = $contact['uid']; } + $origin_uid = 0; + if ($item['uri'] != $item['parent-uri']) { - $parents = dba::select('item', ['uid'], ["`uri` = ? AND `uid` != 0", $item['parent-uri']]); + $parents = dba::select('item', ['uid', 'origin'], ["`uri` = ? AND `uid` != 0", $item['parent-uri']]); while ($parent = dba::fetch($parents)) { $users[$parent['uid']] = $parent['uid']; + if ($parent['origin'] && !$item['origin']) { + $origin_uid = $parent['uid']; + } } } foreach ($users as $uid) { + if ($origin_uid == $uid) { + $item['diaspora_signed_text'] = $signed_text; + } self::storeForUser($itemid, $item, $uid); } } @@ -1047,8 +1495,9 @@ class Item extends BaseObject } // Is this a shadow entry? - if ($item['uid'] == 0) + if ($item['uid'] == 0) { return; + } // Is there a shadow parent? if (!dba::exists('item', ['uri' => $item['parent-uri'], 'uid' => 0])) { @@ -1088,10 +1537,8 @@ 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) { - if (dba::exists('item', ['id' => $parent, 'network' => NETWORK_DIASPORA])) { - self::distribute($public_shadow); - } + if ($origin && dba::exists('item', ['id' => $parent, 'network' => NETWORK_DIASPORA])) { + self::distribute($public_shadow); } } @@ -1102,14 +1549,14 @@ class Item extends BaseObject */ private static function addLanguageInPostopts(&$item) { + $postopts = ""; + if (!empty($item['postopts'])) { if (strstr($item['postopts'], 'lang=')) { // do not override return; } $postopts = $item['postopts']; - } else { - $postopts = ""; } $naked_body = Text\BBCode::toPlaintext($item['body'], false); @@ -1160,6 +1607,29 @@ class Item extends BaseObject return $guid_prefix.$host_hash; } + /** + * generate an unique URI + * + * @param integer $uid User id + * @param string $guid An existing GUID (Otherwise it will be generated) + * + * @return string + */ + public static function newURI($uid, $guid = "") + { + if ($guid == "") { + $guid = get_guid(32); + } + + $hostname = self::getApp()->get_hostname(); + + $user = dba::selectFirst('user', ['nickname'], ['uid' => $uid]); + + $uri = "urn:X-dfrn:" . $hostname . ':' . $user['nickname'] . ':' . $guid; + + return $uri; + } + /** * @brief Set "success_update" and "last-item" to the date of the last time we heard from this contact * @@ -1208,7 +1678,7 @@ class Item extends BaseObject } } - private static function setHashtags(&$item) + public static function setHashtags(&$item) { $tags = get_tags($item["body"]); @@ -1409,8 +1879,7 @@ class Item extends BaseObject $forum_mode = ($prvgroup ? 2 : 1); $fields = ['wall' => true, 'origin' => true, 'forum_mode' => $forum_mode, 'contact-id' => $self['id'], - 'owner-id' => $owner_id, 'owner-name' => $self['name'], 'owner-link' => $self['url'], - 'owner-avatar' => $self['thumb'], 'private' => $private, 'allow_cid' => $user['allow_cid'], + 'owner-id' => $owner_id, 'owner-link' => $self['url'], 'private' => $private, 'allow_cid' => $user['allow_cid'], 'allow_gid' => $user['allow_gid'], 'deny_cid' => $user['deny_cid'], 'deny_gid' => $user['deny_gid']]; dba::update('item', $fields, ['id' => $item_id]); @@ -1477,7 +1946,7 @@ class Item extends BaseObject if ($contact['network'] != NETWORK_FEED) { $datarray["guid"] = get_guid(32); unset($datarray["plink"]); - $datarray["uri"] = item_new_uri($a->get_hostname(), $contact['uid'], $datarray["guid"]); + $datarray["uri"] = self::newURI($contact['uid'], $datarray["guid"]); $datarray["parent-uri"] = $datarray["uri"]; $datarray["thr-parent"] = $datarray["uri"]; $datarray["extid"] = NETWORK_DFRN; @@ -1949,7 +2418,7 @@ EOT; $new_item = [ 'guid' => get_guid(32), - 'uri' => item_new_uri(self::getApp()->get_hostname(), $item['uid']), + 'uri' => self::newURI($item['uid']), 'uid' => $item['uid'], 'contact-id' => $item_contact_id, 'type' => 'activity', @@ -2001,7 +2470,7 @@ EOT; private static function addThread($itemid, $onlyshadow = false) { $fields = ['uid', 'created', 'edited', 'commented', 'received', 'changed', 'wall', 'private', 'pubmail', - 'moderated', 'visible', 'spam', 'starred', 'bookmark', 'contact-id', + 'moderated', 'visible', 'starred', 'bookmark', 'contact-id', 'deleted', 'origin', 'forum_mode', 'mention', 'network', 'author-id', 'owner-id']; $condition = ["`id` = ? AND (`parent` = ? OR `parent` = 0)", $itemid, $itemid]; $item = dba::selectFirst('item', $fields, $condition); @@ -2022,7 +2491,7 @@ EOT; private static function updateThread($itemid, $setmention = false) { $fields = ['uid', 'guid', 'title', 'body', 'created', 'edited', 'commented', 'received', 'changed', - 'wall', 'private', 'pubmail', 'moderated', 'visible', 'spam', 'starred', 'bookmark', 'contact-id', + 'wall', 'private', 'pubmail', 'moderated', 'visible', 'starred', 'bookmark', 'contact-id', 'deleted', 'origin', 'forum_mode', 'network', 'author-id', 'owner-id', 'rendered-html', 'rendered-hash']; $condition = ["`id` = ? AND (`parent` = ? OR `parent` = 0)", $itemid, $itemid];