diff --git a/doc/Addons.md b/doc/Addons.md
index b43a8a915..171b5681a 100644
--- a/doc/Addons.md
+++ b/doc/Addons.md
@@ -790,10 +790,6 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
Hook::callAll('post_local', $datarray);
Hook::callAll('post_local_end', $datarray);
-### mod/editpost.php
-
- Hook::callAll('jot_tool', $jotplugins);
-
### src/Render/FriendicaSmartyEngine.php
Hook::callAll("template_vars", $arr);
@@ -855,6 +851,10 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
Hook::callAll('lockview_content', $item);
+### src/Module/Post/Edit.php
+
+ Hook::callAll('jot_tool', $jotplugins);
+
### src/Module/Settings/Delegation.php
Hook::callAll('authenticate', $addon_auth);
diff --git a/doc/de/Addons.md b/doc/de/Addons.md
index 342dd1b81..143e309cb 100644
--- a/doc/de/Addons.md
+++ b/doc/de/Addons.md
@@ -309,10 +309,6 @@ Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Ap
Hook::callAll('post_local', $datarray);
Hook::callAll('post_local_end', $datarray);
-### mod/editpost.php
-
- Hook::callAll('jot_tool', $jotplugins);
-
### src/Network/FKOAuth1.php
Hook::callAll('logged_in', $a->user);
@@ -422,6 +418,10 @@ Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Ap
Hook::callAll('lockview_content', $item);
+### src/Module/Post/Edit.php
+
+ Hook::callAll('jot_tool', $jotplugins);
+
### src/Worker/Directory.php
Hook::callAll('globaldir_update', $arr);
diff --git a/mod/editpost.php b/mod/editpost.php
deleted file mode 100644
index bec5d3449..000000000
--- a/mod/editpost.php
+++ /dev/null
@@ -1,166 +0,0 @@
-.
- *
- */
-
-use Friendica\App;
-use Friendica\Content\Feature;
-use Friendica\Core\Hook;
-use Friendica\Core\Renderer;
-use Friendica\Database\DBA;
-use Friendica\DI;
-use Friendica\Model\Contact;
-use Friendica\Model\Post;
-use Friendica\Model\User;
-use Friendica\Util\Crypto;
-
-function editpost_content(App $a)
-{
- $o = '';
-
- if (!DI::userSession()->getLocalUserId()) {
- DI::sysmsg()->addNotice(DI::l10n()->t('Permission denied.'));
- return;
- }
-
- $post_id = ((DI::args()->getArgc() > 1) ? intval(DI::args()->getArgv()[1]) : 0);
-
- if (!$post_id) {
- DI::sysmsg()->addNotice(DI::l10n()->t('Item not found'));
- return;
- }
-
- $fields = ['allow_cid', 'allow_gid', 'deny_cid', 'deny_gid',
- 'body', 'title', 'uri-id', 'wall', 'post-type', 'guid'];
-
- $item = Post::selectFirstForUser(DI::userSession()->getLocalUserId(), $fields, ['id' => $post_id, 'uid' => DI::userSession()->getLocalUserId()]);
-
- if (!DBA::isResult($item)) {
- DI::sysmsg()->addNotice(DI::l10n()->t('Item not found'));
- return;
- }
-
- $user = User::getById(DI::userSession()->getLocalUserId());
-
- $geotag = '';
-
- $o .= Renderer::replaceMacros(Renderer::getMarkupTemplate("section_title.tpl"), [
- '$title' => DI::l10n()->t('Edit post')
- ]);
-
- $tpl = Renderer::getMarkupTemplate('jot-header.tpl');
- DI::page()['htmlhead'] .= Renderer::replaceMacros($tpl, [
- '$ispublic' => ' ', // DI::l10n()->t('Visible to everybody'),
- '$geotag' => $geotag,
- '$nickname' => $a->getLoggedInUserNickname(),
- '$is_mobile' => DI::mode()->isMobile(),
- ]);
-
- if (strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])) {
- $lockstate = 'lock';
- } else {
- $lockstate = 'unlock';
- }
-
- $jotplugins = '';
- $jotnets = '';
-
- Hook::callAll('jot_tool', $jotplugins);
-
- $tpl = Renderer::getMarkupTemplate('jot.tpl');
- $o .= Renderer::replaceMacros($tpl, [
- '$is_edit' => true,
- '$return_path' => '/display/' . $item['guid'],
- '$action' => 'item',
- '$share' => DI::l10n()->t('Save'),
- '$loading' => DI::l10n()->t('Loading...'),
- '$upload' => DI::l10n()->t('Upload photo'),
- '$shortupload' => DI::l10n()->t('upload photo'),
- '$attach' => DI::l10n()->t('Attach file'),
- '$shortattach' => DI::l10n()->t('attach file'),
- '$weblink' => DI::l10n()->t('Insert web link'),
- '$shortweblink' => DI::l10n()->t('web link'),
- '$video' => DI::l10n()->t('Insert video link'),
- '$shortvideo' => DI::l10n()->t('video link'),
- '$audio' => DI::l10n()->t('Insert audio link'),
- '$shortaudio' => DI::l10n()->t('audio link'),
- '$setloc' => DI::l10n()->t('Set your location'),
- '$shortsetloc' => DI::l10n()->t('set location'),
- '$noloc' => DI::l10n()->t('Clear browser location'),
- '$shortnoloc' => DI::l10n()->t('clear location'),
- '$wait' => DI::l10n()->t('Please wait'),
- '$permset' => DI::l10n()->t('Permission settings'),
- '$wall' => $item['wall'],
- '$posttype' => $item['post-type'],
- '$content' => undo_post_tagging($item['body']),
- '$post_id' => $post_id,
- '$defloc' => $user['default-location'],
- '$visitor' => 'none',
- '$pvisit' => 'none',
- '$emailcc' => DI::l10n()->t('CC: email addresses'),
- '$public' => DI::l10n()->t('Public post'),
- '$jotnets' => $jotnets,
- '$title' => $item['title'],
- '$placeholdertitle' => DI::l10n()->t('Set title'),
- '$category' => Post\Category::getCSVByURIId($item['uri-id'], DI::userSession()->getLocalUserId(), Post\Category::CATEGORY),
- '$placeholdercategory' => (Feature::isEnabled(DI::userSession()->getLocalUserId(),'categories') ? DI::l10n()->t("Categories \x28comma-separated list\x29") : ''),
- '$emtitle' => DI::l10n()->t('Example: bob@example.com, mary@example.com'),
- '$lockstate' => $lockstate,
- '$acl' => '', // populate_acl((($group) ? $group_acl : $a->user)),
- '$bang' => ($lockstate === 'lock' ? '!' : ''),
- '$profile_uid' => $_SESSION['uid'],
- '$preview' => DI::l10n()->t('Preview'),
- '$jotplugins' => $jotplugins,
- '$cancel' => DI::l10n()->t('Cancel'),
- '$rand_num' => Crypto::randomDigits(12),
-
- // Formatting button labels
- '$edbold' => DI::l10n()->t('Bold'),
- '$editalic' => DI::l10n()->t('Italic'),
- '$eduline' => DI::l10n()->t('Underline'),
- '$edquote' => DI::l10n()->t('Quote'),
- '$edcode' => DI::l10n()->t('Code'),
- '$edurl' => DI::l10n()->t('Link'),
- '$edattach' => DI::l10n()->t('Link or Media'),
-
- //jot nav tab (used in some themes)
- '$message' => DI::l10n()->t('Message'),
- '$browser' => DI::l10n()->t('Browser'),
- '$shortpermset' => DI::l10n()->t('Permissions'),
-
- '$compose_link_title' => DI::l10n()->t('Open Compose page'),
- ]);
-
- return $o;
-}
-
-function undo_post_tagging($s) {
- $matches = null;
- $cnt = preg_match_all('/([!#@])\[url=(.*?)\](.*?)\[\/url\]/ism', $s, $matches, PREG_SET_ORDER);
- if ($cnt) {
- foreach ($matches as $mtch) {
- if (in_array($mtch[1], ['!', '@'])) {
- $contact = Contact::getByURL($mtch[2], false, ['addr']);
- $mtch[3] = empty($contact['addr']) ? $mtch[2] : $contact['addr'];
- }
- $s = str_replace($mtch[0], $mtch[1] . $mtch[3],$s);
- }
- }
- return $s;
-}
diff --git a/src/Module/Post/Edit.php b/src/Module/Post/Edit.php
new file mode 100644
index 000000000..5531cb249
--- /dev/null
+++ b/src/Module/Post/Edit.php
@@ -0,0 +1,228 @@
+.
+ *
+ */
+
+namespace Friendica\Module\Post;
+
+use Friendica\App;
+use Friendica\BaseModule;
+use Friendica\Content\Feature;
+use Friendica\Core\Hook;
+use Friendica\Core\L10n;
+use Friendica\Core\Renderer;
+use Friendica\Core\Session\Capability\IHandleUserSessions;
+use Friendica\Model\Contact;
+use Friendica\Model\Post;
+use Friendica\Model\User;
+use Friendica\Module\Response;
+use Friendica\Navigation\SystemMessages;
+use Friendica\Network\HTTPException;
+use Friendica\Util\Crypto;
+use Friendica\Util\Profiler;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Controller to edit a post
+ */
+class Edit extends BaseModule
+{
+ /** @var IHandleUserSessions */
+ protected $session;
+ /** @var SystemMessages */
+ protected $sysMessages;
+ /** @var App\Page */
+ protected $page;
+ /** @var App\Mode */
+ protected $mode;
+ /** @var App */
+ protected $app;
+ /** @var bool */
+ protected $isModal = false;
+
+ public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IHandleUserSessions $session, SystemMessages $sysMessages, App\Page $page, App\Mode $mode, App $app, array $server, array $parameters = [])
+ {
+ parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
+
+ $this->session = $session;
+ $this->sysMessages = $sysMessages;
+ $this->page = $page;
+ $this->mode = $mode;
+ $this->app = $app;
+ }
+
+
+ protected function content(array $request = []): string
+ {
+ $this->isModal = $request['mode'] ?? '' === 'none';
+
+ if (!$this->session->getLocalUserId()) {
+ $this->errorExit($this->t('Permission denied.'), HTTPException\UnauthorizedException::class);
+ }
+
+ $postId = $this->parameters['post_id'];
+
+ if (empty($postId)) {
+ $this->errorExit($this->t('Post not found.'), HTTPException\BadRequestException::class);
+ }
+
+ $fields = ['allow_cid', 'allow_gid', 'deny_cid', 'deny_gid',
+ 'body', 'title', 'uri-id', 'wall', 'post-type', 'guid'];
+
+ $item = Post::selectFirstForUser($this->session->getLocalUserId(), $fields, [
+ 'id' => $postId,
+ 'uid' => $this->session->getLocalUserId(),
+ ]);
+
+ if (empty($item)) {
+ $this->errorExit($this->t('Post not found.'), HTTPException\BadRequestException::class);
+ }
+
+ $user = User::getById($this->session->getLocalUserId());
+ $geoTag = '';
+
+ $output = Renderer::replaceMacros(Renderer::getMarkupTemplate('section_title.tpl'), [
+ '$title' => $this->t('Edit post'),
+ ]);
+
+ $this->page['htmlhead'] .= Renderer::replaceMacros(Renderer::getMarkupTemplate('jot-header.tpl'), [
+ '$ispublic' => ' ', // $this->t('Visible to everybody'),
+ '$geotag' => $geoTag,
+ '$nickname' => $this->app->getLoggedInUserNickname(),
+ '$is_mobile' => $this->mode->isMobile(),
+ ]);
+
+ if (strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])) {
+ $lockstate = 'lock';
+ } else {
+ $lockstate = 'unlock';
+ }
+
+ $jotplugins = '';
+ $jotnets = '';
+
+ Hook::callAll('jot_tool', $jotplugins);
+
+ $output .= Renderer::replaceMacros(Renderer::getMarkupTemplate('jot.tpl'), [
+ '$is_edit' => true,
+ '$return_path' => '/display/' . $item['guid'],
+ '$action' => 'item',
+ '$share' => $this->t('Save'),
+ '$loading' => $this->t('Loading...'),
+ '$upload' => $this->t('Upload photo'),
+ '$shortupload' => $this->t('upload photo'),
+ '$attach' => $this->t('Attach file'),
+ '$shortattach' => $this->t('attach file'),
+ '$weblink' => $this->t('Insert web link'),
+ '$shortweblink' => $this->t('web link'),
+ '$video' => $this->t('Insert video link'),
+ '$shortvideo' => $this->t('video link'),
+ '$audio' => $this->t('Insert audio link'),
+ '$shortaudio' => $this->t('audio link'),
+ '$setloc' => $this->t('Set your location'),
+ '$shortsetloc' => $this->t('set location'),
+ '$noloc' => $this->t('Clear browser location'),
+ '$shortnoloc' => $this->t('clear location'),
+ '$wait' => $this->t('Please wait'),
+ '$permset' => $this->t('Permission settings'),
+ '$wall' => $item['wall'],
+ '$posttype' => $item['post-type'],
+ '$content' => $this->undoPostTagging($item['body']),
+ '$post_id' => $postId,
+ '$defloc' => $user['default-location'],
+ '$visitor' => 'none',
+ '$pvisit' => 'none',
+ '$emailcc' => $this->t('CC: email addresses'),
+ '$public' => $this->t('Public post'),
+ '$jotnets' => $jotnets,
+ '$title' => $item['title'],
+ '$placeholdertitle' => $this->t('Set title'),
+ '$category' => Post\Category::getCSVByURIId($item['uri-id'], $this->session->getLocalUserId(), Post\Category::CATEGORY),
+ '$placeholdercategory' => (Feature::isEnabled($this->session->getLocalUserId(), 'categories') ? $this->t("Categories \x28comma-separated list\x29") : ''),
+ '$emtitle' => $this->t('Example: bob@example.com, mary@example.com'),
+ '$lockstate' => $lockstate,
+ '$acl' => '', // populate_acl((($group) ? $group_acl : $a->user)),
+ '$bang' => ($lockstate === 'lock' ? '!' : ''),
+ '$profile_uid' => $_SESSION['uid'],
+ '$preview' => $this->t('Preview'),
+ '$jotplugins' => $jotplugins,
+ '$cancel' => $this->t('Cancel'),
+ '$rand_num' => Crypto::randomDigits(12),
+
+ // Formatting button labels
+ '$edbold' => $this->t('Bold'),
+ '$editalic' => $this->t('Italic'),
+ '$eduline' => $this->t('Underline'),
+ '$edquote' => $this->t('Quote'),
+ '$edcode' => $this->t('Code'),
+ '$edurl' => $this->t('Link'),
+ '$edattach' => $this->t('Link or Media'),
+
+ //jot nav tab (used in some themes)
+ '$message' => $this->t('Message'),
+ '$browser' => $this->t('Browser'),
+ '$shortpermset' => $this->t('Permissions'),
+
+ '$compose_link_title' => $this->t('Open Compose page'),
+ ]);
+
+ return $output;
+ }
+
+ /**
+ * Removes Tags from the item-body
+ *
+ * @param string $body The item body
+ *
+ * @return string the new item body without tagging
+ */
+ protected function undoPostTagging(string $body)
+ {
+ $matches = null;
+ $content = preg_match_all('/([!#@])\[url=(.*?)\](.*?)\[\/url\]/ism', $body, $matches, PREG_SET_ORDER);
+ if ($content) {
+ foreach ($matches as $match) {
+ if (in_array($match[1], ['!', '@'])) {
+ $contact = Contact::getByURL($match[2], false, ['addr']);
+ $match[3] = empty($contact['addr']) ? $match[2] : $contact['addr'];
+ }
+ $body = str_replace($match[0], $match[1] . $match[3], $body);
+ }
+ }
+ return $body;
+ }
+
+ /**
+ * Exists the current Module because of an error
+ *
+ * @param string $message The error message
+ * @param string $exceptionClass In case it's a modal, throw an exception instead of an redirect
+ *
+ * @return void
+ */
+ protected function errorExit(string $message, string $exceptionClass)
+ {
+ if ($this->isModal) {
+ throw new $exceptionClass($message);
+ } else {
+ $this->sysMessages->addNotice($message);
+ $this->baseUrl->redirect();
+ }
+ }
+}
diff --git a/src/Object/Post.php b/src/Object/Post.php
index 87951c19c..8b8463f85 100644
--- a/src/Object/Post.php
+++ b/src/Object/Post.php
@@ -220,7 +220,7 @@ class Post
if ($item['event-id'] != 0) {
$edpost = ['calendar/event/edit/' . $item['event-id'], DI::l10n()->t('Edit')];
} else {
- $edpost = ['editpost/' . $item['id'], DI::l10n()->t('Edit')];
+ $edpost = [sprintf('post/%s/edit', $item['id']), DI::l10n()->t('Edit')];
}
}
$dropping = in_array($item['uid'], [0, DI::userSession()->getLocalUserId()]);
diff --git a/static/routes.config.php b/static/routes.config.php
index 7a86d8d03..5f5c238e0 100644
--- a/static/routes.config.php
+++ b/static/routes.config.php
@@ -552,6 +552,7 @@ return [
'/ping' => [Module\Notifications\Ping::class, [R::GET]],
'/post' => [
+ '/{post_id}/edit' => [Module\Post\Edit::class, [R::GET ]],
'/{post_id}/share' => [Module\Post\Share::class, [R::GET ]],
'/{item_id}/tag/add' => [Module\Post\Tag\Add::class, [ R::POST]],
'/{item_id}/tag/remove[/{tag_name}]' => [Module\Post\Tag\Remove::class, [R::GET, R::POST]],