Refactored variable naming to prevent conflicts and added an option for default content handling.
This commit is contained in:
parent
e7cb832d5a
commit
99af4fcd67
5 changed files with 64 additions and 46 deletions
|
|
@ -5,11 +5,12 @@ Usually used to handle cases where the content retrieved via XPath from an artic
|
||||||
|
|
||||||
To use it, upload this entire directory to the FreshRSS `./extensions` directory on your server and enable it on the extension panel in FreshRSS.
|
To use it, upload this entire directory to the FreshRSS `./extensions` directory on your server and enable it on the extension panel in FreshRSS.
|
||||||
|
|
||||||
Note: If an XPath expression error causes content to not be found, return the entire webpage retrieved by cURL by default.
|
Note: If an XPath expression error causes content to not found, The default behavior is not to modify the feed if no content is matched.
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
* 0.2.1 - The test can be used normally.
|
* 0.2.1 - The test can be used normally.
|
||||||
|
* 0.2.2 - Add an option to decide whether to modify the feed when the XPath does not match and Modify the input field to a textarea.
|
||||||
|
|
||||||
## Configuration settings
|
## Configuration settings
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,18 @@
|
||||||
<form action="<?= _url('extension', 'configure', 'e', urlencode($this->getName())) ?>" method="post">
|
<form action="<?= _url('extension', 'configure', 'e', urlencode($this->getName())) ?>" method="post">
|
||||||
<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
|
<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="group-name" for="allow_url"><?= _t('ext.replaceEntryUrl.allow_url') ?></label>
|
<label class="group-name" for="replaceEntryUrl_matchUrlKeyValues"><?= _t('ext.replaceEntryUrl.matchUrlKeyValues') ?></label>
|
||||||
<div class="group-controls">
|
<div class="group-controls">
|
||||||
<input type="text" name="allow_url" id="allow_url"
|
<textarea name="replaceEntryUrl_matchUrlKeyValues" id="replaceEntryUrl_matchUrlKeyValues" rows="5" cols="30"><?= htmlspecialchars(FreshRSS_Context::userConf()->attributeString('replaceEntryUrl_matchUrlKeyValues') ?? '', ENT_COMPAT, 'UTF-8') ?></textarea>
|
||||||
value="<?= htmlspecialchars(FreshRSS_Context::userConf()->attributeString('allow_url') ?? '', ENT_COMPAT, 'UTF-8') ?>">
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="group-name" for="replaceEntryUrl_filterXPathContent"><?= _t('ext.replaceEntryUrl.filterXPathContent') ?></label>
|
||||||
|
<div class="group-controls">
|
||||||
|
<input type="checkbox" name="replaceEntryUrl_filterXPathContent" id="replaceEntryUrl_filterXPathContent" value="1"
|
||||||
|
<?= FreshRSS_Context::userConf()->attributeBool('replaceEntryUrl_filterXPathContent') ? 'checked' : '' ?>>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="form-group form-actions">
|
<div class="form-group form-actions">
|
||||||
<div class="group-controls">
|
<div class="group-controls">
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
class replaceEntryUrlExtension extends Minz_Extension {
|
class replaceEntryUrlExtension extends Minz_Extension {
|
||||||
const ALLOWED_LIST = [];
|
const ALLOWED_LIST = [];
|
||||||
|
const GET_FULL_CONTENT = false;
|
||||||
/**
|
/**
|
||||||
* @throws FreshRSS_Context_Exception
|
* @throws FreshRSS_Context_Exception
|
||||||
*/
|
*/
|
||||||
|
|
@ -13,13 +13,16 @@ class replaceEntryUrlExtension extends Minz_Extension {
|
||||||
}
|
}
|
||||||
$save = false;
|
$save = false;
|
||||||
/*If you want to replace it during refresh, uncomment this line and comment out the line below. it used in test*/
|
/*If you want to replace it during refresh, uncomment this line and comment out the line below. it used in test*/
|
||||||
// $this->registerHook('entry_before_display', [self::class, 'processEntry']);
|
//$this->registerHook('entry_before_display', [self::class, 'processEntry']);
|
||||||
$this->registerHook('entry_before_insert', [self::class, 'processEntry']);
|
$this->registerHook('entry_before_insert', [self::class, 'processEntry']);
|
||||||
if (FreshRSS_Context::userConf()->attributeString('allow_url') === null) {
|
if (FreshRSS_Context::userConf()->attributeString('replaceEntryUrl_matchUrlKeyValues') === null) {
|
||||||
FreshRSS_Context::userConf()->_attribute('allow_url', self::ALLOWED_LIST);
|
FreshRSS_Context::userConf()->_attribute('replaceEntryUrl_matchUrlKeyValues', self::ALLOWED_LIST);
|
||||||
|
$save = true;
|
||||||
|
}
|
||||||
|
if (FreshRSS_Context::userConf()->attributeBool('replaceEntryUrl_filterXPathContent') === null) {
|
||||||
|
FreshRSS_Context::userConf()->_attribute('replaceEntryUrl_filterXPathContent', self::GET_FULL_CONTENT);
|
||||||
$save = true;
|
$save = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -29,7 +32,8 @@ class replaceEntryUrlExtension extends Minz_Extension {
|
||||||
$this->registerTranslates();
|
$this->registerTranslates();
|
||||||
|
|
||||||
if (Minz_Request::isPost()) {
|
if (Minz_Request::isPost()) {
|
||||||
FreshRSS_Context::userConf()->_attribute('allow_url', Minz_Request::paramString('allow_url', plaintext: true) ?: self::ALLOWED_LIST);
|
FreshRSS_Context::userConf()->_attribute('replaceEntryUrl_matchUrlKeyValues', Minz_Request::paramString('replaceEntryUrl_matchUrlKeyValues', plaintext: true) ?: self::ALLOWED_LIST);
|
||||||
|
FreshRSS_Context::userConf()->_attribute('replaceEntryUrl_filterXPathContent', Minz_Request::paramBoolean('replaceEntryUrl_filterXPathContent'));
|
||||||
FreshRSS_Context::userConf()->save();
|
FreshRSS_Context::userConf()->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -41,37 +45,41 @@ class replaceEntryUrlExtension extends Minz_Extension {
|
||||||
* @throws FreshRSS_Context_Exception
|
* @throws FreshRSS_Context_Exception
|
||||||
*/
|
*/
|
||||||
public static function processEntry(FreshRSS_Entry $entry): FreshRSS_Entry {
|
public static function processEntry(FreshRSS_Entry $entry): FreshRSS_Entry {
|
||||||
$allow_array = "";
|
$useDefaultIfEmpty = FreshRSS_Context::userConf()->attributeBool('replaceEntryUrl_filterXPathContent') ?? false;
|
||||||
$allow_url_str = FreshRSS_Context::userConf()->attributeString('allow_url');
|
$allow_array = "";
|
||||||
if (!is_string($allow_url_str) || $allow_url_str === '') {
|
$allow_url_str = FreshRSS_Context::userConf()->attributeString('replaceEntryUrl_matchUrlKeyValues');
|
||||||
return $entry;
|
if (!is_string($allow_url_str) || $allow_url_str === '') {
|
||||||
}
|
return $entry;
|
||||||
$allow_array = json_decode($allow_url_str,true);
|
|
||||||
|
|
||||||
$allow_url = [];
|
|
||||||
|
|
||||||
if(json_last_error() === JSON_ERROR_NONE && is_array($allow_array)){
|
|
||||||
foreach ($allow_array as $key => $value) {
|
|
||||||
array_push($allow_url, (string)$key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!is_array($allow_array)){
|
|
||||||
return $entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$link = $entry->link();
|
|
||||||
$my_xpath = self::isUrlAllowed($link,$allow_url,$allow_array);
|
|
||||||
|
|
||||||
if (empty($my_xpath)) {
|
|
||||||
return $entry;
|
|
||||||
}
|
}
|
||||||
$response = self::curlDownloadContent($link);
|
$allow_array = json_decode($allow_url_str,true);
|
||||||
if($response != false){
|
|
||||||
$article = self:: extractMainContent($response,$my_xpath);
|
$allow_url = [];
|
||||||
$entry->_content ($article);
|
|
||||||
|
if(json_last_error() === JSON_ERROR_NONE && is_array($allow_array)){
|
||||||
|
foreach ($allow_array as $key => $value) {
|
||||||
|
array_push($allow_url, (string)$key);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if(!is_array($allow_array)){
|
||||||
|
return $entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$link = $entry->link();
|
||||||
|
$my_xpath = self::isUrlAllowed($link,$allow_url,$allow_array);
|
||||||
|
|
||||||
|
if (empty($my_xpath)) {
|
||||||
|
return $entry;
|
||||||
|
}
|
||||||
|
$response = self::curlDownloadContent($link);
|
||||||
|
$article = "";
|
||||||
|
if($response != false){
|
||||||
|
$article = self:: extractMainContent($response,$my_xpath,$useDefaultIfEmpty);
|
||||||
|
}
|
||||||
|
if($article != ""){
|
||||||
|
$entry->_content ($article);
|
||||||
|
}
|
||||||
|
|
||||||
return $entry;
|
return $entry;
|
||||||
}
|
}
|
||||||
|
|
@ -102,16 +110,19 @@ class replaceEntryUrlExtension extends Minz_Extension {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function extractMainContent(string $content,string $my_xpath): string {
|
public static function extractMainContent(string $content,string $my_xpath,bool $useDefaultIfEmpty): string {
|
||||||
$doc = new DOMDocument();
|
$doc = new DOMDocument();
|
||||||
libxml_use_internal_errors(true);
|
libxml_use_internal_errors(true);
|
||||||
$doc->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'));
|
$doc->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'));
|
||||||
|
|
||||||
$xpath = new DOMXPath($doc);
|
$xpath = new DOMXPath($doc);
|
||||||
$nodes = $xpath->query($my_xpath);
|
$nodes = $xpath->query($my_xpath);
|
||||||
|
$mainContent = "";
|
||||||
if ($nodes instanceof DOMNodeList && $nodes->length > 0) {
|
if ($nodes instanceof DOMNodeList && $nodes->length > 0) {
|
||||||
$mainContent = $doc->saveHTML($nodes->item(0));
|
$mainContent = $doc->saveHTML($nodes->item(0));
|
||||||
}else{
|
}
|
||||||
|
elseif($useDefaultIfEmpty)
|
||||||
|
{
|
||||||
$mainContent = $content;
|
$mainContent = $content;
|
||||||
}
|
}
|
||||||
libxml_clear_errors();
|
libxml_clear_errors();
|
||||||
|
|
@ -136,7 +147,7 @@ class replaceEntryUrlExtension extends Minz_Extension {
|
||||||
if (is_string($xpath_value)) {
|
if (is_string($xpath_value)) {
|
||||||
return $xpath_value;
|
return $xpath_value;
|
||||||
}
|
}
|
||||||
return '';
|
return "";
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'replaceEntryUrl' => array(
|
'replaceEntryUrl' => array(
|
||||||
'allow_url' => 'replace domain:'
|
'matchUrlKeyValues' => 'domain json:',
|
||||||
|
'filterXPathContent' => 'Return full content by default'
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "replace Entry Url",
|
"name": "replace Entry Url",
|
||||||
"author": "fiifff",
|
"author": "fiifff",
|
||||||
"description": "Replace the URL in the content of subscription entries with the actual content of the URL.",
|
"description": "Replace the URL in the content of subscription entries with the actual content of the URL.",
|
||||||
"version": "0.2.1",
|
"version": "0.2.2",
|
||||||
"entrypoint": "replaceEntryUrl",
|
"entrypoint": "replaceEntryUrl",
|
||||||
"type": "user"
|
"type": "user"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue