mirror of
https://github.com/RSS-Bridge/rss-bridge.git
synced 2024-11-29 23:00:48 +03:00
5165ea265d
* refactor * fix: case-sensitive config from env, fix #2935 * lowercase all config section and keys * test: add test for case-insensitivity
385 lines
13 KiB
PHP
385 lines
13 KiB
PHP
<?php
|
|
|
|
/**
|
|
* This file is part of RSS-Bridge, a PHP project capable of generating RSS and
|
|
* Atom feeds for websites that don't have one.
|
|
*
|
|
* For the full license information, please view the UNLICENSE file distributed
|
|
* with this source code.
|
|
*
|
|
* @package Core
|
|
* @license http://unlicense.org/ UNLICENSE
|
|
* @link https://github.com/rss-bridge/rss-bridge
|
|
*/
|
|
|
|
/**
|
|
* A generator class for a single bridge card on the home page of RSS-Bridge.
|
|
*
|
|
* This class generates the HTML content for a single bridge card for the home
|
|
* page of RSS-Bridge.
|
|
*
|
|
* @todo Return error if a caller creates an object of this class.
|
|
*/
|
|
final class BridgeCard
|
|
{
|
|
/**
|
|
* Gets a single bridge card
|
|
*
|
|
* @param class-string<BridgeInterface> $bridgeClassName The bridge name
|
|
* @param array $formats A list of formats
|
|
* @param bool $isActive Indicates if the bridge is active or not
|
|
* @return string The bridge card
|
|
*/
|
|
public static function displayBridgeCard($bridgeClassName, $formats, $isActive = true)
|
|
{
|
|
$bridgeFactory = new BridgeFactory();
|
|
|
|
$bridge = $bridgeFactory->create($bridgeClassName);
|
|
|
|
$isHttps = strpos($bridge->getURI(), 'https') === 0;
|
|
|
|
$uri = $bridge->getURI();
|
|
$name = $bridge->getName();
|
|
$icon = $bridge->getIcon();
|
|
$description = $bridge->getDescription();
|
|
$parameters = $bridge->getParameters();
|
|
if (Configuration::getConfig('proxy', 'url') && Configuration::getConfig('proxy', 'by_bridge')) {
|
|
$parameters['global']['_noproxy'] = [
|
|
'name' => 'Disable proxy (' . (Configuration::getConfig('proxy', 'name') ?: Configuration::getConfig('proxy', 'url')) . ')',
|
|
'type' => 'checkbox'
|
|
];
|
|
}
|
|
|
|
if (Configuration::getConfig('cache', 'custom_timeout')) {
|
|
$parameters['global']['_cache_timeout'] = [
|
|
'name' => 'Cache timeout in seconds',
|
|
'type' => 'number',
|
|
'defaultValue' => $bridge->getCacheTimeout()
|
|
];
|
|
}
|
|
|
|
$shortName = $bridge->getShortName();
|
|
$card = <<<CARD
|
|
<section
|
|
class="bridge-card"
|
|
id="bridge-{$bridgeClassName}"
|
|
data-ref="{$name}"
|
|
data-short-name="$shortName"
|
|
>
|
|
|
|
<h2><a href="{$uri}">{$name}</a></h2>
|
|
<p class="description">{$description}</p>
|
|
<input type="checkbox" class="showmore-box" id="showmore-{$bridgeClassName}" />
|
|
<label class="showmore" for="showmore-{$bridgeClassName}">Show more</label>
|
|
CARD;
|
|
|
|
// If we don't have any parameter for the bridge, we print a generic form to load it.
|
|
if (count($parameters) === 0) {
|
|
$card .= self::getForm($bridgeClassName, $formats, $isActive, $isHttps);
|
|
|
|
// Display form with cache timeout and/or noproxy options (if enabled) when bridge has no parameters
|
|
} elseif (count($parameters) === 1 && array_key_exists('global', $parameters)) {
|
|
$card .= self::getForm($bridgeClassName, $formats, $isActive, $isHttps, '', $parameters['global']);
|
|
} else {
|
|
foreach ($parameters as $parameterName => $parameter) {
|
|
if (!is_numeric($parameterName) && $parameterName === 'global') {
|
|
continue;
|
|
}
|
|
|
|
if (array_key_exists('global', $parameters)) {
|
|
$parameter = array_merge($parameter, $parameters['global']);
|
|
}
|
|
|
|
if (!is_numeric($parameterName)) {
|
|
$card .= '<h5>' . $parameterName . '</h5>' . PHP_EOL;
|
|
}
|
|
|
|
$card .= self::getForm($bridgeClassName, $formats, $isActive, $isHttps, $parameterName, $parameter);
|
|
}
|
|
}
|
|
|
|
$card .= sprintf('<label class="showless" for="showmore-%s">Show less</label>', $bridgeClassName);
|
|
if ($bridge->getDonationURI() !== '' && Configuration::getConfig('admin', 'donations')) {
|
|
$card .= sprintf(
|
|
'<p class="maintainer">%s ~ <a href="%s">Donate</a></p>',
|
|
$bridge->getMaintainer(),
|
|
$bridge->getDonationURI()
|
|
);
|
|
} else {
|
|
$card .= sprintf('<p class="maintainer">%s</p>', $bridge->getMaintainer());
|
|
}
|
|
$card .= '</section>';
|
|
|
|
return $card;
|
|
}
|
|
|
|
/**
|
|
* Get the form header for a bridge card
|
|
*
|
|
* @param class-string<BridgeInterface> $bridgeClassName The bridge name
|
|
* @param bool $isHttps If disabled, adds a warning to the form
|
|
* @return string The form header
|
|
*/
|
|
private static function getFormHeader($bridgeClassName, $isHttps = false, $parameterName = '')
|
|
{
|
|
$form = <<<EOD
|
|
<form method="GET" action="?">
|
|
<input type="hidden" name="action" value="display" />
|
|
<input type="hidden" name="bridge" value="{$bridgeClassName}" />
|
|
EOD;
|
|
|
|
if (!empty($parameterName)) {
|
|
$form .= sprintf('<input type="hidden" name="context" value="%s" />', $parameterName);
|
|
}
|
|
|
|
if (!$isHttps) {
|
|
$form .= '<div class="secure-warning">Warning :
|
|
This bridge is not fetching its content through a secure connection</div>';
|
|
}
|
|
|
|
return $form;
|
|
}
|
|
|
|
/**
|
|
* Get the form body for a bridge
|
|
*
|
|
* @param class-string<BridgeInterface> $bridgeClassName The bridge name
|
|
* @param array $formats A list of supported formats
|
|
* @param bool $isActive Indicates if a bridge is enabled or not
|
|
* @param bool $isHttps Indicates if a bridge uses HTTPS or not
|
|
* @param string $parameterName Sets the bridge context for the current form
|
|
* @param array $parameters The bridge parameters
|
|
* @return string The form body
|
|
*/
|
|
private static function getForm(
|
|
$bridgeClassName,
|
|
$formats,
|
|
$isActive = false,
|
|
$isHttps = false,
|
|
$parameterName = '',
|
|
$parameters = []
|
|
) {
|
|
$form = self::getFormHeader($bridgeClassName, $isHttps, $parameterName);
|
|
|
|
if (count($parameters) > 0) {
|
|
$form .= '<div class="parameters">';
|
|
|
|
foreach ($parameters as $id => $inputEntry) {
|
|
if (!isset($inputEntry['exampleValue'])) {
|
|
$inputEntry['exampleValue'] = '';
|
|
}
|
|
|
|
if (!isset($inputEntry['defaultValue'])) {
|
|
$inputEntry['defaultValue'] = '';
|
|
}
|
|
|
|
$idArg = 'arg-'
|
|
. urlencode($bridgeClassName)
|
|
. '-'
|
|
. urlencode($parameterName)
|
|
. '-'
|
|
. urlencode($id);
|
|
|
|
$form .= '<label for="'
|
|
. $idArg
|
|
. '">'
|
|
. filter_var($inputEntry['name'], FILTER_SANITIZE_FULL_SPECIAL_CHARS)
|
|
. '</label>'
|
|
. PHP_EOL;
|
|
|
|
if (!isset($inputEntry['type']) || $inputEntry['type'] === 'text') {
|
|
$form .= self::getTextInput($inputEntry, $idArg, $id);
|
|
} elseif ($inputEntry['type'] === 'number') {
|
|
$form .= self::getNumberInput($inputEntry, $idArg, $id);
|
|
} elseif ($inputEntry['type'] === 'list') {
|
|
$form .= self::getListInput($inputEntry, $idArg, $id);
|
|
} elseif ($inputEntry['type'] === 'checkbox') {
|
|
$form .= self::getCheckboxInput($inputEntry, $idArg, $id);
|
|
}
|
|
|
|
if (isset($inputEntry['title'])) {
|
|
$title_filtered = filter_var($inputEntry['title'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
|
$form .= '<i class="info" title="' . $title_filtered . '">i</i>';
|
|
} else {
|
|
$form .= '<i class="no-info"></i>';
|
|
}
|
|
}
|
|
|
|
$form .= '</div>';
|
|
}
|
|
|
|
if ($isActive) {
|
|
$form .= '<button type="submit" name="format" formtarget="_blank" value="Html">Generate feed</button>';
|
|
} else {
|
|
$form .= '<span style="font-weight: bold;">Inactive</span>';
|
|
}
|
|
|
|
return $form . '</form>' . PHP_EOL;
|
|
}
|
|
|
|
/**
|
|
* Get input field attributes
|
|
*
|
|
* @param array $entry The current entry
|
|
* @return string The input field attributes
|
|
*/
|
|
private static function getInputAttributes($entry)
|
|
{
|
|
$retVal = '';
|
|
|
|
if (isset($entry['required']) && $entry['required'] === true) {
|
|
$retVal .= ' required';
|
|
}
|
|
|
|
if (isset($entry['pattern'])) {
|
|
$retVal .= ' pattern="' . $entry['pattern'] . '"';
|
|
}
|
|
|
|
return $retVal;
|
|
}
|
|
|
|
/**
|
|
* Get text input
|
|
*
|
|
* @param array $entry The current entry
|
|
* @param string $id The field ID
|
|
* @param string $name The field name
|
|
* @return string The text input field
|
|
*/
|
|
private static function getTextInput($entry, $id, $name)
|
|
{
|
|
return '<input '
|
|
. self::getInputAttributes($entry)
|
|
. ' id="'
|
|
. $id
|
|
. '" type="text" value="'
|
|
. filter_var($entry['defaultValue'], FILTER_SANITIZE_FULL_SPECIAL_CHARS)
|
|
. '" placeholder="'
|
|
. filter_var($entry['exampleValue'], FILTER_SANITIZE_FULL_SPECIAL_CHARS)
|
|
. '" name="'
|
|
. $name
|
|
. '" />'
|
|
. PHP_EOL;
|
|
}
|
|
|
|
/**
|
|
* Get number input
|
|
*
|
|
* @param array $entry The current entry
|
|
* @param string $id The field ID
|
|
* @param string $name The field name
|
|
* @return string The number input field
|
|
*/
|
|
private static function getNumberInput($entry, $id, $name)
|
|
{
|
|
return '<input '
|
|
. self::getInputAttributes($entry)
|
|
. ' id="'
|
|
. $id
|
|
. '" type="number" value="'
|
|
. filter_var($entry['defaultValue'], FILTER_SANITIZE_NUMBER_INT)
|
|
. '" placeholder="'
|
|
. filter_var($entry['exampleValue'], FILTER_SANITIZE_NUMBER_INT)
|
|
. '" name="'
|
|
. $name
|
|
. '" />'
|
|
. PHP_EOL;
|
|
}
|
|
|
|
/**
|
|
* Get list input
|
|
*
|
|
* @param array $entry The current entry
|
|
* @param string $id The field ID
|
|
* @param string $name The field name
|
|
* @return string The list input field
|
|
*/
|
|
private static function getListInput($entry, $id, $name)
|
|
{
|
|
if (isset($entry['required']) && $entry['required'] === true) {
|
|
Debug::log('The "required" attribute is not supported for lists.');
|
|
unset($entry['required']);
|
|
}
|
|
|
|
$list = '<select '
|
|
. self::getInputAttributes($entry)
|
|
. ' id="'
|
|
. $id
|
|
. '" name="'
|
|
. $name
|
|
. '" >';
|
|
|
|
foreach ($entry['values'] as $name => $value) {
|
|
if (is_array($value)) {
|
|
$list .= '<optgroup label="' . htmlentities($name) . '">';
|
|
foreach ($value as $subname => $subvalue) {
|
|
if (
|
|
$entry['defaultValue'] === $subname
|
|
|| $entry['defaultValue'] === $subvalue
|
|
) {
|
|
$list .= '<option value="'
|
|
. $subvalue
|
|
. '" selected>'
|
|
. $subname
|
|
. '</option>';
|
|
} else {
|
|
$list .= '<option value="'
|
|
. $subvalue
|
|
. '">'
|
|
. $subname
|
|
. '</option>';
|
|
}
|
|
}
|
|
$list .= '</optgroup>';
|
|
} else {
|
|
if (
|
|
$entry['defaultValue'] === $name
|
|
|| $entry['defaultValue'] === $value
|
|
) {
|
|
$list .= '<option value="'
|
|
. $value
|
|
. '" selected>'
|
|
. $name
|
|
. '</option>';
|
|
} else {
|
|
$list .= '<option value="'
|
|
. $value
|
|
. '">'
|
|
. $name
|
|
. '</option>';
|
|
}
|
|
}
|
|
}
|
|
|
|
$list .= '</select>';
|
|
|
|
return $list;
|
|
}
|
|
|
|
/**
|
|
* Get checkbox input
|
|
*
|
|
* @param array $entry The current entry
|
|
* @param string $id The field ID
|
|
* @param string $name The field name
|
|
* @return string The checkbox input field
|
|
*/
|
|
private static function getCheckboxInput($entry, $id, $name)
|
|
{
|
|
if (isset($entry['required']) && $entry['required'] === true) {
|
|
Debug::log('The "required" attribute is not supported for checkboxes.');
|
|
unset($entry['required']);
|
|
}
|
|
|
|
return '<input '
|
|
. self::getInputAttributes($entry)
|
|
. ' id="'
|
|
. $id
|
|
. '" type="checkbox" name="'
|
|
. $name
|
|
. '" '
|
|
. ($entry['defaultValue'] === 'checked' ? 'checked' : '')
|
|
. ' />'
|
|
. PHP_EOL;
|
|
}
|
|
}
|