diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php index 2209a4c43..2096c2fff 100644 --- a/Zotlabs/Daemon/Notifier.php +++ b/Zotlabs/Daemon/Notifier.php @@ -539,7 +539,7 @@ class Notifier { $hubs = q("select hubloc.*, site.site_crypto, site.site_flags from hubloc left join site on site_url = hubloc_url where hubloc_hash in (" . protect_sprintf(implode(',',self::$recipients)) . ") - and hubloc_error = 0 and hubloc_deleted = 0 and ( site_dead = 0 OR site_dead is null ) " + and hubloc_error = 0 and hubloc_deleted = 0 " ); // public posts won't make it to the local public stream unless there's a recipient on this site. diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php index 7eaae1a64..804696fe8 100644 --- a/Zotlabs/Lib/Activity.php +++ b/Zotlabs/Lib/Activity.php @@ -42,7 +42,7 @@ class Activity { // Eventually this needs to be passed in much further up the stack // and base the decision on whether or not we are encoding for ActivityPub or Zot6 - return self::fetch_item($x,((get_config('system','activitypub',true)) ? true : false)); + return self::fetch_item($x,((get_config('system','activitypub', ACTIVITYPUB_ENABLED)) ? true : false)); } if ($x['type'] === ACTIVITY_OBJ_THING) { return self::fetch_thing($x); @@ -1268,10 +1268,10 @@ class Activity { ]; $ret['url'] = $p['xchan_url']; - if ($activitypub && get_config('system','activitypub',true)) { + if ($activitypub && get_config('system','activitypub', ACTIVITYPUB_ENABLED)) { if ($c) { - if (get_pconfig($c['channel_id'],'system','activitypub',true)) { + if (get_pconfig($c['channel_id'],'system','activitypub', ACTIVITYPUB_ENABLED)) { $ret['inbox'] = z_root() . '/inbox/' . $c['channel_address']; } else { @@ -2798,10 +2798,10 @@ class Activity { return; } - static function store($channel,$observer_hash,$act,$item,$fetch_parents = true) { + static function store($channel,$observer_hash,$act,$item,$fetch_parents = true, $force = false) { - if ($act && $act->implied_create) { + if ($act && $act->implied_create && ! $force) { // This is originally a S2S object with no associated activity logger('Not storing implied create activity!'); return; @@ -2927,7 +2927,7 @@ class Activity { } } - if (! $allowed) { + if (! $allowed && ! $force) { logger('no permission'); return; } @@ -2999,7 +2999,7 @@ class Activity { intval($item['uid']) ); if (! $parent) { - if (! get_config('system','activitypub',true)) { + if (! get_config('system','activitypub', ACTIVITYPUB_ENABLED)) { return; } else { diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index ae06a0c4b..46af46479 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -308,82 +308,81 @@ class Apps { static public function translate_system_apps(&$arr) { $apps = array( + 'Admin' => t('Site Admin'), 'Apps' => t('Apps'), - 'Friend Zoom' => t('Friend Zoom'), - 'Virtual Lists' => t('Virtual Lists'), - 'Markup' => t('Markup'), 'Articles' => t('Articles'), + 'CalDAV' => t('CalDAV'), + 'CardDAV' => t('CardDAV'), 'Cards' => t('Cards'), 'Calendar' => t('Calendar'), 'Categories' => t('Categories'), + 'Channel Home' => t('Channel Home'), + 'Channel Manager' => t('Channel Manager'), + 'Channel Sources' => t('Channel Sources'), + 'Chat' => t('Chat'), + 'Chatrooms' => t('Chatrooms'), 'Clients' => t('Clients'), - 'Admin' => t('Site Admin'), + 'Comment Control' => t('Comment Control'), + 'Connections' => t('Connections'), 'Content Filter' => t('Content Filter'), 'Content Import' => t('Content Import'), - 'Report Bug' => t('Report Bug'), - 'View Bookmarks' => t('View Bookmarks'), - 'Chatrooms' => t('Chatrooms'), - 'Followlist' => t('Followlist'), - 'Content Import' => t('Content Import'), - 'Connections' => t('Connections'), + 'Directory' => t('Directory'), + 'Drafts' => t('Drafts'), + 'Events' => t('Events'), 'Expire Posts' => t('Expire Posts'), + 'Features' => t('Features'), + 'Files' => t('Files'), + 'Followlist' => t('Followlist'), + 'Friend Zoom' => t('Friend Zoom'), 'Future Posting' => t('Future Posting'), - 'Remote Diagnostics' => t('Remote Diagnostics'), - 'Suggest Channels' => t('Suggest Channels'), + 'Gallery' => t('Gallery'), + 'Guest Access' => t('Guest Access'), + 'Help' => t('Help'), + 'Invite' => t('Invite'), + 'Language' => t('Language'), + 'Lists' => t('Lists'), 'Login' => t('Login'), - 'Channel Manager' => t('Channel Manager'), + 'Mail' => t('Mail'), + 'Markup' => t('Markup'), + 'Mood' => t('Mood'), + 'My Chatrooms' => t('My Chatrooms'), + 'No Comment' => t('No Comment'), 'Notes' => t('Notes'), - 'Stream' => t('Stream'), + 'Notifications' => t('Notifications'), + 'OAuth Apps Manager' => t('OAuth Apps Manager'), + 'OAuth2 Apps Manager' => t('OAuth2 Apps Manager'), + 'Order Apps' => t('Order Apps'), + 'PDL Editor' => t('PDL Editor'), + 'Permission Categories' => t('Permission Categories'), + 'Photos' => t('Photos'), + 'Photomap' => t('Photomap'), + 'Poke' => t('Poke'), + 'Post' => t('Post'), + 'Premium Channel' => t('Premium Channel'), + 'Probe' => t('Probe'), + 'Profile' => t('Profile'), + 'Profile Photo' => t('Profile Photo'), + 'Profiles' => t('Profiles'), + 'Public Stream' => t('Public Stream'), + 'Random Channel' => t('Random Channel'), + 'Remote Diagnostics' => t('Remote Diagnostics'), + 'Report Bug' => t('Report Bug'), + 'Search' => t('Search'), 'Secrets' => t('Secrets'), 'Settings' => t('Settings'), 'Sites' => t('Sites'), - 'Files' => t('Files'), + 'Stream' => t('Stream'), + 'Stream Order' => t('Stream Order'), + 'Suggest' => t('Suggest'), + 'Suggest Channels' => t('Suggest Channels'), + 'Tagadelic' => t('Tagadelic'), + 'Tasks' => t('Tasks'), + 'View Bookmarks' => t('View Bookmarks'), + 'View Profile' => t('View Profile'), + 'Virtual Lists' => t('Virtual Lists'), 'Webpages' => t('Webpages'), 'Wiki' => t('Wiki'), - 'Channel Home' => t('Channel Home'), - 'View Profile' => t('View Profile'), - 'Photos' => t('Photos'), - 'Photomap' => t('Photomap'), - 'Events' => t('Events'), - 'Tasks' => t('Tasks'), - 'Tagadelic' => t('Tagadelic'), - 'No Comment' => t('No Comment'), - 'Comment Control' => t('Comment Control'), - 'Directory' => t('Directory'), - 'Help' => t('Help'), - 'Mail' => t('Mail'), - 'Mood' => t('Mood'), - 'Poke' => t('Poke'), - 'Chat' => t('Chat'), - 'Search' => t('Search'), - 'Stream Order' => t('Stream Order'), - 'Probe' => t('Probe'), - 'Suggest' => t('Suggest'), - 'Random Channel' => t('Random Channel'), - 'Invite' => t('Invite'), - 'Features' => t('Features'), - 'Language' => t('Language'), - 'Post' => t('Post'), 'ZotPost' => t('ZotPost'), - 'Profile Photo' => t('Profile Photo'), - 'Profile' => t('Profile'), - 'Profiles' => t('Profiles'), - 'Lists' => t('Lists'), - 'Notifications' => t('Notifications'), - 'Order Apps' => t('Order Apps'), - 'CalDAV' => t('CalDAV'), - 'CardDAV' => t('CardDAV'), - 'Channel Sources' => t('Channel Sources'), - 'Gallery' => t('Gallery'), - 'Guest Access' => t('Guest Access'), - 'Notes' => t('Notes'), - 'OAuth Apps Manager' => t('OAuth Apps Manager'), - 'OAuth2 Apps Manager' => t('OAuth2 Apps Manager'), - 'PDL Editor' => t('PDL Editor'), - 'Permission Categories' => t('Permission Categories'), - 'Premium Channel' => t('Premium Channel'), - 'Public Stream' => t('Public Stream'), - 'My Chatrooms' => t('My Chatrooms') ); if (array_key_exists('name',$arr)) { diff --git a/Zotlabs/Lib/Connect.php b/Zotlabs/Lib/Connect.php index c8ee370a0..90e92f331 100644 --- a/Zotlabs/Lib/Connect.php +++ b/Zotlabs/Lib/Connect.php @@ -34,7 +34,7 @@ class Connect { $my_perms = false; $protocol = ''; - $ap_allowed = get_config('system','activitypub',true) && get_pconfig($uid,'system','activitypub',true); + $ap_allowed = get_config('system','activitypub', ACTIVITYPUB_ENABLED) && get_pconfig($uid,'system','activitypub', ACTIVITYPUB_ENABLED); if (substr($url,0,1) === '[') { $x = strpos($url,']'); diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index f6d87a0ea..b9fb17a83 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -3120,7 +3120,7 @@ class Libzot { $ret['channel_role'] = get_pconfig($e['channel_id'],'system','permissions_role','custom'); $ret['channel_type'] = $channel_type; $ret['protocols'] = [ 'zot6' ]; - if (get_pconfig($e['channel_id'],'system','activitypub',get_config('system','activitypub',true))) { + if (get_pconfig($e['channel_id'],'system','activitypub',get_config('system','activitypub', ACTIVITYPUB_ENABLED))) { $ret['protocols'][] = 'activitypub'; } $ret['searchable'] = $searchable; diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index 151540e21..439a37522 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -478,7 +478,7 @@ class ThreadItem { $result['children'] = []; - if (local_channel() && get_pconfig(local_channel(),'system','activitypub',get_config('system','activitypub',true))) { + if (local_channel() && get_pconfig(local_channel(),'system','activitypub',get_config('system','activitypub', ACTIVITYPUB_ENABLED))) { // place to store all the author addresses (links if not available) in the thread so we can auto-mention them in JS. $result['authors'] = []; // fix to add in sub-replies if replying to a comment on your own post from the top level. diff --git a/Zotlabs/Module/Admin/Site.php b/Zotlabs/Module/Admin/Site.php index eeb0525cc..fdbcafdbd 100644 --- a/Zotlabs/Module/Admin/Site.php +++ b/Zotlabs/Module/Admin/Site.php @@ -299,7 +299,7 @@ class Site { '$theme' => [ 'theme', t("System theme"), get_config('system','theme'), t("Default system theme - may be over-ridden by user profiles - change theme settings"), $theme_choices ], // '$theme_mobile' => [ 'theme_mobile', t("Mobile system theme"), get_config('system','mobile_theme'), t("Theme for mobile devices"), $theme_choices_mobile ], // '$site_channel' => [ 'site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel") ], - '$ap_contacts' => [ 'ap_contacts', t('ActivityPub protocol'),get_config('system','activitypub',true),t('Provides access to software supporting the ActivityPub protocol.') ], + '$ap_contacts' => [ 'ap_contacts', t('ActivityPub protocol'),get_config('system','activitypub', ACTIVITYPUB_ENABLED),t('Provides access to software supporting the ActivityPub protocol.') ], '$maximagesize' => [ 'maximagesize', t("Maximum image size"), intval(get_config('system','maximagesize')), t("Maximum size in bytes of uploaded images. Default is 0, which means no limits.") ], '$cache_images' => [ 'cache_images', t('Cache all public images'), intval(get_config('system','cache_images',1)), t('If disabled, proxy non-SSL images, but do not store locally') ], '$register_policy' => [ 'register_policy', t("Does this site allow new member registration?"), get_config('system','register_policy'), "", $register_choices ], diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index a9e939a1e..06cc1fd4b 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -477,6 +477,7 @@ class Channel extends Controller { '$spam' => '0', '$nouveau' => '0', '$wall' => '1', + '$draft' => '0', '$fh' => '0', '$dm' => '0', '$static' => $static, diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php index d828e2cd2..9eb6a38f9 100644 --- a/Zotlabs/Module/Display.php +++ b/Zotlabs/Module/Display.php @@ -233,6 +233,7 @@ class Display extends Controller { '$dm' => '0', '$nouveau' => '0', '$wall' => '0', + '$draft' => '0', '$static' => $static, '$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1), '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0), @@ -323,7 +324,7 @@ class Display extends Controller { if($parents_str) { $items = q("SELECT item.*, item.id AS item_id FROM item - WHERE parent in ( %s ) $item_normal ", + WHERE parent in ( %s ) $item_normal $sql_extra ", dbesc($parents_str) ); xchan_query($items); diff --git a/Zotlabs/Module/Drafts.php b/Zotlabs/Module/Drafts.php new file mode 100644 index 000000000..0d7431452 --- /dev/null +++ b/Zotlabs/Module/Drafts.php @@ -0,0 +1,29 @@ +' . $desc . ''; + + if(! ( local_channel() && Apps::system_app_installed(local_channel(),'Drafts'))) { + return $text; + } + + } +} diff --git a/Zotlabs/Module/Editpost.php b/Zotlabs/Module/Editpost.php index 4d4997a9c..2e0ca6756 100644 --- a/Zotlabs/Module/Editpost.php +++ b/Zotlabs/Module/Editpost.php @@ -85,6 +85,11 @@ class Editpost extends \Zotlabs\Web\Controller { } } + if (intval($itm[0]['item_unpublished'])) { + // clear the old creation date if editing a saved draft. These will always show as just created. + unset($itm[0]['created']); + } + $x = array( 'nickname' => $channel['channel_address'], 'item' => $itm[0], @@ -95,6 +100,7 @@ class Editpost extends \Zotlabs\Web\Controller { 'hide_voting' => true, 'hide_future' => true, 'hide_location' => true, + 'is_draft' => ((intval($itm[0]['item_unpublished'])) ? true : false), 'parent' => (($itm[0]['mid'] === $itm[0]['parent_mid']) ? 0 : $itm[0]['parent']), 'mimetype' => $itm[0]['mimetype'], 'ptyp' => $itm[0]['obj_type'], @@ -104,7 +110,9 @@ class Editpost extends \Zotlabs\Web\Controller { 'visitor' => true, 'title' => htmlspecialchars_decode($itm[0]['title'],ENT_COMPAT), 'category' => $category, - 'showacl' => false, + 'showacl' => ((intval($itm[0]['unpublished'])) ? true : false), + // @todo - need acl and lockstate when item_unpublished is 1 + 'permissions' => $itm[0], 'profile_uid' => $owner_uid, 'catsenabled' => $catsenabled, 'collections' => $collections, diff --git a/Zotlabs/Module/Hq.php b/Zotlabs/Module/Hq.php index 8c763d6be..61a374184 100644 --- a/Zotlabs/Module/Hq.php +++ b/Zotlabs/Module/Hq.php @@ -185,6 +185,7 @@ class Hq extends Controller { '$dm' => '0', '$nouveau' => '0', '$wall' => '0', + '$draft' => '0', '$static' => $static, '$page' => 1, '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0), diff --git a/Zotlabs/Module/Id.php b/Zotlabs/Module/Id.php index 3e8892640..30e87f8d2 100644 --- a/Zotlabs/Module/Id.php +++ b/Zotlabs/Module/Id.php @@ -90,7 +90,7 @@ class Id extends Controller { xchan_query($r,true); $items = fetch_post_tags($r,true); - $i = Activity::encode_item($items[0],( get_config('system','activitypub',true) ? true : false )); + $i = Activity::encode_item($items[0],( get_config('system','activitypub', ACTIVITYPUB_ENABLED) ? true : false )); if(! $i) http_status_exit(404, 'Not found'); diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index e955c6bcb..9acdfa574 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -301,7 +301,7 @@ class Item extends Controller { $parent_mid = ((x($_REQUEST,'parent_mid')) ? trim($_REQUEST['parent_mid']) : ''); $hidden_mentions = ((x($_REQUEST,'hidden_mentions')) ? trim($_REQUEST['hidden_mentions']) : ''); - $comments_closed = ((x($_REQUEST,'comments_closed')) ? datetime_convert(date_default_timezone_get(),'UTC',$_REQUEST['comments_closed']) : NULL_DATE); + /** * Who is viewing this page and posting this thing @@ -338,6 +338,14 @@ class Item extends Controller { if (isset($_REQUEST['comments_enabled'])) { $nocomment = 1 - intval($_REQUEST['comments_enabled']); } + + $channel_comments_closed = get_pconfig($profile_uid,'system','close_comments'); + if (! intval($channel_comments_closed)) { + $channel_comments_closed = NULL_DATE; + } + + $comments_closed = ((x($_REQUEST,'comments_closed')) ? datetime_convert(date_default_timezone_get(),'UTC',$_REQUEST['comments_closed']) : $channel_comments_closed); + $is_poll = ((trim($_REQUEST['poll_answers'][0]) != '' && trim($_REQUEST['poll_answers'][1]) != '') ? true : false); // 'origin' (if non-zero) indicates that this network is where the message originated, @@ -366,8 +374,9 @@ class Item extends Controller { if ($created <= NULL_DATE) { $created = datetime_convert(); } - + $post_id = ((x($_REQUEST,'post_id')) ? intval($_REQUEST['post_id']) : 0); + $app = ((x($_REQUEST,'source')) ? strip_tags($_REQUEST['source']) : ''); $return_path = ((x($_REQUEST,'return')) ? $_REQUEST['return'] : ''); $preview = ((x($_REQUEST,'preview')) ? intval($_REQUEST['preview']) : 0); @@ -379,6 +388,9 @@ class Item extends Controller { $plink = ((x($_REQUEST,'permalink')) ? escape_tags($_REQUEST['permalink']) : ''); $obj_type = ((x($_REQUEST,'obj_type')) ? escape_tags($_REQUEST['obj_type']) : ACTIVITY_OBJ_NOTE); + + $item_unpublished = ((isset($_REQUEST['draft'])) ? intval($_REQUEST['draft']) : 0); + // allow API to bulk load a bunch of imported items without sending out a bunch of posts. $nopush = ((x($_REQUEST,'nopush')) ? intval($_REQUEST['nopush']) : 0); @@ -655,6 +667,7 @@ class Item extends Controller { $private = 1; if($orig_post) { + $private = 0; // webpages are allowed to change ACLs after the fact. Normal conversation items aren't. if($webpage) { @@ -677,40 +690,39 @@ class Item extends Controller { $title = escape_tags(trim($_REQUEST['title'])); $summary = trim($_REQUEST['summary']); $body = trim($_REQUEST['body']); - $item_flags = $orig_post['item_flags']; - $item_origin = $orig_post['item_origin']; - $item_unseen = $orig_post['item_unseen']; - $item_starred = $orig_post['item_starred']; - $item_uplink = $orig_post['item_uplink']; - $item_wall = $orig_post['item_wall']; + $item_flags = $orig_post['item_flags']; + $item_origin = $orig_post['item_origin']; + $item_unseen = $orig_post['item_unseen']; + $item_starred = $orig_post['item_starred']; + $item_uplink = $orig_post['item_uplink']; + $item_wall = $orig_post['item_wall']; $item_thread_top = $orig_post['item_thread_top']; - $item_notshown = $orig_post['item_notshown']; - $item_nsfw = $orig_post['item_nsfw']; - $item_relay = $orig_post['item_relay']; + $item_notshown = $orig_post['item_notshown']; + $item_nsfw = $orig_post['item_nsfw']; + $item_relay = $orig_post['item_relay']; $item_mentionsme = $orig_post['item_mentionsme']; - $item_nocomment = $orig_post['item_nocomment']; - $item_obscured = $orig_post['item_obscured']; - $item_verified = $orig_post['item_verified']; - $item_retained = $orig_post['item_retained']; - $item_rss = $orig_post['item_rss']; - $item_deleted = $orig_post['item_deleted']; - $item_type = $orig_post['item_type']; - $item_hidden = $orig_post['item_hidden']; - $item_unpublished = $orig_post['item_unpublished']; - $item_delayed = $orig_post['item_delayed']; - $item_pending_remove = $orig_post['item_pending_remove']; - $item_blocked = $orig_post['item_blocked']; + $item_nocomment = $orig_post['item_nocomment']; + $item_obscured = $orig_post['item_obscured']; + $item_verified = $orig_post['item_verified']; + $item_retained = $orig_post['item_retained']; + $item_rss = $orig_post['item_rss']; + $item_deleted = $orig_post['item_deleted']; + $item_type = $orig_post['item_type']; + $item_hidden = $orig_post['item_hidden']; + $item_delayed = $orig_post['item_delayed']; + $item_pending_remove = $orig_post['item_pending_remove']; + $item_blocked = $orig_post['item_blocked']; $postopts = $orig_post['postopts']; - $created = $orig_post['created']; - $expires = $orig_post['expires']; + $created = ((intval($orig_post['item_unpublished'])) ? $created : $orig_post['created']); + $expires = ((intval($orig_post['item_unpublished'])) ? NULL_DATE : $orig_post['expires']); $mid = $orig_post['mid']; $parent_mid = $orig_post['parent_mid']; $plink = $orig_post['plink']; - + } else { if(! $walltowall) { @@ -1214,7 +1226,6 @@ class Item extends Controller { } } - if ((! $plink) && ($item_thread_top)) { $plink = z_root() . '/item/' . $uuid; } @@ -1229,11 +1240,11 @@ class Item extends Controller { $datarray['owner_xchan'] = (($owner_hash) ? $owner_hash : $owner_xchan['xchan_hash']); $datarray['author_xchan'] = $observer['xchan_hash']; $datarray['created'] = $created; - $datarray['edited'] = (($orig_post) ? datetime_convert() : $created); + $datarray['edited'] = (($orig_post && (! intval($orig_post['item_unpublished']))) ? datetime_convert() : $created); $datarray['expires'] = $expires; - $datarray['commented'] = (($orig_post) ? datetime_convert() : $created); - $datarray['received'] = (($orig_post) ? datetime_convert() : $created); - $datarray['changed'] = (($orig_post) ? datetime_convert() : $created); + $datarray['commented'] = (($orig_post && (! intval($orig_post['item_unpublished']))) ? datetime_convert() : $created); + $datarray['received'] = (($orig_post && (! intval($orig_post['item_unpublished']))) ? datetime_convert() : $created); + $datarray['changed'] = (($orig_post && (! intval($orig_post['item_unpublished']))) ? datetime_convert() : $created); $datarray['comments_closed'] = $comments_closed; $datarray['mid'] = $mid; $datarray['parent_mid'] = $parent_mid; @@ -1301,7 +1312,7 @@ class Item extends Controller { if(! array_key_exists('obj',$datarray)) { $copy = $datarray; $copy['author'] = $observer; - $datarray['obj'] = Activity::encode_item($copy,((get_config('system','activitypub')) ? true : false)); + $datarray['obj'] = Activity::encode_item($copy,((get_config('system','activitypub', ACTIVITYPUB_ENABLED)) ? true : false)); } Activity::rewrite_mentions($datarray); @@ -1369,6 +1380,9 @@ class Item extends Controller { (($remote_id) ? $remote_id : basename($datarray['mid'])), true); } + if (intval($datarray['item_unpublished'])) { + $draft_msg = t('Draft saved. Use Drafts app to continue editing.'); + } if($orig_post) { $datarray['id'] = $post_id; @@ -1391,6 +1405,13 @@ class Item extends Controller { if($api_source) return($x); + + if (intval($datarray['item_unpublished'])) { + info($draft_msg); + } + + + if((x($_REQUEST,'return')) && strlen($return_path)) { logger('return: ' . $return_path); goaway(z_root() . "/" . $return_path ); @@ -1403,7 +1424,6 @@ class Item extends Controller { $post = item_store($datarray,$execflag); $post_id = $post['item_id']; - $datarray = $post['item']; if($post_id) { @@ -1516,7 +1536,11 @@ class Item extends Controller { if($api_source) return $post; - + + if (intval($datarray['item_unpublished'])) { + info($draft_msg); + } + if($return_path) { goaway(z_root() . "/" . $return_path); } diff --git a/Zotlabs/Module/Profile.php b/Zotlabs/Module/Profile.php index aa19003c2..922aa2b0b 100644 --- a/Zotlabs/Module/Profile.php +++ b/Zotlabs/Module/Profile.php @@ -75,7 +75,7 @@ class Profile extends \Zotlabs\Web\Controller { $chan = channelx_by_nick(argv(1)); if(! $chan) http_status_exit(404, 'Not found'); - $p = Activity::encode_person($chan,true,((get_config('system','activitypub',true)) ? true : false)); + $p = Activity::encode_person($chan,true,((get_config('system','activitypub', ACTIVITYPUB_ENABLED)) ? true : false)); if(! $p) { http_status_exit(404, 'Not found'); } diff --git a/Zotlabs/Module/Pubstream.php b/Zotlabs/Module/Pubstream.php index 57db6cddb..ac12f9474 100644 --- a/Zotlabs/Module/Pubstream.php +++ b/Zotlabs/Module/Pubstream.php @@ -127,6 +127,7 @@ class Pubstream extends Controller { '$dm' => '0', '$nouveau' => '0', '$wall' => '0', + '$draft' => '0', '$list' => '0', '$static' => $static, '$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1), diff --git a/Zotlabs/Module/Search.php b/Zotlabs/Module/Search.php index ca87951c8..375537048 100644 --- a/Zotlabs/Module/Search.php +++ b/Zotlabs/Module/Search.php @@ -62,12 +62,20 @@ class Search extends Controller { $o .= search($search,'search-box','/search',((local_channel()) ? true : false)); - if (strpos($search,'https://') === 0) { + if (local_channel() && strpos($search,'https://') === 0) { $j = Activity::fetch($search,App::get_channel()); if ($j) { $AS = new ActivityStreams($j); if ($AS->is_valid()) { - // check if is_an_actor, otherwise import activity + if (is_array($AS->obj) && ! ActivityStreams::is_an_actor($AS->obj)) { + // The boolean flag enables html cache of the item + $item = Activity::decode_note($AS,true); + if ($item) { + logger('parsed_item: ' . print_r($item,true),LOGGER_DATA); + Activity::store(App::get_channel(),get_observer_hash,$AS,$item, true, true); + goaway(z_root() . '/display/' . gen_link_id($item['mid'])); + } + } } } } @@ -146,6 +154,7 @@ class Search extends Controller { '$dm' => '0', '$nouveau' => '0', '$wall' => '0', + '$draft' => '0', '$static' => $static, '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0), '$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1), diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php index 26b14c529..dad785a53 100644 --- a/Zotlabs/Module/Settings/Channel.php +++ b/Zotlabs/Module/Settings/Channel.php @@ -130,6 +130,7 @@ class Channel { $post_comments = array_key_exists('post_comments',$_POST) ? intval($_POST['post_comments']) : PERMS_SPECIFIC; PermissionLimits::Set(local_channel(),'post_comments',$post_comments); + $publish = (((x($_POST,'profile_in_directory')) && (intval($_POST['profile_in_directory']) == 1)) ? 1: 0); $username = ((x($_POST,'username')) ? escape_tags(trim($_POST['username'])) : ''); $timezone = ((x($_POST,'timezone_select')) ? notags(trim($_POST['timezone_select'])) : ''); @@ -171,7 +172,13 @@ class Channel { $mailhost = ((array_key_exists('mailhost',$_POST)) ? notags(trim($_POST['mailhost'])) : ''); $profile_assign = ((x($_POST,'profile_assign')) ? notags(trim($_POST['profile_assign'])) : ''); $permit_all_mentions = (($_POST['permit_all_mentions'] == 1) ? 1: 0); - + $close_comment_days = (($_POST['close_comments']) ? intval($_POST['close_comments']) : 0); + if ($close_comment_days) { + set_pconfig(local_channel(),'system','close_comments', $close_comment_days . ' days'); + } + else { + set_pconfig(local_channel(),'system','close_comments', EMPTY_STR); + } // allow a permission change to over-ride the autoperms setting from the form if(! isset($autoperms)) { @@ -541,13 +548,13 @@ class Channel { $hyperdrive = [ 'hyperdrive', t('Friend-of-friend conversations'), ((get_pconfig(local_channel(),'system','hyperdrive',true)) ? 1 : 0), t('Import public third-party conversations in which your connections participate.'), $yes_no ]; - if (get_config('system','activitypub',true)) { + if (get_config('system','activitypub', ACTIVITYPUB_ENABLED)) { $apconfig = true; - $activitypub = replace_macros(get_markup_template('field_checkbox.tpl'), [ '$field' => [ 'activitypub', t('Enable ActivityPub protocol'), ((get_pconfig(local_channel(),'system','activitypub',true)) ? 1 : 0), t('ActivityPub is an emerging internet standard for social communications'), $yes_no ]]); + $activitypub = replace_macros(get_markup_template('field_checkbox.tpl'), [ '$field' => [ 'activitypub', t('Enable ActivityPub protocol'), ((get_pconfig(local_channel(),'system','activitypub', ACTIVITYPUB_ENABLED)) ? 1 : 0), t('ActivityPub is an emerging internet standard for social communications'), $yes_no ]]); } else { $apconfig = false; - $activitypub = '' . EOL; + $activitypub = '' . EOL; } $permissions_set = (($permissions_role != 'custom') ? true : false); @@ -603,6 +610,7 @@ class Channel { '$permiss_arr' => $permiss, '$comment_perms' => $comment_perms, '$noindex' => [ 'noindex', t('Forbid indexing of your channel content by search engines'), get_pconfig($channel['channel_id'],'system','noindex'), '', $yes_no], + '$close_comments' => [ 'close_comments', t('Disable acceptance of comments on my posts after this many days'), ((intval(get_pconfig(local_channel(),'system','close_comments'))) ? intval(get_pconfig(local_channel(),'system','close_comments')) : EMPTY_STR), t('Leave unset or enter 0 to allow comments indefinitely') ], '$blocktags' => array('blocktags',t('Allow others to tag your posts'), 1-$blocktags, t('Often used by the community to retro-actively flag inappropriate content'), $yes_no), '$lbl_p2macro' => t('Channel Permission Limits'), diff --git a/Zotlabs/Module/Stream.php b/Zotlabs/Module/Stream.php index 4768ce8cd..403e3b92b 100644 --- a/Zotlabs/Module/Stream.php +++ b/Zotlabs/Module/Stream.php @@ -156,6 +156,7 @@ class Stream extends Controller { $default_cmax = ((Apps::system_app_installed(local_channel(),'Friend Zoom')) ? get_pconfig(local_channel(),'affinity','cmax',99) : (-1)); $cid = ((x($_GET,'cid')) ? intval($_GET['cid']) : 0); + $draft = ((x($_GET,'draft')) ? intval($_GET['draft']) : 0); $star = ((x($_GET,'star')) ? intval($_GET['star']) : 0); $liked = ((x($_GET,'liked')) ? intval($_GET['liked']) : 0); $conv = ((x($_GET,'conv')) ? intval($_GET['conv']) : 0); @@ -170,6 +171,10 @@ class Stream extends Controller { $deftag = ''; + if ($draft) { + $item_normal = item_normal_draft(); + } + if (x($_GET,'search') || $file || (!$pf && $cid)) { $nouveau = true; } @@ -380,6 +385,7 @@ class Stream extends Controller { '$dm' => (($dm) ? $dm : '0'), '$nouveau' => (($nouveau) ? $nouveau : '0'), '$wall' => '0', + '$draft' => (($draft) ? $draft : '0'), '$static' => $static, '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0), '$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1), diff --git a/Zotlabs/Module/Vote.php b/Zotlabs/Module/Vote.php index db58a1212..60db43be8 100644 --- a/Zotlabs/Module/Vote.php +++ b/Zotlabs/Module/Vote.php @@ -100,7 +100,7 @@ class Vote extends Controller { $item['obj_type'] = 'Note'; $item['author'] = channelx_by_n($channel['channel_id']); - $item['obj'] = Activity::encode_item($item,((get_config('system','activitypub')) ? true : false)); + $item['obj'] = Activity::encode_item($item,((get_config('system','activitypub', ACTIVITYPUB_ENABLED)) ? true : false)); // now reset the placeholders diff --git a/Zotlabs/Module/Webfinger.php b/Zotlabs/Module/Webfinger.php index cc96cb17c..44edbc706 100644 --- a/Zotlabs/Module/Webfinger.php +++ b/Zotlabs/Module/Webfinger.php @@ -111,7 +111,7 @@ class Webfinger extends Controller { 'http://webfinger.net/ns/name' => $channel_target['channel_name'], 'http://xmlns.com/foaf/0.1/name' => $channel_target['channel_name'], 'https://w3id.org/security/v1#publicKeyPem' => $channel_target['xchan_pubkey'], - 'http://purl.org/zot/federation' => ((get_config('system','activitypub',true)) ? 'zot6,activitypub' : 'zot6') + 'http://purl.org/zot/federation' => ((get_config('system','activitypub', ACTIVITYPUB_ENABLED)) ? 'zot6,activitypub' : 'zot6') ]; foreach ($aliases as $alias) { diff --git a/Zotlabs/Widget/Site_projects.php b/Zotlabs/Widget/Site_projects.php index 0d790642f..7618d9fd8 100644 --- a/Zotlabs/Widget/Site_projects.php +++ b/Zotlabs/Widget/Site_projects.php @@ -44,7 +44,7 @@ class Site_projects { static function site_sort($a,$b) { if ($a['site_type'] === $b['site_type']) { - return strncmp($a,$b); + return stricmp($a['site_project'],$b['site_project']); } return (($a['site_type'] < $b['site_type']) ? -1 : 1); } diff --git a/app/drafts.apd b/app/drafts.apd new file mode 100644 index 000000000..84d4c6020 --- /dev/null +++ b/app/drafts.apd @@ -0,0 +1,6 @@ +version: 1 +url: $baseurl/stream?draft=1 +requires: local_channel +name: Drafts +photo: icon:floppy-o +categories: Productivity diff --git a/boot.php b/boot.php index 71d8fdd4b..9966db2b6 100755 --- a/boot.php +++ b/boot.php @@ -16,7 +16,7 @@ use Zotlabs\Daemon\Run; * @brief This file defines some global constants and includes the central App class. */ -define ( 'STD_VERSION', '20.11.26' ); +define ( 'STD_VERSION', '20.11.30' ); define ( 'ZOT_REVISION', '6.0' ); define ( 'DB_UPDATE_VERSION', 1245 ); @@ -26,7 +26,8 @@ define ( 'PLATFORM_ARCHITECTURE', 'zap' ); define ( 'PROJECT_BASE', __DIR__ ); - +// This configures the default state of activitypub at the project level. +define ( 'ACTIVITYPUB_ENABLED', true ); // composer autoloader for all namespaced Classes require_once('vendor/autoload.php'); diff --git a/include/acl_selectors.php b/include/acl_selectors.php index f37241992..248a83d68 100644 --- a/include/acl_selectors.php +++ b/include/acl_selectors.php @@ -94,7 +94,7 @@ function populate_acl($defaults = null,$show_jotnets = true, $emptyACL_descripti if ($channel && Apps::system_app_installed($channel['channel_id'],'Virtual Lists')) { $selected = (($single_group && 'connections:' . $channel['channel_hash'] === $allow_gid[0]) ? ' selected = "selected" ' : ''); $groups .= '' . "\r\n"; - if (get_pconfig($channel['channel_id'],'system','activitypub',get_config('system','activitypub',true))) { + if (get_pconfig($channel['channel_id'],'system','activitypub',get_config('system','activitypub', ACTIVITYPUB_ENABLED))) { $selected = (($single_group && 'activitypub:' . $channel['channel_hash'] === $allow_gid[0]) ? ' selected = "selected" ' : ''); $groups .= '' . "\r\n"; } diff --git a/include/conversation.php b/include/conversation.php index ed8a7a3ff..e26ffab78 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -1426,6 +1426,8 @@ function z_status_editor($a, $x, $popup = false) { call_hooks('jot_networks', $jotnets); } + $permanent_draft = ((intval($x['profile_uid']) && intval($x['profile_uid']) === local_channel() && Apps::system_app_installed($x['profile_uid'],'Drafts')) ? ('Save draft') : EMPTY_STR); + $sharebutton = (x($x,'button') ? $x['button'] : t('Share')); $placeholdtext = (x($x,'content_label') ? $x['content_label'] : $sharebutton); @@ -1507,6 +1509,8 @@ function z_status_editor($a, $x, $popup = false) { '$defexpire' => $defexpire, '$feature_expire' => $feature_expire, '$expires' => t('Set expiration date'), + '$save' => $permanent_draft, + '$is_draft' => ((array_key_exists('is_draft',$x) && intval($x['is_draft'])) ? true : false), '$defpublish' => $defpublish, '$feature_future' => $feature_future, '$future_txt' => t('Set publish date'), diff --git a/include/items.php b/include/items.php index 306ea465e..ed50e607d 100644 --- a/include/items.php +++ b/include/items.php @@ -210,6 +210,12 @@ function item_normal() { and item.item_blocked = 0 and item.obj_type != '" . ACTIVITY_OBJ_FILE . "' "; } +function item_normal_draft() { + return " and item.item_hidden = 0 and item.item_type = 0 and item.item_deleted = 0 + and item.item_unpublished = 1 and item.item_pending_remove = 0 + and item.item_blocked = 0 and item.obj_type != '" . ACTIVITY_OBJ_FILE . "' "; +} + function item_normal_search() { return " and item.item_hidden = 0 and item.item_type in (0,3,6,7) and item.item_deleted = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0 @@ -2107,28 +2113,47 @@ function item_store_update($arr, $allow_exec = false, $deliver = true, $linkid = unset($arr['mid']); unset($arr['parent']); unset($arr['parent_mid']); - unset($arr['created']); unset($arr['author_xchan']); unset($arr['owner_xchan']); unset($arr['source_xchan']); unset($arr['thr_parent']); unset($arr['llink']); + if (intval($orig[0]['item_unpublished'])) { + + $arr['created'] = ((x($arr,'created') !== false) ? datetime_convert('UTC','UTC',$arr['created']) : datetime_convert()); + $arr['edited'] = $arr['created']; + $arr['expires'] = ((x($arr,'expires') !== false) ? datetime_convert('UTC','UTC',$arr['expires']) : NULL_DATE); + + if(array_key_exists('comments_closed',$arr) && $arr['comments_closed'] > NULL_DATE) + $arr['comments_closed'] = datetime_convert('UTC','UTC',$arr['comments_closed']); + else + $arr['comments_closed'] = NULL_DATE; + + $arr['commented'] = $arr['created']; + + $arr['received'] = $arr['created']; + $arr['changed'] = $arr['created']; + } + + else { + unset($arr['created']); + + $arr['expires'] = ((x($arr,'expires') !== false) ? datetime_convert('UTC','UTC',$arr['expires']) : $orig[0]['expires']); + + + if(array_key_exists('comments_closed',$arr) && $arr['comments_closed'] > NULL_DATE) + $arr['comments_closed'] = datetime_convert('UTC','UTC',$arr['comments_closed']); + else + $arr['comments_closed'] = $orig[0]['comments_closed']; + + $arr['commented'] = $orig[0]['commented']; + $arr['received'] = $orig[0]['received']; + $arr['changed'] = $orig[0]['changed']; + } + $arr['edited'] = ((x($arr,'edited') !== false) ? datetime_convert('UTC','UTC',$arr['edited']) : datetime_convert()); - $arr['expires'] = ((x($arr,'expires') !== false) ? datetime_convert('UTC','UTC',$arr['expires']) : $orig[0]['expires']); - $arr['revision'] = ((x($arr,'revision') && $arr['revision'] > 0) ? intval($arr['revision']) : 0); - - if(array_key_exists('comments_closed',$arr) && $arr['comments_closed'] > NULL_DATE) - $arr['comments_closed'] = datetime_convert('UTC','UTC',$arr['comments_closed']); - else - $arr['comments_closed'] = $orig[0]['comments_closed']; - - $arr['commented'] = $orig[0]['commented']; - - $arr['received'] = $orig[0]['received']; - $arr['changed'] = $orig[0]['changed']; - $arr['route'] = ((array_key_exists('route',$arr)) ? trim($arr['route']) : $orig[0]['route']); $arr['location'] = ((x($arr,'location')) ? notags(trim($arr['location'])) : $orig[0]['location']); @@ -2944,10 +2969,7 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $group = false $arr['item_private'] = (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 1 : 0); - // Setting item_origin on a deleted item also seems to cause looping - if (! $arr['item_deleted']) { - $arr['item_origin'] = 1; - } + $arr['item_origin'] = 1; $arr['item_wall'] = 1; $arr['item_thread_top'] = 1; @@ -3016,9 +3038,12 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $group = false $private = (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 1 : 0); + // Setting item_origin on a deleted item also seems to cause looping + if (! $arr['item_deleted']) { + $arr['item_origin'] = 1; + } $item_wall = 1; - $item_origin = 1; $item_uplink = 0; $item_nocomment = 0; diff --git a/include/network.php b/include/network.php index da1916360..d33afbca8 100644 --- a/include/network.php +++ b/include/network.php @@ -1260,7 +1260,7 @@ function get_site_info() { } $protocols = [ 'zot' ]; - if (get_config('system','activitypub',true)) { + if (get_config('system','activitypub', ACTIVITYPUB_ENABLED)) { $protocols[] = 'activitypub'; } diff --git a/view/js/main.js b/view/js/main.js index 152a89866..d325e9673 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -1412,6 +1412,20 @@ function preview_post() { return true; } +function save_draft() { + $("#jot-draft").val("1"); + $.post( + "item", + $("#profile-jot-form").serialize(), + function() { + itemCancel(); + document.location.href=document.location.href; + }, + ); + return true; +} + + function preview_mail() { $("#mail-preview").val("1"); $("#mail-preview-content").show(); diff --git a/view/tpl/build_query.tpl b/view/tpl/build_query.tpl index 87bed9716..3e07b8086 100755 --- a/view/tpl/build_query.tpl +++ b/view/tpl/build_query.tpl @@ -16,6 +16,7 @@ var bParam_new = {{$nouveau}}; var bParam_page = {{$page}}; var bParam_wall = {{$wall}}; + var bParam_draft = {{$draft}}; var bParam_list = {{$list}}; var bParam_fh = {{$fh}}; var bParam_dm = {{$dm}}; @@ -49,6 +50,7 @@ if(bParam_spam != 0) bCmd = bCmd + "&spam=" + bParam_spam; if(bParam_new != 0) bCmd = bCmd + "&new=" + bParam_new; if(bParam_wall != 0) bCmd = bCmd + "&wall=" + bParam_wall; + if(bParam_draft != 0) bCmd = bCmd + "&draft=" + bParam_draft; if(bParam_list != 0) bCmd = bCmd + "&list=" + bParam_list; if(bParam_fh != 0) bCmd = bCmd + "&fh=" + bParam_fh; if(bParam_dm != 0) bCmd = bCmd + "&dm=" + bParam_dm; diff --git a/view/tpl/jot.tpl b/view/tpl/jot.tpl index a04d9a9d7..bee738547 100755 --- a/view/tpl/jot.tpl +++ b/view/tpl/jot.tpl @@ -27,6 +27,7 @@ + {{if $webpage}} @@ -215,6 +216,11 @@ {{/if}} + {{if $save}} + + {{/if}} {{if $jotnets}}