diff --git a/database.sql b/database.sql index 1d4f335e4..226c15133 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2021.03-dev (Red Hot Poker) --- DB_UPDATE_VERSION 1385 +-- DB_UPDATE_VERSION 1386 -- ------------------------------------------ @@ -1488,6 +1488,159 @@ CREATE TABLE IF NOT EXISTS `workerqueue` ( INDEX `done_pid_priority_created` (`done`,`pid`,`priority`,`created`) ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Background tasks queue entries'; +-- +-- VIEW post-view +-- +DROP VIEW IF EXISTS `post-view`; +CREATE VIEW `post-view` AS SELECT + `item`.`id` AS `id`, + `item`.`id` AS `item_id`, + `item`.`uid` AS `uid`, + `item`.`uid` AS `internal-uid`, + `item`.`parent` AS `parent`, + `item`.`uri` AS `uri`, + `item`.`uri-id` AS `uri-id`, + `item`.`uri-id` AS `internal-uri-id`, + `item`.`parent-uri` AS `parent-uri`, + `item`.`parent-uri-id` AS `parent-uri-id`, + `item`.`thr-parent` AS `thr-parent`, + `item`.`thr-parent-id` AS `thr-parent-id`, + `item`.`guid` AS `guid`, + `item`.`type` AS `type`, + `item`.`wall` AS `wall`, + `item`.`gravity` AS `gravity`, + `item`.`extid` AS `extid`, + `item`.`created` AS `created`, + `item`.`edited` AS `edited`, + `item`.`commented` AS `commented`, + `item`.`received` AS `received`, + `item`.`changed` AS `changed`, + `item`.`resource-id` AS `resource-id`, + `item`.`post-type` AS `post-type`, + `item`.`private` AS `private`, + `item`.`pubmail` AS `pubmail`, + `item`.`moderated` AS `moderated`, + `item`.`visible` AS `visible`, + `item`.`starred` AS `starred`, + `item`.`bookmark` AS `bookmark`, + `item`.`unseen` AS `unseen`, + `item`.`deleted` AS `deleted`, + `item`.`origin` AS `origin`, + `item`.`forum_mode` AS `forum_mode`, + `item`.`mention` AS `mention`, + `item`.`global` AS `global`, + `item`.`network` AS `network`, + `item`.`icid` AS `icid`, + `item`.`vid` AS `vid`, + `item`.`psid` AS `psid`, + `item`.`attach` AS `attach`, + (SELECT COUNT(*) FROM `post-category` WHERE `post-category`.`uri-id` = `item`.`uri-id`) AS `internal-file-count`, + NULL AS `file`, + IF (`item`.`vid` IS NULL, '', `verb`.`name`) AS `verb`, + `item-content`.`title` AS `title`, + `item-content`.`content-warning` AS `content-warning`, + `item-content`.`raw-body` AS `raw-body`, + `item-content`.`body` AS `body`, + `item-content`.`rendered-hash` AS `rendered-hash`, + `item-content`.`rendered-html` AS `rendered-html`, + `item-content`.`language` AS `language`, + `item-content`.`plink` AS `plink`, + `item-content`.`location` AS `location`, + `item-content`.`coord` AS `coord`, + `item-content`.`app` AS `app`, + `item-content`.`object-type` AS `object-type`, + `item-content`.`object` AS `object`, + `item-content`.`target-type` AS `target-type`, + `item-content`.`target` AS `target`, + `item`.`contact-id` AS `contact-id`, + `contact`.`url` AS `contact-link`, + `contact`.`addr` AS `contact-addr`, + `contact`.`name` AS `contact-name`, + `contact`.`nick` AS `contact-nick`, + `contact`.`thumb` AS `contact-avatar`, + `contact`.`network` AS `contact-network`, + `contact`.`blocked` AS `contact-blocked`, + `contact`.`readonly` AS `contact-readonly`, + `contact`.`pending` AS `contact-pending`, + `contact`.`rel` AS `contact-rel`, + `contact`.`uid` AS `contact-uid`, + IF (`item`.`network` IN ('apub', 'dfrn', 'dspr', 'stat'), true, `contact`.`writable`) AS `writable`, + `contact`.`self` AS `self`, + `contact`.`id` AS `cid`, + `contact`.`alias` AS `alias`, + `contact`.`photo` AS `photo`, + `contact`.`name-date` AS `name-date`, + `contact`.`uri-date` AS `uri-date`, + `contact`.`avatar-date` AS `avatar-date`, + `contact`.`thumb` AS `thumb`, + `contact`.`dfrn-id` AS `dfrn-id`, + `item`.`author-id` AS `author-id`, + `author`.`url` AS `author-link`, + `author`.`addr` AS `author-addr`, + IF (`contact`.`url` = `author`.`url`, `contact`.`name`, `author`.`name`) AS `author-name`, + `author`.`nick` AS `author-nick`, + IF (`contact`.`url` = `author`.`url`, `contact`.`thumb`, `author`.`thumb`) AS `author-avatar`, + `author`.`network` AS `author-network`, + `author`.`blocked` AS `author-blocked`, + `item`.`owner-id` AS `owner-id`, + `owner`.`url` AS `owner-link`, + `owner`.`addr` AS `owner-addr`, + IF (`contact`.`url` = `owner`.`url`, `contact`.`name`, `owner`.`name`) AS `owner-name`, + `owner`.`nick` AS `owner-nick`, + IF (`contact`.`url` = `owner`.`url`, `contact`.`thumb`, `owner`.`thumb`) AS `owner-avatar`, + `owner`.`network` AS `owner-network`, + `owner`.`blocked` AS `owner-blocked`, + `item`.`causer-id` AS `causer-id`, + `causer`.`url` AS `causer-link`, + `causer`.`addr` AS `causer-addr`, + `causer`.`name` AS `causer-name`, + `causer`.`nick` AS `causer-nick`, + `causer`.`thumb` AS `causer-avatar`, + `causer`.`network` AS `causer-network`, + `causer`.`blocked` AS `causer-blocked`, + `causer`.`contact-type` AS `causer-contact-type`, + `post-delivery-data`.`postopts` AS `postopts`, + `post-delivery-data`.`inform` AS `inform`, + `post-delivery-data`.`queue_count` AS `delivery_queue_count`, + `post-delivery-data`.`queue_done` AS `delivery_queue_done`, + `post-delivery-data`.`queue_failed` AS `delivery_queue_failed`, + IF (`item`.`psid` IS NULL, '', `permissionset`.`allow_cid`) AS `allow_cid`, + IF (`item`.`psid` IS NULL, '', `permissionset`.`allow_gid`) AS `allow_gid`, + IF (`item`.`psid` IS NULL, '', `permissionset`.`deny_cid`) AS `deny_cid`, + IF (`item`.`psid` IS NULL, '', `permissionset`.`deny_gid`) AS `deny_gid`, + `item`.`event-id` AS `event-id`, + `event`.`created` AS `event-created`, + `event`.`edited` AS `event-edited`, + `event`.`start` AS `event-start`, + `event`.`finish` AS `event-finish`, + `event`.`summary` AS `event-summary`, + `event`.`desc` AS `event-desc`, + `event`.`location` AS `event-location`, + `event`.`type` AS `event-type`, + `event`.`nofinish` AS `event-nofinish`, + `event`.`adjust` AS `event-adjust`, + `event`.`ignore` AS `event-ignore`, + `diaspora-interaction`.`interaction` AS `signed_text`, + `parent-item`.`guid` AS `parent-guid`, + `parent-item`.`network` AS `parent-network`, + `parent-item`.`author-id` AS `parent-author-id`, + `parent-item-author`.`url` AS `parent-author-link`, + `parent-item-author`.`name` AS `parent-author-name`, + `parent-item-author`.`network` AS `parent-author-network` + FROM `item` + STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` + STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `item`.`author-id` + STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `item`.`owner-id` + STRAIGHT_JOIN `contact` AS `causer` ON `causer`.`id` = `item`.`causer-id` + LEFT JOIN `verb` ON `verb`.`id` = `item`.`vid` + LEFT JOIN `event` ON `event`.`id` = `item`.`event-id` + LEFT JOIN `diaspora-interaction` ON `diaspora-interaction`.`uri-id` = `item`.`uri-id` + LEFT JOIN `item-content` ON `item-content`.`uri-id` = `item`.`uri-id` + LEFT JOIN `post-delivery-data` ON `post-delivery-data`.`uri-id` = `item`.`uri-id` AND `item`.`origin` + LEFT JOIN `permissionset` ON `permissionset`.`id` = `item`.`psid` + STRAIGHT_JOIN `item` AS `parent-item` ON `parent-item`.`id` = `item`.`parent` + STRAIGHT_JOIN `contact` AS `parent-item-author` ON `parent-item-author`.`id` = `parent-item`.`author-id`; + -- -- VIEW category-view -- diff --git a/src/Model/Item.php b/src/Model/Item.php index e4266b41e..60976363a 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -96,7 +96,7 @@ class Item 'deleted', 'extid', 'post-type', 'gravity', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'author-id', 'author-link', 'owner-link', 'contact-uid', - 'signed_text', 'signature', 'signer', 'network']; + 'signed_text', 'network']; // Field list for "item-content" table that is mixed with the item table const MIXED_CONTENT_FIELDLIST = ['title', 'content-warning', 'body', 'location', @@ -262,7 +262,7 @@ class Item // We can always comment on posts from these networks if (array_key_exists('writable', $row) && in_array($row['internal-network'], Protocol::FEDERATED)) { - $row['writable'] = true; + $row['writable'] = 1; } // ---------------------- Transform item content data ---------------------- @@ -663,7 +663,7 @@ class Item 'resource-id', 'event-id', 'post-type', 'file', 'private', 'pubmail', 'moderated', 'visible', 'starred', 'bookmark', 'unseen', 'deleted', 'origin', 'forum_mode', 'mention', 'global', - 'id' => 'item_id', 'network', 'icid', + 'id' => 'item_id', 'network', 'icid', 'event-id', 'uri-id' => 'internal-uri-id', 'uid' => 'internal-uid', 'network' => 'internal-network', 'psid' => 'internal-psid']; @@ -703,7 +703,7 @@ class Item 'summary' => 'event-summary','desc' => 'event-desc', 'location' => 'event-location', 'type' => 'event-type', 'nofinish' => 'event-nofinish','adjust' => 'event-adjust', - 'ignore' => 'event-ignore', 'id' => 'event-id']; + 'ignore' => 'event-ignore']; $fields['diaspora-interaction'] = ['interaction', 'interaction' => 'signed_text']; diff --git a/src/Model/Post.php b/src/Model/Post.php new file mode 100644 index 000000000..981c7071d --- /dev/null +++ b/src/Model/Post.php @@ -0,0 +1,218 @@ +. + * + */ + +namespace Friendica\Model; + +use Friendica\Core\Protocol; +use Friendica\Database\DBA; +use Friendica\Protocol\Activity; +use Friendica\Repository\PermissionSet; + +class Post +{ + /** + * Fetch a single post row + * + * @param mixed $stmt statement object + * @return array|false current row or false + * @throws \Exception + */ + public static function fetch($stmt) + { + $row = DBA::fetch($stmt); + + if (!is_array($row)) { + return $row; + } + + if (array_key_exists('verb', $row)) { + if (in_array($row['verb'], Item::ACTIVITIES)) { + if (array_key_exists('title', $row)) { + $row['title'] = ''; + } + if (array_key_exists('body', $row)) { + $row['body'] = $row['verb']; + } + if (array_key_exists('object', $row)) { + $row['object'] = ''; + } + if (array_key_exists('object-type', $row)) { + $row['object-type'] = Activity\ObjectType::NOTE; + } + } elseif (in_array($row['verb'], ['', Activity::POST, Activity::SHARE])) { + // Posts don't have a target - but having tags or files. + if (array_key_exists('target', $row)) { + $row['target'] = ''; + } + } + } + + if (!array_key_exists('verb', $row) || in_array($row['verb'], ['', Activity::POST, Activity::SHARE])) { + // Build the file string out of the term entries + if (array_key_exists('file', $row)) { + if ($row['internal-file-count'] > 0) { + $row['file'] = Post\Category::getTextByURIId($row['internal-uri-id'], $row['internal-uid']); + } else { + $row['file'] = ''; + } + } + } + + // Remove internal fields + unset($row['internal-file-count']); + unset($row['internal-uri-id']); + unset($row['internal-uid']); + + return $row; + } + + /** + * Fills an array with data from an post query + * + * @param object $stmt statement object + * @param bool $do_close + * @return array Data array + */ + public static function inArray($stmt, $do_close = true) { + if (is_bool($stmt)) { + return $stmt; + } + + $data = []; + while ($row = self::fetch($stmt)) { + $data[] = $row; + } + if ($do_close) { + DBA::close($stmt); + } + return $data; + } + + /** + * Check if post data exists + * + * @param array $condition array of fields for condition + * + * @return boolean Are there rows for that condition? + * @throws \Exception + */ + public static function exists($condition) { + return DBA::exists('post-view', $condition); + } + + /** + * Counts the posts satisfying the provided condition + * + * @param array $condition array of fields for condition + * @param array $params Array of several parameters + * + * @return int + * + * Example: + * $condition = ["uid" => 1, "network" => 'dspr']; + * or: + * $condition = ["`uid` = ? AND `network` IN (?, ?)", 1, 'dfrn', 'dspr']; + * + * $count = Post::count($condition); + * @throws \Exception + */ + public static function count(array $condition = [], array $params = []) + { + return DBA::count('post-view', $condition, $params); + } + + /** + * Retrieve a single record from the post table and returns it in an associative array + * + * @param array $fields + * @param array $condition + * @param array $params + * @return bool|array + * @throws \Exception + * @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 = self::fetch($result); + DBA::close($result); + return $row; + } + } + + /** + * Select rows from the post table and returns them as an array + * + * @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 array + * @throws \Exception + */ + public static function selectToArray(array $fields = [], array $condition = [], $params = []) + { + $result = self::select($fields, $condition, $params); + + if (is_bool($result)) { + return []; + } + + $data = []; + while ($row = self::fetch($result)) { + $data[] = $row; + } + DBA::close($result); + + return $data; + } + + /** + * Select rows from the post 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 + * @throws \Exception + */ + public static function select(array $selected = [], array $condition = [], $params = []) + { + if (empty($selected)) { + $selected = array_merge(['author-addr', 'author-nick', 'owner-addr', 'owner-nick', 'causer-addr', 'causer-nick', + 'causer-network', 'photo', 'name-date', 'uri-date', 'avatar-date', 'thumb', 'dfrn-id', + 'parent-guid', 'parent-network', 'parent-author-id', 'parent-author-link', 'parent-author-name', + 'parent-author-network', 'signed_text'], Item::DISPLAY_FIELDLIST, Item::ITEM_FIELDLIST, Item::CONTENT_FIELDLIST); + } + + $selected = array_merge($selected, ['internal-uri-id', 'internal-uid', 'internal-file-count']); + $selected = array_unique($selected); + + return DBA::select('post-view', $selected, $condition, $params); + } +} diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index 269d62386..90c6e12ed 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -3700,51 +3700,6 @@ class Diaspora return self::buildAndTransmit($owner, $contact, $type, $message, $public_batch, $item["guid"]); } - /** - * Creates a message from a signature record entry - * - * @param array $item The item that will be exported - * @return array The message - */ - private static function messageFromSignature(array $item) - { - // Split the signed text - $signed_parts = explode(";", $item['signed_text']); - - if ($item["deleted"]) { - $message = ["author" => $item['signer'], - "target_guid" => $signed_parts[0], - "target_type" => $signed_parts[1]]; - } elseif (in_array($item["verb"], [Activity::LIKE, Activity::DISLIKE])) { - $message = ["author" => $signed_parts[4], - "guid" => $signed_parts[1], - "parent_guid" => $signed_parts[3], - "parent_type" => $signed_parts[2], - "positive" => $signed_parts[0], - "author_signature" => $item['signature'], - "parent_author_signature" => ""]; - } else { - // Remove the comment guid - $guid = array_shift($signed_parts); - - // Remove the parent guid - $parent_guid = array_shift($signed_parts); - - // Remove the handle - $handle = array_pop($signed_parts); - - $message = [ - "author" => $handle, - "guid" => $guid, - "parent_guid" => $parent_guid, - "text" => implode(";", $signed_parts), - "author_signature" => $item['signature'], - "parent_author_signature" => "" - ]; - } - return $message; - } - /** * Relays messages (like, comment, retraction) to other servers if we are the thread owner * diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index b12ac56b2..27752fb72 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -55,7 +55,7 @@ use Friendica\Database\DBA; if (!defined('DB_UPDATE_VERSION')) { - define('DB_UPDATE_VERSION', 1385); + define('DB_UPDATE_VERSION', 1386); } return [ diff --git a/static/dbview.config.php b/static/dbview.config.php index 5c1836426..b0bf7ed61 100644 --- a/static/dbview.config.php +++ b/static/dbview.config.php @@ -36,7 +36,158 @@ * */ -return [ + return [ + "post-view" => [ + "fields" => [ + "id" => ["item", "id"], + "item_id" => ["item", "id"], + "uid" => ["item", "uid"], + "internal-uid" => ["item", "uid"], + "parent" => ["item", "parent"], + "uri" => ["item", "uri"], + "uri-id" => ["item", "uri-id"], + "internal-uri-id" => ["item", "uri-id"], + "parent-uri" => ["item", "parent-uri"], + "parent-uri-id" => ["item", "parent-uri-id"], + "thr-parent" => ["item", "thr-parent"], + "thr-parent-id" => ["item", "thr-parent-id"], + "guid" => ["item", "guid"], + "type" => ["item", "type"], + "wall" => ["item", "wall"], + "gravity" => ["item", "gravity"], + "extid" => ["item", "extid"], + "created" => ["item", "created"], + "edited" => ["item", "edited"], + "commented" => ["item", "commented"], + "received" => ["item", "received"], + "changed" => ["item", "changed"], + "resource-id" => ["item", "resource-id"], + "post-type" => ["item", "post-type"], + "private" => ["item", "private"], + "pubmail" => ["item", "pubmail"], + "moderated" => ["item", "moderated"], + "visible" => ["item", "visible"], + "starred" => ["item", "starred"], + "bookmark" => ["item", "bookmark"], + "unseen" => ["item", "unseen"], + "deleted" => ["item", "deleted"], + "origin" => ["item", "origin"], + "forum_mode" => ["item", "forum_mode"], + "mention" => ["item", "mention"], + "global" => ["item", "global"], + "network" => ["item", "network"], + "icid" => ["item", "icid"], + "vid" => ["item", "vid"], + "psid" => ["item", "psid"], + "attach" => ["item", "attach"], + "internal-file-count" => "(SELECT COUNT(*) FROM `post-category` WHERE `post-category`.`uri-id` = `item`.`uri-id`)", + "file" => "NULL", + "verb" => "IF (`item`.`vid` IS NULL, '', `verb`.`name`)", + "title" => ["item-content", "title"], + "content-warning" => ["item-content", "content-warning"], + "raw-body" => ["item-content", "raw-body"], + "body" => ["item-content", "body"], + "rendered-hash" => ["item-content", "rendered-hash"], + "rendered-html" => ["item-content", "rendered-html"], + "language" => ["item-content", "language"], + "plink" => ["item-content", "plink"], + "location" => ["item-content", "location"], + "coord" => ["item-content", "coord"], + "app" => ["item-content", "app"], + "object-type" => ["item-content", "object-type"], + "object" => ["item-content", "object"], + "target-type" => ["item-content", "target-type"], + "target" => ["item-content", "target"], + "contact-id" => ["item", "contact-id"], + "contact-link" => ["contact", "url"], + "contact-addr" => ["contact", "addr"], + "contact-name" => ["contact", "name"], + "contact-nick" => ["contact", "nick"], + "contact-avatar" => ["contact", "thumb"], + "contact-network" => ["contact", "network"], + "contact-blocked" => ["contact", "blocked"], + "contact-readonly" => ["contact", "readonly"], + "contact-pending" => ["contact", "pending"], + "contact-rel" => ["contact", "rel"], + "contact-uid" => ["contact", "uid"], + "writable" => "IF (`item`.`network` IN ('apub', 'dfrn', 'dspr', 'stat'), true, `contact`.`writable`)", + "self" => ["contact", "self"], + "cid" => ["contact", "id"], + "alias" => ["contact", "alias"], + "photo" => ["contact", "photo"], + "name-date" => ["contact", "name-date"], + "uri-date" => ["contact", "uri-date"], + "avatar-date" => ["contact", "avatar-date"], + "thumb" => ["contact", "thumb"], + "dfrn-id" => ["contact", "dfrn-id"], + "author-id" => ["item", "author-id"], + "author-link" => ["author", "url"], + "author-addr" => ["author", "addr"], + "author-name" => "IF (`contact`.`url` = `author`.`url`, `contact`.`name`, `author`.`name`)", + "author-nick" => ["author", "nick"], + "author-avatar" => "IF (`contact`.`url` = `author`.`url`, `contact`.`thumb`, `author`.`thumb`)", + "author-network" => ["author", "network"], + "author-blocked" => ["author", "blocked"], + "owner-id" => ["item", "owner-id"], + "owner-link" => ["owner", "url"], + "owner-addr" => ["owner", "addr"], + "owner-name" => "IF (`contact`.`url` = `owner`.`url`, `contact`.`name`, `owner`.`name`)", + "owner-nick" => ["owner", "nick"], + "owner-avatar" => "IF (`contact`.`url` = `owner`.`url`, `contact`.`thumb`, `owner`.`thumb`)", + "owner-network" => ["owner", "network"], + "owner-blocked" => ["owner", "blocked"], + "causer-id" => ["item", "causer-id"], + "causer-link" => ["causer", "url"], + "causer-addr" => ["causer", "addr"], + "causer-name" => ["causer", "name"], + "causer-nick" => ["causer", "nick"], + "causer-avatar" => ["causer", "thumb"], + "causer-network" => ["causer", "network"], + "causer-blocked" => ["causer", "blocked"], + "causer-contact-type" => ["causer", "contact-type"], + "postopts" => ["post-delivery-data", "postopts"], + "inform" => ["post-delivery-data", "inform"], + "delivery_queue_count" => ["post-delivery-data", "queue_count"], + "delivery_queue_done" => ["post-delivery-data", "queue_done"], + "delivery_queue_failed" => ["post-delivery-data", "queue_failed"], + "allow_cid" => "IF (`item`.`psid` IS NULL, '', `permissionset`.`allow_cid`)", + "allow_gid" => "IF (`item`.`psid` IS NULL, '', `permissionset`.`allow_gid`)", + "deny_cid" => "IF (`item`.`psid` IS NULL, '', `permissionset`.`deny_cid`)", + "deny_gid" => "IF (`item`.`psid` IS NULL, '', `permissionset`.`deny_gid`)", + "event-id" => ["item", "event-id"], + "event-created" => ["event", "created"], + "event-edited" => ["event", "edited"], + "event-start" => ["event", "start"], + "event-finish" => ["event", "finish"], + "event-summary" => ["event", "summary"], + "event-desc" => ["event", "desc"], + "event-location" => ["event", "location"], + "event-type" => ["event", "type"], + "event-nofinish" => ["event", "nofinish"], + "event-adjust" => ["event", "adjust"], + "event-ignore" => ["event", "ignore"], + "signed_text" => ["diaspora-interaction", "interaction"], + "parent-guid" => ["parent-item", "guid"], + "parent-network" => ["parent-item", "network"], + "parent-author-id" => ["parent-item", "author-id"], + "parent-author-link" => ["parent-item-author", "url"], + "parent-author-name" => ["parent-item-author", "name"], + "parent-author-network" => ["parent-item-author", "network"], + ], + "query" => "FROM `item` + STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` + STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `item`.`author-id` + STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `item`.`owner-id` + STRAIGHT_JOIN `contact` AS `causer` ON `causer`.`id` = `item`.`causer-id` + LEFT JOIN `verb` ON `verb`.`id` = `item`.`vid` + LEFT JOIN `event` ON `event`.`id` = `item`.`event-id` + LEFT JOIN `diaspora-interaction` ON `diaspora-interaction`.`uri-id` = `item`.`uri-id` + LEFT JOIN `item-content` ON `item-content`.`uri-id` = `item`.`uri-id` + LEFT JOIN `post-delivery-data` ON `post-delivery-data`.`uri-id` = `item`.`uri-id` AND `item`.`origin` + LEFT JOIN `permissionset` ON `permissionset`.`id` = `item`.`psid` + STRAIGHT_JOIN `item` AS `parent-item` ON `parent-item`.`id` = `item`.`parent` + STRAIGHT_JOIN `contact` AS `parent-item-author` ON `parent-item-author`.`id` = `parent-item`.`author-id`" + ], "category-view" => [ "fields" => [ "uri-id" => ["post-category", "uri-id"],