diff options
author | Mario <mario@mariovavti.com> | 2024-06-13 19:07:05 +0000 |
---|---|---|
committer | Mario <mario@mariovavti.com> | 2024-06-13 19:07:05 +0000 |
commit | ff018b975b47a57433b5f76634f9948164919e25 (patch) | |
tree | 408f52fb71a955ab2bf13a3b8f89c6d293b217e6 | |
parent | 6e0d0e38321dda6075586c12244c73eff6623565 (diff) | |
parent | fcd657040e90b957068be0c6010faa78020cf05d (diff) | |
download | volse-hubzilla-ff018b975b47a57433b5f76634f9948164919e25.tar.gz volse-hubzilla-ff018b975b47a57433b5f76634f9948164919e25.tar.bz2 volse-hubzilla-ff018b975b47a57433b5f76634f9948164919e25.zip |
Merge branch 'fix-rpost-module' into 'dev'
Refactoring and fixed for Module\Rpost
See merge request hubzilla/core!2136
-rw-r--r-- | Zotlabs/Module/Rpost.php | 248 | ||||
-rw-r--r-- | include/conversation.php | 3 | ||||
-rw-r--r-- | tests/unit/Module/RpostTest.php | 81 | ||||
-rw-r--r-- | tests/unit/Module/TestCase.php | 1 | ||||
-rw-r--r-- | tests/unit/includes/NetworkTest.php | 8 | ||||
-rw-r--r-- | tests/unit/includes/dba/_files/config.yml | 4 | ||||
-rw-r--r-- | view/tpl/jot-header.tpl | 2 |
7 files changed, 218 insertions, 129 deletions
diff --git a/Zotlabs/Module/Rpost.php b/Zotlabs/Module/Rpost.php index 23324ee3a..45f19d7e7 100644 --- a/Zotlabs/Module/Rpost.php +++ b/Zotlabs/Module/Rpost.php @@ -28,119 +28,31 @@ require_once('include/conversation.php'); * type= choices are 'html' or 'bbcode', default is 'bbcode' * */ - - - - class Rpost extends \Zotlabs\Web\Controller { - function get() { - - $o = ''; - - if(! local_channel()) { - if(remote_channel()) { - // redirect to your own site. - // We can only do this with a GET request so you'll need to keep the text short or risk getting truncated - // by the wretched beast called 'suhosin'. All the browsers now allow long GET requests, but suhosin - // blocks them. - - $url = Libzot::get_rpost_path(App::get_observer()); - // make sure we're not looping to our own hub - if(($url) && (! stristr($url, App::get_hostname()))) { - foreach($_GET as $key => $arg) { - if($key === 'q') - continue; - $url .= '&' . $key . '=' . $arg; - } - goaway($url); - } - } + /** + * Handle requests. + * + * Despite it's name, this method handles both POST and GET requests + * to the module. + */ + public function get(): string { - // The login procedure is going to bugger our $_REQUEST variables - // so save them in the session. + $channel_id = local_channel(); - if(array_key_exists('body',$_REQUEST)) { - $_SESSION['rpost'] = $_REQUEST; - } - return login(); + if(! $channel_id) { + return $this->redirect_or_login(); } nav_set_selected('Post'); - if (local_channel() && array_key_exists('userfile',$_FILES)) { - - $channel = App::get_channel(); - $observer = App::get_observer(); - - $def_album = get_pconfig($channel['channel_id'],'system','photo_path'); - $def_attach = get_pconfig($channel['channel_id'],'system','attach_path'); - - $r = attach_store($channel, (($observer) ? $observer['xchan_hash'] : ''), '', [ - 'source' => 'editor', - 'visible' => 0, - 'album' => $def_album, - 'directory' => $def_attach, - 'flags' => 1, // indicates temporary permissions are created - 'allow_cid' => '<' . $channel['channel_hash'] . '>', - 'allow_gid' => '', - 'deny_cid' => '', - 'deny_gid' => '' - ]); - - if (! $r['success']) { - notice( $r['message'] . EOL); - } - - $s = EMPTY_STR; - - if (intval($r['data']['is_photo'])) { - $s .= "\n\n" . $r['body'] . "\n\n"; - } - - $url = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['data']['display_path']; - - if (strpos($r['data']['filetype'],'video') === 0) { - $s .= "\n\n" . '[zvideo]' . $url . '[/zvideo]' . "\n\n"; - } - - if (strpos($r['data']['filetype'],'audio') === 0) { - $s .= "\n\n" . '[zaudio]' . $url . '[/zaudio]' . "\n\n"; - } - - if ($r['data']['filetype'] === 'image/svg+xml') { - $x = @file_get_contents('store/' . $channel['channel_address'] . '/' . $r['data']['os_path']); - if ($x) { - $bb = svg2bb($x); - if ($bb) { - $s .= "\n\n" . $bb; - } - else { - logger('empty return from svgbb'); - } - } - else { - logger('unable to read svg data file: ' . 'store/' . $channel['channel_address'] . '/' . $r['data']['os_path']); - } - } - - if ($r['data']['filetype'] === 'text/calendar') { - $content = @file_get_contents('store/' . $channel['channel_address'] . '/' . $r['data']['os_path']); - if ($content) { - $ev = ical_to_ev($content); - if ($ev) { - $s .= "\n\n" . format_event_bbcode($ev[0]) . "\n\n"; - } - } - } - - $s .= "\n\n" . '[attachment]' . $r['data']['hash'] . ',' . $r['data']['revision'] . '[/attachment]' . "\n"; - $_REQUEST['body'] = ((array_key_exists('body',$_REQUEST)) ? $_REQUEST['body'] . $s : $s); + if (! empty($_FILES['userfile'])) { + $this->handle_attachments(); } // If we have saved rpost session variables, but nothing in the current $_REQUEST, recover the saved variables - if((! array_key_exists('body',$_REQUEST)) && (array_key_exists('rpost',$_SESSION))) { + if((! array_key_exists('body',$_REQUEST)) && isset($_SESSION['rpost'])) { $_REQUEST = $_SESSION['rpost']; unset($_SESSION['rpost']); } @@ -152,21 +64,10 @@ class Rpost extends \Zotlabs\Web\Controller { ); if($r) { require_once('include/security.php'); - $change = change_channel($r[0]['channel_id']); + change_channel($r[0]['channel_id']); } } - if(isset($_REQUEST['remote_return']) && $_REQUEST['remote_return']) { - $_SESSION['remote_return'] = $_REQUEST['remote_return']; - } - if(argc() > 1 && argv(1) === 'return') { - if($_SESSION['remote_return']) - goaway($_SESSION['remote_return']); - goaway(z_root() . '/network'); - } - - $plaintext = true; - if(isset($_REQUEST['type']) && $_REQUEST['type'] === 'html') { require_once('include/html2bbcode.php'); $_REQUEST['body'] = html2bbcode($_REQUEST['body']); @@ -197,12 +98,12 @@ class Rpost extends \Zotlabs\Web\Controller { 'permissions' => $channel_acl, 'bang' => '', 'visitor' => true, - 'profile_uid' => local_channel(), + 'profile_uid' => $channel_id, 'title' => $_REQUEST['title'] ?? '', 'body' => $_REQUEST['body'] ?? '', 'attachment' => $_REQUEST['attachment'] ?? '', 'source' => ((x($_REQUEST,'source')) ? strip_tags($_REQUEST['source']) : ''), - 'return_path' => 'rpost/return', + 'return_path' => 'hq', 'bbco_autocomplete' => 'bbcode', 'editor_autocomplete' => true, 'bbcode' => true, @@ -210,19 +111,128 @@ class Rpost extends \Zotlabs\Web\Controller { 'reset' => t('Reset form') ); - $a = ''; $editor = status_editor($x, false, 'Rpost'); - $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( + return replace_macros(get_markup_template('edpost_head.tpl'), array( '$title' => t('Edit post'), '$cancel' => '', - '$editor' => $editor + '$editor' => $editor, + '$delete' => null, )); + } + + /** + * Redirect to the observer's instance if not local, or return login form. + * + * The request is saved in the session if there's a `body` request + * param present. (Otherwise not.) + * + * @return string A login form if not redirected. If the session was + * determned to belong to a remote channel, the function does not + * return. + */ + private function redirect_or_login(): string { + if(remote_channel()) { + // redirect to your own site. + // We can only do this with a GET request so you'll need to keep the text short or risk getting truncated + // by the wretched beast called 'suhosin'. All the browsers now allow long GET requests, but suhosin + // blocks them. + + $url = Libzot::get_rpost_path(App::get_observer()); + // make sure we're not looping to our own hub + if(($url) && (! stristr($url, App::get_hostname()))) { + foreach($_GET as $key => $arg) { + if($key === 'q') + continue; + $url .= '&' . $key . '=' . $arg; + } + goaway($url); + } + } - return $o; + // The login procedure is going to bugger our $_REQUEST variables + // so save them in the session. + if(array_key_exists('body',$_REQUEST)) { + $_SESSION['rpost'] = $_REQUEST; + } + return login(); } + /** + * Handle uplads of attachments in the rpost call. + * + * This is only relevant for POST requests. + * + * The function will modify the `$_REQUEST['body']` superglobal + * (or add it if it does not exist). + */ + private function handle_attachments(): void { + $channel = App::get_channel(); + $observer = App::get_observer(); + + $def_album = get_pconfig($channel['channel_id'],'system','photo_path'); + $def_attach = get_pconfig($channel['channel_id'],'system','attach_path'); + + $r = attach_store($channel, (($observer) ? $observer['xchan_hash'] : ''), '', [ + 'source' => 'editor', + 'visible' => 0, + 'album' => $def_album, + 'directory' => $def_attach, + 'flags' => 1, // indicates temporary permissions are created + 'allow_cid' => '<' . $channel['channel_hash'] . '>', + 'allow_gid' => '', + 'deny_cid' => '', + 'deny_gid' => '' + ]); + + if (! $r['success']) { + notice( $r['message'] . EOL); + } + + $s = EMPTY_STR; + + if (intval($r['data']['is_photo'])) { + $s .= "\n\n" . $r['body'] . "\n\n"; + } + + $url = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['data']['display_path']; + if (strpos($r['data']['filetype'],'video') === 0) { + $s .= "\n\n" . '[zvideo]' . $url . '[/zvideo]' . "\n\n"; + } + + if (strpos($r['data']['filetype'],'audio') === 0) { + $s .= "\n\n" . '[zaudio]' . $url . '[/zaudio]' . "\n\n"; + } + if ($r['data']['filetype'] === 'image/svg+xml') { + $x = @file_get_contents('store/' . $channel['channel_address'] . '/' . $r['data']['os_path']); + if ($x) { + $bb = svg2bb($x); + if ($bb) { + $s .= "\n\n" . $bb; + } + else { + logger('empty return from svgbb'); + } + } + else { + logger('unable to read svg data file: ' . 'store/' . $channel['channel_address'] . '/' . $r['data']['os_path']); + } + } + + if ($r['data']['filetype'] === 'text/calendar') { + $content = @file_get_contents('store/' . $channel['channel_address'] . '/' . $r['data']['os_path']); + if ($content) { + $ev = ical_to_ev($content); + if ($ev) { + $s .= "\n\n" . format_event_bbcode($ev[0]) . "\n\n"; + } + } + } + + $s .= "\n\n" . '[attachment]' . $r['data']['hash'] . ',' . $r['data']['revision'] . '[/attachment]' . "\n"; + $_REQUEST['body'] = ((array_key_exists('body',$_REQUEST)) ? $_REQUEST['body'] . $s : $s); + } } diff --git a/include/conversation.php b/include/conversation.php index 3992f06f6..c631d53a2 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -1183,6 +1183,7 @@ function hz_status_editor($x, $popup = false) { '$modalerroralbum' => t('Error getting album'), '$nocomment_enabled' => t('Comments enabled'), '$nocomment_disabled' => t('Comments disabled'), + '$confirmdelete' => t('Confirm delete'), '$auto_save_draft' => $feature_auto_save_draft, '$reset' => $reset, '$popup' => $popup @@ -1263,7 +1264,7 @@ function hz_status_editor($x, $popup = false) { '$poll_option_label' => t('Option'), '$poll_add_option_label' => t('Add option'), '$poll_expire_unit_label' => [t('Minutes'), t('Hours'), t('Days')], - '$multiple_answers' => ['poll_multiple_answers', t("Allow multiple answers"), '', '', [t('No'), t('Yes')]], + '$multiple_answers' => ['poll_multiple_answers', t("Allow multiple answers"), '', '', [t('No'), t('Yes')],null,null], '$consensus' => ((array_key_exists('item',$x)) ? $x['item']['item_consensus'] : 0), '$nocommenttitle' => t('Disable comments'), '$nocommenttitlesub' => t('Toggle comments'), diff --git a/tests/unit/Module/RpostTest.php b/tests/unit/Module/RpostTest.php new file mode 100644 index 000000000..ad94f2f06 --- /dev/null +++ b/tests/unit/Module/RpostTest.php @@ -0,0 +1,81 @@ +<?php +/** + * Tests for Rpost module. + * + * SPDX-FileCopyrightText: 2024 Hubzilla Community + * SPDX-FileContributor: Harald Eilertsen + * + * SPDX-License-Identifier: MIT + */ + +class RpostTest extends \Zotlabs\Tests\Unit\Module\TestCase { + + /** + * Basic test of a get request with no args as an authenticated user. + */ + public function test_get_with_no_args(): void { + $this->get_authenticated(); + + $this->assertPageContains('<form id="profile-jot-form"'); + $this->assertPageContains('<input type="hidden" name="profile_uid" value="42"'); + } + + /** + * Display login form if session is not authenticated. + */ + public function test_display_login_form_if_not_logged_in(): void { + $lc_mock = $this->getFunctionMock('Zotlabs\Module', 'local_channel') + ->expects($this->any()) + ->willReturn(false); + + $this->get('rpost'); + + $this->assertPageContains('<form action="https://hubzilla.test/rpost" id="main_login"'); + } + + public function test_populates_form_from_query_params(): void { + $this->get_authenticated([ + 'title' => 'This is my title', + 'body' => 'The body of the post', + 'source' => 'The temple of the Dagon', + ]); + + $this->assertPageContains('value="This is my title"'); + $this->assertPageContains('>The body of the post</textarea>'); + $this->assertPageContains('value="The temple of the Dagon"'); + } + + public function test_convert_body_from_html_to_bbcode(): void { + $this->get_authenticated([ + 'body' => "<h1>Awesome page</h1>\r\n<p>Awesome content!</p>", + 'type' => 'html', + ]); + + $this->assertPageContains(">[h1]Awesome page[/h1]\n\nAwesome content!</textarea>"); + } + + /** + * Private helper method to perform an authenticated GET request. + * + * @param array $query An associative array of query parameters. + */ + private function get_authenticated(array $query = []): void { + // Mock `local_chanel()` to emulate a valid logged in channel + $lc_mock = $this->getFunctionMock('Zotlabs\Module', 'local_channel') + ->expects($this->any()) + ->willReturn(42); + + // Set basic access controls to keep AccessList happy. + \App::$channel = [ + 'channel_id' => 42, + 'channel_location' => null, + 'channel_address' => '', + 'channel_allow_cid' => '', + 'channel_allow_gid' => '', + 'channel_deny_cid' => '', + 'channel_deny_gid' => '', + ]; + + $this->get('rpost', $query); + } +} diff --git a/tests/unit/Module/TestCase.php b/tests/unit/Module/TestCase.php index e7051e001..f2e19f265 100644 --- a/tests/unit/Module/TestCase.php +++ b/tests/unit/Module/TestCase.php @@ -25,6 +25,7 @@ class TestCase extends \Zotlabs\Tests\Unit\UnitTestCase { $_SERVER['REQUEST_METHOD'] = 'GET'; $_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1'; + $_SERVER['QUERY_STRING'] = "q={$uri}"; $_REQUEST = $_GET; \App::init(); diff --git a/tests/unit/includes/NetworkTest.php b/tests/unit/includes/NetworkTest.php index 5bf175953..a41075f25 100644 --- a/tests/unit/includes/NetworkTest.php +++ b/tests/unit/includes/NetworkTest.php @@ -7,12 +7,6 @@ class NetworkTest extends Zotlabs\Tests\Unit\UnitTestCase { - public function setUp() : void { - parent::setUp(); - - \App::set_baseurl("https://mytest.org"); - } - /** * @dataProvider localUrlTestProvider */ @@ -23,7 +17,7 @@ class NetworkTest extends Zotlabs\Tests\Unit\UnitTestCase { public static function localUrlTestProvider() : array { return [ [ '/some/path', true ], - [ 'https://mytest.org/some/path', true ], + [ 'https://hubzilla.test/some/path', true ], [ 'https://other.site/some/path', false ], ]; } diff --git a/tests/unit/includes/dba/_files/config.yml b/tests/unit/includes/dba/_files/config.yml index e93486857..ac3c8acb0 100644 --- a/tests/unit/includes/dba/_files/config.yml +++ b/tests/unit/includes/dba/_files/config.yml @@ -2,6 +2,10 @@ config: - cat: system + k: baseurl + v: https://hubzilla.test + - + cat: system k: do_not_check_dns v: true - diff --git a/view/tpl/jot-header.tpl b/view/tpl/jot-header.tpl index ca3cabd61..67ba1824b 100644 --- a/view/tpl/jot-header.tpl +++ b/view/tpl/jot-header.tpl @@ -184,7 +184,6 @@ var activeCommentText = ''; } function jotGetExpiry() { - //reply = prompt("{{$expirewhen}}", $('#jot-expire').val()); $('#expiryModal').modal('show'); $('#expiry-modal-OKButton').on('click', function() { reply=$('#expiration-date').val(); @@ -196,7 +195,6 @@ var activeCommentText = ''; } function jotGetPubDate() { - //reply = prompt("{{$expirewhen}}", $('#jot-expire').val()); $('#createdModal').modal('show'); $('#created-modal-OKButton').on('click', function() { reply=$('#created-date').val(); |