From 324cce7a19a61ed3d305c508ad233ee0ab29323d Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 15 May 2022 20:21:56 +0000 Subject: [PATCH 1/3] Issue 11472: Store the "edit" history --- database.sql | 28 ++++++++++- doc/database.md | 1 + doc/database/db_post-history.md | 44 +++++++++++++++++ src/Model/Post/History.php | 65 ++++++++++++++++++++++++++ src/Model/Post/Thread.php | 2 - src/Protocol/ActivityPub/Processor.php | 1 + static/dbstructure.config.php | 28 ++++++++++- 7 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 doc/database/db_post-history.md create mode 100644 src/Model/Post/History.php diff --git a/database.sql b/database.sql index d13a3330c..b9e9d284f 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2022.05-rc (Siberian Iris) --- DB_UPDATE_VERSION 1462 +-- DB_UPDATE_VERSION 1463 -- ------------------------------------------ @@ -1155,6 +1155,32 @@ CREATE TABLE IF NOT EXISTS `post-delivery-data` ( FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Delivery data for items'; +-- +-- TABLE post-history +-- +CREATE TABLE IF NOT EXISTS `post-history` ( + `uri-id` int unsigned NOT NULL COMMENT 'Id of the item-uri table entry that contains the item uri', + `edited` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Date of edit', + `title` varchar(255) NOT NULL DEFAULT '' COMMENT 'item title', + `content-warning` varchar(255) NOT NULL DEFAULT '' COMMENT '', + `body` mediumtext COMMENT 'item body content', + `raw-body` mediumtext COMMENT 'Body without embedded media links', + `location` varchar(255) NOT NULL DEFAULT '' COMMENT 'text location where this item originated', + `coord` varchar(255) NOT NULL DEFAULT '' COMMENT 'longitude/latitude pair representing location where this item originated', + `language` text COMMENT 'Language information about this post', + `app` varchar(255) NOT NULL DEFAULT '' COMMENT 'application which generated this item', + `rendered-hash` varchar(32) NOT NULL DEFAULT '' COMMENT '', + `rendered-html` mediumtext COMMENT 'item.body converted to html', + `object-type` varchar(100) NOT NULL DEFAULT '' COMMENT 'ActivityStreams object type', + `object` text COMMENT 'JSON encoded object structure unless it is an implied object (normal post)', + `target-type` varchar(100) NOT NULL DEFAULT '' COMMENT 'ActivityStreams target type if applicable (URI)', + `target` text COMMENT 'JSON encoded target structure if used', + `resource-id` varchar(32) NOT NULL DEFAULT '' COMMENT 'Used to link other tables to items, it identifies the linked resource (e.g. photo) and if set must also set resource_type', + `plink` varchar(255) NOT NULL DEFAULT '' COMMENT 'permalink or URL to a displayable copy of the message at its source', + PRIMARY KEY(`uri-id`,`edited`), + FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE +) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Post history'; + -- -- TABLE post-link -- diff --git a/doc/database.md b/doc/database.md index bd5bef445..baa920535 100644 --- a/doc/database.md +++ b/doc/database.md @@ -52,6 +52,7 @@ Database Tables | [post-content](help/database/db_post-content) | Content for all posts | | [post-delivery](help/database/db_post-delivery) | Delivery data for posts for the batch processing | | [post-delivery-data](help/database/db_post-delivery-data) | Delivery data for items | +| [post-history](help/database/db_post-history) | Post history | | [post-link](help/database/db_post-link) | Post related external links | | [post-media](help/database/db_post-media) | Attached media | | [post-question](help/database/db_post-question) | Question | diff --git a/doc/database/db_post-history.md b/doc/database/db_post-history.md new file mode 100644 index 000000000..007dcb7f9 --- /dev/null +++ b/doc/database/db_post-history.md @@ -0,0 +1,44 @@ +Table post-history +=========== + +Post history + +Fields +------ + +| Field | Description | Type | Null | Key | Default | Extra | +| --------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------ | ---- | --- | ------------------- | ----- | +| uri-id | Id of the item-uri table entry that contains the item uri | int unsigned | NO | PRI | NULL | | +| edited | Date of edit | datetime | NO | PRI | 0001-01-01 00:00:00 | | +| title | item title | varchar(255) | NO | | | | +| content-warning | | varchar(255) | NO | | | | +| body | item body content | mediumtext | YES | | NULL | | +| raw-body | Body without embedded media links | mediumtext | YES | | NULL | | +| location | text location where this item originated | varchar(255) | NO | | | | +| coord | longitude/latitude pair representing location where this item originated | varchar(255) | NO | | | | +| language | Language information about this post | text | YES | | NULL | | +| app | application which generated this item | varchar(255) | NO | | | | +| rendered-hash | | varchar(32) | NO | | | | +| rendered-html | item.body converted to html | mediumtext | YES | | NULL | | +| object-type | ActivityStreams object type | varchar(100) | NO | | | | +| object | JSON encoded object structure unless it is an implied object (normal post) | text | YES | | NULL | | +| target-type | ActivityStreams target type if applicable (URI) | varchar(100) | NO | | | | +| target | JSON encoded target structure if used | text | YES | | NULL | | +| resource-id | Used to link other tables to items, it identifies the linked resource (e.g. photo) and if set must also set resource_type | varchar(32) | NO | | | | +| plink | permalink or URL to a displayable copy of the message at its source | varchar(255) | NO | | | | + +Indexes +------------ + +| Name | Fields | +| ------- | -------------- | +| PRIMARY | uri-id, edited | + +Foreign Keys +------------ + +| Field | Target Table | Target Field | +|-------|--------------|--------------| +| uri-id | [item-uri](help/database/db_item-uri) | id | + +Return to [database documentation](help/database) diff --git a/src/Model/Post/History.php b/src/Model/Post/History.php new file mode 100644 index 000000000..e889ccf20 --- /dev/null +++ b/src/Model/Post/History.php @@ -0,0 +1,65 @@ +. + * + */ + +namespace Friendica\Model\Post; + +use Friendica\Core\Logger; +use Friendica\Database\DBA; +use Friendica\Database\Database; +use Friendica\Database\DBStructure; +use Friendica\Model\Post; + +class History +{ + /** + * Add a post to the history before it is changed + * + * @param integer $uri_id + * @param array $item + */ + public static function add(int $uri_id, array $item) + { + $allfields = DBStructure::definition('', false); + $fields = array_keys($allfields['post-history']['fields']); + + $post = Post::selectFirstPost($fields, ['uri-id' => $uri_id]); + if (empty($post)) { + return; + } + + $update = false; + $changed = DBStructure::getFieldsForTable('post-history', $item); + unset($changed['uri-id']); + unset($changed['edited']); + foreach ($changed as $field => $content) { + if ($content != $post[$field]) { + $update = true; + } + } + + if ($update) { + DBA::insert('post-history', $post, Database::INSERT_IGNORE); + Logger::info('Added history', ['uri-id' => $uri_id, 'edited' => $post['edited']]); + } else { + Logger::info('No content fields had been changed', ['uri-id' => $uri_id, 'edited' => $post['edited']]); + } + } +} diff --git a/src/Model/Post/Thread.php b/src/Model/Post/Thread.php index 60baf0408..ab7900ad8 100644 --- a/src/Model/Post/Thread.php +++ b/src/Model/Post/Thread.php @@ -22,11 +22,9 @@ namespace Friendica\Model\Post; use \BadMethodCallException; -use Friendica\Core\Protocol; use Friendica\Database\Database; use Friendica\Database\DBA; use Friendica\Database\DBStructure; -use Friendica\Model\Post; class Thread { diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index d603681a4..cde70c0d7 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -215,6 +215,7 @@ class Processor return; } + Post\History::add($item['uri-id'], $item); Item::update($item, ['uri' => $activity['id']]); if ($activity['object_type'] == 'as:Event') { diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index 44b2fc1f8..f13523960 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', 1462); + define('DB_UPDATE_VERSION', 1463); } return [ @@ -1193,6 +1193,32 @@ return [ "PRIMARY" => ["uri-id"], ] ], + "post-history" => [ + "comment" => "Post history", + "fields" => [ + "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"], + "edited" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "primary" => "1", "comment" => "Date of edit"], + "title" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "item title"], + "content-warning" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], + "body" => ["type" => "mediumtext", "comment" => "item body content"], + "raw-body" => ["type" => "mediumtext", "comment" => "Body without embedded media links"], + "location" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "text location where this item originated"], + "coord" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "longitude/latitude pair representing location where this item originated"], + "language" => ["type" => "text", "comment" => "Language information about this post"], + "app" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "application which generated this item"], + "rendered-hash" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""], + "rendered-html" => ["type" => "mediumtext", "comment" => "item.body converted to html"], + "object-type" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => "ActivityStreams object type"], + "object" => ["type" => "text", "comment" => "JSON encoded object structure unless it is an implied object (normal post)"], + "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"], + "resource-id" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => "Used to link other tables to items, it identifies the linked resource (e.g. photo) and if set must also set resource_type"], + "plink" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "permalink or URL to a displayable copy of the message at its source"] + ], + "indexes" => [ + "PRIMARY" => ["uri-id", "edited"], + ] + ], "post-link" => [ "comment" => "Post related external links", "fields" => [ From d77b043d9c8d24b80e2709dfee87226c2eae126c Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 15 May 2022 20:26:14 +0000 Subject: [PATCH 2/3] Fixing tests --- src/Model/Post/History.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Model/Post/History.php b/src/Model/Post/History.php index e889ccf20..68f2e9cda 100644 --- a/src/Model/Post/History.php +++ b/src/Model/Post/History.php @@ -38,14 +38,14 @@ class History public static function add(int $uri_id, array $item) { $allfields = DBStructure::definition('', false); - $fields = array_keys($allfields['post-history']['fields']); + $fields = array_keys($allfields['post-history']['fields']); $post = Post::selectFirstPost($fields, ['uri-id' => $uri_id]); if (empty($post)) { return; } - $update = false; + $update = false; $changed = DBStructure::getFieldsForTable('post-history', $item); unset($changed['uri-id']); unset($changed['edited']); From 2c511b8a2388f5633456963f7b3c75b0070866b5 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 15 May 2022 21:15:31 +0000 Subject: [PATCH 3/3] Check the edit date before storing history --- src/Model/Post/History.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Model/Post/History.php b/src/Model/Post/History.php index 68f2e9cda..24ee7c1e7 100644 --- a/src/Model/Post/History.php +++ b/src/Model/Post/History.php @@ -42,6 +42,12 @@ class History $post = Post::selectFirstPost($fields, ['uri-id' => $uri_id]); if (empty($post)) { + Logger::warning('Post not found', ['uri-id' => $uri_id]); + return; + } + + if ($item['edited'] <= $post['edited']) { + Logger::info('New edit date is not newer than the old one', ['uri-id' => $uri_id, 'old' => $post['edited'], 'new' => $item['edited']]); return; }