You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

578 lines
17 KiB

<?php
namespace App\Widgets\Publish;
use Moxl\Xec\Action\Pubsub\PostPublish;
use Moxl\Xec\Action\Microblog\CommentCreateNode;
use Moxl\Xec\Action\Pubsub\GetConfig;
use Moxl\Xec\Action\Pubsub\Subscribe;
use Movim\Widget\Base;
use Movim\Session;
use League\CommonMark\CommonMarkConverter;
use Respect\Validation\Validator;
use App\Draft;
use App\DraftEmbed;
use App\Post as AppPost;
use App\Upload;
use App\Widgets\Dialog\Dialog;
use App\Widgets\Drawer\Drawer;
use App\Widgets\Post\Post;
use App\Widgets\Toast\Toast;
use Moxl\Xec\Payload\Packet;
class Publish extends Base
{
public function load()
{
$this->registerEvent('pubsub_postpublish_handle', 'onPublish');
$this->registerEvent('pubsub_postpublish_errorforbidden', 'onPublishErrorForbidden');
$this->registerEvent('microblog_commentcreatenode_handle', 'onCommentNodeCreated');
$this->registerEvent('pubsub_getconfig_handle', 'onBlogConfig');
$this->addjs('publish.js');
$this->addcss('publish.css');
}
public function onPublish(Packet $packet)
{
Toast::send($this->__('post.published'));
list($to, $node, $id, $repost, $comments) = array_values($packet->content);
if (!$repost && $comments) {
$this->ajaxCreateComments(($comments === true) ? $to : $comments, $id);
}
if ($node == AppPost::MICROBLOG_NODE) {
$this->rpc('MovimUtils.reload', $this->route('news'));
} elseif ($node != AppPost::STORIES_NODE) {
$this->rpc('MovimUtils.reload', $this->route('community', [$to, $node]));
}
}
public function onBlogConfig(Packet $packet)
{
if ($packet->content['access_model'] == 'presence') {
$view = $this->tpl();
$this->rpc('MovimTpl.fill', '#publish_blog_presence', $view->draw('_publish_blog_presence'));
}
}
public function onPublishErrorForbidden(Packet $packet)
{
Toast::send($this->__('publish.publish_error_forbidden'));
$this->rpc('Publish.enableSend');
}
public function onCommentNodeCreated(Packet $packet)
{
list($server, $parentid) = array_values($packet->content);
$s = new Subscribe;
$s->setTo($server)
->setFrom($this->me->id)
->setNode(AppPost::COMMENTS_NODE . '/' . $parentid)
->request();
}
public function ajaxCreateComments(string $server, string $id)
{
if (!validateServerNode($server, $id)) {
return;
}
$cn = new CommentCreateNode;
$cn->setTo($server)
->setParentId($id)
->request();
}
public function ajaxHttpSaveTitle($id, $title)
{
$draft = $this->me->drafts()->find($id);
if ($draft) {
$draft->title = $title;
$draft->save();
$this->rpc('MovimUtils.addClass', '#publish textarea[name=title] + label span.save', 'saved');
}
}
public function ajaxHttpSaveContent($id, $content)
{
$draft = $this->me->drafts()->find($id);
if ($draft) {
$draft->content = $content;
$draft->save();
$this->rpc('MovimUtils.addClass', '#publish textarea[name=content] + label span.save', 'saved');
}
}
public function ajaxPreview($id)
{
$draft = $this->me->drafts()->find($id);
if ($draft && $draft->isNotEmpty()) {
$view = $this->tpl();
$doc = new \DOMDocument;
$converter = new CommonMarkConverter([
'html_input' => 'escape',
'allow_unsafe_links' => true,
]);
$doc->loadXML('<div>' . $converter->convert($draft->content) . '</div>');
$view->assign('title', $draft->title);
$view->assign('content', substr($doc->saveXML($doc->getElementsByTagName('div')->item(0)), 5, -6));
Drawer::fill('publish_preview', $view->draw('_publish_preview'), true);
} else {
Toast::send($this->__('publish.no_title'));
}
}
public function ajaxPublish($id)
{
$this->rpc('Publish.disableSend');
$draft = $this->me->drafts()->find($id);
if ($draft && $draft->isNotEmpty()) {
$p = new PostPublish;
$p->setFrom($this->me->id)
->setTo($draft->server)
->setNode($draft->node)
->setTitle(htmlspecialchars($draft->title));
$comments = $this->me->session->getCommentsService();
$tags = [];
$tagsTitle = getHashtags(htmlspecialchars($draft->title));
if (is_array($tagsTitle)) {
array_merge($tags, $tagsTitle);
}
if (Validator::stringType()->notEmpty()->isValid(trim($draft->content))) {
$converter = new CommonMarkConverter([
'html_input' => 'escape',
'allow_unsafe_links' => true,
]);
$contentXhtml = $converter->convert($draft->content);
$tagsContent = getHashtags($draft->content);
if (is_array($tagsContent)) {
$tags = array_merge($tags, $tagsContent);
}
if (!empty($draft->content)) {
$p->setContent($draft->content);
}
if (!empty($contentXhtml)) {
$p->setContentXhtml($contentXhtml);
}
}
if (Validator::stringType()->notEmpty()->isValid(trim($draft->nodeid))) {
$p->setId($draft->nodeid);
$post = \App\Post::where('server', $draft->server)
->where('node', $draft->node)
->where('nodeid', $draft->nodeid)
->first();
if (isset($post)) {
$p->setPublished(strtotime($post->published));
}
} else {
$p->setId($this->titleToSlug($draft->title));
}
if (!$draft->comments_disabled) {
if ($comments) {
$p->enableComments($comments->server);
} else {
$p->enableComments();
}
}
if ($draft->open) {
$p->isOpen();
}
if (is_array($tags)) {
$p->setTags($tags);
}
if ($draft->reply) {
$post = \App\Post::where('server', $draft->reply->server)
->where('node', $draft->reply->node)
->where('nodeid', $draft->reply->nodeid)
->first();
$p->setReply($post->getRef());
}
$hasImage = false;
foreach ($draft->embeds as $embed) {
$resolved = $embed->resolve();
// The url is an image
if (
$resolved->type == 'image'
&& $resolved->images[0]['url'] == $embed->url
) {
if (!$hasImage) $hasImage = true;
$p->addImage(
$resolved->images[0]['url'],
$resolved->title,
$resolved->contentType
);
}
// The url is a gallery
/*elseif (is_array($resolved->images) && count($resolved->images) > 1) {
// If an image was picked (0 is not picked)
if ($embed->imagenumber > 0 && array_key_exists($embed->imagenumber-1, $resolved->images)) {
$p->addImage(
$resolved->images[$embed->imagenumber-1]['url'],
$resolved->title,
$resolved->images[$embed->imagenumber-1]['mime']
);
}
$p->addLink(
$embed->url,
$resolved->title,
'text/html',
$resolved->description,
$resolved->providerIcon
);
}*/
// The url is a link
else {
$p->addLink(
$embed->url,
$resolved->title,
'text/html',
$resolved->description,
$resolved->providerIcon
);
}
}
$info = \App\Info::where('server', $draft->server)
->where('node', $draft->node)
->first();
if ($info && $info->isGallery() && !$hasImage) {
$this->rpc('Publish.enableSend');
Toast::send($this->__('publish.no_picture'));
return;
}
$p->request();
$draft->delete();
} else {
$this->rpc('Publish.enableSend');
Toast::send($this->__('publish.no_title'));
}
}
public function ajaxLink()
{
$view = $this->tpl();
Dialog::fill($view->draw('_publish_link'));
}
public function ajaxAddUpload(int $draftId, string $uploadId)
{
$upload = Upload::find($uploadId);
if ($upload && $upload->uploaded) {
$this->addEmbed($draftId, $upload->geturl);
}
}
public function ajaxAddUrl(int $draftId, string $url)
{
$this->addEmbed($draftId, $url);
}
private function addEmbed(int $draftId, string $url)
{
$draft = $this->me->drafts()->find($draftId);
if (Validator::url()->isValid($url)) {
$embed = $draft->embeds()->where('url', $url)->first();
if (!$embed) {
$embed = new DraftEmbed;
$embed->draft_id = $draftId;
$embed->url = $url;
$embed->save();
}
$embed->refresh();
$this->rpc('MovimTpl.append', '#publishembeds', $this->prepareEmbed($embed));
$this->rpc('Dialog_ajaxClear');
} else {
Toast::send($this->__('publish.valid_url'));
}
}
public function ajaxTryResolveShareUrl($id)
{
$session = Session::instance();
$shareUrl = $session->get('share_url');
if ($shareUrl) {
$this->ajaxAddUrl($id, $shareUrl);
$session->delete('share_url');
}
}
public function ajaxHttpRemoveEmbed($id, $embedId)
{
$draft = $this->me->drafts()->find($id);
if ($draft) {
$embed = $draft->embeds()->find($embedId);
if ($embed) {
$this->rpc('MovimTpl.remove', '#' . $embed->HTMLId);
$embed->delete();
}
}
}
public function ajaxOpenlinkPreview($id)
{
$draft = $this->me->drafts()->find($id);
$view = $this->tpl();
if ($draft && $draft->open && !$draft->nodeid) {
$slug = $this->titleToSlug($draft->title);
$view->assign('link', ($draft->node == AppPost::MICROBLOG_NODE)
? $this->route('blog', [$draft->server, $slug])
: $this->route('community', [$draft->server, $draft->node, $slug]));
$this->rpc('MovimTpl.fill', '#publish_preview_url', $view->draw('_publish_preview_url'));
return;
}
$this->rpc('MovimTpl.fill', '#publish_preview_url', '');
}
public function ajaxTogglePrivacy($id, bool $open)
{
$draft = $this->me->drafts()->find($id);
if ($draft) {
$draft->open = $open;
$draft->save();
$this->ajaxCheckPrivacy($id);
if (!$open) {
$this->rpc('MovimTpl.fill', '#publish_preview_url', '');
}
Toast::send(($open)
? $this->__('post.public_yes')
: $this->__('post.public_no'));
}
}
public function ajaxCheckPrivacy($id)
{
$draft = $this->me->drafts()->find($id);
if ($draft && $draft->open) {
(new GetConfig)->setNode(AppPost::MICROBLOG_NODE)->request();
} else {
$this->rpc('MovimTpl.fill', '#publish_blog_presence', '');
}
}
public function ajaxToggleCommentsDisabled($id, bool $commentsDisabled)
{
$draft = $this->me->drafts()->find($id);
if ($draft) {
$draft->comments_disabled = $commentsDisabled;
$draft->save();
Toast::send(($commentsDisabled)
? $this->__('post.comments_disabled_yes')
: $this->__('post.comments_disabled_no'));
}
}
public function ajaxClearReply($id)
{
$draft = $this->me->drafts()->find($id);
if ($draft) {
$draft->reply_id = null;
$draft->save();
$this->rpc('MovimUtils.redirect', $this->route('publish', [$draft->server, $draft->node, $draft->nodeid]));
}
}
public function prepareToggles(Draft $draft)
{
$view = $this->tpl();
$view->assign('draft', $draft);
return $view->draw('_publish_toggles');
}
public function prepareEmbed(DraftEmbed $embed)
{
$view = $this->tpl();
$view->assign('embed', $embed);
return $view->draw('_publish_embed');
}
public function ajaxEmbedChooseImage($id, $embedId)
{
$draft = $this->me->drafts()->find($id);
if ($draft) {
$embed = $draft->embeds()->find($embedId);
if ($embed) {
$view = $this->tpl();
$view->assign('embed', $embed);
Drawer::fill('publish_images', $view->draw('_publish_images'), true);
}
}
}
public function ajaxHttpSetImageNumber($id, $embedId, $imageNumber)
{
$draft = $this->me->drafts()->find($id);
if ($draft) {
$embed = $draft->embeds()->find($embedId);
if ($embed) {
$embed->imagenumber = $imageNumber;
$embed->save();
$this->rpc('MovimTpl.remove', '#' . $embed->HTMLId);
$this->rpc('MovimTpl.append', '#publishembeds', $this->prepareEmbed($embed));
}
}
$this->rpc('Drawer.clear');
}
public function ajaxHttpGet(
string $type = 'brief',
?string $server = null,
?string $node = null,
?string $nodeId = null,
?string $replyServer = null,
?string $replyNode = null,
?string $replyNodeId = null,
) {
$view = $this->tpl();
if ($server == null) {
$server = $this->me->id;
}
if ($node == null) {
$node = AppPost::MICROBLOG_NODE;
}
if ($nodeId == null) {
$nodeId = '';
}
if ($node == AppPost::MICROBLOG_NODE) {
$view->assign('icon', \App\Contact::firstOrNew(['id' => $server]));
} else {
$info = \App\Info::where('server', $server)
->where('node', $node)
->first();
$view->assign('icon', $info);
}
$draft = $this->me->drafts()
->where('server', $server)
->where('node', $node)
->where('nodeid', $nodeId)
->first();
if (!$draft) {
$draft = new Draft;
$draft->user_id = $this->me->id;
$draft->server = $server;
$draft->node = $node;
$draft->nodeid = $nodeId;
// If we find an existing post let's fill the draft
$draft->tryFillPost();
}
if ($draft->content != null) {
$type = "article";
}
// Reply
$reply = null;
if ($replyServer && $replyNode && $replyNodeId) {
$reply = \App\Post::where('server', $replyServer)
->where('node', $replyNode)
->where('nodeid', $replyNodeId)
->first();
} elseif ($draft->reply_id) {
$reply = \App\Post::find($draft->reply_id);
}
if ($reply) {
$draft->reply_id = $reply->id;
} else {
$draft->reply_id = null;
}
$draft->save();
$draft->refresh();
if ($draft->reply) {
$view->assign('replyblock', (new Post)->prepareTicket($draft->reply));
}
$view->assign('type', $type);
$view->assign('draft', $draft);
$this->rpc('MovimTpl.fill', '#publish', $view->draw('_publish_form'));
$this->rpc('Publish.init');
}
private function titleToSlug(?string $title = null): string
{
$slug = slugify(
strtok(wordwrap($title, 80, "\n"), "\n")
);
if (!empty($slug) && strlen($slug) > 24) {
return $slug . '-' . \generateKey(6);
}
return \generateUUID();
}
}