Files
MokoSuiteCross/source/packages/com_mokosuitecross/src/Controller/PreviewController.php
T
jmiller decb1ba8b7
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Universal: PR Check / Secret Scan (pull_request) Successful in 7s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 11s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Auto Version Bump / Version Bump (push) Successful in 13s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
feat(#156): add social preview panel for article editor
PreviewHelper renders platform-specific mockups (Twitter, Facebook,
LinkedIn, Mastodon, Bluesky, Telegram) showing how cross-posted content
will appear. PreviewController serves AJAX requests from the article
editor. Content plugin injects platform selector and preview button
into the Cross-Posting fieldset for existing articles.

Authored-by: Moko Consulting
2026-06-28 11:09:35 -05:00

87 lines
2.7 KiB
PHP

<?php
/**
* @package MokoSuiteCross
* @subpackage com_mokosuitecross
* @author Moko Consulting <hello@mokoconsulting.tech>
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
* @license GNU General Public License version 3 or later; see LICENSE
* SPDX-License-Identifier: GPL-3.0-or-later
*/
namespace Joomla\Component\MokoSuiteCross\Administrator\Controller;
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\CMS\Session\Session;
use Joomla\CMS\Uri\Uri;
use Joomla\Component\MokoSuiteCross\Administrator\Helper\CrossPostDispatcher;
use Joomla\Component\MokoSuiteCross\Administrator\Helper\PreviewHelper;
class PreviewController extends BaseController
{
public function render(): void
{
if (!Session::checkToken('get')) {
echo json_encode(['error' => 'Invalid token']);
$this->app->close();
return;
}
$articleId = $this->input->getInt('article_id', 0);
$platform = $this->input->getCmd('platform', 'twitter');
if ($articleId < 1) {
echo json_encode(['error' => 'Missing article ID']);
$this->app->close();
return;
}
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select('*')
->from($db->quoteName('#__content'))
->where($db->quoteName('id') . ' = ' . $articleId);
$db->setQuery($query);
$article = $db->loadObject();
if (!$article) {
echo json_encode(['error' => 'Article not found']);
$this->app->close();
return;
}
$meta = CrossPostDispatcher::buildArticleMeta($article);
$title = $meta['{title}'] ?? '';
$text = $meta['{introtext}'] ?? '';
$url = $meta['{url}'] ?? '';
$imageUrl = $meta['{image}'] ?? '';
$authorName = $meta['{author}'] ?? '';
$supportedPlatforms = PreviewHelper::getSupportedPlatforms();
$html = '';
if ($platform === 'all') {
foreach ($supportedPlatforms as $p) {
$html .= '<div style="margin-bottom:20px;">'
. '<div style="font-weight:600;font-size:13px;color:#666;margin-bottom:6px;text-transform:uppercase;">' . htmlspecialchars(ucfirst($p)) . '</div>'
. PreviewHelper::render($p, $title, $text, $url, $imageUrl, $authorName)
. '</div>';
}
} else {
$html = PreviewHelper::render($platform, $title, $text, $url, $imageUrl, $authorName);
}
$this->app->setHeader('Content-Type', 'text/html; charset=utf-8');
echo $html;
$this->app->close();
}
}