mirror of
https://github.com/friendica/friendica
synced 2024-11-10 08:22:57 +00:00
Merge pull request #4264 from annando/item-delete
There is now a new delete function in the item class
This commit is contained in:
commit
c69d60644f
8 changed files with 123 additions and 195 deletions
|
@ -19,6 +19,7 @@ use Friendica\Model\Group;
|
|||
use Friendica\Model\Mail;
|
||||
use Friendica\Model\Photo;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Network\FKOAuth1;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Network\HTTPException\BadRequestException;
|
||||
|
@ -2214,7 +2215,7 @@ function api_statuses_destroy($type)
|
|||
|
||||
$ret = api_statuses_show($type);
|
||||
|
||||
drop_item($id, false);
|
||||
Item::delete($id);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
@ -3987,7 +3988,7 @@ function api_fr_photoalbum_delete($type)
|
|||
if (!DBM::is_result($photo_item)) {
|
||||
throw new InternalServerErrorException("problem with deleting items occured");
|
||||
}
|
||||
drop_item($photo_item[0]['id'], false);
|
||||
Item::delete($photo_item[0]['id']);
|
||||
}
|
||||
|
||||
// now let's delete all photos from the album
|
||||
|
@ -4290,7 +4291,7 @@ function api_fr_photo_delete($type)
|
|||
}
|
||||
// function for setting the items to "deleted = 1" which ensures that comments, likes etc. are not shown anymore
|
||||
// to the user and the contacts of the users (drop_items() do all the necessary magic to avoid orphans in database and federate deletion)
|
||||
drop_item($photo_item[0]['id'], false);
|
||||
Item::delete($photo_item[0]['id']);
|
||||
|
||||
$answer = ['result' => 'deleted', 'message' => 'photo with id `' . $photo_id . '` has been deleted from server.'];
|
||||
return api_format_data("photo_delete", $type, ['$result' => $answer]);
|
||||
|
|
|
@ -1980,7 +1980,7 @@ function item_getfeedtags($item) {
|
|||
|
||||
function item_expire($uid, $days, $network = "", $force = false) {
|
||||
|
||||
if ((! $uid) || ($days < 1)) {
|
||||
if (!$uid || ($days < 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1989,7 +1989,7 @@ function item_expire($uid, $days, $network = "", $force = false) {
|
|||
* and just expire conversations started by others
|
||||
*/
|
||||
$expire_network_only = PConfig::get($uid,'expire', 'network_only');
|
||||
$sql_extra = ((intval($expire_network_only)) ? " AND wall = 0 " : "");
|
||||
$sql_extra = (intval($expire_network_only) ? " AND wall = 0 " : "");
|
||||
|
||||
if ($network != "") {
|
||||
$sql_extra .= sprintf(" AND network = '%s' ", dbesc($network));
|
||||
|
@ -2013,7 +2013,7 @@ function item_expire($uid, $days, $network = "", $force = false) {
|
|||
intval($days)
|
||||
);
|
||||
|
||||
if (! DBM::is_result($r)) {
|
||||
if (!DBM::is_result($r)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2050,37 +2050,28 @@ function item_expire($uid, $days, $network = "", $force = false) {
|
|||
continue;
|
||||
}
|
||||
|
||||
drop_item($item['id'], false);
|
||||
Item::delete($item['id'], PRIORITY_LOW);
|
||||
}
|
||||
|
||||
Worker::add(['priority' => PRIORITY_LOW, 'dont_fork' => true], "Notifier", "expire", $uid);
|
||||
}
|
||||
|
||||
/// @TODO type-hint is array
|
||||
function drop_items($items) {
|
||||
$uid = 0;
|
||||
|
||||
if (! local_user() && ! remote_user()) {
|
||||
if (!local_user() && !remote_user()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (count($items)) {
|
||||
foreach ($items as $item) {
|
||||
$owner = drop_item($item,false);
|
||||
$owner = Item::delete($item);
|
||||
if ($owner && ! $uid)
|
||||
$uid = $owner;
|
||||
}
|
||||
}
|
||||
|
||||
// multiple threads may have been deleted, send an expire notification
|
||||
|
||||
if ($uid) {
|
||||
Worker::add(['priority' => PRIORITY_LOW, 'dont_fork' => true], "Notifier", "expire", $uid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function drop_item($id, $interactive = true) {
|
||||
function drop_item($id) {
|
||||
|
||||
$a = get_app();
|
||||
|
||||
|
@ -2090,11 +2081,8 @@ function drop_item($id, $interactive = true) {
|
|||
intval($id)
|
||||
);
|
||||
|
||||
if (! DBM::is_result($r)) {
|
||||
if (! $interactive) {
|
||||
return 0;
|
||||
}
|
||||
notice( t('Item not found.') . EOL);
|
||||
if (!DBM::is_result($r)) {
|
||||
notice(t('Item not found.') . EOL);
|
||||
goaway(System::baseUrl() . '/' . $_SESSION['return_url']);
|
||||
}
|
||||
|
||||
|
@ -2104,8 +2092,6 @@ function drop_item($id, $interactive = true) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
$owner = $item['uid'];
|
||||
|
||||
$contact_id = 0;
|
||||
|
||||
// check if logged in user is either the author or owner of this item
|
||||
|
@ -2119,8 +2105,7 @@ function drop_item($id, $interactive = true) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if ((local_user() == $item['uid']) || $contact_id || !$interactive) {
|
||||
if ((local_user() == $item['uid']) || $contact_id) {
|
||||
|
||||
// Check if we should do HTML-based delete confirmation
|
||||
if ($_REQUEST['confirm']) {
|
||||
|
@ -2150,126 +2135,16 @@ function drop_item($id, $interactive = true) {
|
|||
goaway(System::baseUrl() . '/' . $_SESSION['return_url']);
|
||||
}
|
||||
|
||||
logger('delete item: ' . $item['id'], LOGGER_DEBUG);
|
||||
|
||||
// delete the item
|
||||
dba::update('item', ['deleted' => true, 'title' => '', 'body' => '',
|
||||
'edited' => datetime_convert(), 'changed' => datetime_convert()],
|
||||
['id' => $item['id']]);
|
||||
Item::delete($item['id']);
|
||||
|
||||
create_tags_from_item($item['id']);
|
||||
Term::createFromItem($item['id']);
|
||||
delete_thread($item['id'], $item['parent-uri']);
|
||||
|
||||
// clean up categories and tags so they don't end up as orphans
|
||||
|
||||
$matches = false;
|
||||
$cnt = preg_match_all('/<(.*?)>/', $item['file'], $matches, PREG_SET_ORDER);
|
||||
if ($cnt) {
|
||||
foreach ($matches as $mtch) {
|
||||
file_tag_unsave_file($item['uid'], $item['id'], $mtch[1],true);
|
||||
}
|
||||
}
|
||||
|
||||
$matches = false;
|
||||
|
||||
$cnt = preg_match_all('/\[(.*?)\]/', $item['file'], $matches, PREG_SET_ORDER);
|
||||
if ($cnt) {
|
||||
foreach ($matches as $mtch) {
|
||||
file_tag_unsave_file($item['uid'], $item['id'], $mtch[1],false);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If item is a link to a photo resource, nuke all the associated photos
|
||||
* (visitors will not have photo resources)
|
||||
* This only applies to photos uploaded from the photos page. Photos inserted into a post do not
|
||||
* generate a resource-id and therefore aren't intimately linked to the item.
|
||||
*/
|
||||
if (strlen($item['resource-id'])) {
|
||||
dba::delete('photo', ['resource-id' => $item['resource-id'], 'uid' => $item['uid']]);
|
||||
}
|
||||
|
||||
// If item is a link to an event, nuke the event record.
|
||||
if (intval($item['event-id'])) {
|
||||
dba::delete('event', ['id' => $item['event-id'], 'uid' => $item['uid']]);
|
||||
}
|
||||
|
||||
// If item has attachments, drop them
|
||||
foreach (explode(", ", $item['attach']) as $attach) {
|
||||
preg_match("|attach/(\d+)|", $attach, $matches);
|
||||
dba::delete('attach', ['id' => $matches[1], 'uid' => $item['uid']]);
|
||||
}
|
||||
|
||||
// The new code splits the queries since the mysql optimizer really has bad problems with subqueries
|
||||
|
||||
// Creating list of parents
|
||||
$r = q("SELECT `id` FROM `item` WHERE `parent` = %d AND `uid` = %d",
|
||||
intval($item['id']),
|
||||
intval($item['uid'])
|
||||
);
|
||||
|
||||
$parentid = "";
|
||||
|
||||
foreach ($r as $row) {
|
||||
if ($parentid != "") {
|
||||
$parentid .= ", ";
|
||||
}
|
||||
|
||||
$parentid .= $row["id"];
|
||||
}
|
||||
|
||||
// Now delete them
|
||||
if ($parentid != "") {
|
||||
q("DELETE FROM `sign` WHERE `iid` IN (%s)", dbesc($parentid));
|
||||
}
|
||||
|
||||
// If it's the parent of a comment thread, kill all the kids
|
||||
if ($item['uri'] == $item['parent-uri']) {
|
||||
dba::update('item', ['deleted' => true, 'title' => '', 'body' => '',
|
||||
'edited' => datetime_convert(), 'changed' => datetime_convert()],
|
||||
['parent-uri' => $item['parent-uri'], 'uid' => $item['uid']]);
|
||||
|
||||
create_tags_from_itemuri($item['parent-uri'], $item['uid']);
|
||||
Term::createFromItemURI($item['parent-uri'], $item['uid']);
|
||||
delete_thread_uri($item['parent-uri'], $item['uid']);
|
||||
// ignore the result
|
||||
} else {
|
||||
// ensure that last-child is set in case the comment that had it just got wiped.
|
||||
dba::update('item', ['last-child' => false, 'changed' => datetime_convert()],
|
||||
['parent-uri' => $item['parent-uri'], 'uid' => $item['uid']]);
|
||||
|
||||
// who is the last child now?
|
||||
$r = q("SELECT `id` FROM `item` WHERE `parent-uri` = '%s' AND `type` != 'activity' AND `deleted` = 0 AND `uid` = %d ORDER BY `edited` DESC LIMIT 1",
|
||||
dbesc($item['parent-uri']),
|
||||
intval($item['uid'])
|
||||
);
|
||||
if (DBM::is_result($r)) {
|
||||
dba::update('item', ['last-child' => true], ['id' => $r[0]['id']]);
|
||||
}
|
||||
}
|
||||
|
||||
// send the notification upstream/downstream
|
||||
// The priority depends on how the deletion is done.
|
||||
$drop_id = intval($item['id']);
|
||||
$priority = ($interactive ? PRIORITY_HIGH : PRIORITY_LOW);
|
||||
|
||||
Worker::add(['priority' => $priority, 'dont_fork' => true], "Notifier", "drop", $drop_id);
|
||||
|
||||
if (! $interactive) {
|
||||
return $owner;
|
||||
}
|
||||
goaway(System::baseUrl() . '/' . $_SESSION['return_url']);
|
||||
//NOTREACHED
|
||||
} else {
|
||||
if (! $interactive) {
|
||||
return 0;
|
||||
}
|
||||
notice( t('Permission denied.') . EOL);
|
||||
notice(t('Permission denied.') . EOL);
|
||||
goaway(System::baseUrl() . '/' . $_SESSION['return_url']);
|
||||
//NOTREACHED
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @todo: This query seems to be really slow
|
||||
|
|
|
@ -15,6 +15,7 @@ use Friendica\Database\DBM;
|
|||
use Friendica\Database\DBStructure;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Module\Login;
|
||||
|
||||
require_once 'include/enotify.php';
|
||||
|
@ -492,7 +493,7 @@ function admin_page_deleteitem_post(App $a)
|
|||
// associated threads.
|
||||
$r = dba::select('item', ['id'], ['guid' => $guid]);
|
||||
while ($row = dba::fetch($r)) {
|
||||
drop_item($row['id'], false);
|
||||
Item::delete($row['id']);
|
||||
}
|
||||
dba::close($r);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ use Friendica\Core\System;
|
|||
use Friendica\Core\Worker;
|
||||
use Friendica\Database\DBM;
|
||||
use Friendica\Model\Profile;
|
||||
use Friendica\Model\Item;
|
||||
|
||||
require_once 'include/bbcode.php';
|
||||
require_once 'include/datetime.php';
|
||||
|
@ -547,7 +548,7 @@ function events_content(App $a) {
|
|||
|
||||
// Delete only real events (no birthdays)
|
||||
if (DBM::is_result($ev) && $ev[0]['type'] == 'event') {
|
||||
$del = drop_item($ev[0]['itemid'], false);
|
||||
$del = Item::delete($ev[0]['itemid']);
|
||||
}
|
||||
|
||||
if ($del == 0) {
|
||||
|
|
|
@ -972,7 +972,11 @@ function item_content(App $a) {
|
|||
|
||||
$o = '';
|
||||
if (($a->argc == 3) && ($a->argv[1] === 'drop') && intval($a->argv[2])) {
|
||||
$o = drop_item($a->argv[2], !is_ajax());
|
||||
if (is_ajax()) {
|
||||
$o = Item::delete($a->argv[2]);
|
||||
} else {
|
||||
$o = drop_item($a->argv[2]);
|
||||
}
|
||||
if (is_ajax()) {
|
||||
// ajax return: [<item id>, 0 (no perm) | <owner id>]
|
||||
echo json_encode([intval($a->argv[2]), intval($o)]);
|
||||
|
|
|
@ -64,6 +64,102 @@ class Item
|
|||
return $rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delete an item and notify others about it - if it was ours
|
||||
*
|
||||
* @param integer $item_id Item ID that should be delete
|
||||
*
|
||||
* @return $boolean success
|
||||
*/
|
||||
public static function delete($item_id, $priority = PRIORITY_HIGH)
|
||||
{
|
||||
// locate item to be deleted
|
||||
$fields = ['id', 'uid', 'parent', 'parent-uri', 'origin', 'deleted', 'file', 'resource-id', 'event-id', 'attach'];
|
||||
$item = dba::selectFirst('item', $fields, ['id' => $item_id]);
|
||||
if (!DBM::is_result($item)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($item['deleted']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parent = dba::selectFirst('item', ['origin'], ['id' => $item['parent']]);
|
||||
if (!DBM::is_result($parent)) {
|
||||
$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;
|
||||
$cnt = preg_match_all('/<(.*?)>/', $item['file'], $matches, PREG_SET_ORDER);
|
||||
if ($cnt) {
|
||||
foreach ($matches as $mtch) {
|
||||
file_tag_unsave_file($item['uid'], $item['id'], $mtch[1],true);
|
||||
}
|
||||
}
|
||||
|
||||
$matches = false;
|
||||
|
||||
$cnt = preg_match_all('/\[(.*?)\]/', $item['file'], $matches, PREG_SET_ORDER);
|
||||
if ($cnt) {
|
||||
foreach ($matches as $mtch) {
|
||||
file_tag_unsave_file($item['uid'], $item['id'], $mtch[1],false);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If item is a link to a photo resource, nuke all the associated photos
|
||||
* (visitors will not have photo resources)
|
||||
* This only applies to photos uploaded from the photos page. Photos inserted into a post do not
|
||||
* generate a resource-id and therefore aren't intimately linked to the item.
|
||||
*/
|
||||
if (strlen($item['resource-id'])) {
|
||||
dba::delete('photo', ['resource-id' => $item['resource-id'], 'uid' => $item['uid']]);
|
||||
}
|
||||
|
||||
// If item is a link to an event, nuke the event record.
|
||||
if (intval($item['event-id'])) {
|
||||
dba::delete('event', ['id' => $item['event-id'], 'uid' => $item['uid']]);
|
||||
}
|
||||
|
||||
// If item has attachments, drop them
|
||||
foreach (explode(", ", $item['attach']) as $attach) {
|
||||
preg_match("|attach/(\d+)|", $attach, $matches);
|
||||
dba::delete('attach', ['id' => $matches[1], 'uid' => $item['uid']]);
|
||||
}
|
||||
|
||||
// When it is our item we don't delete it here, since we have to send delete messages
|
||||
if ($item['origin'] || $parent['origin']) {
|
||||
// Set the item to "deleted"
|
||||
dba::update('item', ['deleted' => true, 'title' => '', 'body' => '',
|
||||
'edited' => datetime_convert(), 'changed' => datetime_convert()],
|
||||
['id' => $item['id']]);
|
||||
|
||||
create_tags_from_item($item['id']);
|
||||
Term::createFromItem($item['id']);
|
||||
delete_thread($item['id'], $item['parent-uri']);
|
||||
|
||||
// If it's the parent of a comment thread, kill all the kids
|
||||
if ($item['id'] == $item['parent']) {
|
||||
$items = dba::select('item', ['id'], ['parent' => $item['parent']]);
|
||||
while ($row = dba::fetch($items)) {
|
||||
self::delete($row['id'], $priority);
|
||||
}
|
||||
}
|
||||
|
||||
// send the notification upstream/downstream
|
||||
Worker::add(['priority' => $priority, 'dont_fork' => true], "Notifier", "drop", intval($item['id']));
|
||||
} else {
|
||||
// delete it immediately. All related children will be deleted as well.
|
||||
dba::delete('item', ['id' => $item['id']]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a shadow entry for a given item id that is a thread starter
|
||||
*
|
||||
|
|
|
@ -29,7 +29,6 @@ class Delivery {
|
|||
|
||||
logger('delivery: invoked: '.$cmd.': '.$item_id.' to '.$contact_id, LOGGER_DEBUG);
|
||||
|
||||
$expire = false;
|
||||
$mail = false;
|
||||
$fsuggest = false;
|
||||
$relocate = false;
|
||||
|
@ -54,18 +53,6 @@ class Delivery {
|
|||
$uid = $message[0]['uid'];
|
||||
$recipients[] = $message[0]['contact-id'];
|
||||
$item = $message[0];
|
||||
} elseif ($cmd === 'expire') {
|
||||
$normal_mode = false;
|
||||
$expire = true;
|
||||
$items = q("SELECT * FROM `item` WHERE `uid` = %d AND `wall` = 1
|
||||
AND `deleted` = 1 AND `changed` > UTC_TIMESTAMP() - INTERVAL 30 MINUTE",
|
||||
intval($item_id)
|
||||
);
|
||||
$uid = $item_id;
|
||||
$item_id = 0;
|
||||
if (!count($items)) {
|
||||
return;
|
||||
}
|
||||
} elseif ($cmd === 'suggest') {
|
||||
$normal_mode = false;
|
||||
$fsuggest = true;
|
||||
|
@ -160,16 +147,6 @@ class Delivery {
|
|||
// if $parent['wall'] == 1 we will already have the parent message in our array
|
||||
// and we will relay the whole lot.
|
||||
|
||||
// expire sends an entire group of expire messages and cannot be forwarded.
|
||||
// However the conversation owner will be a part of the conversation and will
|
||||
// be notified during this run.
|
||||
// Other DFRN conversation members will be alerted during polled updates.
|
||||
|
||||
// Diaspora members currently are not notified of expirations, and other networks have
|
||||
// either limited or no ability to process deletions. We should at least fix Diaspora
|
||||
// by stringing togther an array of retractions and sending them onward.
|
||||
|
||||
|
||||
$localhost = $a->get_hostname();
|
||||
if (strpos($localhost,':')) {
|
||||
$localhost = substr($localhost,0,strpos($localhost,':'));
|
||||
|
@ -184,7 +161,7 @@ class Delivery {
|
|||
|
||||
$relay_to_owner = false;
|
||||
|
||||
if (!$top_level && ($parent['wall'] == 0) && !$expire && stristr($target_item['uri'],$localhost)) {
|
||||
if (!$top_level && ($parent['wall'] == 0) && stristr($target_item['uri'], $localhost)) {
|
||||
$relay_to_owner = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@ require_once 'include/bbcode.php';
|
|||
* drop (in diaspora.php, items.php, photos.php)
|
||||
* edit_post (in item.php)
|
||||
* event (in events.php)
|
||||
* expire (in items.php)
|
||||
* like (in like.php, poke.php)
|
||||
* mail (in message.php)
|
||||
* suggest (in fsuggest.php)
|
||||
|
@ -60,7 +59,6 @@ class Notifier {
|
|||
|
||||
logger('notifier: invoked: '.$cmd.': '.$item_id, LOGGER_DEBUG);
|
||||
|
||||
$expire = false;
|
||||
$mail = false;
|
||||
$fsuggest = false;
|
||||
$relocate = false;
|
||||
|
@ -82,19 +80,6 @@ class Notifier {
|
|||
$uid = $message[0]['uid'];
|
||||
$recipients[] = $message[0]['contact-id'];
|
||||
$item = $message[0];
|
||||
|
||||
} elseif ($cmd === 'expire') {
|
||||
$normal_mode = false;
|
||||
$expire = true;
|
||||
$items = q("SELECT * FROM `item` WHERE `uid` = %d AND `wall` = 1
|
||||
AND `deleted` = 1 AND `changed` > UTC_TIMESTAMP() - INTERVAL 10 MINUTE",
|
||||
intval($item_id)
|
||||
);
|
||||
$uid = $item_id;
|
||||
$item_id = 0;
|
||||
if (!count($items)) {
|
||||
return;
|
||||
}
|
||||
} elseif ($cmd === 'suggest') {
|
||||
$normal_mode = false;
|
||||
$fsuggest = true;
|
||||
|
@ -213,18 +198,6 @@ class Notifier {
|
|||
// if $parent['wall'] == 1 we will already have the parent message in our array
|
||||
// and we will relay the whole lot.
|
||||
|
||||
// expire sends an entire group of expire messages and cannot be forwarded.
|
||||
// However the conversation owner will be a part of the conversation and will
|
||||
// be notified during this run.
|
||||
// Other DFRN conversation members will be alerted during polled updates.
|
||||
|
||||
|
||||
|
||||
// Diaspora members currently are not notified of expirations, and other networks have
|
||||
// either limited or no ability to process deletions. We should at least fix Diaspora
|
||||
// by stringing togther an array of retractions and sending them onward.
|
||||
|
||||
|
||||
$localhost = str_replace('www.','',$a->get_hostname());
|
||||
if (strpos($localhost,':')) {
|
||||
$localhost = substr($localhost,0,strpos($localhost,':'));
|
||||
|
@ -239,7 +212,7 @@ class Notifier {
|
|||
|
||||
$relay_to_owner = false;
|
||||
|
||||
if (!$top_level && ($parent['wall'] == 0) && !$expire && (stristr($target_item['uri'],$localhost))) {
|
||||
if (!$top_level && ($parent['wall'] == 0) && (stristr($target_item['uri'],$localhost))) {
|
||||
$relay_to_owner = true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue