init
This commit is contained in:
12
user/plugins/admin/vendor/autoload.php
vendored
Normal file
12
user/plugins/admin/vendor/autoload.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit38a448a612c5797456d245c809d4a914::getLoader();
|
||||
107
user/plugins/admin/vendor/bin/picofeed
vendored
Normal file
107
user/plugins/admin/vendor/bin/picofeed
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Proxy PHP file generated by Composer
|
||||
*
|
||||
* This file includes the referenced bin path (../p3k/picofeed/picofeed)
|
||||
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BinProxyWrapper
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
$data = fread($this->handle, $count);
|
||||
|
||||
if ($this->position === 0) {
|
||||
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||
}
|
||||
|
||||
$this->position += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function stream_cast($castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
public function stream_close()
|
||||
{
|
||||
fclose($this->handle);
|
||||
}
|
||||
|
||||
public function stream_lock($operation)
|
||||
{
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) {
|
||||
include("phpvfscomposer://" . __DIR__ . '/..'.'/p3k/picofeed/picofeed');
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
include __DIR__ . '/..'.'/p3k/picofeed/picofeed';
|
||||
120
user/plugins/admin/vendor/bin/pscss
vendored
Normal file
120
user/plugins/admin/vendor/bin/pscss
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Proxy PHP file generated by Composer
|
||||
*
|
||||
* This file includes the referenced bin path (../scssphp/scssphp/bin/pscss)
|
||||
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BinProxyWrapper
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
$data = fread($this->handle, $count);
|
||||
|
||||
if ($this->position === 0) {
|
||||
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||
}
|
||||
|
||||
$this->position += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function stream_cast($castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
public function stream_close()
|
||||
{
|
||||
fclose($this->handle);
|
||||
}
|
||||
|
||||
public function stream_lock($operation)
|
||||
{
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
include("phpvfscomposer://" . __DIR__ . '/..'.'/scssphp/scssphp/bin/pscss');
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
include __DIR__ . '/..'.'/scssphp/scssphp/bin/pscss';
|
||||
572
user/plugins/admin/vendor/composer/ClassLoader.php
vendored
Normal file
572
user/plugins/admin/vendor/composer/ClassLoader.php
vendored
Normal file
@@ -0,0 +1,572 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
/**
|
||||
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||
*
|
||||
* $loader = new \Composer\Autoload\ClassLoader();
|
||||
*
|
||||
* // register classes with namespaces
|
||||
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||
* $loader->add('Symfony', __DIR__.'/framework');
|
||||
*
|
||||
* // activate the autoloader
|
||||
* $loader->register();
|
||||
*
|
||||
* // to enable searching the include path (eg. for PEAR packages)
|
||||
* $loader->setUseIncludePath(true);
|
||||
*
|
||||
* In this example, if you try to use a class in the Symfony\Component
|
||||
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||
* the autoloader will first look for the class under the component/
|
||||
* directory, and it will then fallback to the framework/ directory if not
|
||||
* found before giving up.
|
||||
*
|
||||
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @see https://www.php-fig.org/psr/psr-0/
|
||||
* @see https://www.php-fig.org/psr/psr-4/
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var ?string */
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, int>>
|
||||
*/
|
||||
private $prefixLengthsPsr4 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<int, string>>
|
||||
*/
|
||||
private $prefixDirsPsr4 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, string[]>>
|
||||
*/
|
||||
private $prefixesPsr0 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
/** @var bool */
|
||||
private $useIncludePath = false;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $classMap = array();
|
||||
|
||||
/** @var bool */
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
/**
|
||||
* @var bool[]
|
||||
* @psalm-var array<string, bool>
|
||||
*/
|
||||
private $missingClasses = array();
|
||||
|
||||
/** @var ?string */
|
||||
private $apcuPrefix;
|
||||
|
||||
/**
|
||||
* @var self[]
|
||||
*/
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
/**
|
||||
* @param ?string $vendorDir
|
||||
*/
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, array<int, string>>
|
||||
*/
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[] Array of classname => path
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $classMap Class to filename map
|
||||
* @psalm-param array<string, string> $classMap
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
if ($this->classMap) {
|
||||
$this->classMap = array_merge($this->classMap, $classMap);
|
||||
} else {
|
||||
$this->classMap = $classMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix, either
|
||||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param string[]|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace, either
|
||||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param string[]|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||
// Register directories for a new namespace.
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix,
|
||||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param string[]|string $paths The PSR-0 base directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr0 = (array) $paths;
|
||||
} else {
|
||||
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace,
|
||||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param string[]|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr4 = (array) $paths;
|
||||
} else {
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
$this->useIncludePath = $useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
return $this->useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off searching the prefix and fallback directories for classes
|
||||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should class lookup fail if not found in the current class map?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClassMapAuthoritative()
|
||||
{
|
||||
return $this->classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getApcuPrefix()
|
||||
{
|
||||
return $this->apcuPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
|
||||
if (null === $this->vendorDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($prepend) {
|
||||
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||
} else {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
|
||||
if (null !== $this->vendorDir) {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return true|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the file where the class is defined.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return string|false The path if found, false otherwise
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
// class map lookup
|
||||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
}
|
||||
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||
return false;
|
||||
}
|
||||
if (null !== $this->apcuPrefix) {
|
||||
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||
if ($hit) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
// Search for Hack files if we are running on HHVM
|
||||
if (false === $file && defined('HHVM_VERSION')) {
|
||||
$file = $this->findFileWithExtension($class, '.hh');
|
||||
}
|
||||
|
||||
if (null !== $this->apcuPrefix) {
|
||||
apcu_add($this->apcuPrefix.$class, $file);
|
||||
}
|
||||
|
||||
if (false === $file) {
|
||||
// Remember that this class does not exist.
|
||||
$this->missingClasses[$class] = true;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered loaders indexed by their corresponding vendor directories.
|
||||
*
|
||||
* @return self[]
|
||||
*/
|
||||
public static function getRegisteredLoaders()
|
||||
{
|
||||
return self::$registeredLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $ext
|
||||
* @return string|false
|
||||
*/
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||
$subPath = $class;
|
||||
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||
$subPath = substr($subPath, 0, $lastPos);
|
||||
$search = $subPath . '\\';
|
||||
if (isset($this->prefixDirsPsr4[$search])) {
|
||||
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||
if (file_exists($file = $dir . $pathEnd)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-4 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 lookup
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||
}
|
||||
|
||||
if (isset($this->prefixesPsr0[$first])) {
|
||||
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 include paths.
|
||||
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
* @private
|
||||
*/
|
||||
function includeFile($file)
|
||||
{
|
||||
include $file;
|
||||
}
|
||||
352
user/plugins/admin/vendor/composer/InstalledVersions.php
vendored
Normal file
352
user/plugins/admin/vendor/composer/InstalledVersions.php
vendored
Normal file
@@ -0,0 +1,352 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Composer\Semver\VersionParser;
|
||||
|
||||
/**
|
||||
* This class is copied in every Composer installed project and available to all
|
||||
*
|
||||
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||
*
|
||||
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private static $canGetVendors;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static $installedByVendor = array();
|
||||
|
||||
/**
|
||||
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||
*
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackages()
|
||||
{
|
||||
$packages = array();
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
$packages[] = array_keys($installed['versions']);
|
||||
}
|
||||
|
||||
if (1 === \count($packages)) {
|
||||
return $packages[0];
|
||||
}
|
||||
|
||||
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all package names with a specific type e.g. 'library'
|
||||
*
|
||||
* @param string $type
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackagesByType($type)
|
||||
{
|
||||
$packagesByType = array();
|
||||
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
foreach ($installed['versions'] as $name => $package) {
|
||||
if (isset($package['type']) && $package['type'] === $type) {
|
||||
$packagesByType[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $packagesByType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package is installed
|
||||
*
|
||||
* This also returns true if the package name is provided or replaced by another package
|
||||
*
|
||||
* @param string $packageName
|
||||
* @param bool $includeDevRequirements
|
||||
* @return bool
|
||||
*/
|
||||
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (isset($installed['versions'][$packageName])) {
|
||||
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package satisfies a version constraint
|
||||
*
|
||||
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||
*
|
||||
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||
*
|
||||
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||
* @param string $packageName
|
||||
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||
* @return bool
|
||||
*/
|
||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||
{
|
||||
$constraint = $parser->parseConstraints($constraint);
|
||||
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||
|
||||
return $provided->matches($constraint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||
*
|
||||
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||
* whether a given version of a package is installed, and not just whether it exists
|
||||
*
|
||||
* @param string $packageName
|
||||
* @return string Version constraint usable with composer/semver
|
||||
*/
|
||||
public static function getVersionRanges($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ranges = array();
|
||||
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||
}
|
||||
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||
}
|
||||
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||
}
|
||||
|
||||
return implode(' || ', $ranges);
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getPrettyVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||
*/
|
||||
public static function getReference($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['reference'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||
*/
|
||||
public static function getInstallPath($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||
*/
|
||||
public static function getRootPackage()
|
||||
{
|
||||
$installed = self::getInstalled();
|
||||
|
||||
return $installed[0]['root'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw installed.php data for custom implementations
|
||||
*
|
||||
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||
* @return array[]
|
||||
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
|
||||
*/
|
||||
public static function getRawData()
|
||||
{
|
||||
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = include __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$installed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||
*
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
public static function getAllRawData()
|
||||
{
|
||||
return self::getInstalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets you reload the static array from another file
|
||||
*
|
||||
* This is only useful for complex integrations in which a project needs to use
|
||||
* this class but then also needs to execute another project's autoloader in process,
|
||||
* and wants to ensure both projects have access to their version of installed.php.
|
||||
*
|
||||
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||
* the data it needs from this class, then call reload() with
|
||||
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||
* the project in which it runs can then also use this class safely, without
|
||||
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||
*
|
||||
* @param array[] $data A vendor/composer/installed.php data set
|
||||
* @return void
|
||||
*
|
||||
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
self::$installed = $data;
|
||||
self::$installedByVendor = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static function getInstalled()
|
||||
{
|
||||
if (null === self::$canGetVendors) {
|
||||
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||
}
|
||||
|
||||
$installed = array();
|
||||
|
||||
if (self::$canGetVendors) {
|
||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir];
|
||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
|
||||
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $installed[count($installed) - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = require __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
$installed[] = self::$installed;
|
||||
|
||||
return $installed;
|
||||
}
|
||||
}
|
||||
21
user/plugins/admin/vendor/composer/LICENSE
vendored
Normal file
21
user/plugins/admin/vendor/composer/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
11
user/plugins/admin/vendor/composer/autoload_classmap.php
vendored
Normal file
11
user/plugins/admin/vendor/composer/autoload_classmap.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||
'Grav\\Plugin\\AdminPlugin' => $baseDir . '/admin.php',
|
||||
);
|
||||
10
user/plugins/admin/vendor/composer/autoload_files.php
vendored
Normal file
10
user/plugins/admin/vendor/composer/autoload_files.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
// autoload_files.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'7e9bd612cc444b3eed788ebbe46263a0' => $vendorDir . '/laminas/laminas-zendframework-bridge/src/autoload.php',
|
||||
);
|
||||
10
user/plugins/admin/vendor/composer/autoload_namespaces.php
vendored
Normal file
10
user/plugins/admin/vendor/composer/autoload_namespaces.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'PicoFeed' => array($vendorDir . '/p3k/picofeed/lib'),
|
||||
);
|
||||
13
user/plugins/admin/vendor/composer/autoload_psr4.php
vendored
Normal file
13
user/plugins/admin/vendor/composer/autoload_psr4.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'ScssPhp\\ScssPhp\\' => array($vendorDir . '/scssphp/scssphp/src'),
|
||||
'Laminas\\ZendFrameworkBridge\\' => array($vendorDir . '/laminas/laminas-zendframework-bridge/src'),
|
||||
'Laminas\\Xml\\' => array($vendorDir . '/laminas/laminas-xml/src'),
|
||||
'Grav\\Plugin\\Admin\\' => array($baseDir . '/classes/plugin'),
|
||||
);
|
||||
57
user/plugins/admin/vendor/composer/autoload_real.php
vendored
Normal file
57
user/plugins/admin/vendor/composer/autoload_real.php
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit38a448a612c5797456d245c809d4a914
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
public static function loadClassLoader($class)
|
||||
{
|
||||
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||
require __DIR__ . '/ClassLoader.php';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
require __DIR__ . '/platform_check.php';
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit38a448a612c5797456d245c809d4a914', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit38a448a612c5797456d245c809d4a914', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit38a448a612c5797456d245c809d4a914::getInitializer($loader));
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
$includeFiles = \Composer\Autoload\ComposerStaticInit38a448a612c5797456d245c809d4a914::$files;
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequire38a448a612c5797456d245c809d4a914($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileIdentifier
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
function composerRequire38a448a612c5797456d245c809d4a914($fileIdentifier, $file)
|
||||
{
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
||||
require $file;
|
||||
}
|
||||
}
|
||||
73
user/plugins/admin/vendor/composer/autoload_static.php
vendored
Normal file
73
user/plugins/admin/vendor/composer/autoload_static.php
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
// autoload_static.php @generated by Composer
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit38a448a612c5797456d245c809d4a914
|
||||
{
|
||||
public static $files = array (
|
||||
'7e9bd612cc444b3eed788ebbe46263a0' => __DIR__ . '/..' . '/laminas/laminas-zendframework-bridge/src/autoload.php',
|
||||
);
|
||||
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'S' =>
|
||||
array (
|
||||
'ScssPhp\\ScssPhp\\' => 16,
|
||||
),
|
||||
'L' =>
|
||||
array (
|
||||
'Laminas\\ZendFrameworkBridge\\' => 28,
|
||||
'Laminas\\Xml\\' => 12,
|
||||
),
|
||||
'G' =>
|
||||
array (
|
||||
'Grav\\Plugin\\Admin\\' => 18,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'ScssPhp\\ScssPhp\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/scssphp/scssphp/src',
|
||||
),
|
||||
'Laminas\\ZendFrameworkBridge\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/laminas/laminas-zendframework-bridge/src',
|
||||
),
|
||||
'Laminas\\Xml\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/laminas/laminas-xml/src',
|
||||
),
|
||||
'Grav\\Plugin\\Admin\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/../..' . '/classes/plugin',
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixesPsr0 = array (
|
||||
'P' =>
|
||||
array (
|
||||
'PicoFeed' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/p3k/picofeed/lib',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
public static $classMap = array (
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
'Grav\\Plugin\\AdminPlugin' => __DIR__ . '/../..' . '/admin.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit38a448a612c5797456d245c809d4a914::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit38a448a612c5797456d245c809d4a914::$prefixDirsPsr4;
|
||||
$loader->prefixesPsr0 = ComposerStaticInit38a448a612c5797456d245c809d4a914::$prefixesPsr0;
|
||||
$loader->classMap = ComposerStaticInit38a448a612c5797456d245c809d4a914::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
}
|
||||
280
user/plugins/admin/vendor/composer/installed.json
vendored
Normal file
280
user/plugins/admin/vendor/composer/installed.json
vendored
Normal file
@@ -0,0 +1,280 @@
|
||||
{
|
||||
"packages": [
|
||||
{
|
||||
"name": "laminas/laminas-xml",
|
||||
"version": "1.4.0",
|
||||
"version_normalized": "1.4.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laminas/laminas-xml.git",
|
||||
"reference": "dcadeefdb6d7ed6b39d772b47e3845003d6ea60f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laminas/laminas-xml/zipball/dcadeefdb6d7ed6b39d772b47e3845003d6ea60f",
|
||||
"reference": "dcadeefdb6d7ed6b39d772b47e3845003d6ea60f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-simplexml": "*",
|
||||
"php": "^7.3 || ~8.0.0 || ~8.1.0"
|
||||
},
|
||||
"conflict": {
|
||||
"zendframework/zendxml": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-iconv": "*",
|
||||
"laminas/laminas-coding-standard": "~1.0.0",
|
||||
"phpunit/phpunit": "^9.5.8",
|
||||
"squizlabs/php_codesniffer": "3.6.1 as 2.9999999.9999999"
|
||||
},
|
||||
"time": "2021-11-30T02:16:35+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laminas\\Xml\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"description": "Utility library for XML usage, best practices, and security in PHP",
|
||||
"homepage": "https://laminas.dev",
|
||||
"keywords": [
|
||||
"laminas",
|
||||
"security",
|
||||
"xml"
|
||||
],
|
||||
"support": {
|
||||
"chat": "https://laminas.dev/chat",
|
||||
"forum": "https://discourse.laminas.dev",
|
||||
"issues": "https://github.com/laminas/laminas-xml/issues",
|
||||
"rss": "https://github.com/laminas/laminas-xml/releases.atom",
|
||||
"source": "https://github.com/laminas/laminas-xml"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://funding.communitybridge.org/projects/laminas-project",
|
||||
"type": "community_bridge"
|
||||
}
|
||||
],
|
||||
"install-path": "../laminas/laminas-xml"
|
||||
},
|
||||
{
|
||||
"name": "laminas/laminas-zendframework-bridge",
|
||||
"version": "1.4.1",
|
||||
"version_normalized": "1.4.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laminas/laminas-zendframework-bridge.git",
|
||||
"reference": "88bf037259869891afce6504cacc4f8a07b24d0f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/88bf037259869891afce6504cacc4f8a07b24d0f",
|
||||
"reference": "88bf037259869891afce6504cacc4f8a07b24d0f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.3 || ~8.0.0 || ~8.1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.3",
|
||||
"psalm/plugin-phpunit": "^0.15.1",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"vimeo/psalm": "^4.6"
|
||||
},
|
||||
"time": "2021-12-21T14:34:37+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laminas": {
|
||||
"module": "Laminas\\ZendFrameworkBridge"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/autoload.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Laminas\\ZendFrameworkBridge\\": "src//"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"description": "Alias legacy ZF class names to Laminas Project equivalents.",
|
||||
"keywords": [
|
||||
"ZendFramework",
|
||||
"autoloading",
|
||||
"laminas",
|
||||
"zf"
|
||||
],
|
||||
"support": {
|
||||
"forum": "https://discourse.laminas.dev/",
|
||||
"issues": "https://github.com/laminas/laminas-zendframework-bridge/issues",
|
||||
"rss": "https://github.com/laminas/laminas-zendframework-bridge/releases.atom",
|
||||
"source": "https://github.com/laminas/laminas-zendframework-bridge"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://funding.communitybridge.org/projects/laminas-project",
|
||||
"type": "community_bridge"
|
||||
}
|
||||
],
|
||||
"install-path": "../laminas/laminas-zendframework-bridge"
|
||||
},
|
||||
{
|
||||
"name": "p3k/picofeed",
|
||||
"version": "v0.1.40",
|
||||
"version_normalized": "0.1.40.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aaronpk/picofeed.git",
|
||||
"reference": "356fd66d48779193b10ac28532cb4a4e11bb801c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aaronpk/picofeed/zipball/356fd66d48779193b10ac28532cb4a4e11bb801c",
|
||||
"reference": "356fd66d48779193b10ac28532cb4a4e11bb801c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-iconv": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-simplexml": "*",
|
||||
"ext-xml": "*",
|
||||
"laminas/laminas-xml": "^1.2",
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"replace": {
|
||||
"miniflux/picofeed": "0.1.35"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpdocumentor/reflection-docblock": "2.0.4",
|
||||
"phpunit/phpunit": "4.8.26",
|
||||
"symfony/yaml": "2.8.7"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-curl": "PicoFeed will use cURL if present"
|
||||
},
|
||||
"time": "2020-04-25T17:48:36+00:00",
|
||||
"bin": [
|
||||
"picofeed"
|
||||
],
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"PicoFeed": "lib/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Frédéric Guillot"
|
||||
}
|
||||
],
|
||||
"description": "Modern library to handle RSS/Atom feeds",
|
||||
"homepage": "https://github.com/aaronpk/picoFeed",
|
||||
"support": {
|
||||
"issues": "https://github.com/aaronpk/picofeed/issues",
|
||||
"source": "https://github.com/aaronpk/picofeed/tree/v0.1.40"
|
||||
},
|
||||
"install-path": "../p3k/picofeed"
|
||||
},
|
||||
{
|
||||
"name": "scssphp/scssphp",
|
||||
"version": "v1.10.4",
|
||||
"version_normalized": "1.10.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/scssphp/scssphp.git",
|
||||
"reference": "8ed20753db2d3d82629e6f5d35535bbbd3893b0c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/scssphp/scssphp/zipball/8ed20753db2d3d82629e6f5d35535bbbd3893b0c",
|
||||
"reference": "8ed20753db2d3d82629e6f5d35535bbbd3893b0c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-ctype": "*",
|
||||
"ext-json": "*",
|
||||
"php": ">=5.6.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"bamarni/composer-bin-plugin": "^1.4",
|
||||
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3 || ^9.4",
|
||||
"sass/sass-spec": "*",
|
||||
"squizlabs/php_codesniffer": "~3.5",
|
||||
"symfony/phpunit-bridge": "^5.1",
|
||||
"thoughtbot/bourbon": "^7.0",
|
||||
"twbs/bootstrap": "~5.0",
|
||||
"twbs/bootstrap4": "4.6.1",
|
||||
"zurb/foundation": "~6.5"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-iconv": "Can be used as fallback when ext-mbstring is not available",
|
||||
"ext-mbstring": "For best performance, mbstring should be installed as it is faster than ext-iconv"
|
||||
},
|
||||
"time": "2022-07-26T16:28:33+00:00",
|
||||
"bin": [
|
||||
"bin/pscss"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"bamarni-bin": {
|
||||
"forward-command": false,
|
||||
"bin-links": false
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"ScssPhp\\ScssPhp\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Anthon Pang",
|
||||
"email": "apang@softwaredevelopment.ca",
|
||||
"homepage": "https://github.com/robocoder"
|
||||
},
|
||||
{
|
||||
"name": "Cédric Morin",
|
||||
"email": "cedric@yterium.com",
|
||||
"homepage": "https://github.com/Cerdic"
|
||||
}
|
||||
],
|
||||
"description": "scssphp is a compiler for SCSS written in PHP.",
|
||||
"homepage": "http://scssphp.github.io/scssphp/",
|
||||
"keywords": [
|
||||
"css",
|
||||
"less",
|
||||
"sass",
|
||||
"scss",
|
||||
"stylesheet"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/scssphp/scssphp/issues",
|
||||
"source": "https://github.com/scssphp/scssphp/tree/v1.10.4"
|
||||
},
|
||||
"install-path": "../scssphp/scssphp"
|
||||
}
|
||||
],
|
||||
"dev": false,
|
||||
"dev-package-names": []
|
||||
}
|
||||
77
user/plugins/admin/vendor/composer/installed.php
vendored
Normal file
77
user/plugins/admin/vendor/composer/installed.php
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'name' => 'getgrav/grav-plugin-admin',
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'reference' => '713002e2b83b9660bfcefe5bb0d76954eedf2b90',
|
||||
'type' => 'grav-plugin',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev' => false,
|
||||
),
|
||||
'versions' => array(
|
||||
'getgrav/grav-plugin-admin' => array(
|
||||
'pretty_version' => 'dev-develop',
|
||||
'version' => 'dev-develop',
|
||||
'reference' => '713002e2b83b9660bfcefe5bb0d76954eedf2b90',
|
||||
'type' => 'grav-plugin',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'laminas/laminas-xml' => array(
|
||||
'pretty_version' => '1.4.0',
|
||||
'version' => '1.4.0.0',
|
||||
'reference' => 'dcadeefdb6d7ed6b39d772b47e3845003d6ea60f',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../laminas/laminas-xml',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'laminas/laminas-zendframework-bridge' => array(
|
||||
'pretty_version' => '1.4.1',
|
||||
'version' => '1.4.1.0',
|
||||
'reference' => '88bf037259869891afce6504cacc4f8a07b24d0f',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../laminas/laminas-zendframework-bridge',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'miniflux/picofeed' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '0.1.35',
|
||||
),
|
||||
),
|
||||
'p3k/picofeed' => array(
|
||||
'pretty_version' => 'v0.1.40',
|
||||
'version' => '0.1.40.0',
|
||||
'reference' => '356fd66d48779193b10ac28532cb4a4e11bb801c',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../p3k/picofeed',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'scssphp/scssphp' => array(
|
||||
'pretty_version' => 'v1.10.4',
|
||||
'version' => '1.10.4.0',
|
||||
'reference' => '8ed20753db2d3d82629e6f5d35535bbbd3893b0c',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../scssphp/scssphp',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-php72' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '*',
|
||||
),
|
||||
),
|
||||
'symfony/polyfill-php73' => array(
|
||||
'dev_requirement' => false,
|
||||
'replaced' => array(
|
||||
0 => '*',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
26
user/plugins/admin/vendor/composer/platform_check.php
vendored
Normal file
26
user/plugins/admin/vendor/composer/platform_check.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
// platform_check.php @generated by Composer
|
||||
|
||||
$issues = array();
|
||||
|
||||
if (!(PHP_VERSION_ID >= 70306)) {
|
||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.6". You are running ' . PHP_VERSION . '.';
|
||||
}
|
||||
|
||||
if ($issues) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
|
||||
} elseif (!headers_sent()) {
|
||||
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
'Composer detected issues in your platform: ' . implode(' ', $issues),
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
22
user/plugins/admin/vendor/laminas/laminas-xml/.github/workflows/auto-close.yml
vendored
Normal file
22
user/plugins/admin/vendor/laminas/laminas-xml/.github/workflows/auto-close.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
name: Autocloser
|
||||
on: [issues, pull_request]
|
||||
jobs:
|
||||
autoclose:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Autoclose new issues and PRs
|
||||
uses: roots/issue-closer@v1.1
|
||||
with:
|
||||
repo-token: ${{ secrets.ORGANIZATION_ADMIN_TOKEN }}
|
||||
issue-pattern: "^exact-string-will-never-match$"
|
||||
pr-pattern: "^exact-string-will-never-match$"
|
||||
issue-close-message: |
|
||||
This package is considered feature-complete, and is now in **security-only** maintenance mode, following a [decision by the Technical Steering Committee](https://github.com/laminas/technical-steering-committee/blob/2b55453e172a1b8c9c4c212be7cf7e7a58b9352c/meetings/minutes/2020-08-03-TSC-Minutes.md#vote-on-components-to-mark-as-security-only).
|
||||
If you have a security issue, please [follow our security reporting guidelines](https://getlaminas.org/security/).
|
||||
If you wish to take on the role of maintainer, please [nominate yourself](https://github.com/laminas/technical-steering-committee/issues/new?assignees=&labels=Nomination&template=Maintainer_Nomination.md&title=%5BNOMINATION%5D%5BMAINTAINER%5D%3A+%7Bname+of+person+being+nominated%7D)
|
||||
|
||||
pr-close-message: |
|
||||
This package is considered feature-complete, and is now in **security-only** maintenance mode, following a [decision by the Technical Steering Committee](https://github.com/laminas/technical-steering-committee/blob/2b55453e172a1b8c9c4c212be7cf7e7a58b9352c/meetings/minutes/2020-08-03-TSC-Minutes.md#vote-on-components-to-mark-as-security-only).
|
||||
If you have a security issue, please [follow our security reporting guidelines](https://getlaminas.org/security/).
|
||||
If you wish to take on the role of maintainer, please [nominate yourself](https://github.com/laminas/technical-steering-committee/issues/new?assignees=&labels=Nomination&template=Maintainer_Nomination.md&title=%5BNOMINATION%5D%5BMAINTAINER%5D%3A+%7Bname+of+person+being+nominated%7D)
|
||||
|
||||
33
user/plugins/admin/vendor/laminas/laminas-xml/.github/workflows/continuous-integration.yml
vendored
Normal file
33
user/plugins/admin/vendor/laminas/laminas-xml/.github/workflows/continuous-integration.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
name: "Continuous Integration"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- '[0-9]+.[0-9]+.x'
|
||||
- 'refs/pull/*'
|
||||
tags:
|
||||
|
||||
jobs:
|
||||
matrix:
|
||||
name: Generate job matrix
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.matrix.outputs.matrix }}
|
||||
steps:
|
||||
- name: Gather CI configuration
|
||||
id: matrix
|
||||
uses: laminas/laminas-ci-matrix-action@v1
|
||||
|
||||
qa:
|
||||
name: QA Checks
|
||||
needs: [matrix]
|
||||
runs-on: ${{ matrix.operatingSystem }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJSON(needs.matrix.outputs.matrix) }}
|
||||
steps:
|
||||
- name: ${{ matrix.name }}
|
||||
uses: laminas/laminas-continuous-integration-action@v1
|
||||
with:
|
||||
job: ${{ matrix.job }}
|
||||
71
user/plugins/admin/vendor/laminas/laminas-xml/.github/workflows/release-on-milestone-closed.yml
vendored
Normal file
71
user/plugins/admin/vendor/laminas/laminas-xml/.github/workflows/release-on-milestone-closed.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
# Alternate workflow example.
|
||||
# This one is identical to the one in release-on-milestone.yml, with one change:
|
||||
# the Release step uses the ORGANIZATION_ADMIN_TOKEN instead, to allow it to
|
||||
# trigger a release workflow event. This is useful if you have other actions
|
||||
# that intercept that event.
|
||||
|
||||
name: "Automatic Releases"
|
||||
|
||||
on:
|
||||
milestone:
|
||||
types:
|
||||
- "closed"
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: "GIT tag, release & create merge-up PR"
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
uses: "actions/checkout@v2"
|
||||
|
||||
- name: "Release"
|
||||
uses: "laminas/automatic-releases@v1"
|
||||
with:
|
||||
command-name: "laminas:automatic-releases:release"
|
||||
env:
|
||||
"GITHUB_TOKEN": ${{ secrets.ORGANIZATION_ADMIN_TOKEN }}
|
||||
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
|
||||
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
|
||||
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
|
||||
|
||||
- name: "Create Merge-Up Pull Request"
|
||||
uses: "laminas/automatic-releases@v1"
|
||||
with:
|
||||
command-name: "laminas:automatic-releases:create-merge-up-pull-request"
|
||||
env:
|
||||
"GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }}
|
||||
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
|
||||
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
|
||||
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
|
||||
|
||||
- name: "Create and/or Switch to new Release Branch"
|
||||
uses: "laminas/automatic-releases@v1"
|
||||
with:
|
||||
command-name: "laminas:automatic-releases:switch-default-branch-to-next-minor"
|
||||
env:
|
||||
"GITHUB_TOKEN": ${{ secrets.ORGANIZATION_ADMIN_TOKEN }}
|
||||
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
|
||||
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
|
||||
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
|
||||
|
||||
- name: "Bump Changelog Version On Originating Release Branch"
|
||||
uses: "laminas/automatic-releases@v1"
|
||||
with:
|
||||
command-name: "laminas:automatic-releases:bump-changelog"
|
||||
env:
|
||||
"GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }}
|
||||
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
|
||||
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
|
||||
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
|
||||
|
||||
- name: "Create new milestones"
|
||||
uses: "laminas/automatic-releases@v1"
|
||||
with:
|
||||
command-name: "laminas:automatic-releases:create-milestones"
|
||||
env:
|
||||
"GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }}
|
||||
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
|
||||
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
|
||||
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
|
||||
1
user/plugins/admin/vendor/laminas/laminas-xml/COPYRIGHT.md
vendored
Normal file
1
user/plugins/admin/vendor/laminas/laminas-xml/COPYRIGHT.md
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/)
|
||||
26
user/plugins/admin/vendor/laminas/laminas-xml/LICENSE.md
vendored
Normal file
26
user/plugins/admin/vendor/laminas/laminas-xml/LICENSE.md
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of Laminas Foundation nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
51
user/plugins/admin/vendor/laminas/laminas-xml/README.md
vendored
Normal file
51
user/plugins/admin/vendor/laminas/laminas-xml/README.md
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
# laminas-xml
|
||||
|
||||
> This package is considered feature-complete, and is now in **security-only** maintenance mode, following a [decision by the Technical Steering Committee](https://github.com/laminas/technical-steering-committee/blob/2b55453e172a1b8c9c4c212be7cf7e7a58b9352c/meetings/minutes/2020-08-03-TSC-Minutes.md#vote-on-components-to-mark-as-security-only).
|
||||
> If you have a security issue, please [follow our security reporting guidelines](https://getlaminas.org/security/).
|
||||
> If you wish to take on the role of maintainer, please [nominate yourself](https://github.com/laminas/technical-steering-committee/issues/new?assignees=&labels=Nomination&template=Maintainer_Nomination.md&title=%5BNOMINATION%5D%5BMAINTAINER%5D%3A+%7Bname+of+person+being+nominated%7D)
|
||||
|
||||
|
||||
[](https://github.com/laminas/laminas-xml/actions?query=workflow%3A"Continuous+Integration")
|
||||
|
||||
An utility component for XML usage and best practices in PHP
|
||||
|
||||
## Installation
|
||||
|
||||
You can install using:
|
||||
|
||||
```bash
|
||||
$ curl -s https://getcomposer.org/installer | php
|
||||
$ php composer.phar install
|
||||
```
|
||||
|
||||
Notice that this library doesn't have any external dependencies, the usage of composer is for autoloading and standard purpose.
|
||||
|
||||
## Laminas\Xml\Security
|
||||
|
||||
This is a security component to prevent [XML eXternal Entity](https://www.owasp.org/index.php/XML_External_Entity_%28XXE%29_Processing) (XXE) and [XML Entity Expansion](http://projects.webappsec.org/w/page/13247002/XML%20Entity%20Expansion) (XEE) attacks on XML documents.
|
||||
|
||||
The XXE attack is prevented disabling the load of external entities in the libxml library used by PHP, using the function [libxml_disable_entity_loader](http://www.php.net/manual/en/function.libxml-disable-entity-loader.php).
|
||||
|
||||
The XEE attack is prevented looking inside the XML document for ENTITY usage. If the XML document uses ENTITY the library throw an Exception.
|
||||
|
||||
We have two static methods to scan and load XML document from a string (scan) and from a file (scanFile). You can decide to get a SimpleXMLElement or DOMDocument as result, using the following use cases:
|
||||
|
||||
```php
|
||||
use Laminas\Xml\Security as XmlSecurity;
|
||||
|
||||
$xml = <<<XML
|
||||
<?xml version="1.0"?>
|
||||
<results>
|
||||
<result>test</result>
|
||||
</results>
|
||||
XML;
|
||||
|
||||
// SimpleXML use case
|
||||
$simplexml = XmlSecurity::scan($xml);
|
||||
printf ("SimpleXMLElement: %s\n", ($simplexml instanceof \SimpleXMLElement) ? 'yes' : 'no');
|
||||
|
||||
// DOMDocument use case
|
||||
$dom = new \DOMDocument('1.0');
|
||||
$dom = XmlSecurity::scan($xml, $dom);
|
||||
printf ("DOMDocument: %s\n", ($dom instanceof \DOMDocument) ? 'yes' : 'no');
|
||||
```
|
||||
55
user/plugins/admin/vendor/laminas/laminas-xml/composer.json
vendored
Normal file
55
user/plugins/admin/vendor/laminas/laminas-xml/composer.json
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"name": "laminas/laminas-xml",
|
||||
"description": "Utility library for XML usage, best practices, and security in PHP",
|
||||
"license": "BSD-3-Clause",
|
||||
"keywords": [
|
||||
"laminas",
|
||||
"xml",
|
||||
"security"
|
||||
],
|
||||
"homepage": "https://laminas.dev",
|
||||
"support": {
|
||||
"issues": "https://github.com/laminas/laminas-xml/issues",
|
||||
"source": "https://github.com/laminas/laminas-xml",
|
||||
"rss": "https://github.com/laminas/laminas-xml/releases.atom",
|
||||
"chat": "https://laminas.dev/chat",
|
||||
"forum": "https://discourse.laminas.dev"
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.3 || ~8.0.0 || ~8.1.0",
|
||||
"ext-dom": "*",
|
||||
"ext-simplexml": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"laminas/laminas-coding-standard": "~1.0.0",
|
||||
"squizlabs/php_codesniffer": "3.6.1 as 2.9999999.9999999",
|
||||
"phpunit/phpunit": "^9.5.8",
|
||||
"ext-iconv": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laminas\\Xml\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"LaminasTest\\Xml\\": "test/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"check": [
|
||||
"@cs-check",
|
||||
"@test"
|
||||
],
|
||||
"cs-check": "phpcs",
|
||||
"cs-fix": "phpcbf",
|
||||
"test": "phpunit --colors=always",
|
||||
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
|
||||
},
|
||||
"conflict": {
|
||||
"zendframework/zendxml": "*"
|
||||
}
|
||||
}
|
||||
2285
user/plugins/admin/vendor/laminas/laminas-xml/composer.lock
generated
vendored
Normal file
2285
user/plugins/admin/vendor/laminas/laminas-xml/composer.lock
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
user/plugins/admin/vendor/laminas/laminas-xml/src/Exception/ExceptionInterface.php
vendored
Normal file
7
user/plugins/admin/vendor/laminas/laminas-xml/src/Exception/ExceptionInterface.php
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Laminas\Xml\Exception;
|
||||
|
||||
interface ExceptionInterface
|
||||
{
|
||||
}
|
||||
10
user/plugins/admin/vendor/laminas/laminas-xml/src/Exception/InvalidArgumentException.php
vendored
Normal file
10
user/plugins/admin/vendor/laminas/laminas-xml/src/Exception/InvalidArgumentException.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Laminas\Xml\Exception;
|
||||
|
||||
/**
|
||||
* Invalid argument exception
|
||||
*/
|
||||
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
10
user/plugins/admin/vendor/laminas/laminas-xml/src/Exception/RuntimeException.php
vendored
Normal file
10
user/plugins/admin/vendor/laminas/laminas-xml/src/Exception/RuntimeException.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Laminas\Xml\Exception;
|
||||
|
||||
/**
|
||||
* Runtime exception
|
||||
*/
|
||||
class RuntimeException extends \RuntimeException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
407
user/plugins/admin/vendor/laminas/laminas-xml/src/Security.php
vendored
Normal file
407
user/plugins/admin/vendor/laminas/laminas-xml/src/Security.php
vendored
Normal file
@@ -0,0 +1,407 @@
|
||||
<?php
|
||||
|
||||
namespace Laminas\Xml;
|
||||
|
||||
use DOMDocument;
|
||||
use SimpleXMLElement;
|
||||
|
||||
class Security
|
||||
{
|
||||
const ENTITY_DETECT = 'Detected use of ENTITY in XML, disabled to prevent XXE/XEE attacks';
|
||||
|
||||
/**
|
||||
* Heuristic scan to detect entity in XML
|
||||
*
|
||||
* @param string $xml
|
||||
* @throws Exception\RuntimeException If entity expansion or external entity declaration was discovered.
|
||||
*/
|
||||
protected static function heuristicScan($xml)
|
||||
{
|
||||
foreach (self::getEntityComparison($xml) as $compare) {
|
||||
if (strpos($xml, $compare) !== false) {
|
||||
throw new Exception\RuntimeException(self::ENTITY_DETECT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan XML string for potential XXE and XEE attacks
|
||||
*
|
||||
* @param string $xml
|
||||
* @param DomDocument $dom
|
||||
* @param int $libXmlConstants additional libxml constants to pass in
|
||||
* @param callable $callback the callback to use to create the dom element
|
||||
* @throws Exception\RuntimeException
|
||||
* @return SimpleXMLElement|DomDocument|boolean
|
||||
*/
|
||||
private static function scanString($xml, DOMDocument $dom = null, $libXmlConstants, callable $callback)
|
||||
{
|
||||
// If running with PHP-FPM we perform an heuristic scan
|
||||
// We cannot use libxml_disable_entity_loader because of this bug
|
||||
// @see https://bugs.php.net/bug.php?id=64938
|
||||
if (self::isPhpFpm()) {
|
||||
self::heuristicScan($xml);
|
||||
}
|
||||
|
||||
if (null === $dom) {
|
||||
$simpleXml = true;
|
||||
$dom = new DOMDocument();
|
||||
}
|
||||
|
||||
if (! self::isPhpFpm()) {
|
||||
if (\PHP_VERSION_ID < 80000) {
|
||||
$loadEntities = libxml_disable_entity_loader(true);
|
||||
}
|
||||
$useInternalXmlErrors = libxml_use_internal_errors(true);
|
||||
}
|
||||
|
||||
// Load XML with network access disabled (LIBXML_NONET)
|
||||
// error disabled with @ for PHP-FPM scenario
|
||||
set_error_handler(function ($errno, $errstr) {
|
||||
if (substr_count($errstr, 'DOMDocument::loadXML()') > 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}, E_WARNING);
|
||||
|
||||
$result = $callback($xml, $dom, LIBXML_NONET | $libXmlConstants);
|
||||
|
||||
restore_error_handler();
|
||||
|
||||
if (! $result) {
|
||||
// Entity load to previous setting
|
||||
if (! self::isPhpFpm()) {
|
||||
if (\PHP_VERSION_ID < 80000) {
|
||||
libxml_disable_entity_loader($loadEntities);
|
||||
}
|
||||
libxml_use_internal_errors($useInternalXmlErrors);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Scan for potential XEE attacks using ENTITY, if not PHP-FPM
|
||||
if (! self::isPhpFpm()) {
|
||||
foreach ($dom->childNodes as $child) {
|
||||
if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
|
||||
if ($child->entities->length > 0) {
|
||||
throw new Exception\RuntimeException(self::ENTITY_DETECT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Entity load to previous setting
|
||||
if (! self::isPhpFpm()) {
|
||||
if (\PHP_VERSION_ID < 80000) {
|
||||
libxml_disable_entity_loader($loadEntities);
|
||||
}
|
||||
libxml_use_internal_errors($useInternalXmlErrors);
|
||||
}
|
||||
|
||||
if (isset($simpleXml)) {
|
||||
$result = simplexml_import_dom($dom);
|
||||
if (! $result instanceof SimpleXMLElement) {
|
||||
return false;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
return $dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan XML string for potential XXE and XEE attacks
|
||||
*
|
||||
* @param string $xml
|
||||
* @param DomDocument $dom
|
||||
* @param int $libXmlConstants additional libxml constants to pass in
|
||||
* @throws Exception\RuntimeException
|
||||
* @return SimpleXMLElement|DomDocument|boolean
|
||||
*/
|
||||
public static function scan($xml, DOMDocument $dom = null, $libXmlConstants = 0)
|
||||
{
|
||||
$callback = function ($xml, $dom, $constants) {
|
||||
return $dom->loadXml($xml, $constants);
|
||||
};
|
||||
return self::scanString($xml, $dom, $libXmlConstants, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan HTML string for potential XXE and XEE attacks
|
||||
*
|
||||
* @param string $xml
|
||||
* @param DomDocument $dom
|
||||
* @param int $libXmlConstants additional libxml constants to pass in
|
||||
* @throws Exception\RuntimeException
|
||||
* @return SimpleXMLElement|DomDocument|boolean
|
||||
*/
|
||||
public static function scanHtml($html, DOMDocument $dom = null, $libXmlConstants = 0)
|
||||
{
|
||||
$callback = function ($html, $dom, $constants) {
|
||||
return $dom->loadHtml($html, $constants);
|
||||
};
|
||||
return self::scanString($html, $dom, $libXmlConstants, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan XML file for potential XXE/XEE attacks
|
||||
*
|
||||
* @param string $file
|
||||
* @param DOMDocument $dom
|
||||
* @throws Exception\InvalidArgumentException
|
||||
* @return SimpleXMLElement|DomDocument
|
||||
*/
|
||||
public static function scanFile($file, DOMDocument $dom = null)
|
||||
{
|
||||
if (! file_exists($file)) {
|
||||
throw new Exception\InvalidArgumentException(
|
||||
"The file $file specified doesn't exist"
|
||||
);
|
||||
}
|
||||
return self::scan(file_get_contents($file), $dom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if PHP is running with PHP-FPM
|
||||
*
|
||||
* This method is mainly used to determine whether or not heuristic checks
|
||||
* (vs libxml checks) should be made, due to threading issues in libxml;
|
||||
* under php-fpm, threading becomes a concern.
|
||||
*
|
||||
* However, PHP versions 5.6.6+ contain a patch to the
|
||||
* libxml support in PHP that makes the libxml checks viable; in such
|
||||
* versions, this method will return false to enforce those checks, which
|
||||
* are more strict and accurate than the heuristic checks.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isPhpFpm()
|
||||
{
|
||||
$isVulnerableVersion = version_compare(PHP_VERSION, '5.6', 'ge')
|
||||
&& version_compare(PHP_VERSION, '5.6.6', 'lt');
|
||||
|
||||
if (0 === strpos(php_sapi_name(), 'fpm') && $isVulnerableVersion) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine and return the string(s) to use for the <!ENTITY comparison.
|
||||
*
|
||||
* @param string $xml
|
||||
* @return string[]
|
||||
*/
|
||||
protected static function getEntityComparison($xml)
|
||||
{
|
||||
$encodingMap = self::getAsciiEncodingMap();
|
||||
return array_map(function ($encoding) use ($encodingMap) {
|
||||
$generator = isset($encodingMap[$encoding]) ? $encodingMap[$encoding] : $encodingMap['UTF-8'];
|
||||
return $generator('<!ENTITY');
|
||||
}, self::detectXmlEncoding($xml, self::detectStringEncoding($xml)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the string encoding.
|
||||
*
|
||||
* Determines string encoding from either a detected BOM or a
|
||||
* heuristic.
|
||||
*
|
||||
* @param string $xml
|
||||
* @return string File encoding
|
||||
*/
|
||||
protected static function detectStringEncoding($xml)
|
||||
{
|
||||
return self::detectBom($xml) ?: self::detectXmlStringEncoding($xml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to match a known BOM.
|
||||
*
|
||||
* Iterates through the return of getBomMap(), comparing the initial bytes
|
||||
* of the provided string to the BOM of each; if a match is determined,
|
||||
* it returns the encoding.
|
||||
*
|
||||
* @param string $string
|
||||
* @return false|string Returns encoding on success.
|
||||
*/
|
||||
protected static function detectBom($string)
|
||||
{
|
||||
foreach (self::getBomMap() as $criteria) {
|
||||
if (0 === strncmp($string, $criteria['bom'], $criteria['length'])) {
|
||||
return $criteria['encoding'];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to detect the string encoding of an XML string.
|
||||
*
|
||||
* @param string $xml
|
||||
* @return string Encoding
|
||||
*/
|
||||
protected static function detectXmlStringEncoding($xml)
|
||||
{
|
||||
foreach (self::getAsciiEncodingMap() as $encoding => $generator) {
|
||||
$prefix = $generator('<' . '?xml');
|
||||
if (0 === strncmp($xml, $prefix, strlen($prefix))) {
|
||||
return $encoding;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback
|
||||
return 'UTF-8';
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to detect the specified XML encoding.
|
||||
*
|
||||
* Using the file's encoding, determines if an "encoding" attribute is
|
||||
* present and well-formed in the XML declaration; if so, it returns a
|
||||
* list with both the ASCII representation of that declaration and the
|
||||
* original file encoding.
|
||||
*
|
||||
* If not, a list containing only the provided file encoding is returned.
|
||||
*
|
||||
* @param string $xml
|
||||
* @param string $fileEncoding
|
||||
* @return string[] Potential XML encodings
|
||||
*/
|
||||
protected static function detectXmlEncoding($xml, $fileEncoding)
|
||||
{
|
||||
$encodingMap = self::getAsciiEncodingMap();
|
||||
$generator = $encodingMap[$fileEncoding];
|
||||
$encAttr = $generator('encoding="');
|
||||
$quote = $generator('"');
|
||||
$close = $generator('>');
|
||||
|
||||
$closePos = strpos($xml, $close);
|
||||
if (false === $closePos) {
|
||||
return [$fileEncoding];
|
||||
}
|
||||
|
||||
$encPos = strpos($xml, $encAttr);
|
||||
if (false === $encPos
|
||||
|| $encPos > $closePos
|
||||
) {
|
||||
return [$fileEncoding];
|
||||
}
|
||||
|
||||
$encPos += strlen($encAttr);
|
||||
$quotePos = strpos($xml, $quote, $encPos);
|
||||
if (false === $quotePos) {
|
||||
return [$fileEncoding];
|
||||
}
|
||||
|
||||
$encoding = self::substr($xml, $encPos, $quotePos);
|
||||
return [
|
||||
// Following line works because we're only supporting 8-bit safe encodings at this time.
|
||||
str_replace('\0', '', $encoding), // detected encoding
|
||||
$fileEncoding, // file encoding
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of BOM maps.
|
||||
*
|
||||
* Returns a list of common encoding -> BOM maps, along with the character
|
||||
* length to compare against.
|
||||
*
|
||||
* @link https://en.wikipedia.org/wiki/Byte_order_mark
|
||||
* @return array
|
||||
*/
|
||||
protected static function getBomMap()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'encoding' => 'UTF-32BE',
|
||||
'bom' => pack('CCCC', 0x00, 0x00, 0xfe, 0xff),
|
||||
'length' => 4,
|
||||
],
|
||||
[
|
||||
'encoding' => 'UTF-32LE',
|
||||
'bom' => pack('CCCC', 0xff, 0xfe, 0x00, 0x00),
|
||||
'length' => 4,
|
||||
],
|
||||
[
|
||||
'encoding' => 'GB-18030',
|
||||
'bom' => pack('CCCC', 0x84, 0x31, 0x95, 0x33),
|
||||
'length' => 4,
|
||||
],
|
||||
[
|
||||
'encoding' => 'UTF-16BE',
|
||||
'bom' => pack('CC', 0xfe, 0xff),
|
||||
'length' => 2,
|
||||
],
|
||||
[
|
||||
'encoding' => 'UTF-16LE',
|
||||
'bom' => pack('CC', 0xff, 0xfe),
|
||||
'length' => 2,
|
||||
],
|
||||
[
|
||||
'encoding' => 'UTF-8',
|
||||
'bom' => pack('CCC', 0xef, 0xbb, 0xbf),
|
||||
'length' => 3,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a map of encoding => generator pairs.
|
||||
*
|
||||
* Returns a map of encoding => generator pairs, where the generator is a
|
||||
* callable that accepts a string and returns the appropriate byte order
|
||||
* sequence of that string for the encoding.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function getAsciiEncodingMap()
|
||||
{
|
||||
return [
|
||||
'UTF-32BE' => function ($ascii) {
|
||||
return preg_replace('/(.)/', "\0\0\0\\1", $ascii);
|
||||
},
|
||||
'UTF-32LE' => function ($ascii) {
|
||||
return preg_replace('/(.)/', "\\1\0\0\0", $ascii);
|
||||
},
|
||||
'UTF-32odd1' => function ($ascii) {
|
||||
return preg_replace('/(.)/', "\0\\1\0\0", $ascii);
|
||||
},
|
||||
'UTF-32odd2' => function ($ascii) {
|
||||
return preg_replace('/(.)/', "\0\0\\1\0", $ascii);
|
||||
},
|
||||
'UTF-16BE' => function ($ascii) {
|
||||
return preg_replace('/(.)/', "\0\\1", $ascii);
|
||||
},
|
||||
'UTF-16LE' => function ($ascii) {
|
||||
return preg_replace('/(.)/', "\\1\0", $ascii);
|
||||
},
|
||||
'UTF-8' => function ($ascii) {
|
||||
return $ascii;
|
||||
},
|
||||
'GB-18030' => function ($ascii) {
|
||||
return $ascii;
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Binary-safe substr.
|
||||
*
|
||||
* substr() is not binary-safe; this method loops by character to ensure
|
||||
* multi-byte characters are aggregated correctly.
|
||||
*
|
||||
* @param string $string
|
||||
* @param int $start
|
||||
* @param int $end
|
||||
* @return string
|
||||
*/
|
||||
protected static function substr($string, $start, $end)
|
||||
{
|
||||
$substr = '';
|
||||
for ($i = $start; $i < $end; $i += 1) {
|
||||
$substr .= $string[$i];
|
||||
}
|
||||
return $substr;
|
||||
}
|
||||
}
|
||||
1
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/.github/FUNDING.yml
vendored
Normal file
1
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
community_bridge: laminas-project
|
||||
@@ -0,0 +1,32 @@
|
||||
name: "Continuous Integration"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- '[0-9]+.[0-9]+.x'
|
||||
- 'refs/pull/*'
|
||||
|
||||
jobs:
|
||||
matrix:
|
||||
name: Generate job matrix
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.matrix.outputs.matrix }}
|
||||
steps:
|
||||
- name: Gather CI configuration
|
||||
id: matrix
|
||||
uses: laminas/laminas-ci-matrix-action@v1
|
||||
|
||||
qa:
|
||||
name: QA Checks
|
||||
needs: [matrix]
|
||||
runs-on: ${{ matrix.operatingSystem }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJSON(needs.matrix.outputs.matrix) }}
|
||||
steps:
|
||||
- name: ${{ matrix.name }}
|
||||
uses: laminas/laminas-continuous-integration-action@v1
|
||||
with:
|
||||
job: ${{ matrix.job }}
|
||||
@@ -0,0 +1,61 @@
|
||||
# Alternate workflow example.
|
||||
# This one is identical to the one in release-on-milestone.yml, with one change:
|
||||
# the Release step uses the ORGANIZATION_ADMIN_TOKEN instead, to allow it to
|
||||
# trigger a release workflow event. This is useful if you have other actions
|
||||
# that intercept that event.
|
||||
|
||||
name: "Automatic Releases"
|
||||
|
||||
on:
|
||||
milestone:
|
||||
types:
|
||||
- "closed"
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: "GIT tag, release & create merge-up PR"
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
uses: "actions/checkout@v2"
|
||||
|
||||
- name: "Release"
|
||||
uses: "laminas/automatic-releases@v1"
|
||||
with:
|
||||
command-name: "laminas:automatic-releases:release"
|
||||
env:
|
||||
"GITHUB_TOKEN": ${{ secrets.ORGANIZATION_ADMIN_TOKEN }}
|
||||
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
|
||||
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
|
||||
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
|
||||
|
||||
- name: "Create Merge-Up Pull Request"
|
||||
uses: "laminas/automatic-releases@v1"
|
||||
with:
|
||||
command-name: "laminas:automatic-releases:create-merge-up-pull-request"
|
||||
env:
|
||||
"GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }}
|
||||
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
|
||||
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
|
||||
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
|
||||
|
||||
- name: "Create and/or Switch to new Release Branch"
|
||||
uses: "laminas/automatic-releases@v1"
|
||||
with:
|
||||
command-name: "laminas:automatic-releases:switch-default-branch-to-next-minor"
|
||||
env:
|
||||
"GITHUB_TOKEN": ${{ secrets.ORGANIZATION_ADMIN_TOKEN }}
|
||||
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
|
||||
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
|
||||
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
|
||||
|
||||
- name: "Create new milestones"
|
||||
uses: "laminas/automatic-releases@v1"
|
||||
with:
|
||||
command-name: "laminas:automatic-releases:create-milestones"
|
||||
env:
|
||||
"GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }}
|
||||
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
|
||||
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
|
||||
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
|
||||
5
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/.laminas-ci.json
vendored
Normal file
5
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/.laminas-ci.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"ignore_php_platform_requirements": {
|
||||
"8.1": true
|
||||
}
|
||||
}
|
||||
1
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/COPYRIGHT.md
vendored
Normal file
1
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/COPYRIGHT.md
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/)
|
||||
26
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/LICENSE.md
vendored
Normal file
26
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/LICENSE.md
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of Laminas Foundation nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
30
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/README.md
vendored
Normal file
30
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/README.md
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
# laminas-zendframework-bridge
|
||||
|
||||
[](https://github.com/laminas/laminas-zendframework-bridge/actions?query=workflow%3A"Continuous+Integration")
|
||||
|
||||
|
||||
This library provides a custom autoloader that aliases legacy Zend Framework,
|
||||
Apigility, and Expressive classes to their replacements under the Laminas
|
||||
Project.
|
||||
|
||||
This package should be installed only if you are also using the composer plugin
|
||||
that installs Laminas packages to replace ZF/Apigility/Expressive packages.
|
||||
|
||||
This tool supports:
|
||||
|
||||
* Zend Framework MVC projects, all v2 and v3 releases
|
||||
* Apigility projects, all stable versions
|
||||
* Expressive versions, all stable versions
|
||||
|
||||
## Installation
|
||||
|
||||
Run the following to install this library:
|
||||
|
||||
```bash
|
||||
$ composer require laminas/laminas-zendframework-bridge
|
||||
```
|
||||
|
||||
## Support
|
||||
|
||||
* [Issues](https://github.com/laminas/laminas-zendframework-bridge/issues/)
|
||||
* [Forum](https://discourse.laminas.dev/)
|
||||
61
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/composer.json
vendored
Normal file
61
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/composer.json
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"name": "laminas/laminas-zendframework-bridge",
|
||||
"description": "Alias legacy ZF class names to Laminas Project equivalents.",
|
||||
"license": "BSD-3-Clause",
|
||||
"keywords": [
|
||||
"autoloading",
|
||||
"laminas",
|
||||
"zf",
|
||||
"zendframework"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/laminas/laminas-zendframework-bridge/issues",
|
||||
"source": "https://github.com/laminas/laminas-zendframework-bridge",
|
||||
"rss": "https://github.com/laminas/laminas-zendframework-bridge/releases.atom",
|
||||
"forum": "https://discourse.laminas.dev/"
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.3 || ~8.0.0 || ~8.1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.3",
|
||||
"psalm/plugin-phpunit": "^0.15.1",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"vimeo/psalm": "^4.6"
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/autoload.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Laminas\\ZendFrameworkBridge\\": "src//"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"files": [
|
||||
"test/classes.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"LaminasTest\\ZendFrameworkBridge\\": "test/",
|
||||
"LaminasTest\\ZendFrameworkBridge\\TestAsset\\": "test/TestAsset/classes/",
|
||||
"Laminas\\ApiTools\\": "test/TestAsset/LaminasApiTools/",
|
||||
"Mezzio\\": "test/TestAsset/Mezzio/",
|
||||
"Laminas\\": "test/TestAsset/Laminas/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"laminas": {
|
||||
"module": "Laminas\\ZendFrameworkBridge"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"scripts": {
|
||||
"cs-check": "phpcs",
|
||||
"cs-fix": "phpcbf",
|
||||
"static-analysis": "psalm --shepherd --stats",
|
||||
"test": "phpunit --colors=always",
|
||||
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
|
||||
}
|
||||
}
|
||||
3841
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/composer.lock
generated
vendored
Normal file
3841
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/composer.lock
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
372
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/config/replacements.php
vendored
Normal file
372
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/config/replacements.php
vendored
Normal file
@@ -0,0 +1,372 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
// NEVER REWRITE
|
||||
'zendframework/zendframework' => 'zendframework/zendframework',
|
||||
'zend-developer-tools/toolbar/bjy' => 'zend-developer-tools/toolbar/bjy',
|
||||
'zend-developer-tools/toolbar/doctrine' => 'zend-developer-tools/toolbar/doctrine',
|
||||
|
||||
// NAMESPACES
|
||||
// Zend Framework components
|
||||
'Zend\\AuraDi\\Config' => 'Laminas\\AuraDi\\Config',
|
||||
'Zend\\Authentication' => 'Laminas\\Authentication',
|
||||
'Zend\\Barcode' => 'Laminas\\Barcode',
|
||||
'Zend\\Cache' => 'Laminas\\Cache',
|
||||
'Zend\\Captcha' => 'Laminas\\Captcha',
|
||||
'Zend\\Code' => 'Laminas\\Code',
|
||||
'ZendCodingStandard\\Sniffs' => 'LaminasCodingStandard\\Sniffs',
|
||||
'ZendCodingStandard\\Utils' => 'LaminasCodingStandard\\Utils',
|
||||
'Zend\\ComponentInstaller' => 'Laminas\\ComponentInstaller',
|
||||
'Zend\\Config' => 'Laminas\\Config',
|
||||
'Zend\\ConfigAggregator' => 'Laminas\\ConfigAggregator',
|
||||
'Zend\\ConfigAggregatorModuleManager' => 'Laminas\\ConfigAggregatorModuleManager',
|
||||
'Zend\\ConfigAggregatorParameters' => 'Laminas\\ConfigAggregatorParameters',
|
||||
'Zend\\Console' => 'Laminas\\Console',
|
||||
'Zend\\ContainerConfigTest' => 'Laminas\\ContainerConfigTest',
|
||||
'Zend\\Crypt' => 'Laminas\\Crypt',
|
||||
'Zend\\Db' => 'Laminas\\Db',
|
||||
'ZendDeveloperTools' => 'Laminas\\DeveloperTools',
|
||||
'Zend\\Di' => 'Laminas\\Di',
|
||||
'Zend\\Diactoros' => 'Laminas\\Diactoros',
|
||||
'ZendDiagnostics\\Check' => 'Laminas\\Diagnostics\\Check',
|
||||
'ZendDiagnostics\\Result' => 'Laminas\\Diagnostics\\Result',
|
||||
'ZendDiagnostics\\Runner' => 'Laminas\\Diagnostics\\Runner',
|
||||
'Zend\\Dom' => 'Laminas\\Dom',
|
||||
'Zend\\Escaper' => 'Laminas\\Escaper',
|
||||
'Zend\\EventManager' => 'Laminas\\EventManager',
|
||||
'Zend\\Feed' => 'Laminas\\Feed',
|
||||
'Zend\\File' => 'Laminas\\File',
|
||||
'Zend\\Filter' => 'Laminas\\Filter',
|
||||
'Zend\\Form' => 'Laminas\\Form',
|
||||
'Zend\\Http' => 'Laminas\\Http',
|
||||
'Zend\\HttpHandlerRunner' => 'Laminas\\HttpHandlerRunner',
|
||||
'Zend\\Hydrator' => 'Laminas\\Hydrator',
|
||||
'Zend\\I18n' => 'Laminas\\I18n',
|
||||
'Zend\\InputFilter' => 'Laminas\\InputFilter',
|
||||
'Zend\\Json' => 'Laminas\\Json',
|
||||
'Zend\\Ldap' => 'Laminas\\Ldap',
|
||||
'Zend\\Loader' => 'Laminas\\Loader',
|
||||
'Zend\\Log' => 'Laminas\\Log',
|
||||
'Zend\\Mail' => 'Laminas\\Mail',
|
||||
'Zend\\Math' => 'Laminas\\Math',
|
||||
'Zend\\Memory' => 'Laminas\\Memory',
|
||||
'Zend\\Mime' => 'Laminas\\Mime',
|
||||
'Zend\\ModuleManager' => 'Laminas\\ModuleManager',
|
||||
'Zend\\Mvc' => 'Laminas\\Mvc',
|
||||
'Zend\\Navigation' => 'Laminas\\Navigation',
|
||||
'Zend\\Paginator' => 'Laminas\\Paginator',
|
||||
'Zend\\Permissions' => 'Laminas\\Permissions',
|
||||
'Zend\\Pimple\\Config' => 'Laminas\\Pimple\\Config',
|
||||
'Zend\\ProblemDetails' => 'Mezzio\\ProblemDetails',
|
||||
'Zend\\ProgressBar' => 'Laminas\\ProgressBar',
|
||||
'Zend\\Psr7Bridge' => 'Laminas\\Psr7Bridge',
|
||||
'Zend\\Router' => 'Laminas\\Router',
|
||||
'Zend\\Serializer' => 'Laminas\\Serializer',
|
||||
'Zend\\Server' => 'Laminas\\Server',
|
||||
'Zend\\ServiceManager' => 'Laminas\\ServiceManager',
|
||||
'ZendService\\ReCaptcha' => 'Laminas\\ReCaptcha',
|
||||
'ZendService\\Twitter' => 'Laminas\\Twitter',
|
||||
'Zend\\Session' => 'Laminas\\Session',
|
||||
'Zend\\SkeletonInstaller' => 'Laminas\\SkeletonInstaller',
|
||||
'Zend\\Soap' => 'Laminas\\Soap',
|
||||
'Zend\\Stdlib' => 'Laminas\\Stdlib',
|
||||
'Zend\\Stratigility' => 'Laminas\\Stratigility',
|
||||
'Zend\\Tag' => 'Laminas\\Tag',
|
||||
'Zend\\Test' => 'Laminas\\Test',
|
||||
'Zend\\Text' => 'Laminas\\Text',
|
||||
'Zend\\Uri' => 'Laminas\\Uri',
|
||||
'Zend\\Validator' => 'Laminas\\Validator',
|
||||
'Zend\\View' => 'Laminas\\View',
|
||||
'ZendXml' => 'Laminas\\Xml',
|
||||
'Zend\\Xml2Json' => 'Laminas\\Xml2Json',
|
||||
'Zend\\XmlRpc' => 'Laminas\\XmlRpc',
|
||||
'ZendOAuth' => 'Laminas\\OAuth',
|
||||
|
||||
// class ZendAcl in zend-expressive-authorization-acl
|
||||
'ZendAcl' => 'LaminasAcl',
|
||||
'Zend\\Expressive\\Authorization\\Acl\\ZendAcl' => 'Mezzio\\Authorization\\Acl\\LaminasAcl',
|
||||
// class ZendHttpClientDecorator in zend-feed
|
||||
'ZendHttp' => 'LaminasHttp',
|
||||
// class ZendModuleProvider in zend-config-aggregator-modulemanager
|
||||
'ZendModule' => 'LaminasModule',
|
||||
// class ZendRbac in zend-expressive-authorization-rbac
|
||||
'ZendRbac' => 'LaminasRbac',
|
||||
'Zend\\Expressive\\Authorization\\Rbac\\ZendRbac' => 'Mezzio\\Authorization\\Rbac\\LaminasRbac',
|
||||
// class ZendRouter in zend-expressive-router-zendrouter
|
||||
'ZendRouter' => 'LaminasRouter',
|
||||
'Zend\\Expressive\\Router\\ZendRouter' => 'Mezzio\\Router\\LaminasRouter',
|
||||
// class ZendViewRenderer in zend-expressive-zendviewrenderer
|
||||
'ZendViewRenderer' => 'LaminasViewRenderer',
|
||||
'Zend\\Expressive\\ZendView\\ZendViewRenderer' => 'Mezzio\\LaminasView\\LaminasViewRenderer',
|
||||
'a\\Zend' => 'a\\Zend',
|
||||
'b\\Zend' => 'b\\Zend',
|
||||
'c\\Zend' => 'c\\Zend',
|
||||
'd\\Zend' => 'd\\Zend',
|
||||
'e\\Zend' => 'e\\Zend',
|
||||
'f\\Zend' => 'f\\Zend',
|
||||
'g\\Zend' => 'g\\Zend',
|
||||
'h\\Zend' => 'h\\Zend',
|
||||
'i\\Zend' => 'i\\Zend',
|
||||
'j\\Zend' => 'j\\Zend',
|
||||
'k\\Zend' => 'k\\Zend',
|
||||
'l\\Zend' => 'l\\Zend',
|
||||
'm\\Zend' => 'm\\Zend',
|
||||
'n\\Zend' => 'n\\Zend',
|
||||
'o\\Zend' => 'o\\Zend',
|
||||
'p\\Zend' => 'p\\Zend',
|
||||
'q\\Zend' => 'q\\Zend',
|
||||
'r\\Zend' => 'r\\Zend',
|
||||
's\\Zend' => 's\\Zend',
|
||||
't\\Zend' => 't\\Zend',
|
||||
'u\\Zend' => 'u\\Zend',
|
||||
'v\\Zend' => 'v\\Zend',
|
||||
'w\\Zend' => 'w\\Zend',
|
||||
'x\\Zend' => 'x\\Zend',
|
||||
'y\\Zend' => 'y\\Zend',
|
||||
'z\\Zend' => 'z\\Zend',
|
||||
|
||||
// Expressive
|
||||
'Zend\\Expressive' => 'Mezzio',
|
||||
'ZendAuthentication' => 'LaminasAuthentication',
|
||||
'ZendAcl' => 'LaminasAcl',
|
||||
'ZendRbac' => 'LaminasRbac',
|
||||
'ZendRouter' => 'LaminasRouter',
|
||||
'ExpressiveUrlGenerator' => 'MezzioUrlGenerator',
|
||||
'ExpressiveInstaller' => 'MezzioInstaller',
|
||||
|
||||
// Apigility
|
||||
'ZF\\Apigility' => 'Laminas\\ApiTools',
|
||||
'ZF\\ApiProblem' => 'Laminas\\ApiTools\\ApiProblem',
|
||||
'ZF\\AssetManager' => 'Laminas\\ApiTools\\AssetManager',
|
||||
'ZF\\ComposerAutoloading' => 'Laminas\\ComposerAutoloading',
|
||||
'ZF\\Configuration' => 'Laminas\\ApiTools\\Configuration',
|
||||
'ZF\\ContentNegotiation' => 'Laminas\\ApiTools\\ContentNegotiation',
|
||||
'ZF\\ContentValidation' => 'Laminas\\ApiTools\\ContentValidation',
|
||||
'ZF\\DevelopmentMode' => 'Laminas\\DevelopmentMode',
|
||||
'ZF\\Doctrine\\QueryBuilder' => 'Laminas\\ApiTools\\Doctrine\\QueryBuilder',
|
||||
'ZF\\Hal' => 'Laminas\\ApiTools\\Hal',
|
||||
'ZF\\HttpCache' => 'Laminas\\ApiTools\\HttpCache',
|
||||
'ZF\\MvcAuth' => 'Laminas\\ApiTools\\MvcAuth',
|
||||
'ZF\\OAuth2' => 'Laminas\\ApiTools\\OAuth2',
|
||||
'ZF\\Rest' => 'Laminas\\ApiTools\\Rest',
|
||||
'ZF\\Rpc' => 'Laminas\\ApiTools\\Rpc',
|
||||
'ZF\\Versioning' => 'Laminas\\ApiTools\\Versioning',
|
||||
'a\\ZF' => 'a\\ZF',
|
||||
'b\\ZF' => 'b\\ZF',
|
||||
'c\\ZF' => 'c\\ZF',
|
||||
'd\\ZF' => 'd\\ZF',
|
||||
'e\\ZF' => 'e\\ZF',
|
||||
'f\\ZF' => 'f\\ZF',
|
||||
'g\\ZF' => 'g\\ZF',
|
||||
'h\\ZF' => 'h\\ZF',
|
||||
'i\\ZF' => 'i\\ZF',
|
||||
'j\\ZF' => 'j\\ZF',
|
||||
'k\\ZF' => 'k\\ZF',
|
||||
'l\\ZF' => 'l\\ZF',
|
||||
'm\\ZF' => 'm\\ZF',
|
||||
'n\\ZF' => 'n\\ZF',
|
||||
'o\\ZF' => 'o\\ZF',
|
||||
'p\\ZF' => 'p\\ZF',
|
||||
'q\\ZF' => 'q\\ZF',
|
||||
'r\\ZF' => 'r\\ZF',
|
||||
's\\ZF' => 's\\ZF',
|
||||
't\\ZF' => 't\\ZF',
|
||||
'u\\ZF' => 'u\\ZF',
|
||||
'v\\ZF' => 'v\\ZF',
|
||||
'w\\ZF' => 'w\\ZF',
|
||||
'x\\ZF' => 'x\\ZF',
|
||||
'y\\ZF' => 'y\\ZF',
|
||||
'z\\ZF' => 'z\\ZF',
|
||||
|
||||
'ApigilityModuleInterface' => 'ApiToolsModuleInterface',
|
||||
'ApigilityProviderInterface' => 'ApiToolsProviderInterface',
|
||||
'ApigilityVersionController' => 'ApiToolsVersionController',
|
||||
|
||||
// PACKAGES
|
||||
// ZF components, MVC
|
||||
'zendframework/skeleton-application' => 'laminas/skeleton-application',
|
||||
'zendframework/zend-auradi-config' => 'laminas/laminas-auradi-config',
|
||||
'zendframework/zend-authentication' => 'laminas/laminas-authentication',
|
||||
'zendframework/zend-barcode' => 'laminas/laminas-barcode',
|
||||
'zendframework/zend-cache' => 'laminas/laminas-cache',
|
||||
'zendframework/zend-captcha' => 'laminas/laminas-captcha',
|
||||
'zendframework/zend-code' => 'laminas/laminas-code',
|
||||
'zendframework/zend-coding-standard' => 'laminas/laminas-coding-standard',
|
||||
'zendframework/zend-component-installer' => 'laminas/laminas-component-installer',
|
||||
'zendframework/zend-composer-autoloading' => 'laminas/laminas-composer-autoloading',
|
||||
'zendframework/zend-config-aggregator' => 'laminas/laminas-config-aggregator',
|
||||
'zendframework/zend-config' => 'laminas/laminas-config',
|
||||
'zendframework/zend-console' => 'laminas/laminas-console',
|
||||
'zendframework/zend-container-config-test' => 'laminas/laminas-container-config-test',
|
||||
'zendframework/zend-crypt' => 'laminas/laminas-crypt',
|
||||
'zendframework/zend-db' => 'laminas/laminas-db',
|
||||
'zendframework/zend-developer-tools' => 'laminas/laminas-developer-tools',
|
||||
'zendframework/zend-diactoros' => 'laminas/laminas-diactoros',
|
||||
'zendframework/zenddiagnostics' => 'laminas/laminas-diagnostics',
|
||||
'zendframework/zend-di' => 'laminas/laminas-di',
|
||||
'zendframework/zend-dom' => 'laminas/laminas-dom',
|
||||
'zendframework/zend-escaper' => 'laminas/laminas-escaper',
|
||||
'zendframework/zend-eventmanager' => 'laminas/laminas-eventmanager',
|
||||
'zendframework/zend-feed' => 'laminas/laminas-feed',
|
||||
'zendframework/zend-file' => 'laminas/laminas-file',
|
||||
'zendframework/zend-filter' => 'laminas/laminas-filter',
|
||||
'zendframework/zend-form' => 'laminas/laminas-form',
|
||||
'zendframework/zend-httphandlerrunner' => 'laminas/laminas-httphandlerrunner',
|
||||
'zendframework/zend-http' => 'laminas/laminas-http',
|
||||
'zendframework/zend-hydrator' => 'laminas/laminas-hydrator',
|
||||
'zendframework/zend-i18n' => 'laminas/laminas-i18n',
|
||||
'zendframework/zend-i18n-resources' => 'laminas/laminas-i18n-resources',
|
||||
'zendframework/zend-inputfilter' => 'laminas/laminas-inputfilter',
|
||||
'zendframework/zend-json' => 'laminas/laminas-json',
|
||||
'zendframework/zend-json-server' => 'laminas/laminas-json-server',
|
||||
'zendframework/zend-ldap' => 'laminas/laminas-ldap',
|
||||
'zendframework/zend-loader' => 'laminas/laminas-loader',
|
||||
'zendframework/zend-log' => 'laminas/laminas-log',
|
||||
'zendframework/zend-mail' => 'laminas/laminas-mail',
|
||||
'zendframework/zend-math' => 'laminas/laminas-math',
|
||||
'zendframework/zend-memory' => 'laminas/laminas-memory',
|
||||
'zendframework/zend-mime' => 'laminas/laminas-mime',
|
||||
'zendframework/zend-modulemanager' => 'laminas/laminas-modulemanager',
|
||||
'zendframework/zend-mvc' => 'laminas/laminas-mvc',
|
||||
'zendframework/zend-navigation' => 'laminas/laminas-navigation',
|
||||
'zendframework/zend-oauth' => 'laminas/laminas-oauth',
|
||||
'zendframework/zend-paginator' => 'laminas/laminas-paginator',
|
||||
'zendframework/zend-permissions-acl' => 'laminas/laminas-permissions-acl',
|
||||
'zendframework/zend-permissions-rbac' => 'laminas/laminas-permissions-rbac',
|
||||
'zendframework/zend-pimple-config' => 'laminas/laminas-pimple-config',
|
||||
'zendframework/zend-progressbar' => 'laminas/laminas-progressbar',
|
||||
'zendframework/zend-psr7bridge' => 'laminas/laminas-psr7bridge',
|
||||
'zendframework/zend-recaptcha' => 'laminas/laminas-recaptcha',
|
||||
'zendframework/zend-router' => 'laminas/laminas-router',
|
||||
'zendframework/zend-serializer' => 'laminas/laminas-serializer',
|
||||
'zendframework/zend-server' => 'laminas/laminas-server',
|
||||
'zendframework/zend-servicemanager' => 'laminas/laminas-servicemanager',
|
||||
'zendframework/zendservice-recaptcha' => 'laminas/laminas-recaptcha',
|
||||
'zendframework/zendservice-twitter' => 'laminas/laminas-twitter',
|
||||
'zendframework/zend-session' => 'laminas/laminas-session',
|
||||
'zendframework/zend-skeleton-installer' => 'laminas/laminas-skeleton-installer',
|
||||
'zendframework/zend-soap' => 'laminas/laminas-soap',
|
||||
'zendframework/zend-stdlib' => 'laminas/laminas-stdlib',
|
||||
'zendframework/zend-stratigility' => 'laminas/laminas-stratigility',
|
||||
'zendframework/zend-tag' => 'laminas/laminas-tag',
|
||||
'zendframework/zend-test' => 'laminas/laminas-test',
|
||||
'zendframework/zend-text' => 'laminas/laminas-text',
|
||||
'zendframework/zend-uri' => 'laminas/laminas-uri',
|
||||
'zendframework/zend-validator' => 'laminas/laminas-validator',
|
||||
'zendframework/zend-view' => 'laminas/laminas-view',
|
||||
'zendframework/zend-xml2json' => 'laminas/laminas-xml2json',
|
||||
'zendframework/zend-xml' => 'laminas/laminas-xml',
|
||||
'zendframework/zend-xmlrpc' => 'laminas/laminas-xmlrpc',
|
||||
|
||||
// Expressive packages
|
||||
'zendframework/zend-expressive' => 'mezzio/mezzio',
|
||||
'zendframework/zend-expressive-zendrouter' => 'mezzio/mezzio-laminasrouter',
|
||||
'zendframework/zend-problem-details' => 'mezzio/mezzio-problem-details',
|
||||
'zendframework/zend-expressive-zendviewrenderer' => 'mezzio/mezzio-laminasviewrenderer',
|
||||
|
||||
// Apigility packages
|
||||
'zfcampus/apigility-documentation' => 'laminas-api-tools/documentation',
|
||||
'zfcampus/statuslib-example' => 'laminas-api-tools/statuslib-example',
|
||||
'zfcampus/zf-apigility' => 'laminas-api-tools/api-tools',
|
||||
'zfcampus/zf-api-problem' => 'laminas-api-tools/api-tools-api-problem',
|
||||
'zfcampus/zf-asset-manager' => 'laminas-api-tools/api-tools-asset-manager',
|
||||
'zfcampus/zf-configuration' => 'laminas-api-tools/api-tools-configuration',
|
||||
'zfcampus/zf-content-negotiation' => 'laminas-api-tools/api-tools-content-negotiation',
|
||||
'zfcampus/zf-content-validation' => 'laminas-api-tools/api-tools-content-validation',
|
||||
'zfcampus/zf-development-mode' => 'laminas/laminas-development-mode',
|
||||
'zfcampus/zf-doctrine-querybuilder' => 'laminas-api-tools/api-tools-doctrine-querybuilder',
|
||||
'zfcampus/zf-hal' => 'laminas-api-tools/api-tools-hal',
|
||||
'zfcampus/zf-http-cache' => 'laminas-api-tools/api-tools-http-cache',
|
||||
'zfcampus/zf-mvc-auth' => 'laminas-api-tools/api-tools-mvc-auth',
|
||||
'zfcampus/zf-oauth2' => 'laminas-api-tools/api-tools-oauth2',
|
||||
'zfcampus/zf-rest' => 'laminas-api-tools/api-tools-rest',
|
||||
'zfcampus/zf-rpc' => 'laminas-api-tools/api-tools-rpc',
|
||||
'zfcampus/zf-versioning' => 'laminas-api-tools/api-tools-versioning',
|
||||
|
||||
// CONFIG KEYS, SCRIPT NAMES, ETC
|
||||
// ZF components
|
||||
'::fromZend' => '::fromLaminas', // psr7bridge
|
||||
'::toZend' => '::toLaminas', // psr7bridge
|
||||
'use_zend_loader' => 'use_laminas_loader', // zend-modulemanager
|
||||
'zend-config' => 'laminas-config',
|
||||
'zend-developer-tools/' => 'laminas-developer-tools/',
|
||||
'zend-tag-cloud' => 'laminas-tag-cloud',
|
||||
'zenddevelopertools' => 'laminas-developer-tools',
|
||||
'zendbarcode' => 'laminasbarcode',
|
||||
'ZendBarcode' => 'LaminasBarcode',
|
||||
'zendcache' => 'laminascache',
|
||||
'ZendCache' => 'LaminasCache',
|
||||
'zendconfig' => 'laminasconfig',
|
||||
'ZendConfig' => 'LaminasConfig',
|
||||
'zendfeed' => 'laminasfeed',
|
||||
'ZendFeed' => 'LaminasFeed',
|
||||
'zendfilter' => 'laminasfilter',
|
||||
'ZendFilter' => 'LaminasFilter',
|
||||
'zendform' => 'laminasform',
|
||||
'ZendForm' => 'LaminasForm',
|
||||
'zendi18n' => 'laminasi18n',
|
||||
'ZendI18n' => 'LaminasI18n',
|
||||
'zendinputfilter' => 'laminasinputfilter',
|
||||
'ZendInputFilter' => 'LaminasInputFilter',
|
||||
'zendlog' => 'laminaslog',
|
||||
'ZendLog' => 'LaminasLog',
|
||||
'zendmail' => 'laminasmail',
|
||||
'ZendMail' => 'LaminasMail',
|
||||
'zendmvc' => 'laminasmvc',
|
||||
'ZendMvc' => 'LaminasMvc',
|
||||
'zendpaginator' => 'laminaspaginator',
|
||||
'ZendPaginator' => 'LaminasPaginator',
|
||||
'zendserializer' => 'laminasserializer',
|
||||
'ZendSerializer' => 'LaminasSerializer',
|
||||
'zendtag' => 'laminastag',
|
||||
'ZendTag' => 'LaminasTag',
|
||||
'zendtext' => 'laminastext',
|
||||
'ZendText' => 'LaminasText',
|
||||
'zendvalidator' => 'laminasvalidator',
|
||||
'ZendValidator' => 'LaminasValidator',
|
||||
'zendview' => 'laminasview',
|
||||
'ZendView' => 'LaminasView',
|
||||
'zend-framework.flf' => 'laminas-project.flf',
|
||||
|
||||
// Expressive-related
|
||||
"'zend-expressive'" => "'mezzio'",
|
||||
'"zend-expressive"' => '"mezzio"',
|
||||
'zend-expressive.' => 'mezzio.',
|
||||
'zend-expressive-authorization' => 'mezzio-authorization',
|
||||
'zend-expressive-hal' => 'mezzio-hal',
|
||||
'zend-expressive-session' => 'mezzio-session',
|
||||
'zend-expressive-swoole' => 'mezzio-swoole',
|
||||
'zend-expressive-tooling' => 'mezzio-tooling',
|
||||
|
||||
// Apigility-related
|
||||
"'zf-apigility'" => "'api-tools'",
|
||||
'"zf-apigility"' => '"api-tools"',
|
||||
'zf-apigility/' => 'api-tools/',
|
||||
'zf-apigility-admin' => 'api-tools-admin',
|
||||
'zf-content-negotiation' => 'api-tools-content-negotiation',
|
||||
'zf-hal' => 'api-tools-hal',
|
||||
'zf-rest' => 'api-tools-rest',
|
||||
'zf-rpc' => 'api-tools-rpc',
|
||||
'zf-content-validation' => 'api-tools-content-validation',
|
||||
'zf-apigility-ui' => 'api-tools-ui',
|
||||
'zf-apigility-documentation-blueprint' => 'api-tools-documentation-blueprint',
|
||||
'zf-apigility-documentation-swagger' => 'api-tools-documentation-swagger',
|
||||
'zf-apigility-welcome' => 'api-tools-welcome',
|
||||
'zf-api-problem' => 'api-tools-api-problem',
|
||||
'zf-configuration' => 'api-tools-configuration',
|
||||
'zf-http-cache' => 'api-tools-http-cache',
|
||||
'zf-mvc-auth' => 'api-tools-mvc-auth',
|
||||
'zf-oauth2' => 'api-tools-oauth2',
|
||||
'zf-versioning' => 'api-tools-versioning',
|
||||
'ZfApigilityDoctrineQueryProviderManager' => 'LaminasApiToolsDoctrineQueryProviderManager',
|
||||
'ZfApigilityDoctrineQueryCreateFilterManager' => 'LaminasApiToolsDoctrineQueryCreateFilterManager',
|
||||
'zf-apigility-doctrine' => 'api-tools-doctrine',
|
||||
'zf-development-mode' => 'laminas-development-mode',
|
||||
'zf-doctrine-querybuilder' => 'api-tools-doctrine-querybuilder',
|
||||
|
||||
// 3rd party Apigility packages
|
||||
'api-skeletons/zf-' => 'api-skeletons/zf-', // api-skeletons packages
|
||||
'zf-oauth2-' => 'zf-oauth2-', // api-skeletons OAuth2-related packages
|
||||
'ZF\\OAuth2\\Client' => 'ZF\\OAuth2\\Client', // api-skeletons/zf-oauth2-client
|
||||
'ZF\\OAuth2\\Doctrine' => 'ZF\\OAuth2\\Doctrine', // api-skeletons/zf-oauth2-doctrine
|
||||
];
|
||||
345
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/psalm-baseline.xml
vendored
Normal file
345
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/psalm-baseline.xml
vendored
Normal file
@@ -0,0 +1,345 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<files psalm-version="4.9.3@4c262932602b9bbab5020863d1eb22d49de0dbf4">
|
||||
<file src="config/replacements.php">
|
||||
<DuplicateArrayKey occurrences="3">
|
||||
<code>'ZendAcl' => 'LaminasAcl'</code>
|
||||
<code>'ZendRbac' => 'LaminasRbac'</code>
|
||||
<code>'ZendRouter' => 'LaminasRouter'</code>
|
||||
</DuplicateArrayKey>
|
||||
</file>
|
||||
<file src="src/Autoloader.php">
|
||||
<MissingClosureParamType occurrences="2">
|
||||
<code>$class</code>
|
||||
<code>$class</code>
|
||||
</MissingClosureParamType>
|
||||
<MissingReturnType occurrences="1">
|
||||
<code>load</code>
|
||||
</MissingReturnType>
|
||||
<MixedArgument occurrences="7">
|
||||
<code>$class</code>
|
||||
<code>$class</code>
|
||||
<code>$class</code>
|
||||
<code>$class</code>
|
||||
<code>$class</code>
|
||||
<code>$class</code>
|
||||
<code>$class</code>
|
||||
</MixedArgument>
|
||||
<MixedArgumentTypeCoercion occurrences="2"/>
|
||||
<MixedArrayOffset occurrences="1">
|
||||
<code>$loaded[$class]</code>
|
||||
</MixedArrayOffset>
|
||||
<MixedOperand occurrences="2">
|
||||
<code>$namespaces[$check]</code>
|
||||
<code>$namespaces[$check]</code>
|
||||
</MixedOperand>
|
||||
</file>
|
||||
<file src="src/ConfigPostProcessor.php">
|
||||
<InvalidArgument occurrences="1">
|
||||
<code>$keys</code>
|
||||
</InvalidArgument>
|
||||
<MissingClosureParamType occurrences="4">
|
||||
<code>$value</code>
|
||||
<code>$value</code>
|
||||
<code>$value</code>
|
||||
<code>$value</code>
|
||||
</MissingClosureParamType>
|
||||
<MissingClosureReturnType occurrences="4">
|
||||
<code>function ($value) {</code>
|
||||
<code>function ($value) {</code>
|
||||
<code>function ($value, array $keys) {</code>
|
||||
<code>function ($value, array $keys) {</code>
|
||||
</MissingClosureReturnType>
|
||||
<MissingReturnType occurrences="3">
|
||||
<code>replaceDependencyConfiguration</code>
|
||||
<code>replaceDependencyFactories</code>
|
||||
<code>replaceDependencyServices</code>
|
||||
</MissingReturnType>
|
||||
<MixedArgument occurrences="5">
|
||||
<code>$config</code>
|
||||
<code>$newKey</code>
|
||||
<code>$newKey</code>
|
||||
<code>$newKey</code>
|
||||
<code>$target</code>
|
||||
</MixedArgument>
|
||||
<MixedArgumentTypeCoercion occurrences="1">
|
||||
<code>[$key]</code>
|
||||
</MixedArgumentTypeCoercion>
|
||||
<MixedArrayAssignment occurrences="4">
|
||||
<code>$config[$key]</code>
|
||||
<code>$config['aliases'][$alias]</code>
|
||||
<code>$config['aliases'][$service]</code>
|
||||
<code>$config['aliases'][$service]</code>
|
||||
</MixedArrayAssignment>
|
||||
<MixedArrayOffset occurrences="7">
|
||||
<code>$aliases[$name]</code>
|
||||
<code>$config[$key]</code>
|
||||
<code>$keys[$key]</code>
|
||||
<code>$rewritten[$newKey]</code>
|
||||
<code>$rewritten[$newKey]</code>
|
||||
<code>$rewritten[$newKey]</code>
|
||||
<code>$this->exactReplacements[$value]</code>
|
||||
</MixedArrayOffset>
|
||||
<MixedArrayTypeCoercion occurrences="1">
|
||||
<code>$aliases[$name]</code>
|
||||
</MixedArrayTypeCoercion>
|
||||
<MixedAssignment occurrences="26">
|
||||
<code>$a[$key]</code>
|
||||
<code>$a[$key]</code>
|
||||
<code>$a[]</code>
|
||||
<code>$config</code>
|
||||
<code>$config</code>
|
||||
<code>$config[$key]</code>
|
||||
<code>$config['factories'][$replacedService]</code>
|
||||
<code>$config['services'][$replacedService]</code>
|
||||
<code>$data</code>
|
||||
<code>$factory</code>
|
||||
<code>$factory</code>
|
||||
<code>$key</code>
|
||||
<code>$key</code>
|
||||
<code>$name</code>
|
||||
<code>$newKey</code>
|
||||
<code>$newValue</code>
|
||||
<code>$notIn[]</code>
|
||||
<code>$result</code>
|
||||
<code>$rewritten[$key]</code>
|
||||
<code>$rewritten[$newKey]</code>
|
||||
<code>$rewritten[$newKey][]</code>
|
||||
<code>$serviceInstance</code>
|
||||
<code>$serviceInstance</code>
|
||||
<code>$target</code>
|
||||
<code>$value</code>
|
||||
<code>$value</code>
|
||||
</MixedAssignment>
|
||||
</file>
|
||||
<file src="src/Module.php">
|
||||
<MissingReturnType occurrences="2">
|
||||
<code>init</code>
|
||||
<code>onMergeConfig</code>
|
||||
</MissingReturnType>
|
||||
<UndefinedDocblockClass occurrences="2">
|
||||
<code>ModuleEvent</code>
|
||||
<code>ModuleManager</code>
|
||||
</UndefinedDocblockClass>
|
||||
</file>
|
||||
<file src="src/Replacements.php">
|
||||
<MixedArgument occurrences="2">
|
||||
<code>$replacement</code>
|
||||
<code>$replacement</code>
|
||||
</MixedArgument>
|
||||
<MixedArgumentTypeCoercion occurrences="3">
|
||||
<code>$original</code>
|
||||
<code>$original</code>
|
||||
<code>$original</code>
|
||||
</MixedArgumentTypeCoercion>
|
||||
<MixedAssignment occurrences="1">
|
||||
<code>$replacement</code>
|
||||
</MixedAssignment>
|
||||
<MixedPropertyTypeCoercion occurrences="3">
|
||||
<code>$this->replacements</code>
|
||||
<code>$this->replacements</code>
|
||||
</MixedPropertyTypeCoercion>
|
||||
</file>
|
||||
<file src="test/AutoloaderTest.php">
|
||||
<InvalidStringClass occurrences="1">
|
||||
<code>new $legacy()</code>
|
||||
</InvalidStringClass>
|
||||
<MissingReturnType occurrences="3">
|
||||
<code>testLegacyClassIsAliasToLaminas</code>
|
||||
<code>testReverseAliasCreated</code>
|
||||
<code>testTypeHint</code>
|
||||
</MissingReturnType>
|
||||
<PossiblyInvalidArgument occurrences="1">
|
||||
<code>testLegacyClassIsAliasToLaminas</code>
|
||||
</PossiblyInvalidArgument>
|
||||
</file>
|
||||
<file src="test/ConfigPostProcessorTest.php">
|
||||
<MissingReturnType occurrences="4">
|
||||
<code>invalidServiceManagerConfiguration</code>
|
||||
<code>testRewritesNestedKeys</code>
|
||||
<code>testServiceManagerServiceInstancesCanBeHandled</code>
|
||||
<code>testWillSkipInvalidConfigurations</code>
|
||||
</MissingReturnType>
|
||||
<MixedArgument occurrences="1">
|
||||
<code>$config</code>
|
||||
</MixedArgument>
|
||||
<MixedAssignment occurrences="2">
|
||||
<code>$config</code>
|
||||
<code>$expected</code>
|
||||
</MixedAssignment>
|
||||
<MixedInferredReturnType occurrences="1">
|
||||
<code>iterable</code>
|
||||
</MixedInferredReturnType>
|
||||
<UnresolvableInclude occurrences="2">
|
||||
<code>require $configLocation</code>
|
||||
<code>require $expectedResultLocation</code>
|
||||
</UnresolvableInclude>
|
||||
</file>
|
||||
<file src="test/ModuleTest.php">
|
||||
<InvalidArgument occurrences="2">
|
||||
<code>$event</code>
|
||||
<code>$moduleManager</code>
|
||||
</InvalidArgument>
|
||||
<MissingReturnType occurrences="2">
|
||||
<code>testInitRegistersListenerWithEventManager</code>
|
||||
<code>testOnMergeConfigProcessesAndReplacesConfigurationPulledFromListener</code>
|
||||
</MissingReturnType>
|
||||
<MixedArgument occurrences="1">
|
||||
<code>$config</code>
|
||||
</MixedArgument>
|
||||
<MixedAssignment occurrences="2">
|
||||
<code>$config</code>
|
||||
<code>$expected</code>
|
||||
</MixedAssignment>
|
||||
<MixedInferredReturnType occurrences="1">
|
||||
<code>iterable</code>
|
||||
</MixedInferredReturnType>
|
||||
<UnresolvableInclude occurrences="2">
|
||||
<code>require $configFile</code>
|
||||
<code>require $expectationsFile</code>
|
||||
</UnresolvableInclude>
|
||||
</file>
|
||||
<file src="test/ReplacementsTest.php">
|
||||
<MissingReturnType occurrences="1">
|
||||
<code>testEdgeCases</code>
|
||||
</MissingReturnType>
|
||||
<MixedInferredReturnType occurrences="1">
|
||||
<code>iterable</code>
|
||||
</MixedInferredReturnType>
|
||||
</file>
|
||||
<file src="test/TestAsset/ConfigPostProcessor/AbstractFactories.php">
|
||||
<UndefinedClass occurrences="4">
|
||||
<code>ConfigAbstractFactory</code>
|
||||
<code>ConfigAbstractFactory</code>
|
||||
<code>InvokableFactory</code>
|
||||
<code>InvokableFactory</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="test/TestAsset/ConfigPostProcessor/CyclicalAliasing.php">
|
||||
<DuplicateArrayKey occurrences="1">
|
||||
<code>'Zend\Db\Adapter\Adapter' => 'ZF\Apigility\DbConnectedAdapter'</code>
|
||||
</DuplicateArrayKey>
|
||||
</file>
|
||||
<file src="test/TestAsset/ConfigPostProcessor/ExpressiveSlimRouterConfig.php">
|
||||
<UndefinedClass occurrences="2">
|
||||
<code>Factory\SlimRouterFactory</code>
|
||||
<code>RouterInterface</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="test/TestAsset/ConfigPostProcessor/LazyServices.php">
|
||||
<UndefinedClass occurrences="1">
|
||||
<code>LazyServiceFactory</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="test/TestAsset/ConfigPostProcessor/MwopNetAppConfig.php">
|
||||
<UndefinedClass occurrences="42">
|
||||
<code>CacheItemPoolInterface</code>
|
||||
<code>ConfigFactory</code>
|
||||
<code>ConfigFactory</code>
|
||||
<code>ConfigFactory</code>
|
||||
<code>ConfigFactory</code>
|
||||
<code>ConfigFactory</code>
|
||||
<code>ConfigFactory</code>
|
||||
<code>Csp</code>
|
||||
<code>DisplayPostHandler</code>
|
||||
<code>Engine</code>
|
||||
<code>EventDispatcherInterface</code>
|
||||
<code>Factory\CachePoolFactory</code>
|
||||
<code>Factory\EventDispatcherFactory</code>
|
||||
<code>Factory\MailTransport</code>
|
||||
<code>Factory\PlatesFunctionsDelegator</code>
|
||||
<code>FeedReaderHttpClientInterface</code>
|
||||
<code>Feed\HttpPlugClientFactory</code>
|
||||
<code>Handler\ComicsPageHandler</code>
|
||||
<code>Handler\ComicsPageHandlerFactory</code>
|
||||
<code>Handler\HomePageHandler</code>
|
||||
<code>Handler\HomePageHandlerFactory</code>
|
||||
<code>Handler\PageHandlerFactory</code>
|
||||
<code>Handler\PageHandlerFactory</code>
|
||||
<code>Handler\ResumePageHandler</code>
|
||||
<code>Handler\ResumePageHandler</code>
|
||||
<code>Middleware\ContentSecurityPolicyMiddlewareFactory</code>
|
||||
<code>Middleware\DisplayBlogPostHandlerDelegator</code>
|
||||
<code>Middleware\RedirectAmpPagesMiddleware</code>
|
||||
<code>Middleware\RedirectAmpPagesMiddlewareFactory</code>
|
||||
<code>Middleware\RedirectsMiddleware</code>
|
||||
<code>Middleware\RedirectsMiddleware</code>
|
||||
<code>Middleware\XClacksOverheadMiddleware</code>
|
||||
<code>Middleware\XClacksOverheadMiddleware</code>
|
||||
<code>Middleware\XPoweredByMiddleware</code>
|
||||
<code>Middleware\XPoweredByMiddleware</code>
|
||||
<code>RequestFactory</code>
|
||||
<code>RequestFactoryInterface</code>
|
||||
<code>ResponseFactory</code>
|
||||
<code>ResponseFactoryInterface</code>
|
||||
<code>SessionCachePool</code>
|
||||
<code>SessionCachePool</code>
|
||||
<code>SessionCachePoolFactory</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="test/TestAsset/Replacements/TestClass.php">
|
||||
<UndefinedClass occurrences="1">
|
||||
<code>\Zend\Expressive\Router</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="test/TestAsset/Replacements/ZFOAuth2Client.php">
|
||||
<UndefinedClass occurrences="1">
|
||||
<code>OAuth2Client</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="test/TestAsset/classes/ConfigListener.php">
|
||||
<MissingReturnType occurrences="1">
|
||||
<code>setMergedConfig</code>
|
||||
</MissingReturnType>
|
||||
</file>
|
||||
<file src="test/TestAsset/classes/EventManager.php">
|
||||
<InvalidArgument occurrences="1">
|
||||
<code>$listener</code>
|
||||
</InvalidArgument>
|
||||
<MissingPropertyType occurrences="1">
|
||||
<code>$listeners</code>
|
||||
</MissingPropertyType>
|
||||
<MissingReturnType occurrences="1">
|
||||
<code>attach</code>
|
||||
</MissingReturnType>
|
||||
<MixedArgument occurrences="1">
|
||||
<code>$this->listeners[$eventName]</code>
|
||||
</MixedArgument>
|
||||
<MixedArrayAccess occurrences="1">
|
||||
<code>$this->listeners[$eventName]</code>
|
||||
</MixedArrayAccess>
|
||||
<MixedArrayAssignment occurrences="1">
|
||||
<code>$this->listeners[$eventName]</code>
|
||||
</MixedArrayAssignment>
|
||||
<MixedInferredReturnType occurrences="1">
|
||||
<code>array</code>
|
||||
</MixedInferredReturnType>
|
||||
<MixedReturnStatement occurrences="1">
|
||||
<code>$this->listeners</code>
|
||||
</MixedReturnStatement>
|
||||
</file>
|
||||
<file src="test/TestAsset/classes/ModuleEvent.php">
|
||||
<MissingPropertyType occurrences="1">
|
||||
<code>$listener</code>
|
||||
</MissingPropertyType>
|
||||
<MixedInferredReturnType occurrences="1">
|
||||
<code>ConfigListener</code>
|
||||
</MixedInferredReturnType>
|
||||
<MixedReturnStatement occurrences="1">
|
||||
<code>$this->listener</code>
|
||||
</MixedReturnStatement>
|
||||
</file>
|
||||
<file src="test/TestAsset/classes/ModuleManager.php">
|
||||
<MixedInferredReturnType occurrences="1">
|
||||
<code>EventManager</code>
|
||||
</MixedInferredReturnType>
|
||||
<MixedReturnStatement occurrences="1">
|
||||
<code>$this->eventManager</code>
|
||||
</MixedReturnStatement>
|
||||
<UndefinedThisPropertyAssignment occurrences="1">
|
||||
<code>$this->eventManager</code>
|
||||
</UndefinedThisPropertyAssignment>
|
||||
<UndefinedThisPropertyFetch occurrences="1">
|
||||
<code>$this->eventManager</code>
|
||||
</UndefinedThisPropertyFetch>
|
||||
</file>
|
||||
</files>
|
||||
33
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/psalm.xml.dist
vendored
Normal file
33
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/psalm.xml.dist
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0"?>
|
||||
<psalm
|
||||
totallyTyped="true"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||
errorBaseline="psalm-baseline.xml"
|
||||
>
|
||||
<projectFiles>
|
||||
<directory name="src"/>
|
||||
<directory name="test"/>
|
||||
<ignoreFiles>
|
||||
<directory name="vendor"/>
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
|
||||
<issueHandlers>
|
||||
<InternalMethod>
|
||||
<errorLevel type="suppress">
|
||||
<referencedMethod name="PHPUnit\Framework\MockObject\Builder\InvocationMocker::method"/>
|
||||
</errorLevel>
|
||||
<errorLevel type="suppress">
|
||||
<referencedMethod name="PHPUnit\Framework\MockObject\Builder\InvocationMocker::willReturn"/>
|
||||
</errorLevel>
|
||||
<errorLevel type="suppress">
|
||||
<referencedMethod name="PHPUnit\Framework\MockObject\Builder\InvocationMocker::with"/>
|
||||
</errorLevel>
|
||||
</InternalMethod>
|
||||
</issueHandlers>
|
||||
<plugins>
|
||||
<pluginClass class="Psalm\PhpUnitPlugin\Plugin"/>
|
||||
</plugins>
|
||||
</psalm>
|
||||
181
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/src/Autoloader.php
vendored
Normal file
181
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/src/Autoloader.php
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
<?php
|
||||
|
||||
namespace Laminas\ZendFrameworkBridge;
|
||||
|
||||
use ArrayObject;
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use RuntimeException;
|
||||
|
||||
use function array_values;
|
||||
use function class_alias;
|
||||
use function class_exists;
|
||||
use function explode;
|
||||
use function file_exists;
|
||||
use function getenv;
|
||||
use function interface_exists;
|
||||
use function spl_autoload_register;
|
||||
use function strlen;
|
||||
use function strtr;
|
||||
use function substr;
|
||||
use function trait_exists;
|
||||
|
||||
/**
|
||||
* Alias legacy Zend Framework project classes/interfaces/traits to Laminas equivalents.
|
||||
*/
|
||||
class Autoloader
|
||||
{
|
||||
private const UPSTREAM_COMPOSER_VENDOR_DIRECTORY = __DIR__ . '/../../..';
|
||||
private const LOCAL_COMPOSER_VENDOR_DIRECTORY = __DIR__ . '/../vendor';
|
||||
|
||||
/**
|
||||
* Attach autoloaders for managing legacy ZF artifacts.
|
||||
*
|
||||
* We attach two autoloaders:
|
||||
*
|
||||
* - The first is _prepended_ to handle new classes and add aliases for
|
||||
* legacy classes. PHP expects any interfaces implemented, classes
|
||||
* extended, or traits used when declaring class_alias() to exist and/or
|
||||
* be autoloadable already at the time of declaration. If not, it will
|
||||
* raise a fatal error. This autoloader helps mitigate errors in such
|
||||
* situations.
|
||||
*
|
||||
* - The second is _appended_ in order to create aliases for legacy
|
||||
* classes.
|
||||
*/
|
||||
public static function load()
|
||||
{
|
||||
$loaded = new ArrayObject([]);
|
||||
$classLoader = self::getClassLoader();
|
||||
|
||||
if ($classLoader === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
spl_autoload_register(self::createPrependAutoloader(
|
||||
RewriteRules::namespaceReverse(),
|
||||
$classLoader,
|
||||
$loaded
|
||||
), true, true);
|
||||
|
||||
spl_autoload_register(self::createAppendAutoloader(
|
||||
RewriteRules::namespaceRewrite(),
|
||||
$loaded
|
||||
));
|
||||
}
|
||||
|
||||
private static function getClassLoader(): ?ClassLoader
|
||||
{
|
||||
$composerVendorDirectory = getenv('COMPOSER_VENDOR_DIR');
|
||||
if (is_string($composerVendorDirectory)) {
|
||||
return self::getClassLoaderFromVendorDirectory($composerVendorDirectory);
|
||||
}
|
||||
|
||||
return self::getClassLoaderFromVendorDirectory(self::UPSTREAM_COMPOSER_VENDOR_DIRECTORY)
|
||||
?? self::getClassLoaderFromVendorDirectory(self::LOCAL_COMPOSER_VENDOR_DIRECTORY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return callable
|
||||
*/
|
||||
private static function createPrependAutoloader(array $namespaces, ClassLoader $classLoader, ArrayObject $loaded)
|
||||
{
|
||||
/**
|
||||
* @param string $class Class name to autoload
|
||||
* @return void
|
||||
*/
|
||||
return static function ($class) use ($namespaces, $classLoader, $loaded) {
|
||||
if (isset($loaded[$class])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$segments = explode('\\', $class);
|
||||
|
||||
$i = 0;
|
||||
$check = '';
|
||||
|
||||
while (isset($segments[$i + 1], $namespaces[$check . $segments[$i] . '\\'])) {
|
||||
$check .= $segments[$i] . '\\';
|
||||
++$i;
|
||||
}
|
||||
|
||||
if ($check === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($classLoader->loadClass($class)) {
|
||||
$legacy = $namespaces[$check]
|
||||
. strtr(substr($class, strlen($check)), [
|
||||
'ApiTools' => 'Apigility',
|
||||
'Mezzio' => 'Expressive',
|
||||
'Laminas' => 'Zend',
|
||||
]);
|
||||
class_alias($class, $legacy);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return callable
|
||||
*/
|
||||
private static function createAppendAutoloader(array $namespaces, ArrayObject $loaded)
|
||||
{
|
||||
/**
|
||||
* @param string $class Class name to autoload
|
||||
* @return void
|
||||
*/
|
||||
return static function ($class) use ($namespaces, $loaded) {
|
||||
$segments = explode('\\', $class);
|
||||
|
||||
if ($segments[0] === 'ZendService' && isset($segments[1])) {
|
||||
$segments[0] .= '\\' . $segments[1];
|
||||
unset($segments[1]);
|
||||
$segments = array_values($segments);
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
$check = '';
|
||||
|
||||
// We are checking segments of the namespace to match quicker
|
||||
while (isset($segments[$i + 1], $namespaces[$check . $segments[$i] . '\\'])) {
|
||||
$check .= $segments[$i] . '\\';
|
||||
++$i;
|
||||
}
|
||||
|
||||
if ($check === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$alias = $namespaces[$check]
|
||||
. strtr(substr($class, strlen($check)), [
|
||||
'Apigility' => 'ApiTools',
|
||||
'Expressive' => 'Mezzio',
|
||||
'Zend' => 'Laminas',
|
||||
'AbstractZendServer' => 'AbstractZendServer',
|
||||
'ZendServerDisk' => 'ZendServerDisk',
|
||||
'ZendServerShm' => 'ZendServerShm',
|
||||
'ZendMonitor' => 'ZendMonitor',
|
||||
]);
|
||||
|
||||
$loaded[$alias] = true;
|
||||
if (class_exists($alias) || interface_exists($alias) || trait_exists($alias)) {
|
||||
class_alias($alias, $class);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static function getClassLoaderFromVendorDirectory(string $composerVendorDirectory): ?ClassLoader
|
||||
{
|
||||
$filename = rtrim($composerVendorDirectory, '/') . '/autoload.php';
|
||||
if (!file_exists($filename)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @psalm-suppress MixedAssignment */
|
||||
$loader = include $filename;
|
||||
if (!$loader instanceof ClassLoader) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
426
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/src/ConfigPostProcessor.php
vendored
Normal file
426
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/src/ConfigPostProcessor.php
vendored
Normal file
@@ -0,0 +1,426 @@
|
||||
<?php
|
||||
|
||||
namespace Laminas\ZendFrameworkBridge;
|
||||
|
||||
use function array_intersect_key;
|
||||
use function array_key_exists;
|
||||
use function array_pop;
|
||||
use function in_array;
|
||||
use function is_array;
|
||||
use function is_callable;
|
||||
use function is_int;
|
||||
use function is_string;
|
||||
|
||||
class ConfigPostProcessor
|
||||
{
|
||||
/** @internal */
|
||||
const SERVICE_MANAGER_KEYS_OF_INTEREST = [
|
||||
'aliases' => true,
|
||||
'factories' => true,
|
||||
'invokables' => true,
|
||||
'services' => true,
|
||||
];
|
||||
|
||||
/** @var array String keys => string values */
|
||||
private $exactReplacements = [
|
||||
'zend-expressive' => 'mezzio',
|
||||
'zf-apigility' => 'api-tools',
|
||||
];
|
||||
|
||||
/** @var Replacements */
|
||||
private $replacements;
|
||||
|
||||
/** @var callable[] */
|
||||
private $rulesets;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->replacements = new Replacements();
|
||||
|
||||
/* Define the rulesets for replacements.
|
||||
*
|
||||
* Each ruleset has the following signature:
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param string[] $keys Full nested key hierarchy leading to the value
|
||||
* @return null|callable
|
||||
*
|
||||
* If no match is made, a null is returned, allowing it to fallback to
|
||||
* the next ruleset in the list. If a match is made, a callback is returned,
|
||||
* and that will be used to perform the replacement on the value.
|
||||
*
|
||||
* The callback should have the following signature:
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param string[] $keys
|
||||
* @return mixed The transformed value
|
||||
*/
|
||||
$this->rulesets = [
|
||||
// Exact values
|
||||
function ($value) {
|
||||
return is_string($value) && isset($this->exactReplacements[$value])
|
||||
? [$this, 'replaceExactValue']
|
||||
: null;
|
||||
},
|
||||
|
||||
// Router (MVC applications)
|
||||
// We do not want to rewrite these.
|
||||
function ($value, array $keys) {
|
||||
$key = array_pop($keys);
|
||||
// Only worried about a top-level "router" key.
|
||||
return $key === 'router' && $keys === [] && is_array($value)
|
||||
? [$this, 'noopReplacement']
|
||||
: null;
|
||||
},
|
||||
|
||||
// service- and pluginmanager handling
|
||||
function ($value) {
|
||||
return is_array($value) && array_intersect_key(self::SERVICE_MANAGER_KEYS_OF_INTEREST, $value) !== []
|
||||
? [$this, 'replaceDependencyConfiguration']
|
||||
: null;
|
||||
},
|
||||
|
||||
// Array values
|
||||
function ($value, array $keys) {
|
||||
return $keys !== [] && is_array($value)
|
||||
? [$this, '__invoke']
|
||||
: null;
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $keys Hierarchy of keys, for determining location in
|
||||
* nested configuration.
|
||||
* @return array
|
||||
*/
|
||||
public function __invoke(array $config, array $keys = [])
|
||||
{
|
||||
$rewritten = [];
|
||||
|
||||
foreach ($config as $key => $value) {
|
||||
// Determine new key from replacements
|
||||
$newKey = is_string($key) ? $this->replace($key, $keys) : $key;
|
||||
|
||||
// Keep original values with original key, if the key has changed, but only at the top-level.
|
||||
if (empty($keys) && $newKey !== $key) {
|
||||
$rewritten[$key] = $value;
|
||||
}
|
||||
|
||||
// Perform value replacements, if any
|
||||
$newValue = $this->replace($value, $keys, $newKey);
|
||||
|
||||
// Key does not already exist and/or is not an array value
|
||||
if (! array_key_exists($newKey, $rewritten) || ! is_array($rewritten[$newKey])) {
|
||||
// Do not overwrite existing values with null values
|
||||
$rewritten[$newKey] = array_key_exists($newKey, $rewritten) && null === $newValue
|
||||
? $rewritten[$newKey]
|
||||
: $newValue;
|
||||
continue;
|
||||
}
|
||||
|
||||
// New value is null; nothing to do.
|
||||
if (null === $newValue) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Key already exists as an array value, but $value is not an array
|
||||
if (! is_array($newValue)) {
|
||||
$rewritten[$newKey][] = $newValue;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Key already exists as an array value, and $value is also an array
|
||||
$rewritten[$newKey] = static::merge($rewritten[$newKey], $newValue);
|
||||
}
|
||||
|
||||
return $rewritten;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform substitutions as needed on an individual value.
|
||||
*
|
||||
* The $key is provided to allow fine-grained selection of rewrite rules.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param string[] $keys Key hierarchy
|
||||
* @param null|int|string $key
|
||||
* @return mixed
|
||||
*/
|
||||
private function replace($value, array $keys, $key = null)
|
||||
{
|
||||
// Add new key to the list of keys.
|
||||
// We do not need to remove it later, as we are working on a copy of the array.
|
||||
$keys[] = $key;
|
||||
|
||||
// Identify rewrite strategy and perform replacements
|
||||
$rewriteRule = $this->replacementRuleMatch($value, $keys);
|
||||
return $rewriteRule($value, $keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge two arrays together.
|
||||
*
|
||||
* If an integer key exists in both arrays, the value from the second array
|
||||
* will be appended to the first array. If both values are arrays, they are
|
||||
* merged together, else the value of the second array overwrites the one
|
||||
* of the first array.
|
||||
*
|
||||
* Based on zend-stdlib Zend\Stdlib\ArrayUtils::merge
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function merge(array $a, array $b)
|
||||
{
|
||||
foreach ($b as $key => $value) {
|
||||
if (! isset($a[$key]) && ! array_key_exists($key, $a)) {
|
||||
$a[$key] = $value;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (null === $value && array_key_exists($key, $a)) {
|
||||
// Leave as-is if value from $b is null
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_int($key)) {
|
||||
$a[] = $value;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_array($value) && is_array($a[$key])) {
|
||||
$a[$key] = static::merge($a[$key], $value);
|
||||
continue;
|
||||
}
|
||||
|
||||
$a[$key] = $value;
|
||||
}
|
||||
|
||||
return $a;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param null|int|string $key
|
||||
* @return callable Callable to invoke with value
|
||||
*/
|
||||
private function replacementRuleMatch($value, $key = null)
|
||||
{
|
||||
foreach ($this->rulesets as $ruleset) {
|
||||
$result = $ruleset($value, $key);
|
||||
if (is_callable($result)) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
return [$this, 'fallbackReplacement'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace a value using the translation table, if the value is a string.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
private function fallbackReplacement($value)
|
||||
{
|
||||
return is_string($value)
|
||||
? $this->replacements->replace($value)
|
||||
: $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace a value matched exactly.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
private function replaceExactValue($value)
|
||||
{
|
||||
return $this->exactReplacements[$value];
|
||||
}
|
||||
|
||||
private function replaceDependencyConfiguration(array $config)
|
||||
{
|
||||
$aliases = isset($config['aliases']) && is_array($config['aliases'])
|
||||
? $this->replaceDependencyAliases($config['aliases'])
|
||||
: [];
|
||||
|
||||
if ($aliases) {
|
||||
$config['aliases'] = $aliases;
|
||||
}
|
||||
|
||||
$config = $this->replaceDependencyInvokables($config);
|
||||
$config = $this->replaceDependencyFactories($config);
|
||||
$config = $this->replaceDependencyServices($config);
|
||||
|
||||
$keys = self::SERVICE_MANAGER_KEYS_OF_INTEREST;
|
||||
foreach ($config as $key => $data) {
|
||||
if (isset($keys[$key])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$config[$key] = is_array($data) ? $this->__invoke($data, [$key]) : $data;
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrite dependency aliases array
|
||||
*
|
||||
* In this case, we want to keep the alias as-is, but rewrite the target.
|
||||
*
|
||||
* We need also provide an additional alias if the alias key is a legacy class.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function replaceDependencyAliases(array $aliases)
|
||||
{
|
||||
foreach ($aliases as $alias => $target) {
|
||||
if (! is_string($alias) || ! is_string($target)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$newTarget = $this->replacements->replace($target);
|
||||
$newAlias = $this->replacements->replace($alias);
|
||||
|
||||
$notIn = [$newTarget];
|
||||
$name = $newTarget;
|
||||
while (isset($aliases[$name])) {
|
||||
$notIn[] = $aliases[$name];
|
||||
$name = $aliases[$name];
|
||||
}
|
||||
|
||||
if ($newAlias === $alias && ! in_array($alias, $notIn, true)) {
|
||||
$aliases[$alias] = $newTarget;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($aliases[$newAlias])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! in_array($newAlias, $notIn, true)) {
|
||||
$aliases[$alias] = $newAlias;
|
||||
$aliases[$newAlias] = $newTarget;
|
||||
}
|
||||
}
|
||||
|
||||
return $aliases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrite dependency invokables array
|
||||
*
|
||||
* In this case, we want to keep the alias as-is, but rewrite the target.
|
||||
*
|
||||
* We need also provide an additional alias if invokable is defined with
|
||||
* an alias which is a legacy class.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function replaceDependencyInvokables(array $config)
|
||||
{
|
||||
if (empty($config['invokables']) || ! is_array($config['invokables'])) {
|
||||
return $config;
|
||||
}
|
||||
|
||||
foreach ($config['invokables'] as $alias => $target) {
|
||||
if (! is_string($alias)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$newTarget = $this->replacements->replace($target);
|
||||
$newAlias = $this->replacements->replace($alias);
|
||||
|
||||
if ($alias === $target || isset($config['aliases'][$newAlias])) {
|
||||
$config['invokables'][$alias] = $newTarget;
|
||||
continue;
|
||||
}
|
||||
|
||||
$config['invokables'][$newAlias] = $newTarget;
|
||||
|
||||
if ($newAlias === $alias) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$config['aliases'][$alias] = $newAlias;
|
||||
|
||||
unset($config['invokables'][$alias]);
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @return mixed Returns $value verbatim.
|
||||
*/
|
||||
private function noopReplacement($value)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
private function replaceDependencyFactories(array $config)
|
||||
{
|
||||
if (empty($config['factories']) || ! is_array($config['factories'])) {
|
||||
return $config;
|
||||
}
|
||||
|
||||
foreach ($config['factories'] as $service => $factory) {
|
||||
if (! is_string($service)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$replacedService = $this->replacements->replace($service);
|
||||
$factory = is_string($factory) ? $this->replacements->replace($factory) : $factory;
|
||||
$config['factories'][$replacedService] = $factory;
|
||||
|
||||
if ($replacedService === $service) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unset($config['factories'][$service]);
|
||||
if (isset($config['aliases'][$service])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$config['aliases'][$service] = $replacedService;
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
private function replaceDependencyServices(array $config)
|
||||
{
|
||||
if (empty($config['services']) || ! is_array($config['services'])) {
|
||||
return $config;
|
||||
}
|
||||
|
||||
foreach ($config['services'] as $service => $serviceInstance) {
|
||||
if (! is_string($service)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$replacedService = $this->replacements->replace($service);
|
||||
$serviceInstance = is_array($serviceInstance) ? $this->__invoke($serviceInstance) : $serviceInstance;
|
||||
|
||||
$config['services'][$replacedService] = $serviceInstance;
|
||||
|
||||
if ($service === $replacedService) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unset($config['services'][$service]);
|
||||
|
||||
if (isset($config['aliases'][$service])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$config['aliases'][$service] = $replacedService;
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
}
|
||||
48
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/src/Module.php
vendored
Normal file
48
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/src/Module.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Laminas\ZendFrameworkBridge;
|
||||
|
||||
use Laminas\ModuleManager\Listener\ConfigMergerInterface;
|
||||
use Laminas\ModuleManager\ModuleEvent;
|
||||
use Laminas\ModuleManager\ModuleManager;
|
||||
|
||||
class Module
|
||||
{
|
||||
/**
|
||||
* Initialize the module.
|
||||
*
|
||||
* Type-hinting deliberately omitted to allow unit testing
|
||||
* without dependencies on packages that do not exist yet.
|
||||
*
|
||||
* @param ModuleManager $moduleManager
|
||||
*/
|
||||
public function init($moduleManager)
|
||||
{
|
||||
$moduleManager
|
||||
->getEventManager()
|
||||
->attach('mergeConfig', [$this, 'onMergeConfig']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform substitutions in the merged configuration.
|
||||
*
|
||||
* Rewrites keys and values matching known ZF classes, namespaces, and
|
||||
* configuration keys to their Laminas equivalents.
|
||||
*
|
||||
* Type-hinting deliberately omitted to allow unit testing
|
||||
* without dependencies on packages that do not exist yet.
|
||||
*
|
||||
* @param ModuleEvent $event
|
||||
*/
|
||||
public function onMergeConfig($event)
|
||||
{
|
||||
/** @var ConfigMergerInterface */
|
||||
$configMerger = $event->getConfigListener();
|
||||
$processor = new ConfigPostProcessor();
|
||||
$configMerger->setMergedConfig(
|
||||
$processor(
|
||||
$configMerger->getMergedConfig($returnAsObject = false)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
40
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/src/Replacements.php
vendored
Normal file
40
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/src/Replacements.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Laminas\ZendFrameworkBridge;
|
||||
|
||||
use function array_merge;
|
||||
use function str_replace;
|
||||
use function strpos;
|
||||
use function strtr;
|
||||
|
||||
class Replacements
|
||||
{
|
||||
/** @var string[] */
|
||||
private $replacements;
|
||||
|
||||
public function __construct(array $additionalReplacements = [])
|
||||
{
|
||||
$this->replacements = array_merge(
|
||||
require __DIR__ . '/../config/replacements.php',
|
||||
$additionalReplacements
|
||||
);
|
||||
|
||||
// Provide multiple variants of strings containing namespace separators
|
||||
foreach ($this->replacements as $original => $replacement) {
|
||||
if (false === strpos($original, '\\')) {
|
||||
continue;
|
||||
}
|
||||
$this->replacements[str_replace('\\', '\\\\', $original)] = str_replace('\\', '\\\\', $replacement);
|
||||
$this->replacements[str_replace('\\', '\\\\\\\\', $original)] = str_replace('\\', '\\\\\\\\', $replacement);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public function replace($value)
|
||||
{
|
||||
return strtr($value, $this->replacements);
|
||||
}
|
||||
}
|
||||
73
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/src/RewriteRules.php
vendored
Normal file
73
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/src/RewriteRules.php
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Laminas\ZendFrameworkBridge;
|
||||
|
||||
class RewriteRules
|
||||
{
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function namespaceRewrite()
|
||||
{
|
||||
return [
|
||||
// Expressive
|
||||
'Zend\\ProblemDetails\\' => 'Mezzio\\ProblemDetails\\',
|
||||
'Zend\\Expressive\\' => 'Mezzio\\',
|
||||
|
||||
// Laminas
|
||||
'Zend\\' => 'Laminas\\',
|
||||
'ZF\\ComposerAutoloading\\' => 'Laminas\\ComposerAutoloading\\',
|
||||
'ZF\\DevelopmentMode\\' => 'Laminas\\DevelopmentMode\\',
|
||||
|
||||
// Apigility
|
||||
'ZF\\Apigility\\' => 'Laminas\\ApiTools\\',
|
||||
'ZF\\' => 'Laminas\\ApiTools\\',
|
||||
|
||||
// ZendXml, API wrappers, zend-http OAuth support, zend-diagnostics, ZendDeveloperTools
|
||||
'ZendXml\\' => 'Laminas\\Xml\\',
|
||||
'ZendOAuth\\' => 'Laminas\\OAuth\\',
|
||||
'ZendDiagnostics\\' => 'Laminas\\Diagnostics\\',
|
||||
'ZendService\\ReCaptcha\\' => 'Laminas\\ReCaptcha\\',
|
||||
'ZendService\\Twitter\\' => 'Laminas\\Twitter\\',
|
||||
'ZendDeveloperTools\\' => 'Laminas\\DeveloperTools\\',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function namespaceReverse()
|
||||
{
|
||||
return [
|
||||
// ZendXml, ZendOAuth, ZendDiagnostics, ZendDeveloperTools
|
||||
'Laminas\\Xml\\' => 'ZendXml\\',
|
||||
'Laminas\\OAuth\\' => 'ZendOAuth\\',
|
||||
'Laminas\\Diagnostics\\' => 'ZendDiagnostics\\',
|
||||
'Laminas\\DeveloperTools\\' => 'ZendDeveloperTools\\',
|
||||
|
||||
// Zend Service
|
||||
'Laminas\\ReCaptcha\\' => 'ZendService\\ReCaptcha\\',
|
||||
'Laminas\\Twitter\\' => 'ZendService\\Twitter\\',
|
||||
|
||||
// Zend
|
||||
'Laminas\\' => 'Zend\\',
|
||||
|
||||
// Expressive
|
||||
'Mezzio\\ProblemDetails\\' => 'Zend\\ProblemDetails\\',
|
||||
'Mezzio\\' => 'Zend\\Expressive\\',
|
||||
|
||||
// Laminas to ZfCampus
|
||||
'Laminas\\ComposerAutoloading\\' => 'ZF\\ComposerAutoloading\\',
|
||||
'Laminas\\DevelopmentMode\\' => 'ZF\\DevelopmentMode\\',
|
||||
|
||||
// Apigility
|
||||
'Laminas\\ApiTools\\Admin\\' => 'ZF\\Apigility\\Admin\\',
|
||||
'Laminas\\ApiTools\\Doctrine\\' => 'ZF\\Apigility\\Doctrine\\',
|
||||
'Laminas\\ApiTools\\Documentation\\' => 'ZF\\Apigility\\Documentation\\',
|
||||
'Laminas\\ApiTools\\Example\\' => 'ZF\\Apigility\\Example\\',
|
||||
'Laminas\\ApiTools\\Provider\\' => 'ZF\\Apigility\\Provider\\',
|
||||
'Laminas\\ApiTools\\Welcome\\' => 'ZF\\Apiglity\\Welcome\\',
|
||||
'Laminas\\ApiTools\\' => 'ZF\\',
|
||||
];
|
||||
}
|
||||
}
|
||||
3
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/src/autoload.php
vendored
Normal file
3
user/plugins/admin/vendor/laminas/laminas-zendframework-bridge/src/autoload.php
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
Laminas\ZendFrameworkBridge\Autoloader::load();
|
||||
21
user/plugins/admin/vendor/p3k/picofeed/LICENSE
vendored
Normal file
21
user/plugins/admin/vendor/p3k/picofeed/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Frederic Guillot
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
38
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Base.php
vendored
Normal file
38
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Base.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed;
|
||||
|
||||
use PicoFeed\Config\Config;
|
||||
use PicoFeed\Logging\Logger;
|
||||
|
||||
/**
|
||||
* Base class
|
||||
*
|
||||
* @package PicoFeed
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
abstract class Base
|
||||
{
|
||||
/**
|
||||
* Config class instance
|
||||
*
|
||||
* @access protected
|
||||
* @var \PicoFeed\Config\Config
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \PicoFeed\Config\Config $config Config class instance
|
||||
*/
|
||||
public function __construct(Config $config = null)
|
||||
{
|
||||
$this->config = $config ?: new Config();
|
||||
Logger::setTimezone($this->config->getTimezone());
|
||||
}
|
||||
|
||||
public function setConfig(Config $config) {
|
||||
$this->config = $config;
|
||||
}
|
||||
}
|
||||
712
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/Client.php
vendored
Normal file
712
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/Client.php
vendored
Normal file
@@ -0,0 +1,712 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Client;
|
||||
|
||||
use DateTime;
|
||||
use Exception;
|
||||
use LogicException;
|
||||
use PicoFeed\Logging\Logger;
|
||||
use PicoFeed\Config\Config;
|
||||
|
||||
/**
|
||||
* Client class.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
abstract class Client
|
||||
{
|
||||
/**
|
||||
* Flag that say if the resource have been modified.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $is_modified = true;
|
||||
|
||||
/**
|
||||
* HTTP Content-Type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $content_type = '';
|
||||
|
||||
/**
|
||||
* HTTP encoding.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $encoding = '';
|
||||
|
||||
/**
|
||||
* HTTP request headers.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $request_headers = array();
|
||||
|
||||
/**
|
||||
* HTTP Etag header.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $etag = '';
|
||||
|
||||
/**
|
||||
* HTTP Last-Modified header.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $last_modified = '';
|
||||
|
||||
/**
|
||||
* Expiration DateTime
|
||||
*
|
||||
* @var DateTime
|
||||
*/
|
||||
protected $expiration = null;
|
||||
|
||||
/**
|
||||
* Proxy hostname.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $proxy_hostname = '';
|
||||
|
||||
/**
|
||||
* Proxy port.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $proxy_port = 3128;
|
||||
|
||||
/**
|
||||
* Proxy username.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $proxy_username = '';
|
||||
|
||||
/**
|
||||
* Proxy password.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $proxy_password = '';
|
||||
|
||||
/**
|
||||
* Basic auth username.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $username = '';
|
||||
|
||||
/**
|
||||
* Basic auth password.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $password = '';
|
||||
|
||||
/**
|
||||
* CURL options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $additional_curl_options = array();
|
||||
|
||||
/**
|
||||
* Client connection timeout.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $timeout = 10;
|
||||
|
||||
/**
|
||||
* User-agent.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $user_agent = 'PicoFeed (https://github.com/miniflux/picoFeed)';
|
||||
|
||||
/**
|
||||
* Real URL used (can be changed after a HTTP redirect).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $url = '';
|
||||
|
||||
/**
|
||||
* Page/Feed content.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $content = '';
|
||||
|
||||
/**
|
||||
* Number maximum of HTTP redirections to avoid infinite loops.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $max_redirects = 5;
|
||||
|
||||
/**
|
||||
* Maximum size of the HTTP body response.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $max_body_size = 2097152; // 2MB
|
||||
|
||||
/**
|
||||
* HTTP response status code.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $status_code = 0;
|
||||
|
||||
/**
|
||||
* Enables direct passthrough to requesting client.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $passthrough = false;
|
||||
|
||||
/**
|
||||
* Do the HTTP request.
|
||||
*
|
||||
* @abstract
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract public function doRequest();
|
||||
|
||||
/**
|
||||
* Get client instance: curl or stream driver.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @return \PicoFeed\Client\Client
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if (function_exists('curl_init')) {
|
||||
return new Curl();
|
||||
} elseif (ini_get('allow_url_fopen')) {
|
||||
return new Stream();
|
||||
}
|
||||
|
||||
throw new LogicException('You must have "allow_url_fopen=1" or curl extension installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add HTTP Header to the request.
|
||||
*
|
||||
* @param array $headers
|
||||
*/
|
||||
public function setHeaders($headers)
|
||||
{
|
||||
$this->request_headers = $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the HTTP request.
|
||||
*
|
||||
* @param string $url URL
|
||||
*
|
||||
* @return Client
|
||||
*/
|
||||
public function execute($url = '')
|
||||
{
|
||||
if ($url !== '') {
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
Logger::setMessage(get_called_class().' Fetch URL: '.$this->url);
|
||||
Logger::setMessage(get_called_class().' Etag provided: '.$this->etag);
|
||||
Logger::setMessage(get_called_class().' Last-Modified provided: '.$this->last_modified);
|
||||
|
||||
$response = $this->doRequest();
|
||||
|
||||
$this->status_code = $response['status'];
|
||||
$this->handleNotModifiedResponse($response);
|
||||
$this->handleErrorResponse($response);
|
||||
$this->handleNormalResponse($response);
|
||||
|
||||
$this->expiration = $this->parseExpiration($response['headers']);
|
||||
Logger::setMessage(get_called_class().' Expiration: '.$this->expiration->format(DATE_ISO8601));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle not modified response.
|
||||
*
|
||||
* @param array $response Client response
|
||||
*/
|
||||
protected function handleNotModifiedResponse(array $response)
|
||||
{
|
||||
if ($response['status'] == 304) {
|
||||
$this->is_modified = false;
|
||||
} elseif ($response['status'] == 200) {
|
||||
$this->is_modified = $this->hasBeenModified($response, $this->etag, $this->last_modified);
|
||||
$this->etag = $this->getHeader($response, 'ETag');
|
||||
$this->last_modified = $this->getHeader($response, 'Last-Modified');
|
||||
}
|
||||
|
||||
if ($this->is_modified === false) {
|
||||
Logger::setMessage(get_called_class().' Resource not modified');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Http Error codes
|
||||
*
|
||||
* @param array $response Client response
|
||||
* @throws ForbiddenException
|
||||
* @throws InvalidUrlException
|
||||
* @throws UnauthorizedException
|
||||
*/
|
||||
protected function handleErrorResponse(array $response)
|
||||
{
|
||||
$status = $response['status'];
|
||||
if ($status == 401) {
|
||||
throw new UnauthorizedException('Wrong or missing credentials');
|
||||
} else if ($status == 403) {
|
||||
throw new ForbiddenException('Not allowed to access resource');
|
||||
} else if ($status == 404) {
|
||||
throw new InvalidUrlException('Resource not found');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle normal response.
|
||||
*
|
||||
* @param array $response Client response
|
||||
*/
|
||||
protected function handleNormalResponse(array $response)
|
||||
{
|
||||
if ($response['status'] == 200) {
|
||||
$this->content = $response['body'];
|
||||
$this->content_type = $this->findContentType($response);
|
||||
$this->encoding = $this->findCharset();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a request has been modified according to the parameters.
|
||||
*
|
||||
* @param array $response
|
||||
* @param string $etag
|
||||
* @param string $lastModified
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function hasBeenModified($response, $etag, $lastModified)
|
||||
{
|
||||
$headers = array(
|
||||
'Etag' => $etag,
|
||||
'Last-Modified' => $lastModified,
|
||||
);
|
||||
|
||||
// Compare the values for each header that is present
|
||||
$presentCacheHeaderCount = 0;
|
||||
foreach ($headers as $key => $value) {
|
||||
if (isset($response['headers'][$key])) {
|
||||
if ($response['headers'][$key] !== $value) {
|
||||
return true;
|
||||
}
|
||||
++$presentCacheHeaderCount;
|
||||
}
|
||||
}
|
||||
|
||||
// If at least one header is present and the values match, the response
|
||||
// was not modified
|
||||
if ($presentCacheHeaderCount > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find content type from response headers.
|
||||
*
|
||||
* @param array $response Client response
|
||||
* @return string
|
||||
*/
|
||||
public function findContentType(array $response)
|
||||
{
|
||||
return strtolower($this->getHeader($response, 'Content-Type'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find charset from response headers.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function findCharset()
|
||||
{
|
||||
$result = explode('charset=', $this->content_type);
|
||||
return isset($result[1]) ? $result[1] : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get header value from a client response.
|
||||
*
|
||||
* @param array $response Client response
|
||||
* @param string $header Header name
|
||||
* @return string
|
||||
*/
|
||||
public function getHeader(array $response, $header)
|
||||
{
|
||||
return isset($response['headers'][$header]) ? $response['headers'][$header] : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Last-Modified HTTP header.
|
||||
*
|
||||
* @param string $last_modified Header value
|
||||
* @return $this
|
||||
*/
|
||||
public function setLastModified($last_modified)
|
||||
{
|
||||
$this->last_modified = $last_modified;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the Last-Modified HTTP header.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLastModified()
|
||||
{
|
||||
return $this->last_modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the Etag HTTP header.
|
||||
*
|
||||
* @param string $etag Etag HTTP header value
|
||||
* @return $this
|
||||
*/
|
||||
public function setEtag($etag)
|
||||
{
|
||||
$this->etag = $etag;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Etag HTTP header value.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEtag()
|
||||
{
|
||||
return $this->etag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the final url value.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl()
|
||||
{
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the url.
|
||||
*
|
||||
* @param $url
|
||||
* @return string
|
||||
*/
|
||||
public function setUrl($url)
|
||||
{
|
||||
$this->url = $url;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTTP response status code.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getStatusCode()
|
||||
{
|
||||
return $this->status_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the body of the HTTP response.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content type value from HTTP headers.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContentType()
|
||||
{
|
||||
return $this->content_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the encoding value from HTTP headers.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEncoding()
|
||||
{
|
||||
return $this->encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the remote resource has changed.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isModified()
|
||||
{
|
||||
return $this->is_modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* return true if passthrough mode is enabled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isPassthroughEnabled()
|
||||
{
|
||||
return $this->passthrough;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set connection timeout.
|
||||
*
|
||||
* @param int $timeout Connection timeout
|
||||
* @return $this
|
||||
*/
|
||||
public function setTimeout($timeout)
|
||||
{
|
||||
$this->timeout = $timeout ?: $this->timeout;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a custom user agent.
|
||||
*
|
||||
* @param string $user_agent User Agent
|
||||
* @return $this
|
||||
*/
|
||||
public function setUserAgent($user_agent)
|
||||
{
|
||||
$this->user_agent = $user_agent ?: $this->user_agent;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of HTTP redirections.
|
||||
*
|
||||
* @param int $max Maximum
|
||||
* @return $this
|
||||
*/
|
||||
public function setMaxRedirections($max)
|
||||
{
|
||||
$this->max_redirects = $max ?: $this->max_redirects;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum size of the HTTP body.
|
||||
*
|
||||
* @param int $max Maximum
|
||||
* @return $this
|
||||
*/
|
||||
public function setMaxBodySize($max)
|
||||
{
|
||||
$this->max_body_size = $max ?: $this->max_body_size;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the proxy hostname.
|
||||
*
|
||||
* @param string $hostname Proxy hostname
|
||||
* @return $this
|
||||
*/
|
||||
public function setProxyHostname($hostname)
|
||||
{
|
||||
$this->proxy_hostname = $hostname ?: $this->proxy_hostname;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the proxy port.
|
||||
*
|
||||
* @param int $port Proxy port
|
||||
* @return $this
|
||||
*/
|
||||
public function setProxyPort($port)
|
||||
{
|
||||
$this->proxy_port = $port ?: $this->proxy_port;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the proxy username.
|
||||
*
|
||||
* @param string $username Proxy username
|
||||
* @return $this
|
||||
*/
|
||||
public function setProxyUsername($username)
|
||||
{
|
||||
$this->proxy_username = $username ?: $this->proxy_username;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the proxy password.
|
||||
*
|
||||
* @param string $password Password
|
||||
* @return $this
|
||||
*/
|
||||
public function setProxyPassword($password)
|
||||
{
|
||||
$this->proxy_password = $password ?: $this->proxy_password;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the username.
|
||||
*
|
||||
* @param string $username Basic Auth username
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setUsername($username)
|
||||
{
|
||||
$this->username = $username ?: $this->username;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the password.
|
||||
*
|
||||
* @param string $password Basic Auth Password
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setPassword($password)
|
||||
{
|
||||
$this->password = $password ?: $this->password;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the CURL options.
|
||||
*
|
||||
* @param array $options
|
||||
* @return $this
|
||||
*/
|
||||
public function setAdditionalCurlOptions(array $options)
|
||||
{
|
||||
$this->additional_curl_options = $options ?: $this->additional_curl_options;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable the passthrough mode.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function enablePassthroughMode()
|
||||
{
|
||||
$this->passthrough = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the passthrough mode.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function disablePassthroughMode()
|
||||
{
|
||||
$this->passthrough = false;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set config object.
|
||||
*
|
||||
* @param \PicoFeed\Config\Config $config Config instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setConfig(Config $config)
|
||||
{
|
||||
if ($config !== null) {
|
||||
$this->setTimeout($config->getClientTimeout());
|
||||
$this->setUserAgent($config->getClientUserAgent());
|
||||
$this->setMaxRedirections($config->getMaxRedirections());
|
||||
$this->setMaxBodySize($config->getMaxBodySize());
|
||||
$this->setProxyHostname($config->getProxyHostname());
|
||||
$this->setProxyPort($config->getProxyPort());
|
||||
$this->setProxyUsername($config->getProxyUsername());
|
||||
$this->setProxyPassword($config->getProxyPassword());
|
||||
$this->setAdditionalCurlOptions($config->getAdditionalCurlOptions() ?: array());
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the HTTP status code is a redirection
|
||||
*
|
||||
* @access protected
|
||||
* @param integer $code
|
||||
* @return boolean
|
||||
*/
|
||||
public function isRedirection($code)
|
||||
{
|
||||
return $code == 301 || $code == 302 || $code == 303 || $code == 307;
|
||||
}
|
||||
|
||||
public function parseExpiration(HttpHeaders $headers)
|
||||
{
|
||||
try {
|
||||
|
||||
if (isset($headers['Cache-Control'])) {
|
||||
if (preg_match('/s-maxage=(\d+)/', $headers['Cache-Control'], $matches)) {
|
||||
return new DateTime('+' . $matches[1] . ' seconds');
|
||||
} else if (preg_match('/max-age=(\d+)/', $headers['Cache-Control'], $matches)) {
|
||||
return new DateTime('+' . $matches[1] . ' seconds');
|
||||
}
|
||||
}
|
||||
|
||||
if (! empty($headers['Expires'])) {
|
||||
return new DateTime($headers['Expires']);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
Logger::setMessage('Unable to parse expiration date: '.$e->getMessage());
|
||||
}
|
||||
|
||||
return new DateTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get expiration date time from "Expires" or "Cache-Control" headers
|
||||
*
|
||||
* @return DateTime
|
||||
*/
|
||||
public function getExpiration()
|
||||
{
|
||||
return $this->expiration ?: new DateTime();
|
||||
}
|
||||
}
|
||||
14
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/ClientException.php
vendored
Normal file
14
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/ClientException.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Client;
|
||||
|
||||
use PicoFeed\PicoFeedException;
|
||||
|
||||
/**
|
||||
* ClientException Exception.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
abstract class ClientException extends PicoFeedException
|
||||
{
|
||||
}
|
||||
412
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/Curl.php
vendored
Normal file
412
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/Curl.php
vendored
Normal file
@@ -0,0 +1,412 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Client;
|
||||
|
||||
use PicoFeed\Logging\Logger;
|
||||
|
||||
/**
|
||||
* cURL HTTP client.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Curl extends Client
|
||||
{
|
||||
protected $nbRedirects = 0;
|
||||
|
||||
/**
|
||||
* HTTP response body.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $body = '';
|
||||
|
||||
/**
|
||||
* Body size.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $body_length = 0;
|
||||
|
||||
/**
|
||||
* HTTP response headers.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $response_headers = array();
|
||||
|
||||
/**
|
||||
* Counter on the number of header received.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $response_headers_count = 0;
|
||||
|
||||
/**
|
||||
* cURL callback to read the HTTP body.
|
||||
*
|
||||
* If the function return -1, curl stop to read the HTTP response
|
||||
*
|
||||
* @param resource $ch cURL handler
|
||||
* @param string $buffer Chunk of data
|
||||
*
|
||||
* @return int Length of the buffer
|
||||
*/
|
||||
public function readBody($ch, $buffer)
|
||||
{
|
||||
$length = strlen($buffer);
|
||||
$this->body_length += $length;
|
||||
|
||||
if ($this->body_length > $this->max_body_size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
$this->body .= $buffer;
|
||||
|
||||
return $length;
|
||||
}
|
||||
|
||||
/**
|
||||
* cURL callback to read HTTP headers.
|
||||
*
|
||||
* @param resource $ch cURL handler
|
||||
* @param string $buffer Header line
|
||||
*
|
||||
* @return int Length of the buffer
|
||||
*/
|
||||
public function readHeaders($ch, $buffer)
|
||||
{
|
||||
$length = strlen($buffer);
|
||||
|
||||
if ($buffer === "\r\n" || $buffer === "\n") {
|
||||
++$this->response_headers_count;
|
||||
} else {
|
||||
if (!isset($this->response_headers[$this->response_headers_count])) {
|
||||
$this->response_headers[$this->response_headers_count] = '';
|
||||
}
|
||||
|
||||
$this->response_headers[$this->response_headers_count] .= $buffer;
|
||||
}
|
||||
|
||||
return $length;
|
||||
}
|
||||
|
||||
/**
|
||||
* cURL callback to passthrough the HTTP body to the client.
|
||||
*
|
||||
* If the function return -1, curl stop to read the HTTP response
|
||||
*
|
||||
* @param resource $ch cURL handler
|
||||
* @param string $buffer Chunk of data
|
||||
*
|
||||
* @return int Length of the buffer
|
||||
*/
|
||||
public function passthroughBody($ch, $buffer)
|
||||
{
|
||||
// do it only at the beginning of a transmission
|
||||
if ($this->body_length === 0) {
|
||||
list($status, $headers) = HttpHeaders::parse(explode("\n", $this->response_headers[$this->response_headers_count - 1]));
|
||||
|
||||
if ($this->isRedirection($status)) {
|
||||
return $this->handleRedirection($headers['Location']);
|
||||
}
|
||||
|
||||
if (isset($headers['Content-Type'])) {
|
||||
header('Content-Type:' .$headers['Content-Type']);
|
||||
}
|
||||
}
|
||||
|
||||
$length = strlen($buffer);
|
||||
$this->body_length += $length;
|
||||
|
||||
echo $buffer;
|
||||
|
||||
return $length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare HTTP headers.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
private function prepareHeaders()
|
||||
{
|
||||
$headers = array(
|
||||
'Connection: close',
|
||||
);
|
||||
|
||||
if ($this->etag) {
|
||||
$headers[] = 'If-None-Match: '.$this->etag;
|
||||
$headers[] = 'A-IM: feed';
|
||||
}
|
||||
|
||||
if ($this->last_modified) {
|
||||
$headers[] = 'If-Modified-Since: '.$this->last_modified;
|
||||
}
|
||||
|
||||
$headers = array_merge($headers, $this->request_headers);
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare curl proxy context.
|
||||
*
|
||||
* @param resource $ch
|
||||
*
|
||||
* @return resource $ch
|
||||
*/
|
||||
private function prepareProxyContext($ch)
|
||||
{
|
||||
if ($this->proxy_hostname) {
|
||||
Logger::setMessage(get_called_class().' Proxy: '.$this->proxy_hostname.':'.$this->proxy_port);
|
||||
|
||||
curl_setopt($ch, CURLOPT_PROXYPORT, $this->proxy_port);
|
||||
curl_setopt($ch, CURLOPT_PROXYTYPE, 'HTTP');
|
||||
curl_setopt($ch, CURLOPT_PROXY, $this->proxy_hostname);
|
||||
|
||||
if ($this->proxy_username) {
|
||||
Logger::setMessage(get_called_class().' Proxy credentials: Yes');
|
||||
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $this->proxy_username.':'.$this->proxy_password);
|
||||
} else {
|
||||
Logger::setMessage(get_called_class().' Proxy credentials: No');
|
||||
}
|
||||
}
|
||||
|
||||
return $ch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare curl auth context.
|
||||
*
|
||||
* @param resource $ch
|
||||
*
|
||||
* @return resource $ch
|
||||
*/
|
||||
private function prepareAuthContext($ch)
|
||||
{
|
||||
if ($this->username && $this->password) {
|
||||
curl_setopt($ch, CURLOPT_USERPWD, $this->username.':'.$this->password);
|
||||
}
|
||||
|
||||
return $ch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set write/header functions.
|
||||
*
|
||||
* @param resource $ch
|
||||
*
|
||||
* @return resource $ch
|
||||
*/
|
||||
private function prepareDownloadMode($ch)
|
||||
{
|
||||
$this->body = '';
|
||||
$this->response_headers = array();
|
||||
$this->response_headers_count = 0;
|
||||
$write_function = 'readBody';
|
||||
$header_function = 'readHeaders';
|
||||
|
||||
if ($this->isPassthroughEnabled()) {
|
||||
$write_function = 'passthroughBody';
|
||||
}
|
||||
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, array($this, $write_function));
|
||||
curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, $header_function));
|
||||
|
||||
return $ch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set additional CURL options.
|
||||
*
|
||||
* @param resource $ch
|
||||
*
|
||||
* @return resource $ch
|
||||
*/
|
||||
private function prepareAdditionalCurlOptions($ch){
|
||||
foreach( $this->additional_curl_options as $c_op => $c_val ){
|
||||
curl_setopt($ch, $c_op, $c_val);
|
||||
}
|
||||
return $ch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare curl context.
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
private function prepareContext()
|
||||
{
|
||||
$ch = curl_init();
|
||||
|
||||
curl_setopt($ch, CURLOPT_URL, $this->url);
|
||||
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->timeout);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, $this->user_agent);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $this->prepareHeaders());
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
|
||||
curl_setopt($ch, CURLOPT_ENCODING, '');
|
||||
curl_setopt($ch, CURLOPT_COOKIEJAR, 'php://memory');
|
||||
curl_setopt($ch, CURLOPT_COOKIEFILE, 'php://memory');
|
||||
|
||||
// Disable SSLv3 by enforcing TLSv1.x for curl >= 7.34.0 and < 7.39.0.
|
||||
// Versions prior to 7.34 and at least when compiled against openssl
|
||||
// interpret this parameter as "limit to TLSv1.0" which fails for sites
|
||||
// which enforce TLS 1.1+.
|
||||
// Starting with curl 7.39.0 SSLv3 is disabled by default.
|
||||
$version = curl_version();
|
||||
if ($version['version_number'] >= 467456 && $version['version_number'] < 468736) {
|
||||
curl_setopt($ch, CURLOPT_SSLVERSION, 1);
|
||||
}
|
||||
|
||||
$ch = $this->prepareDownloadMode($ch);
|
||||
$ch = $this->prepareProxyContext($ch);
|
||||
$ch = $this->prepareAuthContext($ch);
|
||||
$ch = $this->prepareAdditionalCurlOptions($ch);
|
||||
|
||||
return $ch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute curl context.
|
||||
*/
|
||||
private function executeContext()
|
||||
{
|
||||
$ch = $this->prepareContext();
|
||||
curl_exec($ch);
|
||||
|
||||
Logger::setMessage(get_called_class().' cURL total time: '.curl_getinfo($ch, CURLINFO_TOTAL_TIME));
|
||||
Logger::setMessage(get_called_class().' cURL dns lookup time: '.curl_getinfo($ch, CURLINFO_NAMELOOKUP_TIME));
|
||||
Logger::setMessage(get_called_class().' cURL connect time: '.curl_getinfo($ch, CURLINFO_CONNECT_TIME));
|
||||
Logger::setMessage(get_called_class().' cURL speed download: '.curl_getinfo($ch, CURLINFO_SPEED_DOWNLOAD));
|
||||
Logger::setMessage(get_called_class().' cURL effective url: '.curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
|
||||
|
||||
$curl_errno = curl_errno($ch);
|
||||
|
||||
if ($curl_errno) {
|
||||
Logger::setMessage(get_called_class().' cURL error: '.curl_error($ch));
|
||||
curl_close($ch);
|
||||
|
||||
$this->handleError($curl_errno);
|
||||
}
|
||||
|
||||
// Update the url if there where redirects
|
||||
$this->url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
|
||||
|
||||
curl_close($ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the HTTP request.
|
||||
*
|
||||
* @return array HTTP response ['body' => ..., 'status' => ..., 'headers' => ...]
|
||||
*/
|
||||
public function doRequest()
|
||||
{
|
||||
$this->executeContext();
|
||||
|
||||
list($status, $headers) = HttpHeaders::parse(explode("\n", $this->response_headers[$this->response_headers_count - 1]));
|
||||
|
||||
if ($this->isRedirection($status)) {
|
||||
if (empty($headers['Location'])) {
|
||||
$status = 200;
|
||||
} else {
|
||||
return $this->handleRedirection($headers['Location']);
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'status' => $status,
|
||||
'body' => $this->body,
|
||||
'headers' => $headers,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle HTTP redirects
|
||||
*
|
||||
* @param string $location Redirected URL
|
||||
* @return array
|
||||
* @throws MaxRedirectException
|
||||
*/
|
||||
private function handleRedirection($location)
|
||||
{
|
||||
$result = array();
|
||||
$this->url = Url::resolve($location, $this->url);
|
||||
$this->body = '';
|
||||
$this->body_length = 0;
|
||||
$this->response_headers = array();
|
||||
$this->response_headers_count = 0;
|
||||
|
||||
while (true) {
|
||||
$this->nbRedirects++;
|
||||
|
||||
if ($this->nbRedirects >= $this->max_redirects) {
|
||||
throw new MaxRedirectException('Maximum number of redirections reached');
|
||||
}
|
||||
|
||||
$result = $this->doRequest();
|
||||
|
||||
if ($this->isRedirection($result['status'])) {
|
||||
$this->url = Url::resolve($result['headers']['Location'], $this->url);
|
||||
$this->body = '';
|
||||
$this->body_length = 0;
|
||||
$this->response_headers = array();
|
||||
$this->response_headers_count = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle cURL errors (throw individual exceptions).
|
||||
*
|
||||
* We don't use constants because they are not necessary always available
|
||||
* (depends of the version of libcurl linked to php)
|
||||
*
|
||||
* @see http://curl.haxx.se/libcurl/c/libcurl-errors.html
|
||||
*
|
||||
* @param int $errno cURL error code
|
||||
* @throws InvalidCertificateException
|
||||
* @throws InvalidUrlException
|
||||
* @throws MaxRedirectException
|
||||
* @throws MaxSizeException
|
||||
* @throws TimeoutException
|
||||
*/
|
||||
private function handleError($errno)
|
||||
{
|
||||
switch ($errno) {
|
||||
case 78: // CURLE_REMOTE_FILE_NOT_FOUND
|
||||
throw new InvalidUrlException('Resource not found', $errno);
|
||||
case 6: // CURLE_COULDNT_RESOLVE_HOST
|
||||
throw new InvalidUrlException('Unable to resolve hostname', $errno);
|
||||
case 7: // CURLE_COULDNT_CONNECT
|
||||
throw new InvalidUrlException('Unable to connect to the remote host', $errno);
|
||||
case 23: // CURLE_WRITE_ERROR
|
||||
throw new MaxSizeException('Maximum response size exceeded', $errno);
|
||||
case 28: // CURLE_OPERATION_TIMEDOUT
|
||||
throw new TimeoutException('Operation timeout', $errno);
|
||||
case 35: // CURLE_SSL_CONNECT_ERROR
|
||||
case 51: // CURLE_PEER_FAILED_VERIFICATION
|
||||
case 58: // CURLE_SSL_CERTPROBLEM
|
||||
case 60: // CURLE_SSL_CACERT
|
||||
case 59: // CURLE_SSL_CIPHER
|
||||
case 64: // CURLE_USE_SSL_FAILED
|
||||
case 66: // CURLE_SSL_ENGINE_INITFAILED
|
||||
case 77: // CURLE_SSL_CACERT_BADFILE
|
||||
case 83: // CURLE_SSL_ISSUER_ERROR
|
||||
$msg = 'Invalid SSL certificate caused by CURL error number ' . $errno;
|
||||
throw new InvalidCertificateException($msg, $errno);
|
||||
case 47: // CURLE_TOO_MANY_REDIRECTS
|
||||
throw new MaxRedirectException('Maximum number of redirections reached', $errno);
|
||||
case 63: // CURLE_FILESIZE_EXCEEDED
|
||||
throw new MaxSizeException('Maximum response size exceeded', $errno);
|
||||
default:
|
||||
throw new InvalidUrlException('Unable to fetch the URL', $errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
10
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/ForbiddenException.php
vendored
Normal file
10
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/ForbiddenException.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Client;
|
||||
|
||||
/**
|
||||
* @author Bernhard Posselt
|
||||
*/
|
||||
class ForbiddenException extends ClientException
|
||||
{
|
||||
}
|
||||
79
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/HttpHeaders.php
vendored
Normal file
79
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/HttpHeaders.php
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Client;
|
||||
|
||||
use ArrayAccess;
|
||||
use PicoFeed\Logging\Logger;
|
||||
|
||||
/**
|
||||
* Class to handle HTTP headers case insensitivity.
|
||||
*
|
||||
* @author Bernhard Posselt
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class HttpHeaders implements ArrayAccess
|
||||
{
|
||||
private $headers = array();
|
||||
|
||||
public function __construct(array $headers)
|
||||
{
|
||||
foreach ($headers as $key => $value) {
|
||||
$this->headers[strtolower($key)] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->offsetExists($offset) ? $this->headers[strtolower($offset)] : '';
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->headers[strtolower($offset)] = $value;
|
||||
}
|
||||
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->headers[strtolower($offset)]);
|
||||
}
|
||||
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->headers[strtolower($offset)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse HTTP headers.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @param array $lines List of headers
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function parse(array $lines)
|
||||
{
|
||||
$status = 0;
|
||||
$headers = array();
|
||||
|
||||
foreach ($lines as $line) {
|
||||
if (strpos($line, 'HTTP/1') === 0) {
|
||||
$headers = array();
|
||||
$status = (int) substr($line, 9, 3);
|
||||
} elseif (strpos($line, ': ') !== false) {
|
||||
list($name, $value) = explode(': ', $line);
|
||||
if ($value) {
|
||||
$headers[trim($name)] = trim($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Logger::setMessage(get_called_class().' HTTP status code: '.$status);
|
||||
|
||||
foreach ($headers as $name => $value) {
|
||||
Logger::setMessage(get_called_class().' HTTP header: '.$name.' => '.$value);
|
||||
}
|
||||
|
||||
return array($status, new self($headers));
|
||||
}
|
||||
}
|
||||
12
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/InvalidCertificateException.php
vendored
Normal file
12
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/InvalidCertificateException.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Client;
|
||||
|
||||
/**
|
||||
* InvalidCertificateException Exception.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class InvalidCertificateException extends ClientException
|
||||
{
|
||||
}
|
||||
12
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/InvalidUrlException.php
vendored
Normal file
12
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/InvalidUrlException.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Client;
|
||||
|
||||
/**
|
||||
* InvalidUrlException Exception.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class InvalidUrlException extends ClientException
|
||||
{
|
||||
}
|
||||
12
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/MaxRedirectException.php
vendored
Normal file
12
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/MaxRedirectException.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Client;
|
||||
|
||||
/**
|
||||
* MaxRedirectException Exception.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class MaxRedirectException extends ClientException
|
||||
{
|
||||
}
|
||||
12
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/MaxSizeException.php
vendored
Normal file
12
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/MaxSizeException.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Client;
|
||||
|
||||
/**
|
||||
* MaxSizeException Exception.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class MaxSizeException extends ClientException
|
||||
{
|
||||
}
|
||||
205
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/Stream.php
vendored
Normal file
205
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/Stream.php
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Client;
|
||||
|
||||
use PicoFeed\Logging\Logger;
|
||||
|
||||
/**
|
||||
* Stream context HTTP client.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Stream extends Client
|
||||
{
|
||||
/**
|
||||
* Prepare HTTP headers.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
private function prepareHeaders()
|
||||
{
|
||||
$headers = array(
|
||||
'Connection: close',
|
||||
'User-Agent: '.$this->user_agent,
|
||||
);
|
||||
|
||||
// disable compression in passthrough mode. It could result in double
|
||||
// compressed content which isn't decodeable by browsers
|
||||
if (function_exists('gzdecode') && !$this->isPassthroughEnabled()) {
|
||||
$headers[] = 'Accept-Encoding: gzip';
|
||||
}
|
||||
|
||||
if ($this->etag) {
|
||||
$headers[] = 'If-None-Match: '.$this->etag;
|
||||
$headers[] = 'A-IM: feed';
|
||||
}
|
||||
|
||||
if ($this->last_modified) {
|
||||
$headers[] = 'If-Modified-Since: '.$this->last_modified;
|
||||
}
|
||||
|
||||
if ($this->proxy_username) {
|
||||
$headers[] = 'Proxy-Authorization: Basic '.base64_encode($this->proxy_username.':'.$this->proxy_password);
|
||||
}
|
||||
|
||||
if ($this->username && $this->password) {
|
||||
$headers[] = 'Authorization: Basic '.base64_encode($this->username.':'.$this->password);
|
||||
}
|
||||
|
||||
$headers = array_merge($headers, $this->request_headers);
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the final URL from location headers.
|
||||
*
|
||||
* @param array $headers List of HTTP response header
|
||||
*/
|
||||
private function setEffectiveUrl($headers)
|
||||
{
|
||||
foreach ($headers as $header) {
|
||||
if (stripos($header, 'Location') === 0) {
|
||||
list(, $value) = explode(': ', $header);
|
||||
|
||||
$this->url = Url::resolve($value, $this->url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare stream context.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function prepareContext()
|
||||
{
|
||||
$context = array(
|
||||
'http' => array(
|
||||
'method' => 'GET',
|
||||
'protocol_version' => 1.1,
|
||||
'timeout' => $this->timeout,
|
||||
'max_redirects' => $this->max_redirects,
|
||||
),
|
||||
);
|
||||
|
||||
if ($this->proxy_hostname) {
|
||||
Logger::setMessage(get_called_class().' Proxy: '.$this->proxy_hostname.':'.$this->proxy_port);
|
||||
|
||||
$context['http']['proxy'] = 'tcp://'.$this->proxy_hostname.':'.$this->proxy_port;
|
||||
$context['http']['request_fulluri'] = true;
|
||||
|
||||
if ($this->proxy_username) {
|
||||
Logger::setMessage(get_called_class().' Proxy credentials: Yes');
|
||||
} else {
|
||||
Logger::setMessage(get_called_class().' Proxy credentials: No');
|
||||
}
|
||||
}
|
||||
|
||||
$context['http']['header'] = implode("\r\n", $this->prepareHeaders());
|
||||
|
||||
return $context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the HTTP request.
|
||||
*
|
||||
* @return array HTTP response ['body' => ..., 'status' => ..., 'headers' => ...]
|
||||
* @throws InvalidUrlException
|
||||
* @throws MaxSizeException
|
||||
* @throws TimeoutException
|
||||
*/
|
||||
public function doRequest()
|
||||
{
|
||||
$body = '';
|
||||
|
||||
// Create context
|
||||
$context = stream_context_create($this->prepareContext());
|
||||
|
||||
// Make HTTP request
|
||||
$stream = @fopen($this->url, 'r', false, $context);
|
||||
if (!is_resource($stream)) {
|
||||
throw new InvalidUrlException('Unable to establish a connection');
|
||||
}
|
||||
|
||||
// Get HTTP headers response
|
||||
$metadata = stream_get_meta_data($stream);
|
||||
list($status, $headers) = HttpHeaders::parse($metadata['wrapper_data']);
|
||||
|
||||
if ($this->isPassthroughEnabled()) {
|
||||
header(':', true, $status);
|
||||
|
||||
if (isset($headers['Content-Type'])) {
|
||||
header('Content-Type: '.$headers['Content-Type']);
|
||||
}
|
||||
|
||||
fpassthru($stream);
|
||||
} else {
|
||||
// Get the entire body until the max size
|
||||
$body = stream_get_contents($stream, $this->max_body_size + 1);
|
||||
|
||||
// If the body size is too large abort everything
|
||||
if (strlen($body) > $this->max_body_size) {
|
||||
throw new MaxSizeException('Content size too large');
|
||||
}
|
||||
|
||||
if ($metadata['timed_out']) {
|
||||
throw new TimeoutException('Operation timeout');
|
||||
}
|
||||
}
|
||||
|
||||
fclose($stream);
|
||||
|
||||
$this->setEffectiveUrl($metadata['wrapper_data']);
|
||||
|
||||
return array(
|
||||
'status' => $status,
|
||||
'body' => $this->decodeBody($body, $headers),
|
||||
'headers' => $headers,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode body response according to the HTTP headers.
|
||||
*
|
||||
* @param string $body Raw body
|
||||
* @param HttpHeaders $headers HTTP headers
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function decodeBody($body, HttpHeaders $headers)
|
||||
{
|
||||
if (isset($headers['Transfer-Encoding']) && $headers['Transfer-Encoding'] === 'chunked') {
|
||||
$body = $this->decodeChunked($body);
|
||||
}
|
||||
|
||||
if (isset($headers['Content-Encoding']) && $headers['Content-Encoding'] === 'gzip') {
|
||||
$body = gzdecode($body);
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a chunked body.
|
||||
*
|
||||
* @param string $str Raw body
|
||||
*
|
||||
* @return string Decoded body
|
||||
*/
|
||||
public function decodeChunked($str)
|
||||
{
|
||||
for ($result = ''; !empty($str); $str = trim($str)) {
|
||||
|
||||
// Get the chunk length
|
||||
$pos = strpos($str, "\r\n");
|
||||
$len = hexdec(substr($str, 0, $pos));
|
||||
|
||||
// Append the chunk to the result
|
||||
$result .= substr($str, $pos + 2, $len);
|
||||
$str = substr($str, $pos + 2 + $len);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
12
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/TimeoutException.php
vendored
Normal file
12
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/TimeoutException.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Client;
|
||||
|
||||
/**
|
||||
* TimeoutException Exception.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TimeoutException extends ClientException
|
||||
{
|
||||
}
|
||||
10
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/UnauthorizedException.php
vendored
Normal file
10
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/UnauthorizedException.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Client;
|
||||
|
||||
/**
|
||||
* @author Bernhard Posselt
|
||||
*/
|
||||
class UnauthorizedException extends ClientException
|
||||
{
|
||||
}
|
||||
283
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/Url.php
vendored
Normal file
283
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/Url.php
vendored
Normal file
@@ -0,0 +1,283 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Client;
|
||||
|
||||
/**
|
||||
* URL class.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Url
|
||||
{
|
||||
/**
|
||||
* URL.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $url = '';
|
||||
|
||||
/**
|
||||
* URL components.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $components = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $url URL
|
||||
*/
|
||||
public function __construct($url)
|
||||
{
|
||||
$this->url = $url;
|
||||
$this->components = parse_url($url) ?: array();
|
||||
|
||||
// Issue with PHP < 5.4.7 and protocol relative url
|
||||
if (version_compare(PHP_VERSION, '5.4.7', '<') && $this->isProtocolRelative()) {
|
||||
$pos = strpos($this->components['path'], '/', 2);
|
||||
|
||||
if ($pos === false) {
|
||||
$pos = strlen($this->components['path']);
|
||||
}
|
||||
|
||||
$this->components['host'] = substr($this->components['path'], 2, $pos - 2);
|
||||
$this->components['path'] = substr($this->components['path'], $pos);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut method to get an absolute url from relative url.
|
||||
*
|
||||
* @static
|
||||
* @param mixed $item_url Unknown url (can be relative or not)
|
||||
* @param mixed $website_url Website url
|
||||
* @return string
|
||||
*/
|
||||
public static function resolve($item_url, $website_url)
|
||||
{
|
||||
$link = is_string($item_url) ? new self($item_url) : $item_url;
|
||||
$website = is_string($website_url) ? new self($website_url) : $website_url;
|
||||
|
||||
if ($link->isRelativeUrl()) {
|
||||
if ($link->isRelativePath()) {
|
||||
return $link->getAbsoluteUrl($website->getBaseUrl($website->getBasePath()));
|
||||
}
|
||||
|
||||
return $link->getAbsoluteUrl($website->getBaseUrl());
|
||||
} elseif ($link->isProtocolRelative()) {
|
||||
$link->setScheme($website->getScheme());
|
||||
}
|
||||
|
||||
return $link->getAbsoluteUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut method to get a base url.
|
||||
*
|
||||
* @static
|
||||
* @param string $url
|
||||
* @return string
|
||||
*/
|
||||
public static function base($url)
|
||||
{
|
||||
$link = new self($url);
|
||||
|
||||
return $link->getBaseUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base URL.
|
||||
*
|
||||
* @param string $suffix Add a suffix to the url
|
||||
* @return string
|
||||
*/
|
||||
public function getBaseUrl($suffix = '')
|
||||
{
|
||||
return $this->hasHost() ? $this->getScheme('://').$this->getHost().$this->getPort(':').$suffix : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the absolute URL.
|
||||
*
|
||||
* @param string $base_url Use this url as base url
|
||||
* @return string
|
||||
*/
|
||||
public function getAbsoluteUrl($base_url = '')
|
||||
{
|
||||
if ($base_url) {
|
||||
$base = new self($base_url);
|
||||
$url = $base->getAbsoluteUrl().substr($this->getFullPath(), 1);
|
||||
} else {
|
||||
$url = $this->hasHost() ? $this->getBaseUrl().$this->getFullPath() : '';
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the url is relative.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isRelativeUrl()
|
||||
{
|
||||
return !$this->hasScheme() && !$this->isProtocolRelative();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the path is relative.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isRelativePath()
|
||||
{
|
||||
$path = $this->getPath();
|
||||
|
||||
return empty($path) || $path[0]
|
||||
!== '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the path of a URI.
|
||||
*
|
||||
* Imported from Guzzle library: https://github.com/guzzle/psr7/blob/master/src/Uri.php#L568-L582
|
||||
*
|
||||
* @param $path
|
||||
* @param string $charUnreserved
|
||||
* @param string $charSubDelims
|
||||
* @return string
|
||||
*/
|
||||
public function filterPath($path, $charUnreserved = 'a-zA-Z0-9_\-\.~', $charSubDelims = '!\$&\'\(\)\*\+,;=')
|
||||
{
|
||||
return preg_replace_callback(
|
||||
'/(?:[^'.$charUnreserved.$charSubDelims.':@\/%]+|%(?![A-Fa-f0-9]{2}))/',
|
||||
function (array $matches) { return rawurlencode($matches[0]); },
|
||||
$path
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPath()
|
||||
{
|
||||
return $this->filterPath(empty($this->components['path']) ? '' : $this->components['path']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base path.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBasePath()
|
||||
{
|
||||
$current_path = $this->getPath();
|
||||
|
||||
$path = $this->isRelativePath() ? '/' : '';
|
||||
$path .= substr($current_path, -1) === '/' ? $current_path : dirname($current_path);
|
||||
|
||||
return preg_replace('/\\\\\/|\/\//', '/', $path.'/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full path (path + querystring + fragment).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFullPath()
|
||||
{
|
||||
$path = $this->isRelativePath() ? '/' : '';
|
||||
$path .= $this->getPath();
|
||||
$path .= empty($this->components['query']) ? '' : '?'.$this->components['query'];
|
||||
$path .= empty($this->components['fragment']) ? '' : '#'.$this->components['fragment'];
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hostname.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHost()
|
||||
{
|
||||
return empty($this->components['host']) ? '' : $this->components['host'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the url has a hostname.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasHost()
|
||||
{
|
||||
return !empty($this->components['host']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scheme.
|
||||
*
|
||||
* @param string $suffix Suffix to add when there is a scheme
|
||||
* @return string
|
||||
*/
|
||||
public function getScheme($suffix = '')
|
||||
{
|
||||
return ($this->hasScheme() ? $this->components['scheme'] : 'http').$suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the scheme.
|
||||
*
|
||||
* @param string $scheme Set a scheme
|
||||
* @return $this
|
||||
*/
|
||||
public function setScheme($scheme)
|
||||
{
|
||||
$this->components['scheme'] = $scheme;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the url has a scheme.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasScheme()
|
||||
{
|
||||
return !empty($this->components['scheme']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the port.
|
||||
*
|
||||
* @param string $prefix Prefix to add when there is a port
|
||||
* @return string
|
||||
*/
|
||||
public function getPort($prefix = '')
|
||||
{
|
||||
return $this->hasPort() ? $prefix.$this->components['port'] : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the url has a port.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasPort()
|
||||
{
|
||||
return !empty($this->components['port']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the url is protocol relative (start with //).
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isProtocolRelative()
|
||||
{
|
||||
return strpos($this->url, '//') === 0;
|
||||
}
|
||||
}
|
||||
102
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Config/Config.php
vendored
Normal file
102
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Config/Config.php
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Config;
|
||||
|
||||
/**
|
||||
* Config class.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*
|
||||
* @method \PicoFeed\Config\Config setAdditionalCurlOptions(array $options)
|
||||
* @method \PicoFeed\Config\Config setClientTimeout(integer $value)
|
||||
* @method \PicoFeed\Config\Config setClientUserAgent(string $value)
|
||||
* @method \PicoFeed\Config\Config setMaxRedirections(integer $value)
|
||||
* @method \PicoFeed\Config\Config setMaxRecursions(integer $value)
|
||||
* @method \PicoFeed\Config\Config setMaxBodySize(integer $value)
|
||||
* @method \PicoFeed\Config\Config setProxyHostname(string $value)
|
||||
* @method \PicoFeed\Config\Config setProxyPort(integer $value)
|
||||
* @method \PicoFeed\Config\Config setProxyUsername(string $value)
|
||||
* @method \PicoFeed\Config\Config setProxyPassword(string $value)
|
||||
* @method \PicoFeed\Config\Config setGrabberRulesFolder(string $value)
|
||||
* @method \PicoFeed\Config\Config setGrabberTimeout(integer $value)
|
||||
* @method \PicoFeed\Config\Config setGrabberUserAgent(string $value)
|
||||
* @method \PicoFeed\Config\Config setParserHashAlgo(string $value)
|
||||
* @method \PicoFeed\Config\Config setContentFiltering(boolean $value)
|
||||
* @method \PicoFeed\Config\Config setTimezone(string $value)
|
||||
* @method \PicoFeed\Config\Config setFilterIframeWhitelist(array $value)
|
||||
* @method \PicoFeed\Config\Config setFilterIntegerAttributes(array $value)
|
||||
* @method \PicoFeed\Config\Config setFilterAttributeOverrides(array $value)
|
||||
* @method \PicoFeed\Config\Config setFilterRequiredAttributes(array $value)
|
||||
* @method \PicoFeed\Config\Config setFilterMediaBlacklist(array $value)
|
||||
* @method \PicoFeed\Config\Config setFilterMediaAttributes(array $value)
|
||||
* @method \PicoFeed\Config\Config setFilterSchemeWhitelist(array $value)
|
||||
* @method \PicoFeed\Config\Config setFilterWhitelistedTags(array $value)
|
||||
* @method \PicoFeed\Config\Config setFilterBlacklistedTags(array $value)
|
||||
* @method \PicoFeed\Config\Config setFilterImageProxyUrl($value)
|
||||
* @method \PicoFeed\Config\Config setFilterImageProxyCallback($closure)
|
||||
* @method \PicoFeed\Config\Config setFilterImageProxyProtocol($value)
|
||||
* @method integer getClientTimeout()
|
||||
* @method string getClientUserAgent()
|
||||
* @method integer getMaxRedirections()
|
||||
* @method integer getMaxRecursions()
|
||||
* @method integer getMaxBodySize()
|
||||
* @method string getProxyHostname()
|
||||
* @method integer getProxyPort()
|
||||
* @method string getProxyUsername()
|
||||
* @method string getProxyPassword()
|
||||
* @method string getGrabberRulesFolder()
|
||||
* @method integer getGrabberTimeout()
|
||||
* @method string getGrabberUserAgent()
|
||||
* @method string getParserHashAlgo()
|
||||
* @method boolean getContentFiltering(bool $default_value)
|
||||
* @method string getTimezone()
|
||||
* @method array getFilterIframeWhitelist(array $default_value)
|
||||
* @method array getFilterIntegerAttributes(array $default_value)
|
||||
* @method array getFilterAttributeOverrides(array $default_value)
|
||||
* @method array getFilterRequiredAttributes(array $default_value)
|
||||
* @method array getFilterMediaBlacklist(array $default_value)
|
||||
* @method array getFilterMediaAttributes(array $default_value)
|
||||
* @method array getFilterSchemeWhitelist(array $default_value)
|
||||
* @method array getFilterWhitelistedTags(array $default_value)
|
||||
* @method array getFilterBlacklistedTags(array $default_value)
|
||||
* @method string getFilterImageProxyUrl()
|
||||
* @method \Closure getFilterImageProxyCallback()
|
||||
* @method string getFilterImageProxyProtocol()
|
||||
* @method array getAdditionalCurlOptions()
|
||||
*/
|
||||
class Config
|
||||
{
|
||||
/**
|
||||
* Contains all parameters.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $container = array();
|
||||
|
||||
/**
|
||||
* Magic method to have any kind of setters or getters.
|
||||
*
|
||||
* @param string $name Getter/Setter name
|
||||
* @param array $arguments Method arguments
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($name, array $arguments)
|
||||
{
|
||||
$name = strtolower($name);
|
||||
$prefix = substr($name, 0, 3);
|
||||
$parameter = substr($name, 3);
|
||||
|
||||
if ($prefix === 'set' && isset($arguments[0])) {
|
||||
$this->container[$parameter] = $arguments[0];
|
||||
|
||||
return $this;
|
||||
} elseif ($prefix === 'get') {
|
||||
$default_value = isset($arguments[0]) ? $arguments[0] : null;
|
||||
|
||||
return isset($this->container[$parameter]) ? $this->container[$parameter] : $default_value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
33
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Encoding/Encoding.php
vendored
Normal file
33
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Encoding/Encoding.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Encoding;
|
||||
|
||||
/**
|
||||
* Encoding class.
|
||||
*/
|
||||
class Encoding
|
||||
{
|
||||
public static function convert($input, $encoding)
|
||||
{
|
||||
if ($encoding === 'utf-8' || $encoding === '') {
|
||||
return $input;
|
||||
}
|
||||
|
||||
// suppress all notices since it isn't possible to silence only the
|
||||
// notice "Wrong charset, conversion from $in_encoding to $out_encoding is not allowed"
|
||||
set_error_handler(function () {}, E_NOTICE);
|
||||
|
||||
// convert input to utf-8 and strip invalid characters
|
||||
$value = iconv($encoding, 'UTF-8//IGNORE', $input);
|
||||
|
||||
// stop silencing of notices
|
||||
restore_error_handler();
|
||||
|
||||
// return input if something went wrong, maybe it's usable anyway
|
||||
if ($value === false) {
|
||||
return $input;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
700
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Filter/Attribute.php
vendored
Normal file
700
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Filter/Attribute.php
vendored
Normal file
@@ -0,0 +1,700 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Filter;
|
||||
|
||||
use PicoFeed\Client\Url;
|
||||
|
||||
/**
|
||||
* Attribute Filter class.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Attribute
|
||||
{
|
||||
/**
|
||||
* Image proxy url.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $image_proxy_url = '';
|
||||
|
||||
/**
|
||||
* Image proxy callback.
|
||||
*
|
||||
* @var \Closure|null
|
||||
*/
|
||||
private $image_proxy_callback = null;
|
||||
|
||||
/**
|
||||
* limits the image proxy usage to this protocol.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $image_proxy_limit_protocol = '';
|
||||
|
||||
/**
|
||||
* Tags and attribute whitelist.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $attribute_whitelist = array(
|
||||
'audio' => array('controls', 'src'),
|
||||
'video' => array('poster', 'controls', 'height', 'width', 'src'),
|
||||
'source' => array('src', 'type'),
|
||||
'dt' => array(),
|
||||
'dd' => array(),
|
||||
'dl' => array(),
|
||||
'table' => array(),
|
||||
'caption' => array(),
|
||||
'tr' => array(),
|
||||
'th' => array(),
|
||||
'td' => array(),
|
||||
'tbody' => array(),
|
||||
'thead' => array(),
|
||||
'h1' => array(),
|
||||
'h2' => array(),
|
||||
'h3' => array(),
|
||||
'h4' => array(),
|
||||
'h5' => array(),
|
||||
'h6' => array(),
|
||||
'strong' => array(),
|
||||
'em' => array(),
|
||||
'code' => array(),
|
||||
'pre' => array(),
|
||||
'blockquote' => array(),
|
||||
'p' => array(),
|
||||
'ul' => array(),
|
||||
'li' => array(),
|
||||
'ol' => array(),
|
||||
'br' => array(),
|
||||
'del' => array(),
|
||||
'a' => array('href'),
|
||||
'img' => array('src', 'title', 'alt'),
|
||||
'figure' => array(),
|
||||
'figcaption' => array(),
|
||||
'cite' => array(),
|
||||
'time' => array('datetime'),
|
||||
'abbr' => array('title'),
|
||||
'iframe' => array('width', 'height', 'frameborder', 'src', 'allowfullscreen'),
|
||||
'q' => array('cite'),
|
||||
);
|
||||
|
||||
/**
|
||||
* Scheme whitelist.
|
||||
*
|
||||
* For a complete list go to http://en.wikipedia.org/wiki/URI_scheme
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $scheme_whitelist = array(
|
||||
'bitcoin:',
|
||||
'callto:',
|
||||
'ed2k://',
|
||||
'facetime://',
|
||||
'feed:',
|
||||
'ftp://',
|
||||
'geo:',
|
||||
'git://',
|
||||
'http://',
|
||||
'https://',
|
||||
'irc://',
|
||||
'irc6://',
|
||||
'ircs://',
|
||||
'jabber:',
|
||||
'magnet:',
|
||||
'mailto:',
|
||||
'nntp://',
|
||||
'rtmp://',
|
||||
'sftp://',
|
||||
'sip:',
|
||||
'sips:',
|
||||
'skype:',
|
||||
'smb://',
|
||||
'sms:',
|
||||
'spotify:',
|
||||
'ssh:',
|
||||
'steam:',
|
||||
'svn://',
|
||||
'tel:',
|
||||
);
|
||||
|
||||
/**
|
||||
* Iframe source whitelist, everything else is ignored.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $iframe_whitelist = array(
|
||||
'http://www.youtube.com',
|
||||
'https://www.youtube.com',
|
||||
'http://player.vimeo.com',
|
||||
'https://player.vimeo.com',
|
||||
'http://www.dailymotion.com',
|
||||
'https://www.dailymotion.com',
|
||||
'http://vk.com',
|
||||
'https://vk.com',
|
||||
);
|
||||
|
||||
/**
|
||||
* Blacklisted resources.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $media_blacklist = array(
|
||||
'api.flattr.com',
|
||||
'feeds.feedburner.com',
|
||||
'share.feedsportal.com',
|
||||
'da.feedsportal.com',
|
||||
'rc.feedsportal.com',
|
||||
'rss.feedsportal.com',
|
||||
'res.feedsportal.com',
|
||||
'res1.feedsportal.com',
|
||||
'res2.feedsportal.com',
|
||||
'res3.feedsportal.com',
|
||||
'pi.feedsportal.com',
|
||||
'rss.nytimes.com',
|
||||
'feeds.wordpress.com',
|
||||
'stats.wordpress.com',
|
||||
'rss.cnn.com',
|
||||
'twitter.com/home?status=',
|
||||
'twitter.com/share',
|
||||
'twitter_icon_large.png',
|
||||
'www.facebook.com/sharer.php',
|
||||
'facebook_icon_large.png',
|
||||
'plus.google.com/share',
|
||||
'www.gstatic.com/images/icons/gplus-16.png',
|
||||
'www.gstatic.com/images/icons/gplus-32.png',
|
||||
'www.gstatic.com/images/icons/gplus-64.png',
|
||||
);
|
||||
|
||||
/**
|
||||
* Attributes used for external resources.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $media_attributes = array(
|
||||
'src',
|
||||
'href',
|
||||
'poster',
|
||||
);
|
||||
|
||||
/**
|
||||
* Attributes that must be integer.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $integer_attributes = array(
|
||||
'width',
|
||||
'height',
|
||||
'frameborder',
|
||||
);
|
||||
|
||||
/**
|
||||
* Mandatory attributes for specified tags.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $required_attributes = array(
|
||||
'a' => array('href'),
|
||||
'img' => array('src'),
|
||||
'iframe' => array('src'),
|
||||
'audio' => array('src'),
|
||||
'source' => array('src'),
|
||||
);
|
||||
|
||||
/**
|
||||
* Add attributes to specified tags.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $add_attributes = array(
|
||||
'a' => array('rel' => 'noreferrer', 'target' => '_blank'),
|
||||
'video' => array('controls' => 'true'),
|
||||
);
|
||||
|
||||
/**
|
||||
* List of filters to apply.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $filters = array(
|
||||
'filterAllowedAttribute',
|
||||
'filterIntegerAttribute',
|
||||
'rewriteAbsoluteUrl',
|
||||
'filterIframeAttribute',
|
||||
'filterBlacklistResourceAttribute',
|
||||
'filterProtocolUrlAttribute',
|
||||
'rewriteImageProxyUrl',
|
||||
'secureIframeSrc',
|
||||
'removeYouTubeAutoplay',
|
||||
);
|
||||
|
||||
/**
|
||||
* Add attributes to specified tags.
|
||||
*
|
||||
* @var \PicoFeed\Client\Url
|
||||
*/
|
||||
private $website;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \PicoFeed\Client\Url $website Website url instance
|
||||
*/
|
||||
public function __construct(Url $website)
|
||||
{
|
||||
$this->website = $website;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply filters to the attributes list.
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @param array $attributes Attributes dictionary
|
||||
*
|
||||
* @return array Filtered attributes
|
||||
*/
|
||||
public function filter($tag, array $attributes)
|
||||
{
|
||||
foreach ($attributes as $attribute => &$value) {
|
||||
foreach ($this->filters as $filter) {
|
||||
if (!$this->$filter($tag, $attribute, $value)) {
|
||||
unset($attributes[$attribute]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the value is allowed (remove not allowed attributes).
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @param string $attribute Attribute name
|
||||
* @param string $value Attribute value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function filterAllowedAttribute($tag, $attribute, $value)
|
||||
{
|
||||
return isset($this->attribute_whitelist[$tag]) && in_array($attribute, $this->attribute_whitelist[$tag]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the value is not integer (remove attributes that should have an integer value).
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @param string $attribute Attribute name
|
||||
* @param string $value Attribute value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function filterIntegerAttribute($tag, $attribute, $value)
|
||||
{
|
||||
if (in_array($attribute, $this->integer_attributes)) {
|
||||
return ctype_digit($value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the iframe source is allowed (remove not allowed iframe).
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @param string $attribute Attribute name
|
||||
* @param string $value Attribute value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function filterIframeAttribute($tag, $attribute, $value)
|
||||
{
|
||||
if ($tag === 'iframe' && $attribute === 'src') {
|
||||
foreach ($this->iframe_whitelist as $url) {
|
||||
if (strpos($value, $url) === 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the resource is not blacklisted (remove blacklisted resource attributes).
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @param string $attribute Attribute name
|
||||
* @param string $value Attribute value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function filterBlacklistResourceAttribute($tag, $attribute, $value)
|
||||
{
|
||||
if ($this->isResource($attribute) && $this->isBlacklistedMedia($value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert all relative links to absolute url.
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @param string $attribute Attribute name
|
||||
* @param string $value Attribute value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function rewriteAbsoluteUrl($tag, $attribute, &$value)
|
||||
{
|
||||
if ($this->isResource($attribute)) {
|
||||
$value = Url::resolve($value, $this->website);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns iframes' src attribute from http to https to prevent
|
||||
* mixed active content.
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @param array $attribute Atttributes name
|
||||
* @param string $value Attribute value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function secureIframeSrc($tag, $attribute, &$value)
|
||||
{
|
||||
if ($tag === 'iframe' && $attribute === 'src' && strpos($value, 'http://') === 0) {
|
||||
$value = substr_replace($value, 's', 4, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes YouTube autoplay from iframes.
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @param array $attribute Atttributes name
|
||||
* @param string $value Attribute value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function removeYouTubeAutoplay($tag, $attribute, &$value)
|
||||
{
|
||||
$regex = '%^(https://(?:www\.)?youtube.com/.*\?.*autoplay=)(1)(.*)%i';
|
||||
if ($tag === 'iframe' && $attribute === 'src' && preg_match($regex, $value)) {
|
||||
$value = preg_replace($regex, '${1}0$3', $value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrite image url to use with a proxy.
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @param string $attribute Attribute name
|
||||
* @param string $value Attribute value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function rewriteImageProxyUrl($tag, $attribute, &$value)
|
||||
{
|
||||
if ($tag === 'img' && $attribute === 'src'
|
||||
&& !($this->image_proxy_limit_protocol !== '' && stripos($value, $this->image_proxy_limit_protocol.':') !== 0)) {
|
||||
if ($this->image_proxy_url) {
|
||||
$value = sprintf($this->image_proxy_url, rawurlencode($value));
|
||||
} elseif (is_callable($this->image_proxy_callback)) {
|
||||
$value = call_user_func($this->image_proxy_callback, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the scheme is authorized.
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @param string $attribute Attribute name
|
||||
* @param string $value Attribute value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function filterProtocolUrlAttribute($tag, $attribute, $value)
|
||||
{
|
||||
if ($this->isResource($attribute) && !$this->isAllowedProtocol($value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically add/override some attributes for specific tags.
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @param array $attributes Attributes list
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function addAttributes($tag, array $attributes)
|
||||
{
|
||||
if (isset($this->add_attributes[$tag])) {
|
||||
$attributes += $this->add_attributes[$tag];
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if all required attributes are present.
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @param array $attributes Attributes list
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasRequiredAttributes($tag, array $attributes)
|
||||
{
|
||||
if (isset($this->required_attributes[$tag])) {
|
||||
foreach ($this->required_attributes[$tag] as $attribute) {
|
||||
if (!isset($attributes[$attribute])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an attribute name is an external resource.
|
||||
*
|
||||
* @param string $attribute Attribute name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isResource($attribute)
|
||||
{
|
||||
return in_array($attribute, $this->media_attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect if the protocol is allowed or not.
|
||||
*
|
||||
* @param string $value Attribute value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAllowedProtocol($value)
|
||||
{
|
||||
foreach ($this->scheme_whitelist as $protocol) {
|
||||
if (strpos($value, $protocol) === 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect if an url is blacklisted.
|
||||
*
|
||||
* @param string $resource Attribute value (URL)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isBlacklistedMedia($resource)
|
||||
{
|
||||
foreach ($this->media_blacklist as $name) {
|
||||
if (strpos($resource, $name) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the attribute list to html.
|
||||
*
|
||||
* @param array $attributes Attributes
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toHtml(array $attributes)
|
||||
{
|
||||
$html = array();
|
||||
|
||||
foreach ($attributes as $attribute => $value) {
|
||||
$html[] = sprintf('%s="%s"', $attribute, Filter::escape($value));
|
||||
}
|
||||
|
||||
return implode(' ', $html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whitelisted tags and attributes for each tag.
|
||||
*
|
||||
* @param array $values List of tags: ['video' => ['src', 'cover'], 'img' => ['src']]
|
||||
*
|
||||
* @return Attribute
|
||||
*/
|
||||
public function setWhitelistedAttributes(array $values)
|
||||
{
|
||||
$this->attribute_whitelist = $values ?: $this->attribute_whitelist;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set scheme whitelist.
|
||||
*
|
||||
* @param array $values List of scheme: ['http://', 'ftp://']
|
||||
*
|
||||
* @return Attribute
|
||||
*/
|
||||
public function setSchemeWhitelist(array $values)
|
||||
{
|
||||
$this->scheme_whitelist = $values ?: $this->scheme_whitelist;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set media attributes (used to load external resources).
|
||||
*
|
||||
* @param array $values List of values: ['src', 'href']
|
||||
*
|
||||
* @return Attribute
|
||||
*/
|
||||
public function setMediaAttributes(array $values)
|
||||
{
|
||||
$this->media_attributes = $values ?: $this->media_attributes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set blacklisted external resources.
|
||||
*
|
||||
* @param array $values List of tags: ['http://google.com/', '...']
|
||||
*
|
||||
* @return Attribute
|
||||
*/
|
||||
public function setMediaBlacklist(array $values)
|
||||
{
|
||||
$this->media_blacklist = $values ?: $this->media_blacklist;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set mandatory attributes for whitelisted tags.
|
||||
*
|
||||
* @param array $values List of tags: ['img' => 'src']
|
||||
*
|
||||
* @return Attribute
|
||||
*/
|
||||
public function setRequiredAttributes(array $values)
|
||||
{
|
||||
$this->required_attributes = $values ?: $this->required_attributes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set attributes to automatically to specific tags.
|
||||
*
|
||||
* @param array $values List of tags: ['a' => 'target="_blank"']
|
||||
*
|
||||
* @return Attribute
|
||||
*/
|
||||
public function setAttributeOverrides(array $values)
|
||||
{
|
||||
$this->add_attributes = $values ?: $this->add_attributes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set attributes that must be an integer.
|
||||
*
|
||||
* @param array $values List of tags: ['width', 'height']
|
||||
*
|
||||
* @return Attribute
|
||||
*/
|
||||
public function setIntegerAttributes(array $values)
|
||||
{
|
||||
$this->integer_attributes = $values ?: $this->integer_attributes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set allowed iframe resources.
|
||||
*
|
||||
* @param array $values List of tags: ['http://www.youtube.com']
|
||||
*
|
||||
* @return Attribute
|
||||
*/
|
||||
public function setIframeWhitelist(array $values)
|
||||
{
|
||||
$this->iframe_whitelist = $values ?: $this->iframe_whitelist;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set image proxy URL.
|
||||
*
|
||||
* The original image url will be urlencoded
|
||||
*
|
||||
* @param string $url Proxy URL
|
||||
*
|
||||
* @return Attribute
|
||||
*/
|
||||
public function setImageProxyUrl($url)
|
||||
{
|
||||
$this->image_proxy_url = $url ?: $this->image_proxy_url;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set image proxy callback.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
*
|
||||
* @return Attribute
|
||||
*/
|
||||
public function setImageProxyCallback($callback)
|
||||
{
|
||||
$this->image_proxy_callback = $callback ?: $this->image_proxy_callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set image proxy protocol restriction.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return Attribute
|
||||
*/
|
||||
public function setImageProxyProtocol($value)
|
||||
{
|
||||
$this->image_proxy_limit_protocol = $value ?: $this->image_proxy_limit_protocol;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
144
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Filter/Filter.php
vendored
Normal file
144
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Filter/Filter.php
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Filter;
|
||||
|
||||
/**
|
||||
* Filter class.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Filter
|
||||
{
|
||||
/**
|
||||
* Get the Html filter instance.
|
||||
*
|
||||
* @static
|
||||
* @param string $html HTML content
|
||||
* @param string $website Site URL (used to build absolute URL)
|
||||
* @return Html
|
||||
*/
|
||||
public static function html($html, $website)
|
||||
{
|
||||
$filter = new Html($html, $website);
|
||||
|
||||
return $filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape HTML content.
|
||||
*
|
||||
* @static
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
public static function escape($content)
|
||||
{
|
||||
return htmlspecialchars($content, ENT_QUOTES, 'UTF-8', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove HTML tags.
|
||||
*
|
||||
* @param string $data Input data
|
||||
* @return string
|
||||
*/
|
||||
public function removeHTMLTags($data)
|
||||
{
|
||||
return preg_replace('~<(?:!DOCTYPE|/?(?:html|head|body))[^>]*>\s*~i', '', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the XML tag from a document.
|
||||
*
|
||||
* @static
|
||||
* @param string $data Input data
|
||||
* @return string
|
||||
*/
|
||||
public static function stripXmlTag($data)
|
||||
{
|
||||
if (strpos($data, '<?xml') !== false) {
|
||||
$data = ltrim(substr($data, strpos($data, '?>') + 2));
|
||||
}
|
||||
|
||||
do {
|
||||
$pos = strpos($data, '<?xml-stylesheet ');
|
||||
|
||||
if ($pos !== false) {
|
||||
$data = ltrim(substr($data, strpos($data, '?>') + 2));
|
||||
}
|
||||
} while ($pos !== false && $pos < 200);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip head tag from the HTML content.
|
||||
*
|
||||
* @static
|
||||
* @param string $data Input data
|
||||
* @return string
|
||||
*/
|
||||
public static function stripHeadTags($data)
|
||||
{
|
||||
return preg_replace('@<head[^>]*?>.*?</head>@siu', '', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim whitespace from the begining, the end and inside a string and don't break utf-8 string.
|
||||
*
|
||||
* @static
|
||||
* @param string $value Raw data
|
||||
* @return string Normalized data
|
||||
*/
|
||||
public static function stripWhiteSpace($value)
|
||||
{
|
||||
$value = str_replace("\r", ' ', $value);
|
||||
$value = str_replace("\t", ' ', $value);
|
||||
$value = str_replace("\n", ' ', $value);
|
||||
// $value = preg_replace('/\s+/', ' ', $value); <= break utf-8
|
||||
return trim($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes before XML parsing.
|
||||
*
|
||||
* @static
|
||||
* @param string $data Raw data
|
||||
* @return string Normalized data
|
||||
*/
|
||||
public static function normalizeData($data)
|
||||
{
|
||||
$entities = array(
|
||||
'/(&#)(\d+);/m', // decimal encoded
|
||||
'/(&#x)([a-f0-9]+);/mi', // hex encoded
|
||||
);
|
||||
|
||||
// strip invalid XML 1.0 characters which are encoded as entities
|
||||
$data = preg_replace_callback($entities, function ($matches) {
|
||||
$code_point = $matches[2];
|
||||
|
||||
// convert hex entity to decimal
|
||||
if (strtolower($matches[1]) === '&#x') {
|
||||
$code_point = hexdec($code_point);
|
||||
}
|
||||
|
||||
$code_point = (int) $code_point;
|
||||
|
||||
// replace invalid characters
|
||||
if ($code_point < 9
|
||||
|| ($code_point > 10 && $code_point < 13)
|
||||
|| ($code_point > 13 && $code_point < 32)
|
||||
|| ($code_point > 55295 && $code_point < 57344)
|
||||
|| ($code_point > 65533 && $code_point < 65536)
|
||||
|| $code_point > 1114111
|
||||
) {
|
||||
return '';
|
||||
};
|
||||
|
||||
return $matches[0];
|
||||
}, $data);
|
||||
|
||||
// strip every utf-8 character than isn't in the range of valid XML 1.0 characters
|
||||
return (string) preg_replace('/[^\x{0009}\x{000A}\x{000D}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]/u', '', $data);
|
||||
}
|
||||
}
|
||||
243
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Filter/Html.php
vendored
Normal file
243
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Filter/Html.php
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Filter;
|
||||
|
||||
use PicoFeed\Config\Config;
|
||||
use PicoFeed\Client\Url;
|
||||
use PicoFeed\Scraper\RuleLoader;
|
||||
use PicoFeed\Parser\XmlParser;
|
||||
|
||||
/**
|
||||
* HTML Filter class.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Html
|
||||
{
|
||||
/**
|
||||
* Config object.
|
||||
*
|
||||
* @var \PicoFeed\Config\Config
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* Unfiltered XML data.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $input = '';
|
||||
|
||||
/**
|
||||
* Filtered XML data.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $output = '';
|
||||
|
||||
/**
|
||||
* List of empty tags.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $empty_tags = array();
|
||||
|
||||
/**
|
||||
* Empty flag.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $empty = true;
|
||||
|
||||
/**
|
||||
* Tag instance.
|
||||
*
|
||||
* @var \PicoFeed\Filter\Tag
|
||||
*/
|
||||
public $tag = '';
|
||||
|
||||
/**
|
||||
* Attribute instance.
|
||||
*
|
||||
* @var \PicoFeed\Filter\Attribute
|
||||
*/
|
||||
public $attribute = '';
|
||||
|
||||
/**
|
||||
* The website to filter.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $website;
|
||||
|
||||
/**
|
||||
* Initialize the filter, all inputs data must be encoded in UTF-8 before.
|
||||
*
|
||||
* @param string $html HTML content
|
||||
* @param string $website Site URL (used to build absolute URL)
|
||||
*/
|
||||
public function __construct($html, $website)
|
||||
{
|
||||
$this->config = new Config();
|
||||
$this->input = XmlParser::htmlToXml($html);
|
||||
$this->output = '';
|
||||
$this->tag = new Tag($this->config);
|
||||
$this->website = $website;
|
||||
$this->attribute = new Attribute(new Url($website));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set config object.
|
||||
*
|
||||
* @param \PicoFeed\Config\Config $config Config instance
|
||||
* @return \PicoFeed\Filter\Html
|
||||
*/
|
||||
public function setConfig($config)
|
||||
{
|
||||
$this->config = $config;
|
||||
|
||||
if ($this->config !== null) {
|
||||
$this->attribute->setImageProxyCallback($this->config->getFilterImageProxyCallback());
|
||||
$this->attribute->setImageProxyUrl($this->config->getFilterImageProxyUrl());
|
||||
$this->attribute->setImageProxyProtocol($this->config->getFilterImageProxyProtocol());
|
||||
$this->attribute->setIframeWhitelist($this->config->getFilterIframeWhitelist(array()));
|
||||
$this->attribute->setIntegerAttributes($this->config->getFilterIntegerAttributes(array()));
|
||||
$this->attribute->setAttributeOverrides($this->config->getFilterAttributeOverrides(array()));
|
||||
$this->attribute->setRequiredAttributes($this->config->getFilterRequiredAttributes(array()));
|
||||
$this->attribute->setMediaBlacklist($this->config->getFilterMediaBlacklist(array()));
|
||||
$this->attribute->setMediaAttributes($this->config->getFilterMediaAttributes(array()));
|
||||
$this->attribute->setSchemeWhitelist($this->config->getFilterSchemeWhitelist(array()));
|
||||
$this->attribute->setWhitelistedAttributes($this->config->getFilterWhitelistedTags(array()));
|
||||
$this->tag->setWhitelistedTags(array_keys($this->config->getFilterWhitelistedTags(array())));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run tags/attributes filtering.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$this->preFilter();
|
||||
|
||||
$parser = xml_parser_create();
|
||||
|
||||
xml_set_object($parser, $this);
|
||||
xml_set_element_handler($parser, 'startTag', 'endTag');
|
||||
xml_set_character_data_handler($parser, 'dataTag');
|
||||
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
|
||||
xml_parse($parser, $this->input, true);
|
||||
xml_parser_free($parser);
|
||||
|
||||
$this->postFilter();
|
||||
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before XML parsing.
|
||||
*/
|
||||
public function preFilter()
|
||||
{
|
||||
$this->input = $this->tag->removeBlacklistedTags($this->input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after XML parsing.
|
||||
*/
|
||||
public function postFilter()
|
||||
{
|
||||
$this->output = $this->tag->removeEmptyTags($this->output);
|
||||
$this->output = $this->filterRules($this->output);
|
||||
$this->output = $this->tag->removeMultipleBreakTags($this->output);
|
||||
$this->output = trim($this->output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after XML parsing.
|
||||
*
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
public function filterRules($content)
|
||||
{
|
||||
// the constructor should require a config, then this if can be removed
|
||||
if ($this->config === null) {
|
||||
$config = new Config();
|
||||
} else {
|
||||
$config = $this->config;
|
||||
}
|
||||
|
||||
$loader = new RuleLoader($config);
|
||||
$rules = $loader->getRules($this->website);
|
||||
|
||||
$url = new Url($this->website);
|
||||
$sub_url = $url->getFullPath();
|
||||
|
||||
if (isset($rules['filter'])) {
|
||||
foreach ($rules['filter'] as $pattern => $rule) {
|
||||
if (preg_match($pattern, $sub_url)) {
|
||||
foreach ($rule as $search => $replace) {
|
||||
$content = preg_replace($search, $replace, $content);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse opening tag.
|
||||
*
|
||||
* @param resource $parser XML parser
|
||||
* @param string $tag Tag name
|
||||
* @param array $attributes Tag attributes
|
||||
*/
|
||||
public function startTag($parser, $tag, array $attributes)
|
||||
{
|
||||
$this->empty = true;
|
||||
|
||||
if ($this->tag->isAllowed($tag, $attributes)) {
|
||||
$attributes = $this->attribute->filter($tag, $attributes);
|
||||
|
||||
if ($this->attribute->hasRequiredAttributes($tag, $attributes)) {
|
||||
$attributes = $this->attribute->addAttributes($tag, $attributes);
|
||||
|
||||
$this->output .= $this->tag->openHtmlTag($tag, $this->attribute->toHtml($attributes));
|
||||
$this->empty = false;
|
||||
}
|
||||
}
|
||||
|
||||
$this->empty_tags[] = $this->empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse closing tag.
|
||||
*
|
||||
* @param resource $parser XML parser
|
||||
* @param string $tag Tag name
|
||||
*/
|
||||
public function endTag($parser, $tag)
|
||||
{
|
||||
if (!array_pop($this->empty_tags) && $this->tag->isAllowedTag($tag)) {
|
||||
$this->output .= $this->tag->closeHtmlTag($tag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse tag content.
|
||||
*
|
||||
* @param resource $parser XML parser
|
||||
* @param string $content Tag content
|
||||
*/
|
||||
public function dataTag($parser, $content)
|
||||
{
|
||||
// Replace with normal space
|
||||
$content = str_replace("\xc2\xa0", ' ', $content);
|
||||
$this->output .= Filter::escape($content);
|
||||
}
|
||||
}
|
||||
208
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Filter/Tag.php
vendored
Normal file
208
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Filter/Tag.php
vendored
Normal file
@@ -0,0 +1,208 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Filter;
|
||||
|
||||
use DOMXPath;
|
||||
use PicoFeed\Base;
|
||||
use PicoFeed\Parser\XmlParser;
|
||||
|
||||
/**
|
||||
* Tag Filter class.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Tag extends Base
|
||||
{
|
||||
/**
|
||||
* Tags blacklist (Xpath expressions).
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $tag_blacklist = array(
|
||||
'//script',
|
||||
'//style',
|
||||
);
|
||||
|
||||
/**
|
||||
* Tags whitelist.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $tag_whitelist = array(
|
||||
'audio',
|
||||
'video',
|
||||
'source',
|
||||
'dt',
|
||||
'dd',
|
||||
'dl',
|
||||
'table',
|
||||
'caption',
|
||||
'tr',
|
||||
'th',
|
||||
'td',
|
||||
'tbody',
|
||||
'thead',
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'h4',
|
||||
'h5',
|
||||
'h6',
|
||||
'strong',
|
||||
'em',
|
||||
'code',
|
||||
'pre',
|
||||
'blockquote',
|
||||
'p',
|
||||
'ul',
|
||||
'li',
|
||||
'ol',
|
||||
'br',
|
||||
'del',
|
||||
'a',
|
||||
'img',
|
||||
'figure',
|
||||
'figcaption',
|
||||
'cite',
|
||||
'time',
|
||||
'abbr',
|
||||
'iframe',
|
||||
'q',
|
||||
'sup',
|
||||
'sub',
|
||||
);
|
||||
|
||||
/**
|
||||
* Check if the tag is allowed and is not a pixel tracker.
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @param array $attributes Attributes dictionary
|
||||
* @return bool
|
||||
*/
|
||||
public function isAllowed($tag, array $attributes)
|
||||
{
|
||||
return $this->isAllowedTag($tag) && !$this->isPixelTracker($tag, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the HTML opening tag.
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @param string $attributes Attributes converted in html
|
||||
* @return string
|
||||
*/
|
||||
public function openHtmlTag($tag, $attributes = '')
|
||||
{
|
||||
return '<'.$tag.(empty($attributes) ? '' : ' '.$attributes).($this->isSelfClosingTag($tag) ? '/>' : '>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the HTML closing tag.
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @return string
|
||||
*/
|
||||
public function closeHtmlTag($tag)
|
||||
{
|
||||
return $this->isSelfClosingTag($tag) ? '' : '</'.$tag.'>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true is the tag is self-closing.
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @return bool
|
||||
*/
|
||||
public function isSelfClosingTag($tag)
|
||||
{
|
||||
return $tag === 'br' || $tag === 'img';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a tag is on the whitelist.
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @return bool
|
||||
*/
|
||||
public function isAllowedTag($tag)
|
||||
{
|
||||
return in_array($tag, array_merge(
|
||||
$this->tag_whitelist,
|
||||
array_keys($this->config->getFilterWhitelistedTags(array()))
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect if an image tag is a pixel tracker.
|
||||
*
|
||||
* @param string $tag Tag name
|
||||
* @param array $attributes Tag attributes
|
||||
* @return bool
|
||||
*/
|
||||
public function isPixelTracker($tag, array $attributes)
|
||||
{
|
||||
return $tag === 'img' &&
|
||||
isset($attributes['height']) && isset($attributes['width']) &&
|
||||
$attributes['height'] == 1 && $attributes['width'] == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove script tags.
|
||||
*
|
||||
* @param string $data Input data
|
||||
* @return string
|
||||
*/
|
||||
public function removeBlacklistedTags($data)
|
||||
{
|
||||
$dom = XmlParser::getDomDocument($data);
|
||||
|
||||
if ($dom === false) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$xpath = new DOMXpath($dom);
|
||||
|
||||
$nodes = $xpath->query(implode(' | ', $this->tag_blacklist));
|
||||
|
||||
foreach ($nodes as $node) {
|
||||
$node->parentNode->removeChild($node);
|
||||
}
|
||||
|
||||
return $dom->saveXML();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove empty tags.
|
||||
*
|
||||
* @param string $data Input data
|
||||
* @return string
|
||||
*/
|
||||
public function removeEmptyTags($data)
|
||||
{
|
||||
return preg_replace('/<([^<\/>]*)>([\s]*?|(?R))<\/\1>/imsU', '', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace <br/><br/> by only one.
|
||||
*
|
||||
* @param string $data Input data
|
||||
* @return string
|
||||
*/
|
||||
public function removeMultipleBreakTags($data)
|
||||
{
|
||||
return preg_replace("/(<br\s*\/?>\s*)+/", '<br/>', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whitelisted tags adn attributes for each tag.
|
||||
*
|
||||
* @param array $values List of tags: ['video' => ['src', 'cover'], 'img' => ['src']]
|
||||
* @return Tag
|
||||
*/
|
||||
public function setWhitelistedTags(array $values)
|
||||
{
|
||||
$this->tag_whitelist = $values ?: $this->tag_whitelist;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
23
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Generator/ContentGeneratorInterface.php
vendored
Normal file
23
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Generator/ContentGeneratorInterface.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Generator;
|
||||
|
||||
use PicoFeed\Parser\Item;
|
||||
|
||||
/**
|
||||
* Content Generator Interface
|
||||
*
|
||||
* @package PicoFeed\Generator
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
interface ContentGeneratorInterface
|
||||
{
|
||||
/**
|
||||
* Execute Content Generator
|
||||
*
|
||||
* @access public
|
||||
* @param Item $item
|
||||
* @return boolean
|
||||
*/
|
||||
public function execute(Item $item);
|
||||
}
|
||||
36
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Generator/FileContentGenerator.php
vendored
Normal file
36
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Generator/FileContentGenerator.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Generator;
|
||||
|
||||
use PicoFeed\Base;
|
||||
use PicoFeed\Parser\Item;
|
||||
|
||||
/**
|
||||
* File Content Generator
|
||||
*
|
||||
* @package PicoFeed\Generator
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class FileContentGenerator extends Base implements ContentGeneratorInterface
|
||||
{
|
||||
private $extensions = array('pdf');
|
||||
|
||||
/**
|
||||
* Execute Content Generator
|
||||
*
|
||||
* @access public
|
||||
* @param Item $item
|
||||
* @return boolean
|
||||
*/
|
||||
public function execute(Item $item)
|
||||
{
|
||||
foreach ($this->extensions as $extension) {
|
||||
if (substr($item->getUrl(), - strlen($extension)) === $extension) {
|
||||
$item->setContent('<a href="'.$item->getUrl().'" target="_blank">'.$item->getUrl().'</a>');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
67
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Generator/YoutubeContentGenerator.php
vendored
Normal file
67
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Generator/YoutubeContentGenerator.php
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Generator;
|
||||
|
||||
use PicoFeed\Base;
|
||||
use PicoFeed\Parser\Item;
|
||||
|
||||
/**
|
||||
* Youtube Content Generator
|
||||
*
|
||||
* @package PicoFeed\Generator
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class YoutubeContentGenerator extends Base implements ContentGeneratorInterface
|
||||
{
|
||||
/**
|
||||
* Execute Content Generator
|
||||
*
|
||||
* @access public
|
||||
* @param Item $item
|
||||
* @return boolean
|
||||
*/
|
||||
public function execute(Item $item)
|
||||
{
|
||||
if ($item->hasNamespace('yt')) {
|
||||
return $this->generateHtmlFromXml($item);
|
||||
}
|
||||
|
||||
return $this->generateHtmlFromUrl($item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate HTML
|
||||
*
|
||||
* @access public
|
||||
* @param Item $item
|
||||
* @return boolean
|
||||
*/
|
||||
private function generateHtmlFromXml(Item $item)
|
||||
{
|
||||
$videoId = $item->getTag('yt:videoId');
|
||||
|
||||
if (! empty($videoId)) {
|
||||
$item->setContent('<iframe width="560" height="315" src="//www.youtube.com/embed/'.$videoId[0].'" frameborder="0"></iframe>');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate HTML from item URL
|
||||
*
|
||||
* @access public
|
||||
* @param Item $item
|
||||
* @return bool
|
||||
*/
|
||||
public function generateHtmlFromUrl(Item $item)
|
||||
{
|
||||
if (preg_match('/youtube\.com\/watch\?v=(.*)/', $item->getUrl(), $matches)) {
|
||||
$item->setContent('<iframe width="560" height="315" src="//www.youtube.com/embed/'.$matches[1].'" frameborder="0"></iframe>');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
114
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Logging/Logger.php
vendored
Normal file
114
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Logging/Logger.php
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Logging;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeZone;
|
||||
|
||||
/**
|
||||
* Logging class.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Logger
|
||||
{
|
||||
/**
|
||||
* List of messages.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $messages = array();
|
||||
|
||||
/**
|
||||
* Default timezone.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $timezone = 'UTC';
|
||||
|
||||
/**
|
||||
* Enable or disable logging.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public static $enable = false;
|
||||
|
||||
/**
|
||||
* Enable logging.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
public static function enable()
|
||||
{
|
||||
self::$enable = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new message.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @param string $message Message
|
||||
*/
|
||||
public static function setMessage($message)
|
||||
{
|
||||
if (self::$enable) {
|
||||
$date = new DateTime('now', new DateTimeZone(self::$timezone));
|
||||
self::$messages[] = '['.$date->format('Y-m-d H:i:s').'] '.$message;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all logged messages.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getMessages()
|
||||
{
|
||||
return self::$messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all logged messages.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
public static function deleteMessages()
|
||||
{
|
||||
self::$messages = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a different timezone.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @see http://php.net/manual/en/timezones.php
|
||||
*
|
||||
* @param string $timezone Timezone
|
||||
*/
|
||||
public static function setTimeZone($timezone)
|
||||
{
|
||||
self::$timezone = $timezone ?: self::$timezone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all messages serialized into a string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function toString()
|
||||
{
|
||||
return implode(PHP_EOL, self::$messages).PHP_EOL;
|
||||
}
|
||||
}
|
||||
395
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Atom.php
vendored
Normal file
395
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Atom.php
vendored
Normal file
@@ -0,0 +1,395 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Parser;
|
||||
|
||||
use SimpleXMLElement;
|
||||
use PicoFeed\Filter\Filter;
|
||||
use PicoFeed\Client\Url;
|
||||
|
||||
/**
|
||||
* Atom parser.
|
||||
*
|
||||
* @package PicoFeed\Parser
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Atom extends Parser
|
||||
{
|
||||
/**
|
||||
* Supported namespaces.
|
||||
*/
|
||||
protected $namespaces = array(
|
||||
'atom' => 'http://www.w3.org/2005/Atom',
|
||||
);
|
||||
|
||||
/**
|
||||
* Get the path to the items XML tree.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @return SimpleXMLElement[]
|
||||
*/
|
||||
public function getItemsTree(SimpleXMLElement $xml)
|
||||
{
|
||||
return XmlParser::getXPathResult($xml, 'atom:entry', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'entry');
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed url.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedUrl(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$feed->setFeedUrl($this->getUrl($xml, 'self'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the site url.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findSiteUrl(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$feed->setSiteUrl($this->getUrl($xml, 'alternate', true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed description.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedDescription(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$description = XmlParser::getXPathResult($xml, 'atom:subtitle', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'subtitle');
|
||||
|
||||
$feed->setDescription(XmlParser::getValue($description));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed logo url.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedLogo(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$logo = XmlParser::getXPathResult($xml, 'atom:logo', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'logo');
|
||||
|
||||
$feed->setLogo(XmlParser::getValue($logo));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed icon.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedIcon(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$icon = XmlParser::getXPathResult($xml, 'atom:icon', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'icon');
|
||||
|
||||
$feed->setIcon(XmlParser::getValue($icon));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed title.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedTitle(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$title = XmlParser::getXPathResult($xml, 'atom:title', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'title');
|
||||
|
||||
$feed->setTitle(Filter::stripWhiteSpace(XmlParser::getValue($title)) ?: $feed->getSiteUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed language.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedLanguage(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$language = XmlParser::getXPathResult($xml, '*[not(self::atom:entry)]/@xml:lang', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, '@xml:lang');
|
||||
|
||||
$feed->setLanguage(XmlParser::getValue($language));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed id.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedId(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$id = XmlParser::getXPathResult($xml, 'atom:id', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'id');
|
||||
|
||||
$feed->setId(XmlParser::getValue($id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed date.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedDate(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$updated = XmlParser::getXPathResult($xml, 'atom:updated', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'updated');
|
||||
|
||||
$feed->setDate($this->getDateParser()->getDateTime(XmlParser::getValue($updated)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item published date.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findItemPublishedDate(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
$date = XmlParser::getXPathResult($entry, 'atom:published', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($entry, 'published');
|
||||
|
||||
$item->setPublishedDate(!empty($date) ? $this->getDateParser()->getDateTime((string) current($date)) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item updated date.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findItemUpdatedDate(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
$date = XmlParser::getXPathResult($entry, 'atom:updated', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($entry, 'updated');
|
||||
|
||||
$item->setUpdatedDate(!empty($date) ? $this->getDateParser()->getDateTime((string) current($date)) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item title.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
*/
|
||||
public function findItemTitle(SimpleXMLElement $entry, Item $item)
|
||||
{
|
||||
$title = XmlParser::getXPathResult($entry, 'atom:title', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($entry, 'title');
|
||||
|
||||
$item->setTitle(Filter::stripWhiteSpace(XmlParser::getValue($title)) ?: $item->getUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item author.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
*/
|
||||
public function findItemAuthor(SimpleXMLElement $xml, SimpleXMLElement $entry, Item $item)
|
||||
{
|
||||
$author = XmlParser::getXPathResult($entry, 'atom:author/atom:name', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($entry, 'author/name')
|
||||
?: XmlParser::getXPathResult($xml, 'atom:author/atom:name', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'author/name');
|
||||
|
||||
$item->setAuthor(XmlParser::getValue($author));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item author URL.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
*/
|
||||
public function findItemAuthorUrl(SimpleXMLElement $xml, SimpleXMLElement $entry, Item $item)
|
||||
{
|
||||
$authorUrl = XmlParser::getXPathResult($entry, 'atom:author/atom:uri', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($entry, 'author/uri')
|
||||
?: XmlParser::getXPathResult($xml, 'atom:author/atom:uri', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'author/uri');
|
||||
|
||||
$item->setAuthorUrl(XmlParser::getValue($authorUrl));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item content.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
*/
|
||||
public function findItemContent(SimpleXMLElement $entry, Item $item)
|
||||
{
|
||||
$item->setContent($this->getContent($entry));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item URL.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
*/
|
||||
public function findItemUrl(SimpleXMLElement $entry, Item $item)
|
||||
{
|
||||
$item->setUrl($this->getUrl($entry, 'alternate', true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Genereate the item id.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findItemId(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
$id = XmlParser::getXPathResult($entry, 'atom:id', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($entry, 'id');
|
||||
|
||||
if (!empty($id)) {
|
||||
$item->setId($this->generateId(XmlParser::getValue($id)));
|
||||
} else {
|
||||
$item->setId($this->generateId(
|
||||
$item->getTitle(), $item->getUrl(), $item->getContent()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item enclosure.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findItemEnclosure(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
$enclosure = $this->findLink($entry, 'enclosure');
|
||||
|
||||
if ($enclosure) {
|
||||
$item->setEnclosureUrl(Url::resolve((string) $enclosure['href'], $feed->getSiteUrl()));
|
||||
$item->setEnclosureType((string) $enclosure['type']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item language.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findItemLanguage(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
$language = XmlParser::getXPathResult($entry, './/@xml:lang');
|
||||
$item->setLanguage(XmlParser::getValue($language) ?: $feed->getLanguage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item categories.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function findItemCategories(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
$categories = XmlParser::getXPathResult($entry, 'atom:category/@term', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($entry, 'category/@term');
|
||||
$item->setCategoriesFromXml($categories);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL from a link tag.
|
||||
*
|
||||
* @param SimpleXMLElement $xml XML tag
|
||||
* @param string $rel Link relationship: alternate, enclosure, related, self, via
|
||||
* @return string
|
||||
*/
|
||||
private function getUrl(SimpleXMLElement $xml, $rel, $fallback = false)
|
||||
{
|
||||
$link = $this->findLink($xml, $rel);
|
||||
|
||||
if ($link) {
|
||||
return (string) $link['href'];
|
||||
}
|
||||
|
||||
if ($fallback) {
|
||||
$link = $this->findLink($xml, '');
|
||||
return $link ? (string) $link['href'] : '';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a link tag that match a relationship.
|
||||
*
|
||||
* @param SimpleXMLElement $xml XML tag
|
||||
* @param string $rel Link relationship: alternate, enclosure, related, self, via
|
||||
* @return SimpleXMLElement|null
|
||||
*/
|
||||
private function findLink(SimpleXMLElement $xml, $rel)
|
||||
{
|
||||
$links = XmlParser::getXPathResult($xml, 'atom:link', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'link');
|
||||
|
||||
foreach ($links as $link) {
|
||||
if ($rel === (string) $link['rel']) {
|
||||
return $link;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the entry content.
|
||||
*
|
||||
* @param SimpleXMLElement $entry XML Entry
|
||||
* @return string
|
||||
*/
|
||||
private function getContent(SimpleXMLElement $entry)
|
||||
{
|
||||
$content = current(
|
||||
XmlParser::getXPathResult($entry, 'atom:content', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($entry, 'content')
|
||||
);
|
||||
|
||||
if (!empty($content) && count($content->children())) {
|
||||
$xml_string = '';
|
||||
|
||||
foreach ($content->children() as $child) {
|
||||
$xml_string .= $child->asXML();
|
||||
}
|
||||
|
||||
return $xml_string;
|
||||
} elseif (trim((string) $content) !== '') {
|
||||
return (string) $content;
|
||||
}
|
||||
|
||||
$summary = XmlParser::getXPathResult($entry, 'atom:summary', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($entry, 'summary');
|
||||
|
||||
return (string) current($summary);
|
||||
}
|
||||
}
|
||||
128
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/DateParser.php
vendored
Normal file
128
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/DateParser.php
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Parser;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeZone;
|
||||
use PicoFeed\Base;
|
||||
|
||||
/**
|
||||
* Date Parser.
|
||||
*
|
||||
* @package PicoFeed\Parser
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class DateParser extends Base
|
||||
{
|
||||
/**
|
||||
* Timezone used to parse feed dates.
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $timezone = 'UTC';
|
||||
|
||||
/**
|
||||
* Supported formats [ 'format' => length ].
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $formats = array(
|
||||
DATE_ATOM => null,
|
||||
DATE_RSS => null,
|
||||
DATE_COOKIE => null,
|
||||
DATE_ISO8601 => null,
|
||||
DATE_RFC822 => null,
|
||||
DATE_RFC850 => null,
|
||||
DATE_RFC1036 => null,
|
||||
DATE_RFC1123 => null,
|
||||
DATE_RFC2822 => null,
|
||||
DATE_RFC3339 => null,
|
||||
'l, d M Y H:i:s' => null,
|
||||
'D, d M Y H:i:s' => 25,
|
||||
'D, d M Y h:i:s' => 25,
|
||||
'D M d Y H:i:s' => 24,
|
||||
'j M Y H:i:s' => 20,
|
||||
'Y-m-d H:i:s' => 19,
|
||||
'Y-m-d\TH:i:s' => 19,
|
||||
'd/m/Y H:i:s' => 19,
|
||||
'D, d M Y' => 16,
|
||||
'Y-m-d' => 10,
|
||||
'd-m-Y' => 10,
|
||||
'm-d-Y' => 10,
|
||||
'd.m.Y' => 10,
|
||||
'm.d.Y' => 10,
|
||||
'd/m/Y' => 10,
|
||||
'm/d/Y' => 10,
|
||||
);
|
||||
|
||||
/**
|
||||
* Try to parse all date format for broken feeds.
|
||||
*
|
||||
* @param string $value Original date format
|
||||
*
|
||||
* @return DateTime
|
||||
*/
|
||||
public function getDateTime($value)
|
||||
{
|
||||
$value = trim($value);
|
||||
|
||||
foreach ($this->formats as $format => $length) {
|
||||
$truncated_value = $value;
|
||||
if ($length !== null) {
|
||||
$truncated_value = substr($truncated_value, 0, $length);
|
||||
}
|
||||
|
||||
$date = $this->getValidDate($format, $truncated_value);
|
||||
if ($date !== false) {
|
||||
return $date;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->getCurrentDateTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a valid date from a given format.
|
||||
*
|
||||
* @param string $format Date format
|
||||
* @param string $value Original date value
|
||||
*
|
||||
* @return DateTime|bool
|
||||
*/
|
||||
public function getValidDate($format, $value)
|
||||
{
|
||||
$date = DateTime::createFromFormat($format, $value, $this->getTimeZone());
|
||||
|
||||
if ($date !== false) {
|
||||
$errors = DateTime::getLastErrors();
|
||||
|
||||
if ($errors['error_count'] === 0 && $errors['warning_count'] === 0) {
|
||||
return $date;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current datetime.
|
||||
*
|
||||
* @return DateTime
|
||||
*/
|
||||
public function getCurrentDateTime()
|
||||
{
|
||||
return new DateTime('now', $this->getTimeZone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get DateTimeZone instance
|
||||
*
|
||||
* @access public
|
||||
* @return DateTimeZone
|
||||
*/
|
||||
public function getTimeZone()
|
||||
{
|
||||
return new DateTimeZone($this->config->getTimezone() ?: $this->timezone);
|
||||
}
|
||||
}
|
||||
315
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Feed.php
vendored
Normal file
315
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Feed.php
vendored
Normal file
@@ -0,0 +1,315 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Parser;
|
||||
|
||||
/**
|
||||
* Feed.
|
||||
*
|
||||
* @package PicoFeed\Parser
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Feed
|
||||
{
|
||||
/**
|
||||
* Feed items.
|
||||
*
|
||||
* @var Item[]
|
||||
*/
|
||||
public $items = array();
|
||||
|
||||
/**
|
||||
* Feed id.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $id = '';
|
||||
|
||||
/**
|
||||
* Feed title.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $title = '';
|
||||
|
||||
/**
|
||||
* Feed description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $description = '';
|
||||
|
||||
/**
|
||||
* Feed url.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $feedUrl = '';
|
||||
|
||||
/**
|
||||
* Site url.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $siteUrl = '';
|
||||
|
||||
/**
|
||||
* Feed date.
|
||||
*
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $date = null;
|
||||
|
||||
/**
|
||||
* Feed language.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $language = '';
|
||||
|
||||
/**
|
||||
* Feed logo URL.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $logo = '';
|
||||
|
||||
/**
|
||||
* Feed icon URL.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $icon = '';
|
||||
|
||||
/**
|
||||
* Return feed information.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$output = '';
|
||||
|
||||
foreach (array('id', 'title', 'feedUrl', 'siteUrl', 'language', 'description', 'logo') as $property) {
|
||||
$output .= 'Feed::'.$property.' = '.$this->$property.PHP_EOL;
|
||||
}
|
||||
|
||||
$output .= 'Feed::date = '.$this->date->format(DATE_RFC822).PHP_EOL;
|
||||
$output .= 'Feed::isRTL() = '.($this->isRTL() ? 'true' : 'false').PHP_EOL;
|
||||
$output .= 'Feed::items = '.count($this->items).' items'.PHP_EOL;
|
||||
|
||||
foreach ($this->items as $item) {
|
||||
$output .= '----'.PHP_EOL;
|
||||
$output .= $item;
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get title.
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get description.
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the logo url.
|
||||
*/
|
||||
public function getLogo()
|
||||
{
|
||||
return $this->logo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the icon url.
|
||||
*/
|
||||
public function getIcon()
|
||||
{
|
||||
return $this->icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get feed url.
|
||||
*/
|
||||
public function getFeedUrl()
|
||||
{
|
||||
return $this->feedUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get site url.
|
||||
*/
|
||||
public function getSiteUrl()
|
||||
{
|
||||
return $this->siteUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get date.
|
||||
*/
|
||||
public function getDate()
|
||||
{
|
||||
return $this->date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get language.
|
||||
*/
|
||||
public function getLanguage()
|
||||
{
|
||||
return $this->language;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get id.
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get feed items.
|
||||
*/
|
||||
public function getItems()
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the feed is "Right to Left".
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isRTL()
|
||||
{
|
||||
return Parser::isLanguageRTL($this->language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set feed items.
|
||||
*
|
||||
* @param Item[] $items
|
||||
* @return Feed
|
||||
*/
|
||||
public function setItems(array $items)
|
||||
{
|
||||
$this->items = $items;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set feed id.
|
||||
*
|
||||
* @param string $id
|
||||
* @return Feed
|
||||
*/
|
||||
public function setId($id)
|
||||
{
|
||||
$this->id = $id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set feed title.
|
||||
*
|
||||
* @param string $title
|
||||
* @return Feed
|
||||
*/
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->title = $title;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set feed description.
|
||||
*
|
||||
* @param string $description
|
||||
* @return Feed
|
||||
*/
|
||||
public function setDescription($description)
|
||||
{
|
||||
$this->description = $description;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set feed url.
|
||||
*
|
||||
* @param string $feedUrl
|
||||
* @return Feed
|
||||
*/
|
||||
public function setFeedUrl($feedUrl)
|
||||
{
|
||||
$this->feedUrl = $feedUrl;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set feed website url.
|
||||
*
|
||||
* @param string $siteUrl
|
||||
* @return Feed
|
||||
*/
|
||||
public function setSiteUrl($siteUrl)
|
||||
{
|
||||
$this->siteUrl = $siteUrl;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set feed date.
|
||||
*
|
||||
* @param \DateTime $date
|
||||
* @return Feed
|
||||
*/
|
||||
public function setDate($date)
|
||||
{
|
||||
$this->date = $date;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set feed language.
|
||||
*
|
||||
* @param string $language
|
||||
* @return Feed
|
||||
*/
|
||||
public function setLanguage($language)
|
||||
{
|
||||
$this->language = $language;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set feed logo.
|
||||
*
|
||||
* @param string $logo
|
||||
* @return Feed
|
||||
*/
|
||||
public function setLogo($logo)
|
||||
{
|
||||
$this->logo = $logo;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set feed icon.
|
||||
*
|
||||
* @param string $icon
|
||||
* @return Feed
|
||||
*/
|
||||
public function setIcon($icon)
|
||||
{
|
||||
$this->icon = $icon;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
562
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Item.php
vendored
Normal file
562
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Item.php
vendored
Normal file
@@ -0,0 +1,562 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Parser;
|
||||
|
||||
/**
|
||||
* Feed Item.
|
||||
*
|
||||
* @package PicoFeed\Parser
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Item
|
||||
{
|
||||
/**
|
||||
* List of known RTL languages.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public $rtl = array(
|
||||
'ar', // Arabic (ar-**)
|
||||
'fa', // Farsi (fa-**)
|
||||
'ur', // Urdu (ur-**)
|
||||
'ps', // Pashtu (ps-**)
|
||||
'syr', // Syriac (syr-**)
|
||||
'dv', // Divehi (dv-**)
|
||||
'he', // Hebrew (he-**)
|
||||
'yi', // Yiddish (yi-**)
|
||||
);
|
||||
|
||||
/**
|
||||
* Item id.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $id = '';
|
||||
|
||||
/**
|
||||
* Item title.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $title = '';
|
||||
|
||||
/**
|
||||
* Item url.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $url = '';
|
||||
|
||||
/**
|
||||
* Item author.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $author = '';
|
||||
|
||||
/**
|
||||
* Item author URL.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $authorUrl = '';
|
||||
|
||||
/**
|
||||
* Item date.
|
||||
*
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $date = null;
|
||||
|
||||
/**
|
||||
* Item published date.
|
||||
*
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $publishedDate = null;
|
||||
|
||||
/**
|
||||
* Item updated date.
|
||||
*
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $updatedDate = null;
|
||||
|
||||
/**
|
||||
* Item content.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $content = '';
|
||||
|
||||
/**
|
||||
* Item enclosure url.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $enclosureUrl = '';
|
||||
|
||||
/**
|
||||
* Item enclusure type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $enclosureType = '';
|
||||
|
||||
/**
|
||||
* Item language.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $language = '';
|
||||
|
||||
/**
|
||||
* Item categories.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $categories = array();
|
||||
|
||||
/**
|
||||
* Raw XML.
|
||||
*
|
||||
* @var \SimpleXMLElement
|
||||
*/
|
||||
public $xml;
|
||||
|
||||
/**
|
||||
* List of namespaces.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $namespaces = array();
|
||||
|
||||
/**
|
||||
* Check if a XML namespace exists
|
||||
*
|
||||
* @access public
|
||||
* @param string $namespace
|
||||
* @return bool
|
||||
*/
|
||||
public function hasNamespace($namespace)
|
||||
{
|
||||
return array_key_exists($namespace, $this->namespaces);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get specific XML tag or attribute value.
|
||||
*
|
||||
* @param string $tag Tag name (examples: guid, media:content)
|
||||
* @param string $attribute Tag attribute
|
||||
*
|
||||
* @return array|false Tag values or error
|
||||
*/
|
||||
public function getTag($tag, $attribute = '')
|
||||
{
|
||||
if ($attribute !== '') {
|
||||
$attribute = '/@'.$attribute;
|
||||
}
|
||||
|
||||
$query = './/'.$tag.$attribute;
|
||||
$elements = XmlParser::getXPathResult($this->xml, $query, $this->namespaces);
|
||||
|
||||
if ($elements === false) { // xPath error
|
||||
return false;
|
||||
}
|
||||
|
||||
return array_map(function ($element) { return (string) $element;}, $elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return item information.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$output = '';
|
||||
|
||||
foreach (array('id', 'title', 'url', 'language', 'author', 'enclosureUrl', 'enclosureType') as $property) {
|
||||
$output .= 'Item::'.$property.' = '.$this->$property.PHP_EOL;
|
||||
}
|
||||
|
||||
$publishedDate = $this->publishedDate != null ? $this->publishedDate->format(DATE_RFC822) : null;
|
||||
$updatedDate = $this->updatedDate != null ? $this->updatedDate->format(DATE_RFC822) : null;
|
||||
|
||||
$categoryString = $this->categories != null ? implode(',', $this->categories) : null;
|
||||
|
||||
$output .= 'Item::date = '.$this->date->format(DATE_RFC822).PHP_EOL;
|
||||
$output .= 'Item::publishedDate = '.$publishedDate.PHP_EOL;
|
||||
$output .= 'Item::updatedDate = '.$updatedDate.PHP_EOL;
|
||||
$output .= 'Item::isRTL() = '.($this->isRTL() ? 'true' : 'false').PHP_EOL;
|
||||
$output .= 'Item::categories = ['.$categoryString.']'.PHP_EOL;
|
||||
$output .= 'Item::content = '.strlen($this->content).' bytes'.PHP_EOL;
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get title.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get URL
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl()
|
||||
{
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set URL
|
||||
*
|
||||
* @access public
|
||||
* @param string $url
|
||||
* @return Item
|
||||
*/
|
||||
public function setUrl($url)
|
||||
{
|
||||
$this->url = $url;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get id.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get date.
|
||||
*
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getDate()
|
||||
{
|
||||
return $this->date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get published date.
|
||||
*
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getPublishedDate()
|
||||
{
|
||||
return $this->publishedDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get updated date.
|
||||
*
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getUpdatedDate()
|
||||
{
|
||||
return $this->updatedDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get content.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set content
|
||||
*
|
||||
* @access public
|
||||
* @param string $value
|
||||
* @return Item
|
||||
*/
|
||||
public function setContent($value)
|
||||
{
|
||||
$this->content = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get enclosure url.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEnclosureUrl()
|
||||
{
|
||||
return $this->enclosureUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get enclosure type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEnclosureType()
|
||||
{
|
||||
return $this->enclosureType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get language.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLanguage()
|
||||
{
|
||||
return $this->language;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get categories.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCategories()
|
||||
{
|
||||
return $this->categories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get author.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAuthor()
|
||||
{
|
||||
return $this->author;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get author URL.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAuthorUrl()
|
||||
{
|
||||
return $this->authorUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the item is "Right to Left".
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isRTL()
|
||||
{
|
||||
return Parser::isLanguageRTL($this->language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set item id.
|
||||
*
|
||||
* @param string $id
|
||||
* @return Item
|
||||
*/
|
||||
public function setId($id)
|
||||
{
|
||||
$this->id = $id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set item title.
|
||||
*
|
||||
* @param string $title
|
||||
* @return Item
|
||||
*/
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->title = $title;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set author.
|
||||
*
|
||||
* @param string $author
|
||||
* @return Item
|
||||
*/
|
||||
public function setAuthor($author)
|
||||
{
|
||||
$this->author = $author;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set author URL.
|
||||
*
|
||||
* @param string $authorUrl
|
||||
* @return Item
|
||||
*/
|
||||
public function setAuthorUrl($authorUrl)
|
||||
{
|
||||
$this->authorUrl = $authorUrl;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set item date.
|
||||
*
|
||||
* @param \DateTime $date
|
||||
* @return Item
|
||||
*/
|
||||
public function setDate($date)
|
||||
{
|
||||
$this->date = $date;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set item published date.
|
||||
*
|
||||
* @param \DateTime $publishedDate
|
||||
* @return Item
|
||||
*/
|
||||
public function setPublishedDate($publishedDate)
|
||||
{
|
||||
$this->publishedDate = $publishedDate;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set item updated date.
|
||||
*
|
||||
* @param \DateTime $updatedDate
|
||||
* @return Item
|
||||
*/
|
||||
public function setUpdatedDate($updatedDate)
|
||||
{
|
||||
$this->updatedDate = $updatedDate;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set enclosure url.
|
||||
*
|
||||
* @param string $enclosureUrl
|
||||
* @return Item
|
||||
*/
|
||||
public function setEnclosureUrl($enclosureUrl)
|
||||
{
|
||||
$this->enclosureUrl = $enclosureUrl;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set enclosure type.
|
||||
*
|
||||
* @param string $enclosureType
|
||||
* @return Item
|
||||
*/
|
||||
public function setEnclosureType($enclosureType)
|
||||
{
|
||||
$this->enclosureType = $enclosureType;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set item language.
|
||||
*
|
||||
* @param string $language
|
||||
* @return Item
|
||||
*/
|
||||
public function setLanguage($language)
|
||||
{
|
||||
$this->language = $language;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set item categories.
|
||||
*
|
||||
* @param array $categories
|
||||
* @return Item
|
||||
*/
|
||||
public function setCategories($categories)
|
||||
{
|
||||
$this->categories = $categories;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set item categories from xml.
|
||||
*
|
||||
* @param |SimpleXMLElement[] $categories
|
||||
* @return Item
|
||||
*/
|
||||
public function setCategoriesFromXml($categories)
|
||||
{
|
||||
if ($categories !== false) {
|
||||
$this->setCategories(
|
||||
array_map(
|
||||
function ($element) {
|
||||
return trim((string) $element);
|
||||
},
|
||||
$categories
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set raw XML.
|
||||
*
|
||||
* @param \SimpleXMLElement $xml
|
||||
* @return Item
|
||||
*/
|
||||
public function setXml($xml)
|
||||
{
|
||||
$this->xml = $xml;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get raw XML.
|
||||
*
|
||||
* @return \SimpleXMLElement
|
||||
*/
|
||||
public function getXml()
|
||||
{
|
||||
return $this->xml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set XML namespaces.
|
||||
*
|
||||
* @param array $namespaces
|
||||
* @return Item
|
||||
*/
|
||||
public function setNamespaces($namespaces)
|
||||
{
|
||||
$this->namespaces = $namespaces;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get XML namespaces.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getNamespaces()
|
||||
{
|
||||
return $this->namespaces;
|
||||
}
|
||||
}
|
||||
13
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/MalformedXmlException.php
vendored
Normal file
13
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/MalformedXmlException.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Parser;
|
||||
|
||||
/**
|
||||
* MalformedXmlException Exception.
|
||||
*
|
||||
* @package PicoFeed\Parser
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class MalformedXmlException extends ParserException
|
||||
{
|
||||
}
|
||||
397
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Parser.php
vendored
Normal file
397
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Parser.php
vendored
Normal file
@@ -0,0 +1,397 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Parser;
|
||||
|
||||
use PicoFeed\Processor\ContentFilterProcessor;
|
||||
use PicoFeed\Processor\ContentGeneratorProcessor;
|
||||
use PicoFeed\Processor\ItemPostProcessor;
|
||||
use PicoFeed\Processor\ScraperProcessor;
|
||||
use SimpleXMLElement;
|
||||
use PicoFeed\Client\Url;
|
||||
use PicoFeed\Encoding\Encoding;
|
||||
use PicoFeed\Filter\Filter;
|
||||
use PicoFeed\Logging\Logger;
|
||||
|
||||
/**
|
||||
* Base parser class.
|
||||
*
|
||||
* @package PicoFeed\Parser
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
abstract class Parser implements ParserInterface
|
||||
{
|
||||
/**
|
||||
* Config object.
|
||||
*
|
||||
* @var \PicoFeed\Config\Config
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* DateParser object.
|
||||
*
|
||||
* @var \PicoFeed\Parser\DateParser
|
||||
*/
|
||||
private $dateParser;
|
||||
|
||||
/**
|
||||
* Hash algorithm used to generate item id, any value supported by PHP, see hash_algos().
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $hash_algo = 'sha256';
|
||||
|
||||
/**
|
||||
* Feed content (XML data).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $content = '';
|
||||
|
||||
/**
|
||||
* Fallback url.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $fallback_url = '';
|
||||
|
||||
/**
|
||||
* XML namespaces supported by parser.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $namespaces = array();
|
||||
|
||||
/**
|
||||
* XML namespaces used in document.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $used_namespaces = array();
|
||||
|
||||
/**
|
||||
* Item Post Processor instance
|
||||
*
|
||||
* @access private
|
||||
* @var ItemPostProcessor
|
||||
*/
|
||||
private $itemPostProcessor;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $content Feed content
|
||||
* @param string $http_encoding HTTP encoding (headers)
|
||||
* @param string $fallback_url Fallback url when the feed provide relative or broken url
|
||||
*/
|
||||
public function __construct($content, $http_encoding = '', $fallback_url = '')
|
||||
{
|
||||
$this->fallback_url = $fallback_url;
|
||||
$xml_encoding = XmlParser::getEncodingFromXmlTag($content);
|
||||
|
||||
// Strip XML tag to avoid multiple encoding/decoding in the next XML processing
|
||||
$this->content = Filter::stripXmlTag($content);
|
||||
|
||||
// Encode everything in UTF-8
|
||||
Logger::setMessage(get_called_class().': HTTP Encoding "'.$http_encoding.'" ; XML Encoding "'.$xml_encoding.'"');
|
||||
$this->content = Encoding::convert($this->content, $xml_encoding ?: $http_encoding);
|
||||
|
||||
$this->itemPostProcessor = new ItemPostProcessor($this->config);
|
||||
$this->itemPostProcessor->register(new ContentGeneratorProcessor($this->config));
|
||||
$this->itemPostProcessor->register(new ContentFilterProcessor($this->config));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the document.
|
||||
* @return Feed
|
||||
* @throws MalformedXmlException
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
Logger::setMessage(get_called_class().': begin parsing');
|
||||
|
||||
$xml = XmlParser::getSimpleXml($this->content);
|
||||
|
||||
if ($xml === false) {
|
||||
Logger::setMessage(get_called_class().': Applying XML workarounds');
|
||||
$this->content = Filter::normalizeData($this->content);
|
||||
$xml = XmlParser::getSimpleXml($this->content);
|
||||
|
||||
if ($xml === false) {
|
||||
Logger::setMessage(get_called_class().': XML parsing error');
|
||||
Logger::setMessage(XmlParser::getErrors());
|
||||
throw new MalformedXmlException('XML parsing error');
|
||||
}
|
||||
}
|
||||
|
||||
$this->used_namespaces = $xml->getNamespaces(true);
|
||||
$xml = $this->registerSupportedNamespaces($xml);
|
||||
|
||||
$feed = new Feed();
|
||||
|
||||
$this->findFeedUrl($xml, $feed);
|
||||
$this->checkFeedUrl($feed);
|
||||
|
||||
$this->findSiteUrl($xml, $feed);
|
||||
$this->checkSiteUrl($feed);
|
||||
|
||||
$this->findFeedTitle($xml, $feed);
|
||||
$this->findFeedDescription($xml, $feed);
|
||||
$this->findFeedLanguage($xml, $feed);
|
||||
$this->findFeedId($xml, $feed);
|
||||
$this->findFeedDate($xml, $feed);
|
||||
$this->findFeedLogo($xml, $feed);
|
||||
$this->findFeedIcon($xml, $feed);
|
||||
|
||||
foreach ($this->getItemsTree($xml) as $entry) {
|
||||
$entry = $this->registerSupportedNamespaces($entry);
|
||||
|
||||
$item = new Item();
|
||||
$item->xml = $entry;
|
||||
$item->namespaces = $this->used_namespaces;
|
||||
|
||||
$this->findItemAuthor($xml, $entry, $item);
|
||||
$this->findItemAuthorUrl($xml, $entry, $item);
|
||||
|
||||
$this->findItemUrl($entry, $item);
|
||||
$this->checkItemUrl($feed, $item);
|
||||
|
||||
$this->findItemTitle($entry, $item);
|
||||
$this->findItemContent($entry, $item);
|
||||
|
||||
// Id generation can use the item url/title/content (order is important)
|
||||
$this->findItemId($entry, $item, $feed);
|
||||
$this->findItemDate($entry, $item, $feed);
|
||||
$this->findItemEnclosure($entry, $item, $feed);
|
||||
$this->findItemLanguage($entry, $item, $feed);
|
||||
$this->findItemCategories($entry, $item, $feed);
|
||||
|
||||
$this->itemPostProcessor->execute($feed, $item);
|
||||
$feed->items[] = $item;
|
||||
}
|
||||
|
||||
Logger::setMessage(get_called_class().PHP_EOL.$feed);
|
||||
|
||||
return $feed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the feed url is correct.
|
||||
*
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function checkFeedUrl(Feed $feed)
|
||||
{
|
||||
if ($feed->getFeedUrl() === '') {
|
||||
$feed->feedUrl = $this->fallback_url;
|
||||
} else {
|
||||
$feed->feedUrl = Url::resolve($feed->getFeedUrl(), $this->fallback_url);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the site url is correct.
|
||||
*
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function checkSiteUrl(Feed $feed)
|
||||
{
|
||||
if ($feed->getSiteUrl() === '') {
|
||||
$feed->siteUrl = Url::base($feed->getFeedUrl());
|
||||
} else {
|
||||
$feed->siteUrl = Url::resolve($feed->getSiteUrl(), $this->fallback_url);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the item url is correct.
|
||||
*
|
||||
* @param Feed $feed Feed object
|
||||
* @param Item $item Item object
|
||||
*/
|
||||
public function checkItemUrl(Feed $feed, Item $item)
|
||||
{
|
||||
$item->url = Url::resolve($item->getUrl(), $feed->getSiteUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item date.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findItemDate(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
$this->findItemPublishedDate($entry, $item, $feed);
|
||||
$this->findItemUpdatedDate($entry, $item, $feed);
|
||||
|
||||
if ($item->getPublishedDate() === null) {
|
||||
// Use the updated date if available, otherwise use the feed date
|
||||
$item->setPublishedDate($item->getUpdatedDate() ?: $feed->getDate());
|
||||
}
|
||||
|
||||
if ($item->getUpdatedDate() === null) {
|
||||
// Use the published date as fallback
|
||||
$item->setUpdatedDate($item->getPublishedDate());
|
||||
}
|
||||
|
||||
// Use the most recent of published and updated dates
|
||||
$item->setDate(max($item->getPublishedDate(), $item->getUpdatedDate()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Item Post Processor instance
|
||||
*
|
||||
* @access public
|
||||
* @return ItemPostProcessor
|
||||
*/
|
||||
public function getItemPostProcessor()
|
||||
{
|
||||
return $this->itemPostProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get DateParser instance
|
||||
*
|
||||
* @access public
|
||||
* @return DateParser
|
||||
*/
|
||||
public function getDateParser()
|
||||
{
|
||||
if ($this->dateParser === null) {
|
||||
$this->dateParser = new DateParser($this->config);
|
||||
}
|
||||
|
||||
return $this->dateParser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique id for an entry (hash all arguments).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateId()
|
||||
{
|
||||
return hash($this->hash_algo, implode(func_get_args()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the given language is "Right to Left".
|
||||
*
|
||||
* @static
|
||||
* @param string $language Language: fr-FR, en-US
|
||||
* @return bool
|
||||
*/
|
||||
public static function isLanguageRTL($language)
|
||||
{
|
||||
$language = strtolower($language);
|
||||
|
||||
$rtl_languages = array(
|
||||
'ar', // Arabic (ar-**)
|
||||
'fa', // Farsi (fa-**)
|
||||
'ur', // Urdu (ur-**)
|
||||
'ps', // Pashtu (ps-**)
|
||||
'syr', // Syriac (syr-**)
|
||||
'dv', // Divehi (dv-**)
|
||||
'he', // Hebrew (he-**)
|
||||
'yi', // Yiddish (yi-**)
|
||||
);
|
||||
|
||||
foreach ($rtl_languages as $prefix) {
|
||||
if (strpos($language, $prefix) === 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Hash algorithm used for id generation.
|
||||
*
|
||||
* @param string $algo Algorithm name
|
||||
* @return \PicoFeed\Parser\Parser
|
||||
*/
|
||||
public function setHashAlgo($algo)
|
||||
{
|
||||
$this->hash_algo = $algo ?: $this->hash_algo;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set config object.
|
||||
*
|
||||
* @param \PicoFeed\Config\Config $config Config instance
|
||||
* @return \PicoFeed\Parser\Parser
|
||||
*/
|
||||
public function setConfig($config)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->itemPostProcessor->setConfig($config);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the content grabber.
|
||||
*
|
||||
* @return \PicoFeed\Parser\Parser
|
||||
*/
|
||||
public function disableContentFiltering()
|
||||
{
|
||||
$this->itemPostProcessor->unregister('PicoFeed\Processor\ContentFilterProcessor');
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the content grabber.
|
||||
*
|
||||
* @param bool $needsRuleFile true if only pages with rule files should be
|
||||
* scraped
|
||||
* @param null|\Closure $scraperCallback Callback function that gets called for each
|
||||
* scraper execution
|
||||
* @return \PicoFeed\Parser\Parser
|
||||
*/
|
||||
public function enableContentGrabber($needsRuleFile = false, $scraperCallback = null)
|
||||
{
|
||||
$processor = new ScraperProcessor($this->config);
|
||||
|
||||
if ($needsRuleFile) {
|
||||
$processor->getScraper()->disableCandidateParser();
|
||||
}
|
||||
|
||||
if ($scraperCallback !== null) {
|
||||
$processor->setExecutionCallback($scraperCallback);
|
||||
}
|
||||
|
||||
$this->itemPostProcessor->register($processor);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ignored URLs for the content grabber.
|
||||
*
|
||||
* @param array $urls URLs
|
||||
* @return \PicoFeed\Parser\Parser
|
||||
*/
|
||||
public function setGrabberIgnoreUrls(array $urls)
|
||||
{
|
||||
$this->itemPostProcessor->getProcessor('PicoFeed\Processor\ScraperProcessor')->ignoreUrls($urls);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register all supported namespaces to be used within an xpath query.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @return SimpleXMLElement
|
||||
*/
|
||||
public function registerSupportedNamespaces(SimpleXMLElement $xml)
|
||||
{
|
||||
foreach ($this->namespaces as $prefix => $ns) {
|
||||
$xml->registerXPathNamespace($prefix, $ns);
|
||||
}
|
||||
|
||||
return $xml;
|
||||
}
|
||||
}
|
||||
15
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/ParserException.php
vendored
Normal file
15
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/ParserException.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Parser;
|
||||
|
||||
use PicoFeed\PicoFeedException;
|
||||
|
||||
/**
|
||||
* ParserException Exception.
|
||||
*
|
||||
* @package PicoFeed\Parser
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
abstract class ParserException extends PicoFeedException
|
||||
{
|
||||
}
|
||||
191
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/ParserInterface.php
vendored
Normal file
191
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/ParserInterface.php
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Parser;
|
||||
|
||||
use SimpleXMLElement;
|
||||
|
||||
/**
|
||||
* Interface ParserInterface
|
||||
*
|
||||
* @package PicoFeed\Parser
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
interface ParserInterface
|
||||
{
|
||||
/**
|
||||
* Find the feed url.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedUrl(SimpleXMLElement $xml, Feed $feed);
|
||||
|
||||
/**
|
||||
* Find the site url.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function findSiteUrl(SimpleXMLElement $xml, Feed $feed);
|
||||
|
||||
/**
|
||||
* Find the feed title.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedTitle(SimpleXMLElement $xml, Feed $feed);
|
||||
|
||||
/**
|
||||
* Find the feed description.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedDescription(SimpleXMLElement $xml, Feed $feed);
|
||||
|
||||
/**
|
||||
* Find the feed language.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedLanguage(SimpleXMLElement $xml, Feed $feed);
|
||||
|
||||
/**
|
||||
* Find the feed id.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedId(SimpleXMLElement $xml, Feed $feed);
|
||||
|
||||
/**
|
||||
* Find the feed date.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedDate(SimpleXMLElement $xml, Feed $feed);
|
||||
|
||||
/**
|
||||
* Find the feed logo url.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedLogo(SimpleXMLElement $xml, Feed $feed);
|
||||
|
||||
/**
|
||||
* Find the feed icon.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedIcon(SimpleXMLElement $xml, Feed $feed);
|
||||
|
||||
/**
|
||||
* Get the path to the items XML tree.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
*
|
||||
* @return SimpleXMLElement
|
||||
*/
|
||||
public function getItemsTree(SimpleXMLElement $xml);
|
||||
|
||||
/**
|
||||
* Find the item author.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
*/
|
||||
public function findItemAuthor(SimpleXMLElement $xml, SimpleXMLElement $entry, Item $item);
|
||||
|
||||
/**
|
||||
* Find the item author URL.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
*/
|
||||
public function findItemAuthorUrl(SimpleXMLElement $xml, SimpleXMLElement $entry, Item $item);
|
||||
|
||||
/**
|
||||
* Find the item URL.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
*/
|
||||
public function findItemUrl(SimpleXMLElement $entry, Item $item);
|
||||
|
||||
/**
|
||||
* Find the item title.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
*/
|
||||
public function findItemTitle(SimpleXMLElement $entry, Item $item);
|
||||
|
||||
/**
|
||||
* Genereate the item id.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function findItemId(SimpleXMLElement $entry, Item $item, Feed $feed);
|
||||
|
||||
/**
|
||||
* Find the item published date.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function findItemPublishedDate(SimpleXMLElement $entry, Item $item, Feed $feed);
|
||||
|
||||
/**
|
||||
* Find the item updated date.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function findItemUpdatedDate(SimpleXMLElement $entry, Item $item, Feed $feed);
|
||||
|
||||
/**
|
||||
* Find the item content.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
*/
|
||||
public function findItemContent(SimpleXMLElement $entry, Item $item);
|
||||
|
||||
/**
|
||||
* Find the item enclosure.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function findItemEnclosure(SimpleXMLElement $entry, Item $item, Feed $feed);
|
||||
|
||||
/**
|
||||
* Find the item language.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function findItemLanguage(SimpleXMLElement $entry, Item $item, Feed $feed);
|
||||
|
||||
/**
|
||||
* Find the item categories.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function findItemCategories(SimpleXMLElement $entry, Item $item, Feed $feed);
|
||||
}
|
||||
318
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Rss10.php
vendored
Normal file
318
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Rss10.php
vendored
Normal file
@@ -0,0 +1,318 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Parser;
|
||||
|
||||
use SimpleXMLElement;
|
||||
use PicoFeed\Filter\Filter;
|
||||
|
||||
/**
|
||||
* RSS 1.0 parser.
|
||||
*
|
||||
* @package PicoFeed\Parser
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Rss10 extends Parser
|
||||
{
|
||||
/**
|
||||
* Supported namespaces.
|
||||
*/
|
||||
protected $namespaces = array(
|
||||
'rss' => 'http://purl.org/rss/1.0/',
|
||||
'dc' => 'http://purl.org/dc/elements/1.1/',
|
||||
'content' => 'http://purl.org/rss/1.0/modules/content/',
|
||||
'feedburner' => 'http://rssnamespace.org/feedburner/ext/1.0',
|
||||
);
|
||||
|
||||
/**
|
||||
* Get the path to the items XML tree.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @return SimpleXMLElement[]
|
||||
*/
|
||||
public function getItemsTree(SimpleXMLElement $xml)
|
||||
{
|
||||
return XmlParser::getXPathResult($xml, 'rss:item', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'item')
|
||||
?: $xml->item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed url.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedUrl(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$feed->setFeedUrl('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the site url.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findSiteUrl(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$value = XmlParser::getXPathResult($xml, 'rss:channel/rss:link', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'channel/link')
|
||||
?: $xml->channel->link;
|
||||
|
||||
$feed->setSiteUrl(XmlParser::getValue($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed description.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedDescription(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$description = XmlParser::getXPathResult($xml, 'rss:channel/rss:description', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'channel/description')
|
||||
?: $xml->channel->description;
|
||||
|
||||
$feed->setDescription(XmlParser::getValue($description));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed logo url.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedLogo(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$logo = XmlParser::getXPathResult($xml, 'rss:image/rss:url', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'image/url');
|
||||
|
||||
$feed->setLogo(XmlParser::getValue($logo));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed icon.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedIcon(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$feed->setIcon('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed title.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedTitle(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$title = XmlParser::getXPathResult($xml, 'rss:channel/rss:title', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'channel/title')
|
||||
?: $xml->channel->title;
|
||||
|
||||
$feed->setTitle(Filter::stripWhiteSpace(XmlParser::getValue($title)) ?: $feed->getSiteUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed language.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedLanguage(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$language = XmlParser::getXPathResult($xml, 'rss:channel/dc:language', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'channel/dc:language', $this->namespaces);
|
||||
|
||||
$feed->setLanguage(XmlParser::getValue($language));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed id.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedId(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$feed->setId($feed->getFeedUrl() ?: $feed->getSiteUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed date.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedDate(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$date = XmlParser::getXPathResult($xml, 'rss:channel/dc:date', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'channel/dc:date', $this->namespaces);
|
||||
|
||||
$feed->setDate($this->getDateParser()->getDateTime(XmlParser::getValue($date)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item published date.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findItemPublishedDate(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
$date = XmlParser::getXPathResult($entry, 'dc:date', $this->namespaces);
|
||||
|
||||
$item->setPublishedDate(!empty($date) ? $this->getDateParser()->getDateTime(XmlParser::getValue($date)) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item updated date.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findItemUpdatedDate(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
if ($item->publishedDate === null) {
|
||||
$this->findItemPublishedDate($entry, $item, $feed);
|
||||
}
|
||||
$item->setUpdatedDate($item->getPublishedDate()); // No updated date in RSS 1.0 specifications
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item title.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
*/
|
||||
public function findItemTitle(SimpleXMLElement $entry, Item $item)
|
||||
{
|
||||
$title = XmlParser::getXPathResult($entry, 'rss:title', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($entry, 'title')
|
||||
?: $entry->title;
|
||||
|
||||
$item->setTitle(Filter::stripWhiteSpace(XmlParser::getValue($title)) ?: $item->getUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item author.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
*/
|
||||
public function findItemAuthor(SimpleXMLElement $xml, SimpleXMLElement $entry, Item $item)
|
||||
{
|
||||
$author = XmlParser::getXPathResult($entry, 'dc:creator', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'rss:channel/dc:creator', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'channel/dc:creator', $this->namespaces);
|
||||
|
||||
$item->setAuthor(XmlParser::getValue($author));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item author URL.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
*/
|
||||
public function findItemAuthorUrl(SimpleXMLElement $xml, SimpleXMLElement $entry, Item $item)
|
||||
{
|
||||
// There appears to be no support for author URL in the dc: terms
|
||||
$item->setAuthorUrl('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item content.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
*/
|
||||
public function findItemContent(SimpleXMLElement $entry, Item $item)
|
||||
{
|
||||
$content = XmlParser::getXPathResult($entry, 'content:encoded', $this->namespaces);
|
||||
|
||||
if (XmlParser::getValue($content) === '') {
|
||||
$content = XmlParser::getXPathResult($entry, 'rss:description', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($entry, 'description')
|
||||
?: $entry->description;
|
||||
}
|
||||
|
||||
$item->setContent(XmlParser::getValue($content));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item URL.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
*/
|
||||
public function findItemUrl(SimpleXMLElement $entry, Item $item)
|
||||
{
|
||||
$link = XmlParser::getXPathResult($entry, 'feedburner:origLink', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($entry, 'rss:link', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($entry, 'link')
|
||||
?: $entry->link;
|
||||
|
||||
$item->setUrl(XmlParser::getValue($link));
|
||||
}
|
||||
|
||||
/**
|
||||
* Genereate the item id.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findItemId(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
$item->setId($this->generateId(
|
||||
$item->getTitle(), $item->getUrl(), $item->getContent()
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item enclosure.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findItemEnclosure(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item language.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findItemLanguage(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
$language = XmlParser::getXPathResult($entry, 'dc:language', $this->namespaces);
|
||||
|
||||
$item->setLanguage(XmlParser::getValue($language) ?: $feed->getLanguage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item categories.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function findItemCategories(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
$categories = XmlParser::getXPathResult($entry, 'dc:subject', $this->namespaces);
|
||||
$item->setCategoriesFromXml($categories);
|
||||
}
|
||||
}
|
||||
330
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Rss20.php
vendored
Normal file
330
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Rss20.php
vendored
Normal file
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Parser;
|
||||
|
||||
use SimpleXMLElement;
|
||||
use PicoFeed\Filter\Filter;
|
||||
use PicoFeed\Client\Url;
|
||||
|
||||
/**
|
||||
* RSS 2.0 Parser.
|
||||
*
|
||||
* @package PicoFeed\Parser
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Rss20 extends Parser
|
||||
{
|
||||
/**
|
||||
* Supported namespaces.
|
||||
*/
|
||||
protected $namespaces = array(
|
||||
'dc' => 'http://purl.org/dc/elements/1.1/',
|
||||
'content' => 'http://purl.org/rss/1.0/modules/content/',
|
||||
'feedburner' => 'http://rssnamespace.org/feedburner/ext/1.0',
|
||||
'atom' => 'http://www.w3.org/2005/Atom',
|
||||
);
|
||||
|
||||
/**
|
||||
* Get the path to the items XML tree.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @return SimpleXMLElement[]
|
||||
*/
|
||||
public function getItemsTree(SimpleXMLElement $xml)
|
||||
{
|
||||
return XmlParser::getXPathResult($xml, 'channel/item');
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed url.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedUrl(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$feed->setFeedUrl('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the site url.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findSiteUrl(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$value = XmlParser::getXPathResult($xml, 'channel/link');
|
||||
$feed->setSiteUrl(XmlParser::getValue($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed description.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedDescription(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$value = XmlParser::getXPathResult($xml, 'channel/description');
|
||||
$feed->setDescription(XmlParser::getValue($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed logo url.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedLogo(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$value = XmlParser::getXPathResult($xml, 'channel/image/url');
|
||||
$feed->setLogo(XmlParser::getValue($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed icon.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedIcon(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$feed->setIcon('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed title.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedTitle(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$title = XmlParser::getXPathResult($xml, 'channel/title');
|
||||
$feed->setTitle(Filter::stripWhiteSpace(XmlParser::getValue($title)) ?: $feed->getSiteUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed language.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedLanguage(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$value = XmlParser::getXPathResult($xml, 'channel/language');
|
||||
$feed->setLanguage(XmlParser::getValue($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed id.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedId(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$feed->setId($feed->getFeedUrl() ?: $feed->getSiteUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the feed date.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed xml
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findFeedDate(SimpleXMLElement $xml, Feed $feed)
|
||||
{
|
||||
$publish_date = XmlParser::getXPathResult($xml, 'channel/pubDate');
|
||||
$update_date = XmlParser::getXPathResult($xml, 'channel/lastBuildDate');
|
||||
|
||||
$published = !empty($publish_date) ? $this->getDateParser()->getDateTime(XmlParser::getValue($publish_date)) : null;
|
||||
$updated = !empty($update_date) ? $this->getDateParser()->getDateTime(XmlParser::getValue($update_date)) : null;
|
||||
|
||||
if ($published === null && $updated === null) {
|
||||
$feed->setDate($this->getDateParser()->getCurrentDateTime()); // We use the current date if there is no date for the feed
|
||||
} elseif ($published !== null && $updated !== null) {
|
||||
$feed->setDate(max($published, $updated)); // We use the most recent date between published and updated
|
||||
} else {
|
||||
$feed->setDate($updated ?: $published);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item published date.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findItemPublishedDate(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
$date = XmlParser::getXPathResult($entry, 'pubDate');
|
||||
|
||||
$item->setPublishedDate(!empty($date) ? $this->getDateParser()->getDateTime(XmlParser::getValue($date)) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item updated date.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findItemUpdatedDate(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
if ($item->publishedDate === null) {
|
||||
$this->findItemPublishedDate($entry, $item, $feed);
|
||||
}
|
||||
$item->setUpdatedDate($item->getPublishedDate()); // No updated date in RSS 2.0 specifications
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item title.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
*/
|
||||
public function findItemTitle(SimpleXMLElement $entry, Item $item)
|
||||
{
|
||||
$value = XmlParser::getXPathResult($entry, 'title');
|
||||
$item->setTitle(Filter::stripWhiteSpace(XmlParser::getValue($value)) ?: $item->getUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item author.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
*/
|
||||
public function findItemAuthor(SimpleXMLElement $xml, SimpleXMLElement $entry, Item $item)
|
||||
{
|
||||
$value = XmlParser::getXPathResult($entry, 'dc:creator', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($entry, 'author')
|
||||
?: XmlParser::getXPathResult($xml, 'channel/dc:creator', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($xml, 'channel/managingEditor');
|
||||
|
||||
$item->setAuthor(XmlParser::getValue($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item author URL.
|
||||
*
|
||||
* @param SimpleXMLElement $xml Feed
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
*/
|
||||
public function findItemAuthorUrl(SimpleXMLElement $xml, SimpleXMLElement $entry, Item $item)
|
||||
{
|
||||
// There appears to be no support for author URL in the dc: terms or author element
|
||||
$item->setAuthorUrl('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item content.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
*/
|
||||
public function findItemContent(SimpleXMLElement $entry, Item $item)
|
||||
{
|
||||
$content = XmlParser::getXPathResult($entry, 'content:encoded', $this->namespaces);
|
||||
|
||||
if (XmlParser::getValue($content) === '') {
|
||||
$content = XmlParser::getXPathResult($entry, 'description');
|
||||
}
|
||||
|
||||
$item->setContent(XmlParser::getValue($content));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item URL.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
*/
|
||||
public function findItemUrl(SimpleXMLElement $entry, Item $item)
|
||||
{
|
||||
$link = XmlParser::getXPathResult($entry, 'feedburner:origLink', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($entry, 'link')
|
||||
?: XmlParser::getXPathResult($entry, 'atom:link/@href', $this->namespaces);
|
||||
|
||||
if (!empty($link)) {
|
||||
$item->setUrl(XmlParser::getValue($link));
|
||||
} else {
|
||||
$link = XmlParser::getXPathResult($entry, 'guid');
|
||||
$link = XmlParser::getValue($link);
|
||||
|
||||
if (filter_var($link, FILTER_VALIDATE_URL) !== false) {
|
||||
$item->setUrl($link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Genereate the item id.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findItemId(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
$id = XmlParser::getValue(XmlParser::getXPathResult($entry, 'guid'));
|
||||
|
||||
if ($id) {
|
||||
$item->setId($this->generateId($id));
|
||||
} else {
|
||||
$item->setId($this->generateId(
|
||||
$item->getTitle(), $item->getUrl(), $item->getContent()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item enclosure.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findItemEnclosure(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
if (isset($entry->enclosure)) {
|
||||
$type = XmlParser::getXPathResult($entry, 'enclosure/@type');
|
||||
$url = XmlParser::getXPathResult($entry, 'feedburner:origEnclosureLink', $this->namespaces)
|
||||
?: XmlParser::getXPathResult($entry, 'enclosure/@url');
|
||||
|
||||
$item->setEnclosureUrl(Url::resolve(XmlParser::getValue($url), $feed->getSiteUrl()));
|
||||
$item->setEnclosureType(XmlParser::getValue($type));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item language.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param \PicoFeed\Parser\Item $item Item object
|
||||
* @param \PicoFeed\Parser\Feed $feed Feed object
|
||||
*/
|
||||
public function findItemLanguage(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
$language = XmlParser::getXPathResult($entry, 'dc:language', $this->namespaces);
|
||||
$item->setLanguage(XmlParser::getValue($language) ?: $feed->getLanguage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the item categories.
|
||||
*
|
||||
* @param SimpleXMLElement $entry Feed item
|
||||
* @param Item $item Item object
|
||||
* @param Feed $feed Feed object
|
||||
*/
|
||||
public function findItemCategories(SimpleXMLElement $entry, Item $item, Feed $feed)
|
||||
{
|
||||
$categories = XmlParser::getXPathResult($entry, 'category');
|
||||
$item->setCategoriesFromXml($categories);
|
||||
}
|
||||
}
|
||||
13
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Rss91.php
vendored
Normal file
13
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Rss91.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Parser;
|
||||
|
||||
/**
|
||||
* RSS 0.91 Parser.
|
||||
*
|
||||
* @package PicoFeed\Parser
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Rss91 extends Rss20
|
||||
{
|
||||
}
|
||||
13
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Rss92.php
vendored
Normal file
13
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Rss92.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Parser;
|
||||
|
||||
/**
|
||||
* RSS 0.92 Parser.
|
||||
*
|
||||
* @package PicoFeed\Parser
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Rss92 extends Rss20
|
||||
{
|
||||
}
|
||||
13
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/XmlEntityException.php
vendored
Normal file
13
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/XmlEntityException.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Parser;
|
||||
|
||||
/**
|
||||
* XmlEntityException Exception.
|
||||
*
|
||||
* @package PicoFeed\Parser
|
||||
* @author Bernhard Posselt
|
||||
*/
|
||||
class XmlEntityException extends MalformedXmlException
|
||||
{
|
||||
}
|
||||
249
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/XmlParser.php
vendored
Normal file
249
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/XmlParser.php
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Parser;
|
||||
|
||||
use DOMDocument;
|
||||
use SimpleXMLElement;
|
||||
use Laminas\Xml\Exception\RuntimeException;
|
||||
use Laminas\Xml\Security;
|
||||
|
||||
/**
|
||||
* XML parser class.
|
||||
*
|
||||
* Checks for XML eXternal Entity (XXE) and XML Entity Expansion (XEE) attacks on XML documents
|
||||
*
|
||||
* @package PicoFeed\Parser
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class XmlParser
|
||||
{
|
||||
protected static $errors = [];
|
||||
|
||||
/**
|
||||
* Get a SimpleXmlElement instance or return false.
|
||||
*
|
||||
* @static
|
||||
* @param string $input XML content
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getSimpleXml($input)
|
||||
{
|
||||
return self::scan($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a DomDocument instance or return false.
|
||||
*
|
||||
* @static
|
||||
* @param string $input XML content
|
||||
* @return DOMDocument|bool
|
||||
*/
|
||||
public static function getDomDocument($input)
|
||||
{
|
||||
if (empty($input)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$dom = self::scan($input, new DOMDocument());
|
||||
|
||||
// The document is empty, there is probably some parsing errors
|
||||
if ($dom && $dom->childNodes->length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Small wrapper around Laminas Xml to turn their exceptions into PicoFeed exceptions
|
||||
*
|
||||
* @static
|
||||
* @access private
|
||||
* @param string $input
|
||||
* @param DOMDocument $dom
|
||||
* @throws XmlEntityException
|
||||
* @return SimpleXMLElement|DomDocument|boolean
|
||||
*/
|
||||
private static function scan($input, $dom = null)
|
||||
{
|
||||
try {
|
||||
return Security::scan($input, $dom);
|
||||
} catch(RuntimeException $e) {
|
||||
throw new XmlEntityException($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load HTML document by using a DomDocument instance or return false on failure.
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @param string $input XML content
|
||||
* @return DOMDocument
|
||||
*/
|
||||
public static function getHtmlDocument($input)
|
||||
{
|
||||
$dom = new DomDocument();
|
||||
|
||||
if (empty($input)) {
|
||||
return $dom;
|
||||
}
|
||||
|
||||
libxml_use_internal_errors(true);
|
||||
|
||||
if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
|
||||
$dom->loadHTML($input, LIBXML_NONET);
|
||||
} else {
|
||||
$dom->loadHTML($input);
|
||||
}
|
||||
|
||||
self::$errors = [];
|
||||
foreach (libxml_get_errors() as $error) {
|
||||
self::$errors[] = sprintf('XML error: %s (Line: %d - Column: %d - Code: %d)',
|
||||
$error->message,
|
||||
$error->line,
|
||||
$error->column,
|
||||
$error->code
|
||||
);
|
||||
}
|
||||
|
||||
libxml_use_internal_errors(false);
|
||||
|
||||
return $dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a HTML document to XML.
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @param string $html HTML document
|
||||
* @return string
|
||||
*/
|
||||
public static function htmlToXml($html)
|
||||
{
|
||||
$dom = self::getHtmlDocument('<?xml version="1.0" encoding="UTF-8">'.$html);
|
||||
return $dom->saveXML($dom->getElementsByTagName('body')->item(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get XML parser errors.
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public static function getErrors()
|
||||
{
|
||||
return implode(', ', self::$errors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the encoding from a xml tag.
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @param string $data Input data
|
||||
* @return string
|
||||
*/
|
||||
public static function getEncodingFromXmlTag($data)
|
||||
{
|
||||
$encoding = '';
|
||||
|
||||
if (strpos($data, '<?xml') !== false) {
|
||||
$data = substr($data, 0, strrpos($data, '?>'));
|
||||
$data = str_replace("'", '"', $data);
|
||||
|
||||
$p1 = strpos($data, 'encoding=');
|
||||
$p2 = strpos($data, '"', $p1 + 10);
|
||||
|
||||
if ($p1 !== false && $p2 !== false) {
|
||||
$encoding = substr($data, $p1 + 10, $p2 - $p1 - 10);
|
||||
$encoding = strtolower($encoding);
|
||||
}
|
||||
}
|
||||
|
||||
return $encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the charset from a meta tag.
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @param string $data Input data
|
||||
* @return string
|
||||
*/
|
||||
public static function getEncodingFromMetaTag($data)
|
||||
{
|
||||
$encoding = '';
|
||||
|
||||
if (preg_match('/<meta.*?charset\s*=\s*["\']?\s*([^"\'\s\/>;]+)/i', $data, $match) === 1) {
|
||||
$encoding = strtolower($match[1]);
|
||||
}
|
||||
|
||||
return $encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrite XPath query to use namespace-uri and local-name derived from prefix.
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @param string $query XPath query
|
||||
* @param array $ns Prefix to namespace URI mapping
|
||||
* @return string
|
||||
*/
|
||||
public static function replaceXPathPrefixWithNamespaceURI($query, array $ns)
|
||||
{
|
||||
return preg_replace_callback('/([A-Z0-9]+):([A-Z0-9]+)/iu', function ($matches) use ($ns) {
|
||||
// don't try to map the special prefix XML
|
||||
if (strtolower($matches[1]) === 'xml') {
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
return '*[namespace-uri()="'.$ns[$matches[1]].'" and local-name()="'.$matches[2].'"]';
|
||||
},
|
||||
$query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the result elements of a XPath query.
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @param SimpleXMLElement $xml XML element
|
||||
* @param string $query XPath query
|
||||
* @param array $ns Prefix to namespace URI mapping
|
||||
* @return SimpleXMLElement[]
|
||||
*/
|
||||
public static function getXPathResult(SimpleXMLElement $xml, $query, array $ns = array())
|
||||
{
|
||||
if (!empty($ns)) {
|
||||
$query = static::replaceXPathPrefixWithNamespaceURI($query, $ns);
|
||||
}
|
||||
|
||||
return $xml->xpath($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first Xpath result or SimpleXMLElement value
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @param mixed $value
|
||||
* @return string
|
||||
*/
|
||||
public static function getValue($value)
|
||||
{
|
||||
$result = '';
|
||||
|
||||
if (is_array($value) && count($value) > 0) {
|
||||
$result = (string) $value[0];
|
||||
} elseif (is_a($value, 'SimpleXMLElement')) {
|
||||
return $result = (string) $value;
|
||||
}
|
||||
|
||||
return trim($result);
|
||||
}
|
||||
}
|
||||
14
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/PicoFeedException.php
vendored
Normal file
14
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/PicoFeedException.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* PicoFeedException Exception.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
abstract class PicoFeedException extends Exception
|
||||
{
|
||||
}
|
||||
39
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Processor/ContentFilterProcessor.php
vendored
Normal file
39
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Processor/ContentFilterProcessor.php
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Processor;
|
||||
|
||||
use PicoFeed\Base;
|
||||
use PicoFeed\Filter\Filter;
|
||||
use PicoFeed\Logging\Logger;
|
||||
use PicoFeed\Parser\Feed;
|
||||
use PicoFeed\Parser\Item;
|
||||
|
||||
/**
|
||||
* Item Content Filter
|
||||
*
|
||||
* @package PicoFeed\Processor
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class ContentFilterProcessor extends Base implements ItemProcessorInterface
|
||||
{
|
||||
/**
|
||||
* Execute Item Processor
|
||||
*
|
||||
* @access public
|
||||
* @param Feed $feed
|
||||
* @param Item $item
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(Feed $feed, Item $item)
|
||||
{
|
||||
if ($this->config->getContentFiltering(true)) {
|
||||
$filter = Filter::html($item->getContent(), $feed->getSiteUrl());
|
||||
$filter->setConfig($this->config);
|
||||
$item->setContent($filter->execute());
|
||||
} else {
|
||||
Logger::setMessage(get_called_class().': Content filtering disabled');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
49
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Processor/ContentGeneratorProcessor.php
vendored
Normal file
49
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Processor/ContentGeneratorProcessor.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Processor;
|
||||
|
||||
use PicoFeed\Base;
|
||||
use PicoFeed\Parser\Feed;
|
||||
use PicoFeed\Parser\Item;
|
||||
|
||||
/**
|
||||
* Item Content Generator
|
||||
*
|
||||
* @package PicoFeed\Processor
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class ContentGeneratorProcessor extends Base implements ItemProcessorInterface
|
||||
{
|
||||
/**
|
||||
* List of generators
|
||||
*
|
||||
* @access protected
|
||||
* @var array
|
||||
*/
|
||||
protected $generators = array(
|
||||
'youtube',
|
||||
'file',
|
||||
);
|
||||
|
||||
/**
|
||||
* Execute Item Processor
|
||||
*
|
||||
* @access public
|
||||
* @param Feed $feed
|
||||
* @param Item $item
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(Feed $feed, Item $item)
|
||||
{
|
||||
foreach ($this->generators as $generator) {
|
||||
$className = '\PicoFeed\Generator\\'.ucfirst($generator).'ContentGenerator';
|
||||
$object = new $className($this->config);
|
||||
|
||||
if ($object->execute($item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
106
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Processor/ItemPostProcessor.php
vendored
Normal file
106
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Processor/ItemPostProcessor.php
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Processor;
|
||||
|
||||
use PicoFeed\Base;
|
||||
use PicoFeed\Parser\Feed;
|
||||
use PicoFeed\Parser\Item;
|
||||
use PicoFeed\Config\Config;
|
||||
|
||||
/**
|
||||
* Item Post Processor
|
||||
*
|
||||
* @package PicoFeed\Processor
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class ItemPostProcessor extends Base
|
||||
{
|
||||
/**
|
||||
* List of processors
|
||||
*
|
||||
* @access private
|
||||
* @var array
|
||||
*/
|
||||
private $processors = array();
|
||||
|
||||
/**
|
||||
* Execute all processors
|
||||
*
|
||||
* @access public
|
||||
* @param Feed $feed
|
||||
* @param Item $item
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(Feed $feed, Item $item)
|
||||
{
|
||||
foreach ($this->processors as $processor) {
|
||||
if ($processor->execute($feed, $item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new Item post-processor
|
||||
*
|
||||
* @access public
|
||||
* @param ItemProcessorInterface $processor
|
||||
* @return ItemPostProcessor
|
||||
*/
|
||||
public function register(ItemProcessorInterface $processor)
|
||||
{
|
||||
$this->processors[get_class($processor)] = $processor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Processor instance
|
||||
*
|
||||
* @access public
|
||||
* @param string $class
|
||||
* @return ItemPostProcessor
|
||||
*/
|
||||
public function unregister($class)
|
||||
{
|
||||
if (isset($this->processors[$class])) {
|
||||
unset($this->processors[$class]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a specific processor is registered or not
|
||||
*
|
||||
* @access public
|
||||
* @param string $class
|
||||
* @return bool
|
||||
*/
|
||||
public function hasProcessor($class)
|
||||
{
|
||||
return isset($this->processors[$class]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Processor instance
|
||||
*
|
||||
* @access public
|
||||
* @param string $class
|
||||
* @return ItemProcessorInterface|null
|
||||
*/
|
||||
public function getProcessor($class)
|
||||
{
|
||||
return isset($this->processors[$class]) ? $this->processors[$class] : null;
|
||||
}
|
||||
|
||||
public function setConfig(Config $config)
|
||||
{
|
||||
foreach ($this->processors as $processor) {
|
||||
$processor->setConfig($config);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
25
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Processor/ItemProcessorInterface.php
vendored
Normal file
25
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Processor/ItemProcessorInterface.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Processor;
|
||||
|
||||
use PicoFeed\Parser\Feed;
|
||||
use PicoFeed\Parser\Item;
|
||||
|
||||
/**
|
||||
* Item Processor Interface
|
||||
*
|
||||
* @package PicoFeed\Processor
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
interface ItemProcessorInterface
|
||||
{
|
||||
/**
|
||||
* Execute Item Processor
|
||||
*
|
||||
* @access public
|
||||
* @param Feed $feed
|
||||
* @param Item $item
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(Feed $feed, Item $item);
|
||||
}
|
||||
96
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Processor/ScraperProcessor.php
vendored
Normal file
96
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Processor/ScraperProcessor.php
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Processor;
|
||||
|
||||
use Closure;
|
||||
use PicoFeed\Base;
|
||||
use PicoFeed\Parser\Feed;
|
||||
use PicoFeed\Parser\Item;
|
||||
use PicoFeed\Scraper\Scraper;
|
||||
|
||||
/**
|
||||
* Scraper Processor
|
||||
*
|
||||
* @package PicoFeed\Processor
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class ScraperProcessor extends Base implements ItemProcessorInterface
|
||||
{
|
||||
private $ignoredUrls = array();
|
||||
private $scraper;
|
||||
|
||||
/**
|
||||
* Callback function for each scraper execution
|
||||
*
|
||||
* @var Closure
|
||||
*/
|
||||
private $executionCallback;
|
||||
|
||||
/**
|
||||
* Add a new execution callback
|
||||
*
|
||||
* @access public
|
||||
* @param Closure $executionCallback
|
||||
* @return $this
|
||||
*/
|
||||
public function setExecutionCallback(Closure $executionCallback)
|
||||
{
|
||||
$this->executionCallback = $executionCallback;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute Item Processor
|
||||
*
|
||||
* @access public
|
||||
* @param Feed $feed
|
||||
* @param Item $item
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(Feed $feed, Item $item)
|
||||
{
|
||||
if (!in_array($item->getUrl(), $this->ignoredUrls)) {
|
||||
$scraper = $this->getScraper();
|
||||
$scraper->setUrl($item->getUrl());
|
||||
$scraper->execute();
|
||||
|
||||
if ($this->executionCallback && is_callable($this->executionCallback)) {
|
||||
call_user_func($this->executionCallback, $feed, $item, $scraper);
|
||||
}
|
||||
|
||||
if ($scraper->hasRelevantContent()) {
|
||||
$item->setContent($scraper->getFilteredContent());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ignore list of URLs
|
||||
*
|
||||
* @access public
|
||||
* @param array $urls
|
||||
* @return $this
|
||||
*/
|
||||
public function ignoreUrls(array $urls)
|
||||
{
|
||||
$this->ignoredUrls = $urls;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Scraper instance
|
||||
*
|
||||
* @access public
|
||||
* @return Scraper
|
||||
*/
|
||||
public function getScraper()
|
||||
{
|
||||
if ($this->scraper === null) {
|
||||
$this->scraper = new Scraper($this->config);
|
||||
}
|
||||
|
||||
return $this->scraper;
|
||||
}
|
||||
}
|
||||
186
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Reader/Favicon.php
vendored
Normal file
186
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Reader/Favicon.php
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Reader;
|
||||
|
||||
use DOMXPath;
|
||||
use PicoFeed\Base;
|
||||
use PicoFeed\Client\Client;
|
||||
use PicoFeed\Client\ClientException;
|
||||
use PicoFeed\Client\Url;
|
||||
use PicoFeed\Logging\Logger;
|
||||
use PicoFeed\Parser\XmlParser;
|
||||
|
||||
/**
|
||||
* Favicon class.
|
||||
*
|
||||
* https://en.wikipedia.org/wiki/Favicon
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Favicon extends Base
|
||||
{
|
||||
/**
|
||||
* Valid types for favicon (supported by browsers).
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $types = array(
|
||||
'image/png',
|
||||
'image/gif',
|
||||
'image/x-icon',
|
||||
'image/jpeg',
|
||||
'image/jpg',
|
||||
'image/svg+xml',
|
||||
);
|
||||
|
||||
/**
|
||||
* Icon binary content.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $content = '';
|
||||
|
||||
/**
|
||||
* Icon content type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $content_type = '';
|
||||
|
||||
/**
|
||||
* Get the icon file content (available only after the download).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the icon file type (available only after the download).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
foreach ($this->types as $type) {
|
||||
if (strpos($this->content_type, $type) === 0) {
|
||||
return $type;
|
||||
}
|
||||
}
|
||||
|
||||
return 'image/x-icon';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data URI (http://en.wikipedia.org/wiki/Data_URI_scheme).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDataUri()
|
||||
{
|
||||
if (empty($this->content)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
'data:%s;base64,%s',
|
||||
$this->getType(),
|
||||
base64_encode($this->content)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download and check if a resource exists.
|
||||
*
|
||||
* @param string $url URL
|
||||
* @return \PicoFeed\Client\Client Client instance
|
||||
*/
|
||||
public function download($url)
|
||||
{
|
||||
$client = Client::getInstance();
|
||||
$client->setConfig($this->config);
|
||||
|
||||
Logger::setMessage(get_called_class().' Download => '.$url);
|
||||
|
||||
try {
|
||||
$client->execute($url);
|
||||
} catch (ClientException $e) {
|
||||
Logger::setMessage(get_called_class().' Download Failed => '.$e->getMessage());
|
||||
}
|
||||
|
||||
return $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a remote file exists.
|
||||
*
|
||||
* @param string $url URL
|
||||
* @return bool
|
||||
*/
|
||||
public function exists($url)
|
||||
{
|
||||
return $this->download($url)->getContent() !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the icon link for a website.
|
||||
*
|
||||
* @param string $website_link URL
|
||||
* @param string $favicon_link optional URL
|
||||
* @return string
|
||||
*/
|
||||
public function find($website_link, $favicon_link = '')
|
||||
{
|
||||
$website = new Url($website_link);
|
||||
|
||||
if ($favicon_link !== '') {
|
||||
$icons = array($favicon_link);
|
||||
} else {
|
||||
$icons = $this->extract($this->download($website->getBaseUrl('/'))->getContent());
|
||||
$icons[] = $website->getBaseUrl('/favicon.ico');
|
||||
}
|
||||
|
||||
foreach ($icons as $icon_link) {
|
||||
$icon_link = Url::resolve($icon_link, $website);
|
||||
$resource = $this->download($icon_link);
|
||||
$this->content = $resource->getContent();
|
||||
$this->content_type = $resource->getContentType();
|
||||
|
||||
if ($this->content !== '') {
|
||||
return $icon_link;
|
||||
} elseif ($favicon_link !== '') {
|
||||
return $this->find($website_link);
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the icon links from the HTML.
|
||||
*
|
||||
* @param string $html HTML
|
||||
* @return array
|
||||
*/
|
||||
public function extract($html)
|
||||
{
|
||||
$icons = array();
|
||||
|
||||
if (empty($html)) {
|
||||
return $icons;
|
||||
}
|
||||
|
||||
$dom = XmlParser::getHtmlDocument($html);
|
||||
|
||||
$xpath = new DOMXpath($dom);
|
||||
$elements = $xpath->query('//link[@rel="icon" or @rel="shortcut icon" or @rel="Shortcut Icon" or @rel="icon shortcut"]');
|
||||
|
||||
for ($i = 0; $i < $elements->length; ++$i) {
|
||||
$icons[] = $elements->item($i)->getAttribute('href');
|
||||
}
|
||||
|
||||
return $icons;
|
||||
}
|
||||
}
|
||||
189
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Reader/Reader.php
vendored
Normal file
189
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Reader/Reader.php
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Reader;
|
||||
|
||||
use DOMXPath;
|
||||
use PicoFeed\Base;
|
||||
use PicoFeed\Client\Client;
|
||||
use PicoFeed\Client\Url;
|
||||
use PicoFeed\Logging\Logger;
|
||||
use PicoFeed\Parser\XmlParser;
|
||||
|
||||
/**
|
||||
* Reader class.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Reader extends Base
|
||||
{
|
||||
/**
|
||||
* Feed formats for detection.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $formats = array(
|
||||
'Atom' => '//feed',
|
||||
'Rss20' => '//rss[@version="2.0"]',
|
||||
'Rss92' => '//rss[@version="0.92"]',
|
||||
'Rss91' => '//rss[@version="0.91"]',
|
||||
'Rss10' => '//rdf',
|
||||
);
|
||||
|
||||
/**
|
||||
* Download a feed (no discovery).
|
||||
*
|
||||
* @param string $url Feed url
|
||||
* @param string $last_modified Last modified HTTP header
|
||||
* @param string $etag Etag HTTP header
|
||||
* @param string $username HTTP basic auth username
|
||||
* @param string $password HTTP basic auth password
|
||||
*
|
||||
* @return \PicoFeed\Client\Client
|
||||
*/
|
||||
public function download($url, $last_modified = '', $etag = '', $username = '', $password = '')
|
||||
{
|
||||
$url = $this->prependScheme($url);
|
||||
|
||||
return Client::getInstance()
|
||||
->setConfig($this->config)
|
||||
->setLastModified($last_modified)
|
||||
->setEtag($etag)
|
||||
->setUsername($username)
|
||||
->setPassword($password)
|
||||
->execute($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover and download a feed.
|
||||
*
|
||||
* @param string $url Feed or website url
|
||||
* @param string $last_modified Last modified HTTP header
|
||||
* @param string $etag Etag HTTP header
|
||||
* @param string $username HTTP basic auth username
|
||||
* @param string $password HTTP basic auth password
|
||||
* @return Client
|
||||
* @throws SubscriptionNotFoundException
|
||||
*/
|
||||
public function discover($url, $last_modified = '', $etag = '', $username = '', $password = '')
|
||||
{
|
||||
$client = $this->download($url, $last_modified, $etag, $username, $password);
|
||||
|
||||
// It's already a feed or the feed was not modified
|
||||
if (!$client->isModified() || $this->detectFormat($client->getContent())) {
|
||||
return $client;
|
||||
}
|
||||
|
||||
// Try to find a subscription
|
||||
$links = $this->find($client->getUrl(), $client->getContent());
|
||||
|
||||
if (empty($links)) {
|
||||
throw new SubscriptionNotFoundException('Unable to find a subscription');
|
||||
}
|
||||
|
||||
return $this->download($links[0], $last_modified, $etag, $username, $password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find feed urls inside a HTML document.
|
||||
*
|
||||
* @param string $url Website url
|
||||
* @param string $html HTML content
|
||||
*
|
||||
* @return array List of feed links
|
||||
*/
|
||||
public function find($url, $html)
|
||||
{
|
||||
Logger::setMessage(get_called_class().': Try to discover subscriptions');
|
||||
|
||||
$dom = XmlParser::getHtmlDocument($html);
|
||||
$xpath = new DOMXPath($dom);
|
||||
$links = array();
|
||||
|
||||
$queries = array(
|
||||
'//link[@type="application/rss+xml"]',
|
||||
'//link[@type="application/atom+xml"]',
|
||||
);
|
||||
|
||||
foreach ($queries as $query) {
|
||||
$nodes = $xpath->query($query);
|
||||
|
||||
foreach ($nodes as $node) {
|
||||
$link = $node->getAttribute('href');
|
||||
|
||||
if (!empty($link)) {
|
||||
$feedUrl = new Url($link);
|
||||
$siteUrl = new Url($url);
|
||||
|
||||
$links[] = $feedUrl->getAbsoluteUrl($feedUrl->isRelativeUrl() ? $siteUrl->getBaseUrl() : '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Logger::setMessage(get_called_class().': '.implode(', ', $links));
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a parser instance.
|
||||
*
|
||||
* @param string $url Site url
|
||||
* @param string $content Feed content
|
||||
* @param string $encoding HTTP encoding
|
||||
* @return \PicoFeed\Parser\Parser
|
||||
* @throws UnsupportedFeedFormatException
|
||||
*/
|
||||
public function getParser($url, $content, $encoding)
|
||||
{
|
||||
$format = $this->detectFormat($content);
|
||||
|
||||
if (empty($format)) {
|
||||
throw new UnsupportedFeedFormatException('Unable to detect feed format');
|
||||
}
|
||||
|
||||
$className = '\PicoFeed\Parser\\'.$format;
|
||||
|
||||
$parser = new $className($content, $encoding, $url);
|
||||
$parser->setHashAlgo($this->config->getParserHashAlgo());
|
||||
$parser->setConfig($this->config);
|
||||
|
||||
return $parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect the feed format.
|
||||
*
|
||||
* @param string $content Feed content
|
||||
* @return string
|
||||
*/
|
||||
public function detectFormat($content)
|
||||
{
|
||||
$dom = XmlParser::getHtmlDocument($content);
|
||||
$xpath = new DOMXPath($dom);
|
||||
|
||||
foreach ($this->formats as $parser_name => $query) {
|
||||
$nodes = $xpath->query($query);
|
||||
|
||||
if ($nodes->length === 1) {
|
||||
return $parser_name;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the prefix "http://" if the end-user just enter a domain name.
|
||||
*
|
||||
* @param string $url Url
|
||||
* @return string
|
||||
*/
|
||||
public function prependScheme($url)
|
||||
{
|
||||
if (!preg_match('%^https?://%', $url)) {
|
||||
$url = 'http://'.$url;
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
14
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Reader/ReaderException.php
vendored
Normal file
14
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Reader/ReaderException.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Reader;
|
||||
|
||||
use PicoFeed\PicoFeedException;
|
||||
|
||||
/**
|
||||
* ReaderException Exception.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
abstract class ReaderException extends PicoFeedException
|
||||
{
|
||||
}
|
||||
12
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Reader/SubscriptionNotFoundException.php
vendored
Normal file
12
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Reader/SubscriptionNotFoundException.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Reader;
|
||||
|
||||
/**
|
||||
* SubscriptionNotFoundException Exception.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class SubscriptionNotFoundException extends ReaderException
|
||||
{
|
||||
}
|
||||
12
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Reader/UnsupportedFeedFormatException.php
vendored
Normal file
12
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Reader/UnsupportedFeedFormatException.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace PicoFeed\Reader;
|
||||
|
||||
/**
|
||||
* UnsupportedFeedFormatException Exception.
|
||||
*
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class UnsupportedFeedFormatException extends ReaderException
|
||||
{
|
||||
}
|
||||
14
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.blog.lemonde.fr.php
vendored
Normal file
14
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.blog.lemonde.fr.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
return array(
|
||||
'grabber' => array(
|
||||
'%.*%' => array(
|
||||
'test_url' => 'http://combat.blog.lemonde.fr/2013/08/31/teddy-riner-le-rookie-devenu-rambo/#xtor=RSS-3208',
|
||||
'body' => array(
|
||||
'//div[@class="entry-content"]',
|
||||
),
|
||||
'strip' => array(
|
||||
'//*[contains(@class, "fb-like") or contains(@class, "social")]'
|
||||
),
|
||||
)
|
||||
)
|
||||
);
|
||||
15
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.blogs.nytimes.com.php
vendored
Normal file
15
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.blogs.nytimes.com.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
return array(
|
||||
'grabber' => array(
|
||||
'%.*%' => array(
|
||||
'title' => '//header/h1',
|
||||
'test_url' => 'http://bits.blogs.nytimes.com/2012/01/16/wikipedia-plans-to-go-dark-on-wednesday-to-protest-sopa/',
|
||||
'body' => array(
|
||||
'//div[@class="postContent"]',
|
||||
),
|
||||
'strip' => array(
|
||||
'//*[@class="shareToolsBox"]',
|
||||
),
|
||||
)
|
||||
)
|
||||
);
|
||||
13
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.igen.fr.php
vendored
Normal file
13
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.igen.fr.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
return array(
|
||||
'grabber' => array(
|
||||
'%.*%' => array(
|
||||
'test_url' => 'http://www.igen.fr/ailleurs/2014/05/nvidia-va-delaisser-les-smartphones-grand-public-86031',
|
||||
'body' => array(
|
||||
'//div[contains(@class, "field-name-body")]'
|
||||
),
|
||||
'strip' => array(
|
||||
),
|
||||
)
|
||||
)
|
||||
);
|
||||
11
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.nytimes.com.php
vendored
Normal file
11
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.nytimes.com.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
return array(
|
||||
'grabber' => array(
|
||||
'%.*%' => array(
|
||||
'test_url' => 'http://www.nytimes.com/2011/05/15/world/middleeast/15prince.html',
|
||||
'body' => array(
|
||||
'//p[contains(@class, "story-content")] | //div[@class="image"]',
|
||||
),
|
||||
)
|
||||
)
|
||||
);
|
||||
11
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.over-blog.com.php
vendored
Normal file
11
user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.over-blog.com.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
return array(
|
||||
'grabber' => array(
|
||||
'%.*%' => array(
|
||||
'test_url' => 'http://eliascarpe.over-blog.com/2015/12/re-upload-projets-d-avenir.html',
|
||||
'body' => array(
|
||||
'//div[contains(concat(" ", normalize-space(@class), " "), " ob-section ")]',
|
||||
),
|
||||
)
|
||||
)
|
||||
);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user