diff --git a/source/packages/com_mokosuitecross/config.xml b/source/packages/com_mokosuitecross/config.xml index 0ee1c826..b20dd5b1 100644 --- a/source/packages/com_mokosuitecross/config.xml +++ b/source/packages/com_mokosuitecross/config.xml @@ -120,6 +120,42 @@ /> +
+ + + + + + + + + +
+
$titleText, '{introtext}' => $introStripped, '{fulltext}' => strip_tags(mb_substr($article->fulltext ?? '', 0, 500)), '{url}' => $url, '{url_raw}' => $urlRaw, + '{url_short}' => $urlShort, '{image}' => $introImage, '{category}' => $categoryName, '{author}' => $authorName, diff --git a/source/packages/com_mokosuitecross/src/Helper/LinkShortenerHelper.php b/source/packages/com_mokosuitecross/src/Helper/LinkShortenerHelper.php new file mode 100644 index 00000000..9850e4f9 --- /dev/null +++ b/source/packages/com_mokosuitecross/src/Helper/LinkShortenerHelper.php @@ -0,0 +1,172 @@ + + * @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\Helper; + +defined('_JEXEC') or die; + +use Joomla\CMS\Component\ComponentHelper; + +/** + * Shortens URLs via Bitly, Rebrandly, or YOURLS. + * + * Returns the original URL on any failure so cross-posts are never broken. + */ +class LinkShortenerHelper +{ + /** + * Shorten a URL using the configured provider. + * + * @param string $url The URL to shorten + * + * @return string Shortened URL, or the original on failure/disabled + */ + public static function shorten(string $url): string + { + $params = ComponentHelper::getParams('com_mokosuitecross'); + $provider = $params->get('link_shortener', 'none'); + + if ($provider === 'none' || empty($url)) { + return $url; + } + + $apiKey = $params->get('link_shortener_api_key', ''); + + switch ($provider) { + case 'bitly': + return self::shortenWithBitly($url, $apiKey); + + case 'rebrandly': + return self::shortenWithRebrandly($url, $apiKey); + + case 'yourls': + $apiUrl = $params->get('link_shortener_yourls_url', ''); + $token = $params->get('link_shortener_yourls_token', ''); + return self::shortenWithYourls($url, $apiUrl, $token); + + default: + return $url; + } + } + + /** + * Shorten via Bitly API v4. + */ + public static function shortenWithBitly(string $url, string $apiKey): string + { + if (empty($apiKey)) { + return $url; + } + + $ch = curl_init(); + curl_setopt_array($ch, [ + CURLOPT_URL => 'https://api-ssl.bitly.com/v4/shorten', + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => json_encode(['long_url' => $url]), + CURLOPT_HTTPHEADER => [ + 'Authorization: Bearer ' . $apiKey, + 'Content-Type: application/json', + ], + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 10, + ]); + + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + if ($response === false || $httpCode < 200 || $httpCode >= 300) { + return $url; + } + + $data = json_decode($response, true); + + return $data['link'] ?? $url; + } + + /** + * Shorten via Rebrandly API. + */ + public static function shortenWithRebrandly(string $url, string $apiKey, string $workspace = ''): string + { + if (empty($apiKey)) { + return $url; + } + + $headers = [ + 'apikey: ' . $apiKey, + 'Content-Type: application/json', + ]; + + if (!empty($workspace)) { + $headers[] = 'workspace: ' . $workspace; + } + + $ch = curl_init(); + curl_setopt_array($ch, [ + CURLOPT_URL => 'https://api.rebrandly.com/v1/links', + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => json_encode(['destination' => $url]), + CURLOPT_HTTPHEADER => $headers, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 10, + ]); + + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + if ($response === false || $httpCode < 200 || $httpCode >= 300) { + return $url; + } + + $data = json_decode($response, true); + $short = $data['shortUrl'] ?? ''; + + return !empty($short) ? 'https://' . ltrim($short, 'https://') : $url; + } + + /** + * Shorten via YOURLS API (self-hosted). + */ + public static function shortenWithYourls(string $url, string $apiUrl, string $signatureToken): string + { + if (empty($apiUrl) || empty($signatureToken)) { + return $url; + } + + $endpoint = rtrim($apiUrl, '/') . '?' . http_build_query([ + 'action' => 'shorturl', + 'format' => 'json', + 'signature' => $signatureToken, + 'url' => $url, + ]); + + $ch = curl_init(); + curl_setopt_array($ch, [ + CURLOPT_URL => $endpoint, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 10, + ]); + + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + if ($response === false || $httpCode < 200 || $httpCode >= 300) { + return $url; + } + + $data = json_decode($response, true); + + return $data['shorturl'] ?? $url; + } +}