From 88931e50531bf087fead5bded166bd1586e1f8bc Mon Sep 17 00:00:00 2001
From: Michael <heluecht@pirati.ca>
Date: Thu, 30 Apr 2020 06:09:57 +0000
Subject: [PATCH] Post update functionality for tags

---
 src/Database/PostUpdate.php   | 130 ++++++++++++++++++++++++++++++++++
 static/dbstructure.config.php |   2 +-
 2 files changed, 131 insertions(+), 1 deletion(-)

diff --git a/src/Database/PostUpdate.php b/src/Database/PostUpdate.php
index cd7e8b9462..4a6507ff5f 100644
--- a/src/Database/PostUpdate.php
+++ b/src/Database/PostUpdate.php
@@ -28,7 +28,9 @@ use Friendica\Model\Contact;
 use Friendica\Model\Item;
 use Friendica\Model\ItemURI;
 use Friendica\Model\PermissionSet;
+use Friendica\Model\Tag;
 use Friendica\Model\UserItem;
+use Friendica\Util\Strings;
 
 /**
  * These database-intensive post update routines are meant to be executed in the background by the cronjob.
@@ -64,6 +66,12 @@ class PostUpdate
 		if (!self::update1329()) {
 			return false;
 		}
+		if (!self::update1341()) {
+			return false;
+		}
+		if (!self::update1342()) {
+			return false;
+		}
 
 		return true;
 	}
@@ -533,4 +541,126 @@ class PostUpdate
 
 		return false;
 	}
+
+	/**
+	 * Fill the "tag" table with tags and mentions from the body
+	 *
+	 * @return bool "true" when the job is done
+	 * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+	 */
+	private static function update1341()
+	{
+		// Was the script completed?
+		if (DI::config()->get('system', 'post_update_version') >= 1341) {
+			return true;
+		}
+
+		$id = DI::config()->get('system', 'post_update_version_1341_id', 0);
+
+		Logger::info('Start', ['item' => $id]);
+
+		$start_id = $id;
+		$rows = 0;
+
+		$items = DBA::p("SELECT `uri-id`,`body` FROM `item-content` WHERE
+			(`body` LIKE ? OR `body` LIKE ? OR `body` LIKE ?) AND `uri-id` >= ?
+			ORDER BY `uri-id` LIMIT 100000", '%#%', '%@%', '%!%', $id);
+
+		if (DBA::errorNo() != 0) {
+			Logger::error('Database error', ['no' => DBA::errorNo(), 'message' => DBA::errorMessage()]);
+			return false;
+		}
+
+		while ($item = DBA::fetch($items)) {
+			Tag::storeFromBody($item['uri-id'], $item['body'], '#!@', false);
+			$id = $item['uri-id'];
+			++$rows;
+			if ($rows % 1000 == 0) {
+				DI::config()->set('system', 'post_update_version_1341_id', $id);
+			}
+		}
+		DBA::close($items);
+
+		DI::config()->set('system', 'post_update_version_1341_id', $id);
+
+		Logger::info('Processed', ['rows' => $rows, 'last' => $id]);
+
+		if ($start_id == $id) {
+			DI::config()->set('system', 'post_update_version', 1341);
+			Logger::info('Done');
+			return true;
+		}
+
+		return false;
+	}
+
+	/**
+	 * Fill the "tag" table with tags and mentions from the "term" table
+	 *
+	 * @return bool "true" when the job is done
+	 * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+	 */
+	private static function update1342()
+	{
+		// Was the script completed?
+		if (DI::config()->get('system', 'post_update_version') >= 1342) {
+			return true;
+		}
+
+		$id = DI::config()->get('system', 'post_update_version_1342_id', 0);
+
+		Logger::info('Start', ['item' => $id]);
+
+		$start_id = $id;
+		$rows = 0;
+
+		$terms = DBA::p("SELECT `term`.`tid`, `item`.`uri-id`, `term`.`type`, `term`.`term`, `term`.`url`, `item-content`.`body`
+			FROM `term`
+			INNER JOIN `item` ON `item`.`id` = `term`.`oid`
+			INNER JOIN `item-content` ON `item-content`.`uri-id` = `item`.`uri-id`
+			WHERE term.type IN (?, ?, ?, ?) AND `tid` >= ? ORDER BY `tid` LIMIT 100000",
+			Tag::HASHTAG, Tag::MENTION, Tag::EXCLUSIVE_MENTION, Tag::IMPLICIT_MENTION, $id);
+
+		if (DBA::errorNo() != 0) {
+			Logger::error('Database error', ['no' => DBA::errorNo(), 'message' => DBA::errorMessage()]);
+			return false;
+		}
+
+		while ($term = DBA::fetch($terms)) {
+			if (($term['type'] == Tag::MENTION) && !empty($term['url']) && !strstr($term['body'], $term['url'])) {
+                $condition = ['nurl' => Strings::normaliseLink($term['url']), 'uid' => 0, 'deleted' => false];
+                $contact = DBA::selectFirst('contact', ['url', 'alias'], $condition, ['order' => ['id']]);
+                if (!DBA::isResult($contact)) {
+                        $ssl_url = str_replace('http://', 'https://', $term['url']);
+                        $condition = ['`alias` IN (?, ?, ?) AND `uid` = ? AND NOT `deleted`', $term['url'], Strings::normaliseLink($term['url']), $ssl_url, 0];
+                        $contact = DBA::selectFirst('contact', ['url', 'alias'], $condition, ['order' => ['id']]);
+                }
+
+                if (DBA::isResult($contact) && (!strstr($term['body'], $contact['url']) && (empty($contact['alias']) || !strstr($term['body'], $contact['alias'])))) {
+                        $term['type'] = Tag::IMPLICIT_MENTION;
+                }
+			}
+
+			Tag::store($term['uri-id'], $term['type'], $term['term'], $term['url'], false);
+
+			$id = $term['tid'];
+			++$rows;
+			if ($rows % 1000 == 0) {
+				DI::config()->set('system', 'post_update_version_1342_id', $id);
+			}
+		}
+		DBA::close($terms);
+
+		DI::config()->set('system', 'post_update_version_1342_id', $id);
+
+		Logger::info('Processed', ['rows' => $rows, 'last' => $id]);
+
+		if ($start_id == $id) {
+			DI::config()->set('system', 'post_update_version', 1342);
+			Logger::info('Done');
+			return true;
+		}
+
+		return false;
+	}
 }
diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php
index 8b4d1528c6..72235d2777 100755
--- a/static/dbstructure.config.php
+++ b/static/dbstructure.config.php
@@ -51,7 +51,7 @@
 use Friendica\Database\DBA;
 
 if (!defined('DB_UPDATE_VERSION')) {
-	define('DB_UPDATE_VERSION', 1341);
+	define('DB_UPDATE_VERSION', 1342);
 }
 
 return [
-- 
2.39.5