Merge pull request #9843 from annando/no-filetag

Legacy file/category storage is removed
This commit is contained in:
Hypolite Petovan 2021-01-21 18:50:57 -05:00 committed by GitHub
commit 215c6ecc14
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 153 additions and 333 deletions

View file

@ -1,6 +1,6 @@
-- ------------------------------------------ -- ------------------------------------------
-- Friendica 2021.03-dev (Red Hot Poker) -- Friendica 2021.03-dev (Red Hot Poker)
-- DB_UPDATE_VERSION 1393 -- DB_UPDATE_VERSION 1394
-- ------------------------------------------ -- ------------------------------------------
@ -1494,11 +1494,9 @@ CREATE VIEW `post-view` AS SELECT
`item`.`id` AS `id`, `item`.`id` AS `id`,
`item`.`id` AS `item_id`, `item`.`id` AS `item_id`,
`item`.`uid` AS `uid`, `item`.`uid` AS `uid`,
`item`.`uid` AS `internal-uid`,
`item`.`parent` AS `parent`, `item`.`parent` AS `parent`,
`item`.`uri` AS `uri`, `item`.`uri` AS `uri`,
`item`.`uri-id` AS `uri-id`, `item`.`uri-id` AS `uri-id`,
`item`.`uri-id` AS `internal-uri-id`,
`item`.`parent-uri` AS `parent-uri`, `item`.`parent-uri` AS `parent-uri`,
`item`.`parent-uri-id` AS `parent-uri-id`, `item`.`parent-uri-id` AS `parent-uri-id`,
`item`.`thr-parent` AS `thr-parent`, `item`.`thr-parent` AS `thr-parent`,
@ -1530,9 +1528,6 @@ CREATE VIEW `post-view` AS SELECT
`item`.`network` AS `network`, `item`.`network` AS `network`,
`item`.`vid` AS `vid`, `item`.`vid` AS `vid`,
`item`.`psid` AS `psid`, `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`, IF (`item`.`vid` IS NULL, '', `verb`.`name`) AS `verb`,
`item-content`.`title` AS `title`, `item-content`.`title` AS `title`,
`item-content`.`content-warning` AS `content-warning`, `item-content`.`content-warning` AS `content-warning`,
@ -1653,11 +1648,9 @@ CREATE VIEW `post-thread-view` AS SELECT
`thread`.`iid` AS `iid`, `thread`.`iid` AS `iid`,
`item`.`id` AS `item_id`, `item`.`id` AS `item_id`,
`thread`.`uid` AS `uid`, `thread`.`uid` AS `uid`,
`item`.`uid` AS `internal-uid`,
`item`.`parent` AS `parent`, `item`.`parent` AS `parent`,
`item`.`uri` AS `uri`, `item`.`uri` AS `uri`,
`item`.`uri-id` AS `uri-id`, `item`.`uri-id` AS `uri-id`,
`item`.`uri-id` AS `internal-uri-id`,
`item`.`parent-uri` AS `parent-uri`, `item`.`parent-uri` AS `parent-uri`,
`item`.`parent-uri-id` AS `parent-uri-id`, `item`.`parent-uri-id` AS `parent-uri-id`,
`item`.`thr-parent` AS `thr-parent`, `item`.`thr-parent` AS `thr-parent`,
@ -1690,9 +1683,6 @@ CREATE VIEW `post-thread-view` AS SELECT
`thread`.`network` AS `network`, `thread`.`network` AS `network`,
`item`.`vid` AS `vid`, `item`.`vid` AS `vid`,
`item`.`psid` AS `psid`, `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`, IF (`item`.`vid` IS NULL, '', `verb`.`name`) AS `verb`,
`item-content`.`title` AS `title`, `item-content`.`title` AS `title`,
`item-content`.`content-warning` AS `content-warning`, `item-content`.`content-warning` AS `content-warning`,

View file

@ -26,8 +26,6 @@ use Friendica\Core\Renderer;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Contact; use Friendica\Model\Contact;
use Friendica\Model\FileTag;
use Friendica\Model\Item;
use Friendica\Model\Post; use Friendica\Model\Post;
use Friendica\Util\Crypto; use Friendica\Util\Crypto;
@ -48,7 +46,7 @@ function editpost_content(App $a)
} }
$fields = ['allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', $fields = ['allow_cid', 'allow_gid', 'deny_cid', 'deny_gid',
'type', 'body', 'title', 'file', 'wall', 'post-type', 'guid']; 'type', 'body', 'title', 'uri-id', 'wall', 'post-type', 'guid'];
$item = Post::selectFirstForUser(local_user(), $fields, ['id' => $post_id, 'uid' => local_user()]); $item = Post::selectFirstForUser(local_user(), $fields, ['id' => $post_id, 'uid' => local_user()]);
@ -117,7 +115,7 @@ function editpost_content(App $a)
'$jotnets' => $jotnets, '$jotnets' => $jotnets,
'$title' => $item['title'], '$title' => $item['title'],
'$placeholdertitle' => DI::l10n()->t('Set title'), '$placeholdertitle' => DI::l10n()->t('Set title'),
'$category' => FileTag::fileToList($item['file'], 'category'), '$category' => Post\Category::getCSVByURIId($item['uri-id'], local_user(), Post\Category::CATEGORY),
'$placeholdercategory' => (Feature::isEnabled(local_user(),'categories') ? DI::l10n()->t("Categories \x28comma-separated list\x29") : ''), '$placeholdercategory' => (Feature::isEnabled(local_user(),'categories') ? DI::l10n()->t("Categories \x28comma-separated list\x29") : ''),
'$emtitle' => DI::l10n()->t('Example: bob@example.com, mary@example.com'), '$emtitle' => DI::l10n()->t('Example: bob@example.com, mary@example.com'),
'$lockstate' => $lockstate, '$lockstate' => $lockstate,

