From a6d8668a5f31def1a74fcdfe15a184acfe3d696d Mon Sep 17 00:00:00 2001 From: friendica Date: Thu, 27 Mar 2014 20:28:48 -0700 Subject: try and sort out the item delete mess --- boot.php | 8 +++++++ include/expire.php | 16 ++++++++++++-- include/items.php | 65 ++++++++++++++++++++++++++++++++++++++++++------------ include/zot.php | 6 ++--- mod/item.php | 14 ++++++++++-- 5 files changed, 88 insertions(+), 21 deletions(-) diff --git a/boot.php b/boot.php index 115b5cd0c..737e11001 100755 --- a/boot.php +++ b/boot.php @@ -329,6 +329,12 @@ define ( 'UPDATE_FLAGS_FORCED', 0x0002); define ( 'UPDATE_FLAGS_DELETED', 0x1000); + +define ( 'DROPITEM_NORMAL', 0); +define ( 'DROPITEM_PHASE1', 1); +define ( 'DROPITEM_PHASE2', 2); + + /** * Maximum number of "people who like (or don't like) this" that we will list by name */ @@ -511,6 +517,8 @@ define ( 'ITEM_DELAYED_PUBLISH', 0x0080); define ( 'ITEM_BUILDBLOCK', 0x0100); // Named thusly to make sure nobody confuses this with ITEM_BLOCKED define ( 'ITEM_PDL', 0x0200); // Page Description Language - e.g. Comanche define ( 'ITEM_BUG', 0x0400); // Is a bug, can be used by the internal bug tracker +define ( 'ITEM_PENDING_REMOVE', 0x0800); // deleted, notification period has lapsed + /** * Item Flags */ diff --git a/include/expire.php b/include/expire.php index efce64ee4..442914a39 100644 --- a/include/expire.php +++ b/include/expire.php @@ -7,10 +7,20 @@ function expire_run($argv, $argc){ cli_startup(); + $r = q("select id from item where (item_restrict & %d) and not (item_restrict & %d) and changed < UTC_TIMESTAMP() - INTERVAL 10 DAY", + intval(ITEM_DELETED), + intval(ITEM_PENDING_REMOVE) + ); + if($r) { + foreach($r as $rr) { + drop_item($rr['id'],false,DROPITEM_PHASE2); + } + } + // physically remove anything that has been deleted for more than two months - $r = q("delete from item where ( item_flags & %d ) and changed < UTC_TIMESTAMP() - INTERVAL 60 DAY", - intval(ITEM_DELETED) + $r = q("delete from item where ( item_restrict & %d ) and changed < UTC_TIMESTAMP() - INTERVAL 36 DAY", + intval(ITEM_PENDING_REMOVE) ); // make this optional as it could have a performance impact on large sites @@ -42,6 +52,8 @@ function expire_run($argv, $argc){ if($expire_days) item_expire($x['channel_id'],$expire_days); } + + return; } diff --git a/include/items.php b/include/items.php index cd86918d6..dcf9f5bc2 100755 --- a/include/items.php +++ b/include/items.php @@ -3493,7 +3493,12 @@ function drop_items($items) { // permissions to carry out this act. If it is non-interactive, we are deleting something at the // system's request and do not check permission. This is very important to know. -function drop_item($id,$interactive = true) { +// Some deletion requests (those coming from remote sites) must be staged. +// $stage = 0 => unstaged +// $stage = 1 => set deleted flag on the item and perform intial notifications +// $stage = 2 => perform low level delete at a later stage + +function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL) { $a = get_app(); @@ -3503,7 +3508,7 @@ function drop_item($id,$interactive = true) { intval($id) ); - if((! $r) || ($r[0]['item_restrict'] & ITEM_DELETED)) { + if((! $r) || (($r[0]['item_restrict'] & ITEM_DELETED) && ($stage === DROPITEM_NORMAL))) { if(! $interactive) return 0; notice( t('Item not found.') . EOL); @@ -3537,7 +3542,7 @@ function drop_item($id,$interactive = true) { intval($item['id']) ); - $arr = array('item' => $item); + $arr = array('item' => $item, 'interactive' => $interactive, 'stage' => $stage); call_hooks('drop_item', $arr ); $notify_id = intval($item['id']); @@ -3548,10 +3553,10 @@ function drop_item($id,$interactive = true) { ); if($items) { foreach($items as $i) - delete_item_lowlevel($i); + delete_item_lowlevel($i,$stage); } else - delete_item_lowlevel($item); + delete_item_lowlevel($item,$stage); if(! $interactive) return 1; @@ -3559,7 +3564,7 @@ function drop_item($id,$interactive = true) { // send the notification upstream/downstream as the case may be // only send notifications to others if this is the owner's wall item. - if($item['item_flags'] & ITEM_WALL) + if(($item['item_flags'] & ITEM_WALL) && ($stage != DROPITEM_PHASE2)) proc_run('php','include/notifier.php','drop',$notify_id); goaway($a->get_baseurl() . '/' . $_SESSION['return_url']); @@ -3578,15 +3583,47 @@ function drop_item($id,$interactive = true) { // It merely destroys all resources associated with an item. // Please do not use without a suitable wrapper. -function delete_item_lowlevel($item) { +function delete_item_lowlevel($item,$stage = DROPITEM_NORMAL) { - $r = q("UPDATE item SET item_restrict = ( item_restrict | %d ), title = '', body = '', - changed = '%s', edited = '%s' WHERE id = %d LIMIT 1", - intval(ITEM_DELETED), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - intval($item['id']) - ); + + switch($stage) { + case DROPITEM_PHASE2: + $r = q("UPDATE item SET item_restrict = ( item_restrict | %d ), body = '', title = '', + changed = '%s', edited = '%s' WHERE id = %d LIMIT 1", + intval(ITEM_PENDING_REMOVE), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + intval($item['id']) + ); + break; + + case DROPITEM_PHASE1: + $r = q("UPDATE item SET item_restrict = ( item_restrict | %d ), + changed = '%s', edited = '%s' WHERE id = %d LIMIT 1", + intval(ITEM_DELETED), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + intval($item['id']) + ); + break; + + case DROPITEM_NORMAL: + default: + $r = q("UPDATE item SET item_restrict = ( item_restrict | %d ), body = '', title = '', + changed = '%s', edited = '%s' WHERE id = %d LIMIT 1", + intval(ITEM_DELETED), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + intval($item['id']) + ); + break; + } + + // network deletion request. Keep the message structure so that we can deliver delete notifications. + // Come back after several days (or perhaps a month) to do the lowlevel delete (DROPITEM_PHASE2). + + if($stage == DROPITEM_PHASE1) + return true; $r = q("delete from term where otype = %d and oid = %d limit 1", intval(TERM_OBJ_POST), diff --git a/include/zot.php b/include/zot.php index 394563563..b23c18bdb 100644 --- a/include/zot.php +++ b/include/zot.php @@ -1597,10 +1597,10 @@ function delete_imported_item($sender,$item,$uid) { // We can't reverse the order because drop_item refuses to run if the item already has the deleted flag set and we need to // set that flag prior to calling tag_deliver. - // One possibility would be to set the deleted flag, call both tag_deliver and the notifier to notify downstream channels - // and then clean up after ourselves with a cron job after a day or two to do the delete_item_lowlevel(). + // Use phased deletion to set the deleted flag, call both tag_deliver and the notifier to notify downstream channels + // and then clean up after ourselves with a cron job after several days to do the delete_item_lowlevel() (DROPITEM_PHASE2). - drop_item($r[0]['uid'],false); + drop_item($r[0]['id'],false, DROPITEM_PHASE1); tag_deliver($uid,$r[0]['id']); diff --git a/mod/item.php b/mod/item.php index 5a3691d5e..2fa978b44 100644 --- a/mod/item.php +++ b/mod/item.php @@ -890,9 +890,19 @@ function item_content(&$a) { require_once('include/security.php'); - if(($a->argc == 3) && ($a->argv[1] === 'drop') && intval($a->argv[2])) { + if((argc() == 3) && (argv(1) === 'drop') && intval(argv(2))) { require_once('include/items.php'); - drop_item($a->argv[2]); + $i = q("select id, item_restrict from item where id = %d and uid = %d limit 1", + intval(argv(2)) + ); + if($i) { + if($i[0]['item_restrict']) + drop_item($i[0]['id']); + else { + drop_item($i[0]['id'],true,DROPITEM_PHASE1); + tag_deliver($uid,$i[0]['id']); + } + } } } -- cgit v1.2.3