View file

@ -252,7 +252,7 @@ function item_post(App $a) {
$verb = $orig_post['verb']; $verb = $orig_post['verb'];
$objecttype = $orig_post['object-type']; $objecttype = $orig_post['object-type'];
$app = $orig_post['app']; $app = $orig_post['app'];
$categories = $orig_post['file'] ?? ''; $categories = Post\Category::getTextByURIId($orig_post['uri-id'], $orig_post['uid']);
$title = trim($_REQUEST['title'] ?? ''); $title = trim($_REQUEST['title'] ?? '');
$body = trim($body); $body = trim($body);
$private = $orig_post['private']; $private = $orig_post['private'];
@ -344,10 +344,7 @@ function item_post(App $a) {
$filedas = FileTag::fileToArray($categories); $filedas = FileTag::fileToArray($categories);
} }
// save old and new categories, so we can determine what needs to be deleted from pconfig
$categories_old = $categories;
$categories = FileTag::listToFile(trim($_REQUEST['category'] ?? ''), 'category'); $categories = FileTag::listToFile(trim($_REQUEST['category'] ?? ''), 'category');
$categories_new = $categories;
if (!empty($filedas) && is_array($filedas)) { if (!empty($filedas) && is_array($filedas)) {
// append the fileas stuff to the new categories list // append the fileas stuff to the new categories list
@ -696,9 +693,6 @@ function item_post(App $a) {
Item::update($fields, ['id' => $post_id]); Item::update($fields, ['id' => $post_id]);
// update filetags in pconfig
FileTag::updatePconfig($uid, $categories_old, $categories_new, 'category');
if ($return_path) { if ($return_path) {
DI::baseUrl()->redirect($return_path); DI::baseUrl()->redirect($return_path);
} }
@ -745,9 +739,6 @@ function item_post(App $a) {
Tag::createImplicitMentions($datarray['uri-id'], $datarray['thr-parent-id']); Tag::createImplicitMentions($datarray['uri-id'], $datarray['thr-parent-id']);
} }
// update filetags in pconfig
FileTag::updatePconfig($uid, $categories_old, $categories_new, 'category');
// These notifications are sent if someone else is commenting other your wall // These notifications are sent if someone else is commenting other your wall
if ($contact_record != $author) { if ($contact_record != $author) {
if ($toplevel_item_id) { if ($toplevel_item_id) {

View file

@ -23,8 +23,8 @@ namespace Friendica\Content;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\Model\Contact; use Friendica\Model\Contact;
use Friendica\Model\FileTag;
use Friendica\Model\Tag; use Friendica\Model\Tag;
use Friendica\Model\Post;
/** /**
* A content helper class for displaying items * A content helper class for displaying items
@ -64,7 +64,7 @@ class Item
$folders = []; $folders = [];
$first = true; $first = true;
foreach (FileTag::fileToArray($item['file'] ?? '', 'category') as $savedFolderName) { foreach (Post\Category::getArrayByURIId($item['uri-id'], $item['uid'], Post\Category::CATEGORY) as $savedFolderName) {
if (!empty($item['author-link'])) { if (!empty($item['author-link'])) {
$url = $item['author-link'] . "?category=" . rawurlencode($savedFolderName); $url = $item['author-link'] . "?category=" . rawurlencode($savedFolderName);
} else { } else {
@ -85,7 +85,7 @@ class Item
} }
if (local_user() == $item['uid']) { if (local_user() == $item['uid']) {
foreach (FileTag::fileToArray($item['file'] ?? '') as $savedFolderName) { foreach (Post\Category::getArrayByURIId($item['uri-id'], $item['uid'], Post\Category::FILE) as $savedFolderName) {
$folders[] = [ $folders[] = [
'name' => $savedFolderName, 'name' => $savedFolderName,
'url' => "#", 'url' => "#",

View file

@ -27,9 +27,9 @@ use Friendica\Core\Renderer;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Contact; use Friendica\Model\Contact;
use Friendica\Model\FileTag;
use Friendica\Model\Group; use Friendica\Model\Group;
use Friendica\Model\Item; use Friendica\Model\Item;
use Friendica\Model\Post;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\Temporal; use Friendica\Util\Temporal;
@ -305,19 +305,10 @@ class Widget
return ''; return '';
} }
$saved = DI::pConfig()->get(local_user(), 'system', 'filetags');
if (!strlen($saved)) {
return;
}
$terms = []; $terms = [];
foreach (FileTag::fileToArray($saved) as $savedFolderName) { foreach (Post\Category::getArray(local_user(), Post\Category::FILE) as $savedFolderName) {
$terms[] = ['ref' => $savedFolderName, 'name' => $savedFolderName]; $terms[] = ['ref' => $savedFolderName, 'name' => $savedFolderName];
} }
usort($terms, function ($a, $b) {
return strcmp($a['name'], $b['name']);
});
return self::filter( return self::filter(
'file', 'file',
@ -348,13 +339,8 @@ class Widget
return ''; return '';
} }
$saved = DI::pConfig()->get($uid, 'system', 'filetags');
if (!strlen($saved)) {
return;
}
$terms = array(); $terms = array();
foreach (FileTag::fileToArray($saved, 'category') as $savedFolderName) { foreach (Post\Category::getArray(local_user(), Post\Category::CATEGORY) as $savedFolderName) {
$terms[] = ['ref' => $savedFolderName, 'name' => $savedFolderName]; $terms[] = ['ref' => $savedFolderName, 'name' => $savedFolderName];
} }

View file

@ -21,10 +21,6 @@
namespace Friendica\Model; namespace Friendica\Model;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Model\Post\Category;
/** /**
* This class handles FileTag related functions * This class handles FileTag related functions
* *
@ -42,7 +38,7 @@ class FileTag
* *
* @return string The URL encoded string. * @return string The URL encoded string.
*/ */
public static function encode($s) private static function encode($s)
{ {
return str_replace(['<', '>', '[', ']'], ['%3c', '%3e', '%5b', '%5d'], $s); return str_replace(['<', '>', '[', ']'], ['%3c', '%3e', '%5b', '%5d'], $s);
} }
@ -54,31 +50,11 @@ class FileTag
* *
* @return string The decoded string. * @return string The decoded string.
*/ */
public static function decode($s) private static function decode($s)
{ {
return str_replace(['%3c', '%3e', '%5b', '%5d'], ['<', '>', '[', ']'], $s); return str_replace(['%3c', '%3e', '%5b', '%5d'], ['<', '>', '[', ']'], $s);
} }
/**
* Query files for tag
*
* @param string $table The table to be queired.
* @param string $s The search term
* @param string $type Optional file type.
*
* @return string Query string.
*/
public static function fileQuery($table, $s, $type = 'file')
{
if ($type == 'file') {
$str = preg_quote('[' . str_replace('%', '%%', self::encode($s)) . ']');
} else {
$str = preg_quote('<' . str_replace('%', '%%', self::encode($s)) . '>');
}
return " AND " . (($table) ? DBA::escape($table) . '.' : '') . "file regexp '" . DBA::escape($str) . "' ";
}
/** /**
* Get file tags from array * Get file tags from array
* *
@ -155,167 +131,4 @@ class FileTag
return self::arrayToFile($list_array, $type); return self::arrayToFile($list_array, $type);
} }
/**
* Get list from file tags
*
* ex. given <music><video>[friends], return music,video or friends
* @param string $file File tags
* @param string $type Optional file type.
*
* @return string Comma delimited list of tag names.
* @deprecated since 2019.06 use fileToArray() instead
*/
public static function fileToList(string $file, $type = 'file')
{
return implode(',', self::fileToArray($file, $type));
}
/**
* Update file tags in PConfig
*
* @param int $uid Unique Identity.
* @param string $file_old Categories previously associated with an item
* @param string $file_new New list of categories for an item
* @param string $type Optional file type.
*
* @return boolean A value indicating success or failure.
* @throws \Exception
*/
public static function updatePconfig(int $uid, string $file_old, string $file_new, string $type = 'file')
{
if (!intval($uid)) {
return false;
} elseif ($file_old == $file_new) {
return true;
}
$saved = DI::pConfig()->get($uid, 'system', 'filetags');
if (strlen($saved)) {
if ($type == 'file') {
$lbracket = '[';
$rbracket = ']';
$termtype = Category::FILE;
} else {
$lbracket = '<';
$rbracket = '>';
$termtype = Category::CATEGORY;
}
$filetags_updated = $saved;
// check for new tags to be added as filetags in pconfig
$new_tags = [];
foreach (self::fileToArray($file_new, $type) as $tag) {
if (!stristr($saved, $lbracket . self::encode($tag) . $rbracket)) {
$new_tags[] = $tag;
}
}
$filetags_updated .= self::arrayToFile($new_tags, $type);
// check for deleted tags to be removed from filetags in pconfig
$deleted_tags = [];
foreach (self::fileToArray($file_old, $type) as $tag) {
if (!stristr($file_new, $lbracket . self::encode($tag) . $rbracket)) {
$deleted_tags[] = $tag;
}
}
foreach ($deleted_tags as $key => $tag) {
if (DBA::exists('category-view', ['name' => $tag, 'type' => $termtype, 'uid' => $uid])) {
unset($deleted_tags[$key]);
} else {
$filetags_updated = str_replace($lbracket . self::encode($tag) . $rbracket, '', $filetags_updated);
}
}
if ($saved != $filetags_updated) {
DI::pConfig()->set($uid, 'system', 'filetags', $filetags_updated);
}
return true;
} elseif (strlen($file_new)) {
DI::pConfig()->set($uid, 'system', 'filetags', $file_new);
}
return true;
}
/**
* Add tag to file
*
* @param int $uid Unique identity.
* @param int $item_id Item identity.
* @param string $file File tag.
*
* @return boolean A value indicating success or failure.
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function saveFile($uid, $item_id, $file)
{
if (!intval($uid)) {
return false;
}
$item = Post::selectFirst(['file'], ['id' => $item_id, 'uid' => $uid]);
if (DBA::isResult($item)) {
if (!stristr($item['file'], '[' . self::encode($file) . ']')) {
$fields = ['file' => $item['file'] . '[' . self::encode($file) . ']'];
Item::update($fields, ['id' => $item_id]);
}
$saved = DI::pConfig()->get($uid, 'system', 'filetags');
if (!strlen($saved) || !stristr($saved, '[' . self::encode($file) . ']')) {
DI::pConfig()->set($uid, 'system', 'filetags', $saved . '[' . self::encode($file) . ']');
}
}
return true;
}
/**
* Remove tag from file
*
* @param int $uid Unique identity.
* @param int $item_id Item identity.
* @param string $file File tag.
* @param boolean $cat Optional value indicating the term type (i.e. Category or File)
*
* @return boolean A value indicating success or failure.
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function unsaveFile($uid, $item_id, $file, $cat = false)
{
if (!intval($uid)) {
return false;
}
if ($cat == true) {
$pattern = '<' . self::encode($file) . '>';
$termtype = Category::CATEGORY;
} else {
$pattern = '[' . self::encode($file) . ']';
$termtype = Category::FILE;
}
$item = Post::selectFirst(['file'], ['id' => $item_id, 'uid' => $uid]);
if (!DBA::isResult($item)) {
return false;
}
$fields = ['file' => str_replace($pattern, '', $item['file'])];
Item::update($fields, ['id' => $item_id]);
if (!DBA::exists('category-view', ['name' => $file, 'type' => $termtype, 'uid' => $uid])) {
$saved = DI::pConfig()->get($uid, 'system', 'filetags');
DI::pConfig()->set($uid, 'system', 'filetags', str_replace($pattern, '', $saved));
}
return true;
}
} }

View file

@ -75,7 +75,7 @@ class Item
const DISPLAY_FIELDLIST = [ const DISPLAY_FIELDLIST = [
'uid', 'id', 'parent', 'uri-id', 'uri', 'thr-parent', 'parent-uri', 'guid', 'network', 'gravity', 'uid', 'id', 'parent', 'uri-id', 'uri', 'thr-parent', 'parent-uri', 'guid', 'network', 'gravity',
'commented', 'created', 'edited', 'received', 'verb', 'object-type', 'postopts', 'plink', 'commented', 'created', 'edited', 'received', 'verb', 'object-type', 'postopts', 'plink',
'wall', 'private', 'starred', 'origin', 'title', 'body', 'file', 'language', 'wall', 'private', 'starred', 'origin', 'title', 'body', 'language',
'content-warning', 'location', 'coord', 'app', 'rendered-hash', 'rendered-html', 'object', 'content-warning', 'location', 'coord', 'app', 'rendered-hash', 'rendered-html', 'object',
'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'item_id', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'item_id',
'author-id', 'author-link', 'author-name', 'author-avatar', 'author-network', 'author-id', 'author-link', 'author-name', 'author-avatar', 'author-network',
@ -112,7 +112,7 @@ class Item
'contact-id', 'type', 'wall', 'gravity', 'extid', 'psid', 'contact-id', 'type', 'wall', 'gravity', 'extid', 'psid',
'created', 'edited', 'commented', 'received', 'changed', 'verb', 'created', 'edited', 'commented', 'received', 'changed', 'verb',
'postopts', 'plink', 'resource-id', 'event-id', 'inform', 'postopts', 'plink', 'resource-id', 'event-id', 'inform',
'file', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'post-type', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'post-type',
'private', 'pubmail', 'moderated', 'visible', 'starred', 'bookmark', 'private', 'pubmail', 'moderated', 'visible', 'starred', 'bookmark',
'unseen', 'deleted', 'origin', 'forum_mode', 'mention', 'global', 'network', 'unseen', 'deleted', 'origin', 'forum_mode', 'mention', 'global', 'network',
'title', 'content-warning', 'body', 'location', 'coord', 'app', 'title', 'content-warning', 'body', 'location', 'coord', 'app',
@ -203,17 +203,13 @@ class Item
// We cannot simply expand the condition to check for origin entries // We cannot simply expand the condition to check for origin entries
// The condition needn't to be a simple array but could be a complex condition. // The condition needn't to be a simple array but could be a complex condition.
// And we have to execute this query before the update to ensure to fetch the same data. // And we have to execute this query before the update to ensure to fetch the same data.
$items = DBA::select('item', ['id', 'origin', 'uri', 'uri-id', 'uid', 'file'], $condition); $items = DBA::select('item', ['id', 'origin', 'uri', 'uri-id', 'uid'], $condition);
$content_fields = []; $content_fields = [];
foreach (array_merge(self::CONTENT_FIELDLIST, self::MIXED_CONTENT_FIELDLIST) as $field) { foreach (array_merge(self::CONTENT_FIELDLIST, self::MIXED_CONTENT_FIELDLIST) as $field) {
if (isset($fields[$field])) { if (isset($fields[$field])) {
$content_fields[$field] = $fields[$field]; $content_fields[$field] = $fields[$field];
if (in_array($field, self::CONTENT_FIELDLIST)) { unset($fields[$field]);
unset($fields[$field]);
} else {
$fields[$field] = null;
}
} }
} }
@ -221,14 +217,12 @@ class Item
$clear_fields = ['bookmark', 'type', 'author-name', 'author-avatar', 'author-link', 'owner-name', 'owner-avatar', 'owner-link', 'postopts', 'inform']; $clear_fields = ['bookmark', 'type', 'author-name', 'author-avatar', 'author-link', 'owner-name', 'owner-avatar', 'owner-link', 'postopts', 'inform'];
foreach ($clear_fields as $field) { foreach ($clear_fields as $field) {
if (array_key_exists($field, $fields)) { unset($fields[$field]);
$fields[$field] = null;
}
} }
if (array_key_exists('file', $fields)) { if (array_key_exists('file', $fields)) {
$files = $fields['file']; $files = $fields['file'];
$fields['file'] = null; unset($fields['file']);
} else { } else {
$files = null; $files = null;
} }
@ -269,9 +263,6 @@ class Item
if (!is_null($files)) { if (!is_null($files)) {
Post\Category::storeTextByURIId($item['uri-id'], $item['uid'], $files); Post\Category::storeTextByURIId($item['uri-id'], $item['uid'], $files);
if (!empty($item['file'])) {
DBA::update('item', ['file' => ''], ['id' => $item['id']]);
}
} }
if (!empty($fields['attach'])) { if (!empty($fields['attach'])) {
@ -358,7 +349,7 @@ class Item
Logger::info('Mark item for deletion by id', ['id' => $item_id, 'callstack' => System::callstack()]); Logger::info('Mark item for deletion by id', ['id' => $item_id, 'callstack' => System::callstack()]);
// locate item to be deleted // locate item to be deleted
$fields = ['id', 'uri', 'uri-id', 'uid', 'parent', 'parent-uri', 'origin', $fields = ['id', 'uri', 'uri-id', 'uid', 'parent', 'parent-uri', 'origin',
'deleted', 'file', 'resource-id', 'event-id', 'deleted', 'resource-id', 'event-id',
'verb', 'object-type', 'object', 'target', 'contact-id', 'psid', 'gravity']; 'verb', 'object-type', 'object', 'target', 'contact-id', 'psid', 'gravity'];
$item = Post::selectFirst($fields, ['id' => $item_id]); $item = Post::selectFirst($fields, ['id' => $item_id]);
if (!DBA::isResult($item)) { if (!DBA::isResult($item)) {
@ -377,25 +368,7 @@ class Item
} }
// clean up categories and tags so they don't end up as orphans // clean up categories and tags so they don't end up as orphans
Post\Category::deleteByURIId($item['uri-id'], $item['uid']);
$matches = [];
$cnt = preg_match_all('/<(.*?)>/', $item['file'], $matches, PREG_SET_ORDER);
if ($cnt) {
foreach ($matches as $mtch) {
FileTag::unsaveFile($item['uid'], $item['id'], $mtch[1],true);
}
}
$matches = [];
$cnt = preg_match_all('/\[(.*?)\]/', $item['file'], $matches, PREG_SET_ORDER);
if ($cnt) {
foreach ($matches as $mtch) {
FileTag::unsaveFile($item['uid'], $item['id'], $mtch[1],false);
}
}
/* /*
* If item is a link to a photo resource, nuke all the associated photos * If item is a link to a photo resource, nuke all the associated photos
@ -2363,7 +2336,7 @@ class Item
$condition[0] .= " AND `received` < UTC_TIMESTAMP() - INTERVAL ? DAY"; $condition[0] .= " AND `received` < UTC_TIMESTAMP() - INTERVAL ? DAY";
$condition[] = $days; $condition[] = $days;
$items = Post::select(['file', 'resource-id', 'starred', 'type', 'id', 'post-type'], $condition); $items = Post::select(['resource-id', 'starred', 'type', 'id', 'post-type', 'uid', 'uri-id'], $condition);
if (!DBA::isResult($items)) { if (!DBA::isResult($items)) {
return; return;
@ -2386,8 +2359,7 @@ class Item
while ($item = Post::fetch($items)) { while ($item = Post::fetch($items)) {
// don't expire filed items // don't expire filed items
if (DBA::exists('post-category', ['uri-id' => $item['uri-id'], 'uid' => $item['uid'], 'type' => Post\Category::FILE])) {
if (strpos($item['file'], '[') !== false) {
continue; continue;
} }

View file

@ -63,22 +63,6 @@ class Post
} }
} }
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; return $row;
} }
@ -213,7 +197,6 @@ class Post
} }
} }
$selected = array_merge($selected, ['internal-uri-id', 'internal-uid', 'internal-file-count']);
$selected = array_unique($selected); $selected = array_unique($selected);
return DBA::select($view, $selected, $condition, $params); return DBA::select($view, $selected, $condition, $params);
@ -267,8 +250,6 @@ class Post
$selected = Item::DISPLAY_FIELDLIST; $selected = Item::DISPLAY_FIELDLIST;
} }
$selected = array_unique(array_merge($selected, ['internal-uri-id', 'internal-uid', 'internal-file-count']));
$condition = DBA::mergeConditions($condition, $condition = DBA::mergeConditions($condition,
["`visible` AND NOT `deleted` AND NOT `moderated` ["`visible` AND NOT `deleted` AND NOT `moderated`
AND NOT `author-blocked` AND NOT `owner-blocked` AND NOT `author-blocked` AND NOT `owner-blocked`

View file

@ -22,7 +22,6 @@
namespace Friendica\Model\Post; namespace Friendica\Model\Post;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\Model\Item;
use Friendica\Model\Post; use Friendica\Model\Post;
use Friendica\Model\Tag; use Friendica\Model\Tag;
@ -38,11 +37,42 @@ class Category
const CATEGORY = 3; const CATEGORY = 3;
const FILE = 5; const FILE = 5;
/**
* Delete all categories and files from a given uri-id and user
*
* @param int $uri_id
* @param int $uid
* @return boolean success
* @throws \Exception
*/
public static function deleteByURIId(int $uri_id, int $uid)
{
return DBA::delete('post-category', ['uri-id' => $uri_id, 'uid' => $uid]);
}
/**
* Delete all categories and files from a given uri-id and user
*
* @param int $uri_id
* @param int $uid
* @return boolean success
* @throws \Exception
*/
public static function deleteFileByURIId(int $uri_id, int $uid, int $type, string $file)
{
$tagid = Tag::getID($file);
if (empty($tagid)) {
return false;
}
return DBA::delete('post-category', ['uri-id' => $uri_id, 'uid' => $uid, 'type' => $type, 'tid' => $tagid]);
}
/** /**
* Generates the legacy item.file field string from an item ID. * Generates the legacy item.file field string from an item ID.
* Includes only file and category terms. * Includes only file and category terms.
* *
* @param int $item_id * @param int $uri_id
* @param int $uid
* @return string * @return string
* @throws \Exception * @throws \Exception
*/ */
@ -62,6 +92,58 @@ class Category
return $file_text; return $file_text;
} }
/**
* Generates an array of files or categories of a given uri-id
*
* @param int $uid
* @param int $type
* @return array
* @throws \Exception
*/
public static function getArray(int $uid, int $type)
{
$tags = DBA::selectToArray('category-view', ['name'], ['uid' => $uid, 'type' => $type],
['group_by' => ['name'], 'order' => ['name']]);
if (empty($tags)) {
return [];
}
return array_column($tags, 'name');
}
/**
* Generates an array of files or categories of a given uri-id
*
* @param int $uri_id
* @param int $uid
* @param int $type
* @return array
* @throws \Exception
*/
public static function getArrayByURIId(int $uri_id, int $uid, int $type = self::CATEGORY)
{
$tags = DBA::selectToArray('category-view', ['type', 'name'], ['uri-id' => $uri_id, 'uid' => $uid, 'type' => $type]);
if (empty($tags)) {
return [];
}
return array_column($tags, 'name');
}
/**
* Generates a comma separated list of files or categories
*
* @param int $uri_id
* @param int $uid
* @param int $type
* @return string
* @throws \Exception
*/
public static function getCSVByURIId(int $uri_id, int $uid, int $type)
{
return implode(',', self::getArrayByURIId($uri_id, $uid, $type));
}
/** /**
* Inserts new terms for the provided item ID based on the legacy item.file field BBCode content. * Inserts new terms for the provided item ID based on the legacy item.file field BBCode content.
* Deletes all previous file terms for the same item ID. * Deletes all previous file terms for the same item ID.
@ -101,18 +183,23 @@ class Category
if (preg_match_all("/\<(.*?)\>/ism", $files, $result)) { if (preg_match_all("/\<(.*?)\>/ism", $files, $result)) {
foreach ($result[1] as $file) { foreach ($result[1] as $file) {
$tagid = Tag::getID($file); self::storeFileByURIId($uri_id, $uid, self::FILE, $file);
if (empty($tagid)) {
continue;
}
DBA::replace('post-category', [
'uri-id' => $uri_id,
'uid' => $uid,
'type' => self::CATEGORY,
'tid' => $tagid
]);
} }
} }
} }
public static function storeFileByURIId(int $uri_id, int $uid, int $type, string $file)
{
$tagid = Tag::getID($file);
if (empty($tagid)) {
return false;
}
return DBA::replace('post-category', [
'uri-id' => $uri_id,
'uid' => $uid,
'type' => $type,
'tid' => $tagid
]);
}
} }

View file

@ -22,8 +22,9 @@
namespace Friendica\Module\Filer; namespace Friendica\Module\Filer;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\FileTag; use Friendica\Model\Post;
use Friendica\Network\HTTPException; use Friendica\Network\HTTPException;
use Friendica\Util\XML; use Friendica\Util\XML;
@ -46,26 +47,33 @@ class RemoveTag extends BaseModule
$term = XML::unescape(trim($_GET['term'] ?? '')); $term = XML::unescape(trim($_GET['term'] ?? ''));
$cat = XML::unescape(trim($_GET['cat'] ?? '')); $cat = XML::unescape(trim($_GET['cat'] ?? ''));
$category = (($cat) ? true : false); if (!empty($cat)) {
$type = Post\Category::CATEGORY;
if ($category) {
$term = $cat; $term = $cat;
} else {
$type = Post\Category::FILE;
} }
$logger->info('Filer - Remove Tag', [ $logger->info('Filer - Remove Tag', [
'term' => $term, 'term' => $term,
'item' => $item_id, 'item' => $item_id,
'category' => ($category ? 'true' : 'false') 'type' => $type
]); ]);
if ($item_id && strlen($term)) { if ($item_id && strlen($term)) {
if (!FileTag::unsaveFile(local_user(), $item_id, $term, $category)) { $item = Post::selectFirst(['uri-id'], ['id' => $item_id]);
if (!DBA::isResult($item)) {
return;
}
if (!Post\Category::deleteFileByURIId($item['uri-id'], local_user(), $type, $term)) {
notice(DI::l10n()->t('Item was not removed')); notice(DI::l10n()->t('Item was not removed'));
} }
} else { } else {
notice(DI::l10n()->t('Item was not deleted')); notice(DI::l10n()->t('Item was not deleted'));
} }
DI::baseUrl()->redirect('network?file=' . rawurlencode($term)); if ($type == Post\Category::FILE) {
DI::baseUrl()->redirect('filed?file=' . rawurlencode($term));
}
} }
} }

View file

@ -23,8 +23,10 @@ namespace Friendica\Module\Filer;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Core\Renderer; use Friendica\Core\Renderer;
use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model; use Friendica\Model;
use Friendica\Network\HTTPException;
use Friendica\Util\XML; use Friendica\Util\XML;
/** /**
@ -52,13 +54,15 @@ class SaveTag extends BaseModule
$logger->info('filer', ['tag' => $term, 'item' => $item_id]); $logger->info('filer', ['tag' => $term, 'item' => $item_id]);
if ($item_id && strlen($term)) { if ($item_id && strlen($term)) {
// file item $item = Model\Post::selectFirst(['uri-id'], ['id' => $item_id]);
Model\FileTag::saveFile(local_user(), $item_id, $term); if (!DBA::isResult($item)) {
throw new HTTPException\NotFoundException();
}
Model\Post\Category::storeFileByURIId($item['uri-id'], local_user(), Model\Post\Category::FILE, $term);
} }
// return filer dialog // return filer dialog
$filetags = DI::pConfig()->get(local_user(), 'system', 'filetags', ''); $filetags = Model\Post\Category::getArray(local_user(), Model\Post\Category::FILE);
$filetags = Model\FileTag::fileToArray($filetags);
$tpl = Renderer::getMarkupTemplate("filer_dialog.tpl"); $tpl = Renderer::getMarkupTemplate("filer_dialog.tpl");
echo Renderer::replaceMacros($tpl, [ echo Renderer::replaceMacros($tpl, [

View file

@ -2508,14 +2508,14 @@ class DFRN
} }
$condition = ['uri' => $uri, 'uid' => $importer["importer_uid"]]; $condition = ['uri' => $uri, 'uid' => $importer["importer_uid"]];
$item = Post::selectFirst(['id', 'parent', 'contact-id', 'file', 'deleted', 'gravity'], $condition); $item = Post::selectFirst(['id', 'parent', 'contact-id', 'uri-id', 'deleted', 'gravity'], $condition);
if (!DBA::isResult($item)) { if (!DBA::isResult($item)) {
Logger::log("Item with uri " . $uri . " for user " . $importer["importer_uid"] . " wasn't found.", Logger::DEBUG); Logger::log("Item with uri " . $uri . " for user " . $importer["importer_uid"] . " wasn't found.", Logger::DEBUG);
return; return;
} }
if (strstr($item['file'], '[')) { if (DBA::exists('post-category', ['uri-id' => $item['uri-id'], 'uid' => $importer['importer_uid'], 'type' => Post\Category::FILE])) {
Logger::log("Item with uri " . $uri . " for user " . $importer["importer_uid"] . " is filed. So it won't be deleted.", Logger::DEBUG); Logger::notice("Item is filed. It won't be deleted.", ['uri' => $uri, 'uri-id' => $item['uri_id'], 'uid' => $importer["importer_uid"]]);
return; return;
} }

View file

@ -2526,7 +2526,7 @@ class Diaspora
} }
// Fetch items that are about to be deleted // Fetch items that are about to be deleted
$fields = ['uid', 'id', 'parent', 'author-link', 'file']; $fields = ['uid', 'id', 'parent', 'author-link', 'uri-id'];
// When we receive a public retraction, we delete every item that we find. // When we receive a public retraction, we delete every item that we find.
if ($importer['uid'] == 0) { if ($importer['uid'] == 0) {
@ -2542,7 +2542,7 @@ class Diaspora
} }
while ($item = Post::fetch($r)) { while ($item = Post::fetch($r)) {
if (strstr($item['file'], '[')) { if (DBA::exists('post-category', ['uri-id' => $item['uri-id'], 'uid' => $item['uid'], 'type' => Post\Category::FILE])) {
Logger::log("Target guid " . $target_guid . " for user " . $item['uid'] . " is filed. So it won't be deleted.", Logger::DEBUG); Logger::log("Target guid " . $target_guid . " for user " . $item['uid'] . " is filed. So it won't be deleted.", Logger::DEBUG);
continue; continue;
} }

View file

@ -55,7 +55,7 @@
use Friendica\Database\DBA; use Friendica\Database\DBA;
if (!defined('DB_UPDATE_VERSION')) { if (!defined('DB_UPDATE_VERSION')) {
define('DB_UPDATE_VERSION', 1393); define('DB_UPDATE_VERSION', 1394);
} }
return [ return [

View file

@ -42,11 +42,9 @@
"id" => ["item", "id"], "id" => ["item", "id"],
"item_id" => ["item", "id"], "item_id" => ["item", "id"],
"uid" => ["item", "uid"], "uid" => ["item", "uid"],
"internal-uid" => ["item", "uid"],
"parent" => ["item", "parent"], "parent" => ["item", "parent"],
"uri" => ["item", "uri"], "uri" => ["item", "uri"],
"uri-id" => ["item", "uri-id"], "uri-id" => ["item", "uri-id"],
"internal-uri-id" => ["item", "uri-id"],
"parent-uri" => ["item", "parent-uri"], "parent-uri" => ["item", "parent-uri"],
"parent-uri-id" => ["item", "parent-uri-id"], "parent-uri-id" => ["item", "parent-uri-id"],
"thr-parent" => ["item", "thr-parent"], "thr-parent" => ["item", "thr-parent"],
@ -78,9 +76,6 @@
"network" => ["item", "network"], "network" => ["item", "network"],
"vid" => ["item", "vid"], "vid" => ["item", "vid"],
"psid" => ["item", "psid"], "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`)", "verb" => "IF (`item`.`vid` IS NULL, '', `verb`.`name`)",
"title" => ["item-content", "title"], "title" => ["item-content", "title"],
"content-warning" => ["item-content", "content-warning"], "content-warning" => ["item-content", "content-warning"],
@ -199,11 +194,9 @@
"iid" => ["thread", "iid"], "iid" => ["thread", "iid"],
"item_id" => ["item", "id"], "item_id" => ["item", "id"],
"uid" => ["thread", "uid"], "uid" => ["thread", "uid"],
"internal-uid" => ["item", "uid"],
"parent" => ["item", "parent"], "parent" => ["item", "parent"],
"uri" => ["item", "uri"], "uri" => ["item", "uri"],
"uri-id" => ["item", "uri-id"], "uri-id" => ["item", "uri-id"],
"internal-uri-id" => ["item", "uri-id"],
"parent-uri" => ["item", "parent-uri"], "parent-uri" => ["item", "parent-uri"],
"parent-uri-id" => ["item", "parent-uri-id"], "parent-uri-id" => ["item", "parent-uri-id"],
"thr-parent" => ["item", "thr-parent"], "thr-parent" => ["item", "thr-parent"],
@ -236,9 +229,6 @@
"network" => ["thread", "network"], "network" => ["thread", "network"],
"vid" => ["item", "vid"], "vid" => ["item", "vid"],
"psid" => ["item", "psid"], "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`)", "verb" => "IF (`item`.`vid` IS NULL, '', `verb`.`name`)",
"title" => ["item-content", "title"], "title" => ["item-content", "title"],
"content-warning" => ["item-content", "content-warning"], "content-warning" => ["item-content", "content-warning"],