WIP - New imap class
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
"require": {
|
||||
"tinymce/tinymce": "*",
|
||||
"phpmailer/phpmailer": "dev-master",
|
||||
"php-imap/php-imap": "5.0"
|
||||
"webklex/php-imap": "^4.1"
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
|
||||
1279
composer.lock
generated
1279
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,7 @@ class Emailinbox extends Renderer {
|
||||
}
|
||||
|
||||
protected function readEmailHeaders(): array {
|
||||
return [];
|
||||
$cleanedHeaders = [];
|
||||
try {
|
||||
$mailsIds = $this->mbox->searchMailbox('ALL');
|
||||
@@ -69,12 +70,12 @@ class Emailinbox extends Renderer {
|
||||
|
||||
protected function generateFolders(): void {
|
||||
$this->connectToImap();
|
||||
$folders = $this->mbox->getMailboxes("*");
|
||||
$folders = $this->mbox->generateFolders();
|
||||
$folderItems = [];
|
||||
foreach ($folders as $folder) {
|
||||
$item = '<li><a href="/emailinbox?folder=' . urlencode($folder['shortpath']) . '"' .
|
||||
(utf8_encode($folder['shortpath']) === $this->folder ? ' class="active-folder"' : '') . '>' .
|
||||
utf8_encode($folder['shortpath']) . '</a></li>';
|
||||
$item = '<li><a href="/emailinbox?folder=' . urlencode($folder->name) . '"' .
|
||||
(utf8_encode($folder->name) === $this->folder ? ' class="active-folder"' : '') . '>' .
|
||||
utf8_encode($folder->full_name) . '</a></li>';
|
||||
$folderItems[] = $item;
|
||||
}
|
||||
$this->content['folders'] = implode('', $folderItems);
|
||||
|
||||
@@ -21,6 +21,8 @@ class Mail extends Mailhandling {
|
||||
|
||||
protected function generateContent(): void {
|
||||
$this->mail = $this->fetchEmail();
|
||||
$textHtml = $this->mail->textHtml;
|
||||
$textPlain = $this->mail->textPlain;
|
||||
$this->content['sender'] = $this->mail->headers->senderaddress;
|
||||
$this->content['receiver'] = $this->mail->headers->toaddress;
|
||||
$this->content['senddate'] = (new DateTime($this->mail->date))->format('d.m.Y');
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
use PhpImap\Mailbox;
|
||||
use Webklex\PHPIMAP\ClientManager;
|
||||
use Webklex\PHPIMAP\Client;
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
@@ -34,7 +35,8 @@ class Renderer {
|
||||
protected int $smtpPort = 465;
|
||||
protected string $emailUser = 'foerderverein-ajs@gmx.de';
|
||||
protected string $emailPassword = 'HarheimerWeg16';
|
||||
protected $mbox;
|
||||
protected ClientManager $imapClientManager;
|
||||
protected Client $mbox;
|
||||
|
||||
public function __construct(?string $templateName = null) {
|
||||
session_start();
|
||||
@@ -452,21 +454,18 @@ class Renderer {
|
||||
}
|
||||
|
||||
protected function connectToImap($folder = ''): bool {
|
||||
$this->mbox = new PhpImap\Mailbox(
|
||||
'{' . $this->imapServer . ':' . $this->imapPort . '/imap/ssl}' . imap_utf7_encode($folder),
|
||||
$this->emailUser,
|
||||
$this->emailPassword,
|
||||
__DIR__,
|
||||
'UTF-8',
|
||||
true,
|
||||
false
|
||||
);
|
||||
$this->mbox->setConnectionArgs(
|
||||
CL_EXPUNGE,
|
||||
3,
|
||||
[]
|
||||
);
|
||||
return ($this->mbox !== false);
|
||||
$this->imapClientManager = new ClientManager('conf/imap.php');
|
||||
$this->mbox = $this->imapClientManager->make([
|
||||
'host' => $this->imapServer,
|
||||
'port' => $this->imapPort,
|
||||
'encryption' => 'ssl',
|
||||
'validate_cert' => true,
|
||||
'username' => $this->emailUser,
|
||||
'password' => $this->emailPassword,
|
||||
'protocol' => 'imap'
|
||||
]);
|
||||
$this->mbox->connect();
|
||||
return $this->mbox->isConnected();;
|
||||
}
|
||||
|
||||
protected function saveFileLocal(string $newFileName, string $content, string $salt): void {
|
||||
|
||||
96
vendor/composer/ClassLoader.php
vendored
96
vendor/composer/ClassLoader.php
vendored
@@ -45,35 +45,34 @@ class ClassLoader
|
||||
/** @var \Closure(string):void */
|
||||
private static $includeFile;
|
||||
|
||||
/** @var ?string */
|
||||
/** @var string|null */
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, int>>
|
||||
* @var array<string, array<string, int>>
|
||||
*/
|
||||
private $prefixLengthsPsr4 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<int, string>>
|
||||
* @var array<string, list<string>>
|
||||
*/
|
||||
private $prefixDirsPsr4 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
* @var list<string>
|
||||
*/
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, string[]>>
|
||||
* List of PSR-0 prefixes
|
||||
*
|
||||
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
|
||||
*
|
||||
* @var array<string, array<string, list<string>>>
|
||||
*/
|
||||
private $prefixesPsr0 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
* @var list<string>
|
||||
*/
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
@@ -81,8 +80,7 @@ class ClassLoader
|
||||
private $useIncludePath = false;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
* @psalm-var array<string, string>
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private $classMap = array();
|
||||
|
||||
@@ -90,21 +88,20 @@ class ClassLoader
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
/**
|
||||
* @var bool[]
|
||||
* @psalm-var array<string, bool>
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
private $missingClasses = array();
|
||||
|
||||
/** @var ?string */
|
||||
/** @var string|null */
|
||||
private $apcuPrefix;
|
||||
|
||||
/**
|
||||
* @var self[]
|
||||
* @var array<string, self>
|
||||
*/
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
/**
|
||||
* @param ?string $vendorDir
|
||||
* @param string|null $vendorDir
|
||||
*/
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
@@ -113,7 +110,7 @@ class ClassLoader
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
* @return array<string, list<string>>
|
||||
*/
|
||||
public function getPrefixes()
|
||||
{
|
||||
@@ -125,8 +122,7 @@ class ClassLoader
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, array<int, string>>
|
||||
* @return array<string, list<string>>
|
||||
*/
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
@@ -134,8 +130,7 @@ class ClassLoader
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
@@ -143,8 +138,7 @@ class ClassLoader
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
@@ -152,8 +146,7 @@ class ClassLoader
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[] Array of classname => path
|
||||
* @psalm-return array<string, string>
|
||||
* @return array<string, string> Array of classname => path
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
@@ -161,8 +154,7 @@ class ClassLoader
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $classMap Class to filename map
|
||||
* @psalm-param array<string, string> $classMap
|
||||
* @param array<string, string> $classMap Class to filename map
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@@ -179,24 +171,25 @@ class ClassLoader
|
||||
* 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
|
||||
* @param string $prefix The prefix
|
||||
* @param list<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)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
(array) $paths,
|
||||
$paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
(array) $paths
|
||||
$paths
|
||||
);
|
||||
}
|
||||
|
||||
@@ -205,19 +198,19 @@ class ClassLoader
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
||||
$this->prefixesPsr0[$first][$prefix] = $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
(array) $paths
|
||||
$paths
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -226,9 +219,9 @@ class ClassLoader
|
||||
* 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
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param list<string>|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
@@ -236,17 +229,18 @@ class ClassLoader
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
(array) $paths,
|
||||
$paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
(array) $paths
|
||||
$paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||
@@ -256,18 +250,18 @@ class ClassLoader
|
||||
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;
|
||||
$this->prefixDirsPsr4[$prefix] = $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
(array) $paths
|
||||
$paths
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -276,8 +270,8 @@ class ClassLoader
|
||||
* 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
|
||||
* @param string $prefix The prefix
|
||||
* @param list<string>|string $paths The PSR-0 base directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@@ -294,8 +288,8 @@ class ClassLoader
|
||||
* 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
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param list<string>|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
@@ -481,9 +475,9 @@ class ClassLoader
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered loaders indexed by their corresponding vendor directories.
|
||||
* Returns the currently registered loaders keyed by their corresponding vendor directories.
|
||||
*
|
||||
* @return self[]
|
||||
* @return array<string, self>
|
||||
*/
|
||||
public static function getRegisteredLoaders()
|
||||
{
|
||||
|
||||
5
vendor/composer/autoload_classmap.php
vendored
5
vendor/composer/autoload_classmap.php
vendored
@@ -6,5 +6,10 @@ $vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
|
||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||
'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
|
||||
'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
|
||||
'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
|
||||
'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
|
||||
);
|
||||
|
||||
16
vendor/composer/autoload_psr4.php
vendored
16
vendor/composer/autoload_psr4.php
vendored
@@ -6,6 +6,20 @@ $vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'PhpImap\\' => array($vendorDir . '/php-imap/php-imap/src/PhpImap'),
|
||||
'voku\\' => array($vendorDir . '/voku/portable-ascii/src/voku'),
|
||||
'Webklex\\PHPIMAP\\' => array($vendorDir . '/webklex/php-imap/src'),
|
||||
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
|
||||
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
|
||||
'Symfony\\Contracts\\Translation\\' => array($vendorDir . '/symfony/translation-contracts'),
|
||||
'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
|
||||
'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
|
||||
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
|
||||
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
|
||||
'Psr\\Clock\\' => array($vendorDir . '/psr/clock/src'),
|
||||
'PHPMailer\\PHPMailer\\' => array($vendorDir . '/phpmailer/phpmailer/src'),
|
||||
'Illuminate\\Support\\' => array($vendorDir . '/illuminate/macroable', $vendorDir . '/illuminate/collections', $vendorDir . '/illuminate/support'),
|
||||
'Illuminate\\Pagination\\' => array($vendorDir . '/illuminate/pagination'),
|
||||
'Illuminate\\Contracts\\' => array($vendorDir . '/illuminate/contracts'),
|
||||
'Doctrine\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib/Doctrine/Inflector'),
|
||||
'Carbon\\' => array($vendorDir . '/nesbot/carbon/src/Carbon'),
|
||||
);
|
||||
|
||||
12
vendor/composer/autoload_real.php
vendored
12
vendor/composer/autoload_real.php
vendored
@@ -33,6 +33,18 @@ class ComposerAutoloaderInitb3a3dfb766a515d49b7f8665bad574b3
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInitb3a3dfb766a515d49b7f8665bad574b3::$files;
|
||||
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
||||
require $file;
|
||||
}
|
||||
}, null, null);
|
||||
foreach ($filesToLoad as $fileIdentifier => $file) {
|
||||
$requireFile($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
||||
110
vendor/composer/autoload_static.php
vendored
110
vendor/composer/autoload_static.php
vendored
@@ -6,27 +6,131 @@ namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInitb3a3dfb766a515d49b7f8665bad574b3
|
||||
{
|
||||
public static $files = array (
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
|
||||
'60799491728b879e74601d83e38b2cad' => __DIR__ . '/..' . '/illuminate/collections/helpers.php',
|
||||
'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php',
|
||||
'72579e7bd17821bb1321b87411366eae' => __DIR__ . '/..' . '/illuminate/support/helpers.php',
|
||||
);
|
||||
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'v' =>
|
||||
array (
|
||||
'voku\\' => 5,
|
||||
),
|
||||
'W' =>
|
||||
array (
|
||||
'Webklex\\PHPIMAP\\' => 16,
|
||||
),
|
||||
'S' =>
|
||||
array (
|
||||
'Symfony\\Polyfill\\Php80\\' => 23,
|
||||
'Symfony\\Polyfill\\Mbstring\\' => 26,
|
||||
'Symfony\\Contracts\\Translation\\' => 30,
|
||||
'Symfony\\Component\\Translation\\' => 30,
|
||||
'Symfony\\Component\\HttpFoundation\\' => 33,
|
||||
),
|
||||
'P' =>
|
||||
array (
|
||||
'PhpImap\\' => 8,
|
||||
'Psr\\SimpleCache\\' => 16,
|
||||
'Psr\\Container\\' => 14,
|
||||
'Psr\\Clock\\' => 10,
|
||||
'PHPMailer\\PHPMailer\\' => 20,
|
||||
),
|
||||
'I' =>
|
||||
array (
|
||||
'Illuminate\\Support\\' => 19,
|
||||
'Illuminate\\Pagination\\' => 22,
|
||||
'Illuminate\\Contracts\\' => 21,
|
||||
),
|
||||
'D' =>
|
||||
array (
|
||||
'Doctrine\\Inflector\\' => 19,
|
||||
),
|
||||
'C' =>
|
||||
array (
|
||||
'Carbon\\' => 7,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'PhpImap\\' =>
|
||||
'voku\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/php-imap/php-imap/src/PhpImap',
|
||||
0 => __DIR__ . '/..' . '/voku/portable-ascii/src/voku',
|
||||
),
|
||||
'Webklex\\PHPIMAP\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/webklex/php-imap/src',
|
||||
),
|
||||
'Symfony\\Polyfill\\Php80\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
|
||||
),
|
||||
'Symfony\\Polyfill\\Mbstring\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
|
||||
),
|
||||
'Symfony\\Contracts\\Translation\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/translation-contracts',
|
||||
),
|
||||
'Symfony\\Component\\Translation\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/translation',
|
||||
),
|
||||
'Symfony\\Component\\HttpFoundation\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/http-foundation',
|
||||
),
|
||||
'Psr\\SimpleCache\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/simple-cache/src',
|
||||
),
|
||||
'Psr\\Container\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/container/src',
|
||||
),
|
||||
'Psr\\Clock\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/clock/src',
|
||||
),
|
||||
'PHPMailer\\PHPMailer\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/phpmailer/phpmailer/src',
|
||||
),
|
||||
'Illuminate\\Support\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/illuminate/macroable',
|
||||
1 => __DIR__ . '/..' . '/illuminate/collections',
|
||||
2 => __DIR__ . '/..' . '/illuminate/support',
|
||||
),
|
||||
'Illuminate\\Pagination\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/illuminate/pagination',
|
||||
),
|
||||
'Illuminate\\Contracts\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/illuminate/contracts',
|
||||
),
|
||||
'Doctrine\\Inflector\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/doctrine/inflector/lib/Doctrine/Inflector',
|
||||
),
|
||||
'Carbon\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon',
|
||||
),
|
||||
);
|
||||
|
||||
public static $classMap = array (
|
||||
'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
|
||||
'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
|
||||
'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
|
||||
'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
|
||||
1330
vendor/composer/installed.json
vendored
1330
vendor/composer/installed.json
vendored
File diff suppressed because it is too large
Load Diff
185
vendor/composer/installed.php
vendored
185
vendor/composer/installed.php
vendored
@@ -3,7 +3,7 @@
|
||||
'name' => '__root__',
|
||||
'pretty_version' => 'dev-main',
|
||||
'version' => 'dev-main',
|
||||
'reference' => '1c6f08b77a9f8f7d91de74616da0b18dfccef4e8',
|
||||
'reference' => '54d30dd3c3ff737ecc0ef62de19a7c9ed29fea2d',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
@@ -13,25 +13,81 @@
|
||||
'__root__' => array(
|
||||
'pretty_version' => 'dev-main',
|
||||
'version' => 'dev-main',
|
||||
'reference' => '1c6f08b77a9f8f7d91de74616da0b18dfccef4e8',
|
||||
'reference' => '54d30dd3c3ff737ecc0ef62de19a7c9ed29fea2d',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'php-imap/php-imap' => array(
|
||||
'pretty_version' => '5.0.0',
|
||||
'version' => '5.0.0.0',
|
||||
'reference' => '13bdfa9a6f541798253e24e2d8f44332c8be098c',
|
||||
'doctrine/inflector' => array(
|
||||
'pretty_version' => '2.1.x-dev',
|
||||
'version' => '2.1.9999999.9999999-dev',
|
||||
'reference' => 'd62dadcaaf16432c7c1364bf50be9e03f26ff043',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../php-imap/php-imap',
|
||||
'install_path' => __DIR__ . '/../doctrine/inflector',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'illuminate/collections' => array(
|
||||
'pretty_version' => '8.x-dev',
|
||||
'version' => '8.9999999.9999999.9999999-dev',
|
||||
'reference' => '705a4e1ef93cd492c45b9b3e7911cccc990a07f4',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../illuminate/collections',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'illuminate/contracts' => array(
|
||||
'pretty_version' => '8.x-dev',
|
||||
'version' => '8.9999999.9999999.9999999-dev',
|
||||
'reference' => '5e0fd287a1b22a6b346a9f7cd484d8cf0234585d',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../illuminate/contracts',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'illuminate/macroable' => array(
|
||||
'pretty_version' => '8.x-dev',
|
||||
'version' => '8.9999999.9999999.9999999-dev',
|
||||
'reference' => 'aed81891a6e046fdee72edd497f822190f61c162',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../illuminate/macroable',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'illuminate/pagination' => array(
|
||||
'pretty_version' => '8.x-dev',
|
||||
'version' => '8.9999999.9999999.9999999-dev',
|
||||
'reference' => '16fe8dc35f9d18c58a3471469af656a02e9ab692',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../illuminate/pagination',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'illuminate/support' => array(
|
||||
'pretty_version' => '8.x-dev',
|
||||
'version' => '8.9999999.9999999.9999999-dev',
|
||||
'reference' => 'ad030d68770e00a395822a4c243b931be3e4d3c7',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../illuminate/support',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'nesbot/carbon' => array(
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => '98276233188583f2ff845a0f992a235472d9466a',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../nesbot/carbon',
|
||||
'aliases' => array(
|
||||
0 => '2.x-dev',
|
||||
),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'phpmailer/phpmailer' => array(
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => '312ed95ab03e7f3f0316191e5bfb9f920b705825',
|
||||
'reference' => 'a1fa2714c447adda7e6b07c4bfa290dfc1a035b2',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpmailer/phpmailer',
|
||||
'aliases' => array(
|
||||
@@ -39,10 +95,103 @@
|
||||
),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/clock' => array(
|
||||
'pretty_version' => '1.0.0',
|
||||
'version' => '1.0.0.0',
|
||||
'reference' => 'e41a24703d4560fd0acb709162f73b8adfc3aa0d',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/clock',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/clock-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/container' => array(
|
||||
'pretty_version' => '1.x-dev',
|
||||
'version' => '1.9999999.9999999.9999999-dev',
|
||||
'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/container',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/simple-cache' => array(
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/simple-cache',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/deprecation-contracts' => array(
|
||||
'pretty_version' => '2.5.x-dev',
|
||||
'version' => '2.5.9999999.9999999-dev',
|
||||
'reference' => '80d075412b557d41002320b96a096ca65aa2c98d',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/http-foundation' => array(
|
||||
'pretty_version' => '5.4.x-dev',
|
||||
'version' => '5.4.9999999.9999999-dev',
|
||||
'reference' => '365992c83a836dfe635f1e903ccca43ee03d3dd2',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/http-foundation',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-mbstring' => array(
|
||||
'pretty_version' => '1.x-dev',
|
||||
'version' => '1.9999999.9999999.9999999-dev',
|
||||
'reference' => '42292d99c55abe617799667f454222c54c60e229',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-php80' => array(
|
||||
'pretty_version' => '1.x-dev',
|
||||
'version' => '1.9999999.9999999.9999999-dev',
|
||||
'reference' => '6caa57379c4aec19c0a12a38b59b26487dcfe4b5',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/translation' => array(
|
||||
'pretty_version' => '5.4.x-dev',
|
||||
'version' => '5.4.9999999.9999999-dev',
|
||||
'reference' => '96015d73801bb59de5a43d71906c5690759f29ea',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/translation',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/translation-contracts' => array(
|
||||
'pretty_version' => '2.5.x-dev',
|
||||
'version' => '2.5.9999999.9999999-dev',
|
||||
'reference' => '129138dd46853de65d8e4fcc526ba1f3f777ba57',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/translation-contracts',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/translation-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '2.3',
|
||||
),
|
||||
),
|
||||
'tinymce/tinymce' => array(
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => '6a37da4822eebcd2706793454b07bd891c5277a8',
|
||||
'reference' => '02e194ec4d37aab8335332f8ac3e8d2292ba2d47',
|
||||
'type' => 'component',
|
||||
'install_path' => __DIR__ . '/../tinymce/tinymce',
|
||||
'aliases' => array(
|
||||
@@ -50,5 +199,23 @@
|
||||
),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'voku/portable-ascii' => array(
|
||||
'pretty_version' => '1.6.1',
|
||||
'version' => '1.6.1.0',
|
||||
'reference' => '87337c91b9dfacee02452244ee14ab3c43bc485a',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../voku/portable-ascii',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'webklex/php-imap' => array(
|
||||
'pretty_version' => '4.1.2',
|
||||
'version' => '4.1.2.0',
|
||||
'reference' => '94bf93ae8868ac1e073cfbaef377f0ca1acac2bc',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../webklex/php-imap',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
36
vendor/php-imap/php-imap/.codeclimate.yml
vendored
36
vendor/php-imap/php-imap/.codeclimate.yml
vendored
@@ -1,36 +0,0 @@
|
||||
# Advanced Configuration for CodeClimate: https://docs.codeclimate.com/docs
|
||||
languages:
|
||||
PHP: true
|
||||
exclude_paths: ["tests/*", "examples/*"]
|
||||
version: "2" # required to adjust maintainability checks
|
||||
checks:
|
||||
argument-count:
|
||||
config:
|
||||
threshold: 5
|
||||
complex-logic:
|
||||
config:
|
||||
threshold: 4
|
||||
file-lines:
|
||||
config:
|
||||
threshold: 250
|
||||
method-complexity:
|
||||
config:
|
||||
threshold: 5
|
||||
method-count:
|
||||
config:
|
||||
threshold: 20
|
||||
method-lines:
|
||||
config:
|
||||
threshold: 40
|
||||
nested-control-flow:
|
||||
config:
|
||||
threshold: 4
|
||||
return-statements:
|
||||
config:
|
||||
threshold: 4
|
||||
similar-code:
|
||||
config:
|
||||
threshold: # language-specific defaults. an override will affect all languages.
|
||||
identical-code:
|
||||
config:
|
||||
threshold: # language-specific defaults. an override will affect all languages.
|
||||
15
vendor/php-imap/php-imap/.editorconfig
vendored
15
vendor/php-imap/php-imap/.editorconfig
vendored
@@ -1,15 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.yml]
|
||||
indent_size = 2
|
||||
|
||||
[composer.json]
|
||||
indent_style = space
|
||||
@@ -1,21 +0,0 @@
|
||||
# How to contribute
|
||||
|
||||
First of all, thanks for taking the time to contribute!
|
||||
|
||||
Every contribution, being it pull requests, bug reports or feature requests, will help to improve this library!
|
||||
|
||||
## Ways to contribute
|
||||
|
||||
* Found a bug? Want a feature? Or just having question? [Open an
|
||||
issue!](https://github.com/barbushin/php-imap/issues/new/choose)
|
||||
* Add a feature or fix a bug:
|
||||
* Check for existing issue or create a new one.
|
||||
* Fork the repo, make your changes.
|
||||
* Create a pull request, and reference the issue.
|
||||
* Add examples, tests, or improve documentation.
|
||||
|
||||
## Test
|
||||
|
||||
When committing code, please make sure to test before creating a pull request.
|
||||
|
||||
We use PHPUnit for testing, feel free to add new tests. This is not a requirement, but helps us maintain code coverage.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[BUG] A short description of what the bug is"
|
||||
labels: needs investigation
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Environment (please complete the following information):**
|
||||
- PHP IMAP version: [e.g. 3.0.11]
|
||||
- PHP Version: [e.g. 7.1.26]
|
||||
- Type of execution: [e.g. Daemon / CLI or Web Server]
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior.
|
||||
|
||||
The used code:
|
||||
```php
|
||||
$mailbox = new Mailbox(...
|
||||
```
|
||||
|
||||
The headers of the parsed email, if required and possible (only, if it's NOT confidential):
|
||||
```
|
||||
Received: from BN3NAM04HT142.eop-NAM04.prod.protection.outlook.com
|
||||
(2603:10a6:209:2a::30) by AM6PR05MB6294.eurprd05.prod.outlook.com with HTTPS
|
||||
via AM6PR07CA0017.EURPRD07.PROD.OUTLOOK.COM; Sun, 5 May 2019 12:29:42 +0000
|
||||
Received: from BN3NAM04FT054.eop-NAM04.prod.protection.outlook.com
|
||||
(10.152.92.54) by BN3NAM04HT142.eop-NAM04.prod.protection.outlook.com
|
||||
(10.152.92.244) with Microsoft SMTP Server (version=TLS1_2,
|
||||
cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.1835.13; Sun, 5 May
|
||||
2019 12:29:41 +0000
|
||||
...
|
||||
```
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots / Outputs**
|
||||
If applicable, add screenshots or outputs of your script to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: "[Feature Request] A short description of what you want to happen"
|
||||
labels: needs investigation
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -1,16 +0,0 @@
|
||||
---
|
||||
name: Other Issue
|
||||
about: Ask your question, if it's not a bug or feature request
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Environment (please complete the following information):**
|
||||
- PHP IMAP version: [e.g. 3.0.11]
|
||||
- PHP Version: [e.g. 7.1.26]
|
||||
- Type of execution: [e.g. Daemon / CLI or Web Server]
|
||||
|
||||
**Your Text**
|
||||
A clear and concise description of what you want.
|
||||
@@ -1,16 +0,0 @@
|
||||
**Describe the change(s)**
|
||||
|
||||
A clear and concise description of what you changed and why you changed it.
|
||||
|
||||
**Example code to use new / updated methods**
|
||||
|
||||
```php
|
||||
$mailbox = new Mailbox(...
|
||||
```
|
||||
|
||||
---
|
||||
Make sure, that these boxes are checked before creating your pull request:
|
||||
|
||||
- [ ] A short description of this change is provided
|
||||
- [ ] A short example code is provided, if possible
|
||||
- [ ] PHPUnit tests for your changes exists
|
||||
@@ -1,53 +0,0 @@
|
||||
name: PHP Code Coverage
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
coverage:
|
||||
name: Coverage
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
strategy:
|
||||
matrix:
|
||||
operating-system: ['ubuntu-20.04']
|
||||
php-versions: ['8.1']
|
||||
|
||||
steps:
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
coverage: xdebug
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Validate composer.json and composer.lock
|
||||
run: composer validate
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: Cache Files
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
${{ steps.composer-cache.outputs.dir }}
|
||||
**/.php_cs.cache
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-composer-
|
||||
- name: Install dependencies
|
||||
if: steps.composer-cache.outputs.cache-hit != 'true'
|
||||
run: composer install --prefer-dist --no-progress --no-suggest
|
||||
|
||||
- name: Run tests
|
||||
uses: paambaati/codeclimate-action@v2.7.2
|
||||
env:
|
||||
CC_TEST_REPORTER_ID: "945dfb58a832d233a3caeb84e3e6d3be212e8c7abcb48117fce63b9adcb43647"
|
||||
with:
|
||||
coverageCommand: ./vendor/bin/phpunit --testdox --stop-on-failure --coverage-clover=clover.xml
|
||||
@@ -1,50 +0,0 @@
|
||||
name: PHP Static Analysis & Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
static-analysis:
|
||||
name: Static Analysis PHP ${{ matrix.php-versions }}
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
strategy:
|
||||
matrix:
|
||||
operating-system: ['ubuntu-20.04']
|
||||
php-versions: ['7.4', '8.0', '8.1']
|
||||
|
||||
steps:
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
coverage: none
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Validate composer.json and composer.lock
|
||||
run: composer validate
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: Cache Files
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
${{ steps.composer-cache.outputs.dir }}
|
||||
**/.php_cs.cache
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-composer-
|
||||
|
||||
- name: Install dependencies
|
||||
if: steps.composer-cache.outputs.cache-hit != 'true'
|
||||
run: composer install --prefer-dist --no-progress --no-suggest
|
||||
|
||||
- name: Run static analysis
|
||||
run: composer run static-analysis
|
||||
@@ -1,50 +0,0 @@
|
||||
name: PHP Unit Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
phpunit:
|
||||
name: PHP ${{ matrix.php-versions }} Unit Tests
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
strategy:
|
||||
matrix:
|
||||
operating-system: ['ubuntu-20.04']
|
||||
php-versions: ['7.4', '8.0', '8.1']
|
||||
|
||||
steps:
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
coverage: none
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Validate composer.json and composer.lock
|
||||
run: composer validate
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: Cache Files
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
${{ steps.composer-cache.outputs.dir }}
|
||||
**/.php_cs.cache
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-composer-
|
||||
|
||||
- name: Install dependencies
|
||||
if: steps.composer-cache.outputs.cache-hit != 'true'
|
||||
run: composer install --prefer-dist --no-progress --no-suggest
|
||||
|
||||
- name: Run tests
|
||||
run: ./vendor/bin/phpunit --testdox --stop-on-failure
|
||||
179
vendor/php-imap/php-imap/.gitignore
vendored
179
vendor/php-imap/php-imap/.gitignore
vendored
@@ -1,179 +0,0 @@
|
||||
# All of the vendor directory should be installed by running 'composer install'
|
||||
vendor/
|
||||
composer.lock
|
||||
*.phar
|
||||
.php-cs-fixer.cache
|
||||
coverage/
|
||||
psalm/cache/
|
||||
|
||||
#################
|
||||
## Eclipse
|
||||
#################
|
||||
|
||||
*.pydevproject
|
||||
.project
|
||||
.metadata
|
||||
.idea
|
||||
bin/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.classpath
|
||||
.settings/
|
||||
.loadpath
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# CDT-specific
|
||||
.cproject
|
||||
|
||||
# PDT-specific
|
||||
.buildpath
|
||||
|
||||
|
||||
#################
|
||||
## Visual Studio
|
||||
#################
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Rr]elease/
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.vspscc
|
||||
.builds
|
||||
*.dotCover
|
||||
|
||||
## TODO: If you have NuGet Package Restore enabled, uncomment this
|
||||
#packages/
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish
|
||||
|
||||
# Others
|
||||
[Bb]in
|
||||
[Oo]bj
|
||||
sql
|
||||
TestResults
|
||||
*.Cache
|
||||
ClientBin
|
||||
stylecop.*
|
||||
~$*
|
||||
*.dbmdl
|
||||
Generated_Code #added for RIA/Silverlight projects
|
||||
|
||||
# Backup & report files from converting an old project file to a newer
|
||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
|
||||
|
||||
|
||||
############
|
||||
## Windows
|
||||
############
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
|
||||
#############
|
||||
## Python
|
||||
#############
|
||||
|
||||
*.py[co]
|
||||
|
||||
# Packages
|
||||
*.egg
|
||||
*.egg-info
|
||||
dist
|
||||
build
|
||||
eggs
|
||||
parts
|
||||
bin
|
||||
var
|
||||
sdist
|
||||
develop-eggs
|
||||
.installed.cfg
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
.coverage
|
||||
.tox
|
||||
clover.xml
|
||||
|
||||
#Translations
|
||||
*.mo
|
||||
|
||||
#Mr Developer
|
||||
.mr.developer.cfg
|
||||
|
||||
# Mac crap
|
||||
.DS_Store
|
||||
|
||||
# NetBeans IDE
|
||||
nbproject/
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/
|
||||
39
vendor/php-imap/php-imap/.php-cs-fixer.dist.php
vendored
39
vendor/php-imap/php-imap/.php-cs-fixer.dist.php
vendored
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* This document has been generated with
|
||||
* https://mlocati.github.io/php-cs-fixer-configurator/#version:3.0.0-rc.1|configurator
|
||||
* you can change this configuration by importing this file.
|
||||
*/
|
||||
return (new PhpCsFixer\Config())
|
||||
->setRiskyAllowed(true)
|
||||
->setRules([
|
||||
'@Symfony' => true,
|
||||
'@Symfony:risky' => true,
|
||||
'@PHP71Migration' => true, // @PHP72Migration does not exist
|
||||
'@PHP71Migration:risky' => true, // @PHP72Migration:risky does not exist
|
||||
'array_syntax' => ['syntax' => 'short'],
|
||||
'declare_strict_types' => true,
|
||||
'global_namespace_import' => [
|
||||
'import_classes' => true,
|
||||
'import_constants' => true,
|
||||
'import_functions' => false,
|
||||
],
|
||||
'native_constant_invocation' => true,
|
||||
'native_function_invocation' => [
|
||||
'strict' => false,
|
||||
'include' => ['@compiler_optimized'],
|
||||
],
|
||||
'no_superfluous_phpdoc_tags' => true,
|
||||
'ordered_class_elements' => true,
|
||||
'ordered_imports' => true,
|
||||
'php_unit_dedicate_assert' => ['target' => 'newest'],
|
||||
'php_unit_method_casing' => true,
|
||||
'php_unit_test_case_static_method_calls' => ['call_type' => 'this'],
|
||||
'phpdoc_to_comment' => false,
|
||||
'void_return' => true,
|
||||
])
|
||||
->setFinder(PhpCsFixer\Finder::create()
|
||||
->exclude('vendor')
|
||||
->in(__DIR__)
|
||||
)
|
||||
;
|
||||
21
vendor/php-imap/php-imap/LICENSE
vendored
21
vendor/php-imap/php-imap/LICENSE
vendored
@@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2012 Sergey Barbushin <barbushin@gmail.com>
|
||||
|
||||
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.
|
||||
193
vendor/php-imap/php-imap/README.md
vendored
193
vendor/php-imap/php-imap/README.md
vendored
@@ -1,193 +0,0 @@
|
||||
# PHP IMAP
|
||||
|
||||
[](https://packagist.org/packages/php-imap/php-imap)
|
||||
[](README.md)
|
||||
[](LICENSE)
|
||||
[](https://packagist.org/packages/php-imap/php-imap)
|
||||
|
||||
[](https://github.com/barbushin/php-imap/actions/workflows/php_unit_tests.yml)
|
||||
[](https://github.com/barbushin/php-imap/actions/workflows/php_static_analysis.yml)
|
||||
[](https://github.com/barbushin/php-imap/actions/workflows/php_code_coverage.yml)
|
||||
|
||||
[](https://codeclimate.com/github/barbushin/php-imap/maintainability)
|
||||
[](https://codeclimate.com/github/barbushin/php-imap/test_coverage)
|
||||
[](https://shepherd.dev/github/barbushin/php-imap)
|
||||
|
||||
Initially released in December 2012, the PHP IMAP Mailbox is a powerful and open source library to connect to a mailbox by POP3, IMAP and NNTP using the PHP IMAP extension. This library allows you to fetch emails from your email server. Extend the functionality or create powerful web applications to handle your incoming emails.
|
||||
|
||||
### Features
|
||||
|
||||
* Connect to mailbox by POP3/IMAP/NNTP, using [PHP IMAP extension](http://php.net/manual/book.imap.php)
|
||||
* Get emails with attachments and inline images
|
||||
* Get emails filtered or sorted by custom criteria
|
||||
* Mark emails as seen/unseen
|
||||
* Delete emails
|
||||
* Manage mailbox folders
|
||||
|
||||
### Requirements
|
||||
|
||||
| PHP Version | php-imap Version | php-imap status |
|
||||
| ------------- | ------------- | ------------- |
|
||||
| 5.6 | 3.x | End of life |
|
||||
| 7.0 | 3.x | End of life |
|
||||
| 7.1 | 3.x | End of life |
|
||||
| 7.2 | 3.x, 4.x | End of life |
|
||||
| 7.3 | 3.x, 4.x | End of life |
|
||||
| 7.4 | >3.0.33, 4.x, 5.x | Active support |
|
||||
| 8.0 | >3.0.33, 4.x, 5.x | Active support |
|
||||
| 8.1 | >4.3.0, 5.x | Active support |
|
||||
|
||||
* PHP `fileinfo` extension must be present; so make sure this line is active in your php.ini: `extension=php_fileinfo.dll`
|
||||
* PHP `iconv` extension must be present; so make sure this line is active in your php.ini: `extension=php_iconv.dll`
|
||||
* PHP `imap` extension must be present; so make sure this line is active in your php.ini: `extension=php_imap.dll`
|
||||
* PHP `mbstring` extension must be present; so make sure this line is active in your php.ini: `extension=php_mbstring.dll`
|
||||
* PHP `json` extension must be present; so make sure this line is active in your php.ini: `extension=json.dll`
|
||||
|
||||
### Installation by Composer
|
||||
|
||||
Install the [latest available release](https://github.com/barbushin/php-imap/releases):
|
||||
|
||||
$ composer require php-imap/php-imap
|
||||
|
||||
Install the latest available and stable source code from `master`, which is may not released / tagged yet:
|
||||
|
||||
$ composer require php-imap/php-imap:dev-master
|
||||
|
||||
### Run Tests
|
||||
|
||||
Before you can run the any tests you may need to run `composer install` to install all (development) dependencies.
|
||||
|
||||
#### Run all tests
|
||||
|
||||
You can run all available tests by running the following command (inside of the installed `php-imap` directory): `composer run tests`
|
||||
|
||||
#### Run only PHPUnit tests
|
||||
|
||||
You can run all PHPUnit tests by running the following command (inside of the installed `php-imap` directory): `php vendor/bin/phpunit --testdox`
|
||||
|
||||
### Integration with frameworks
|
||||
|
||||
* Symfony - https://github.com/secit-pl/imap-bundle
|
||||
|
||||
### Getting Started Example
|
||||
|
||||
Below, you'll find an example code how you can use this library. For further information and other examples, you may take a look at the [wiki](https://github.com/barbushin/php-imap/wiki).
|
||||
|
||||
By default, this library uses random filenames for attachments as identical file names from other emails would overwrite other attachments. If you want to keep the original file name, you can set the attachment filename mode to ``true``, but then you also need to ensure, that those files don't get overwritten by other emails for example.
|
||||
|
||||
```php
|
||||
// Create PhpImap\Mailbox instance for all further actions
|
||||
$mailbox = new PhpImap\Mailbox(
|
||||
'{imap.gmail.com:993/imap/ssl}INBOX', // IMAP server and mailbox folder
|
||||
'some@gmail.com', // Username for the before configured mailbox
|
||||
'*********', // Password for the before configured username
|
||||
__DIR__, // Directory, where attachments will be saved (optional)
|
||||
'UTF-8', // Server encoding (optional)
|
||||
true, // Trim leading/ending whitespaces of IMAP path (optional)
|
||||
false // Attachment filename mode (optional; false = random filename; true = original filename)
|
||||
);
|
||||
|
||||
// set some connection arguments (if appropriate)
|
||||
$mailbox->setConnectionArgs(
|
||||
CL_EXPUNGE // expunge deleted mails upon mailbox close
|
||||
| OP_SECURE // don't do non-secure authentication
|
||||
);
|
||||
|
||||
try {
|
||||
// Get all emails (messages)
|
||||
// PHP.net imap_search criteria: http://php.net/manual/en/function.imap-search.php
|
||||
$mailsIds = $mailbox->searchMailbox('ALL');
|
||||
} catch(PhpImap\Exceptions\ConnectionException $ex) {
|
||||
echo "IMAP connection failed: " . implode(",", $ex->getErrors('all'));
|
||||
die();
|
||||
}
|
||||
|
||||
// If $mailsIds is empty, no emails could be found
|
||||
if(!$mailsIds) {
|
||||
die('Mailbox is empty');
|
||||
}
|
||||
|
||||
// Get the first message
|
||||
// If '__DIR__' was defined in the first line, it will automatically
|
||||
// save all attachments to the specified directory
|
||||
$mail = $mailbox->getMail($mailsIds[0]);
|
||||
|
||||
// Show, if $mail has one or more attachments
|
||||
echo "\nMail has attachments? ";
|
||||
if($mail->hasAttachments()) {
|
||||
echo "Yes\n";
|
||||
} else {
|
||||
echo "No\n";
|
||||
}
|
||||
|
||||
// Print all information of $mail
|
||||
print_r($mail);
|
||||
|
||||
// Print all attachements of $mail
|
||||
echo "\n\nAttachments:\n";
|
||||
print_r($mail->getAttachments());
|
||||
```
|
||||
|
||||
Method `imap()` allows to call any [PHP IMAP function](https://www.php.net/manual/ref.imap.php) in a context of the instance. Example:
|
||||
|
||||
```php
|
||||
// Call imap_check() - see http://php.net/manual/function.imap-check.php
|
||||
$info = $mailbox->imap('check');
|
||||
|
||||
|
||||
// Show current time for the mailbox
|
||||
$currentServerTime = isset($info->Date) && $info->Date ? date('Y-m-d H:i:s', strtotime($info->Date)) : 'Unknown';
|
||||
|
||||
echo $currentServerTime;
|
||||
```
|
||||
|
||||
Some request require much time and resources:
|
||||
|
||||
```php
|
||||
// If you don't need to grab attachments you can significantly increase performance of your application
|
||||
$mailbox->setAttachmentsIgnore(true);
|
||||
|
||||
// get the list of folders/mailboxes
|
||||
$folders = $mailbox->getMailboxes('*');
|
||||
|
||||
// loop through mailboxs
|
||||
foreach($folders as $folder) {
|
||||
|
||||
// switch to particular mailbox
|
||||
$mailbox->switchMailbox($folder['fullpath']);
|
||||
|
||||
// search in particular mailbox
|
||||
$mails_ids[$folder['fullpath']] = $mailbox->searchMailbox('SINCE "1 Jan 2018" BEFORE "28 Jan 2018"');
|
||||
}
|
||||
|
||||
print_r($mails_ids);
|
||||
```
|
||||
|
||||
### Upgrading from 3.x
|
||||
|
||||
Prior to 3.1, `Mailbox` used a "magic" method (`Mailbox::imap()`), with the
|
||||
class `Imap` now performing it's purpose to call many `imap_*` functions with
|
||||
automated string encoding/decoding of arguments and return values:
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
public function checkMailbox()
|
||||
{
|
||||
return $this->imap('check');
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
public function checkMailbox(): object
|
||||
{
|
||||
return Imap::check($this->getImapStream());
|
||||
}
|
||||
```
|
||||
|
||||
### Recommended
|
||||
|
||||
* Google Chrome extension [PHP Console](https://chrome.google.com/webstore/detail/php-console/nfhmhhlpfleoednkpnnnkolmclajemef)
|
||||
* Google Chrome extension [JavaScript Errors Notifier](https://chrome.google.com/webstore/detail/javascript-errors-notifie/jafmfknfnkoekkdocjiaipcnmkklaajd)
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"symbol-whitelist" : [
|
||||
"null", "true", "false",
|
||||
"static", "self", "parent",
|
||||
"array", "string", "int", "float", "bool", "iterable", "callable", "void", "object", "mixed", "never",
|
||||
"IMAP\\Connection"
|
||||
],
|
||||
"php-core-extensions" : [
|
||||
"Core",
|
||||
"date",
|
||||
"pcre",
|
||||
"Phar",
|
||||
"Reflection",
|
||||
"SPL",
|
||||
"standard"
|
||||
],
|
||||
"scan-files" : []
|
||||
}
|
||||
72
vendor/php-imap/php-imap/composer.json
vendored
72
vendor/php-imap/php-imap/composer.json
vendored
@@ -1,72 +0,0 @@
|
||||
{
|
||||
"name": "php-imap/php-imap",
|
||||
"description": "Manage mailboxes, filter/get/delete emails in PHP (supports IMAP/POP3/NNTP)",
|
||||
"keywords": [
|
||||
"PHP",
|
||||
"mail",
|
||||
"IMAP",
|
||||
"POP3",
|
||||
"mailbox",
|
||||
"receive emails"
|
||||
],
|
||||
"homepage": "https://github.com/barbushin/php-imap",
|
||||
"license": "MIT",
|
||||
"type": "library",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sergey Barbushin",
|
||||
"homepage": "http://linkedin.com/in/barbushin",
|
||||
"email": "barbushin@gmail.com"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"ext-fileinfo": "*",
|
||||
"ext-iconv": "*",
|
||||
"ext-imap": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-json": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.4",
|
||||
"maglnet/composer-require-checker": "^2.0|^3.2",
|
||||
"nikic/php-parser": "^4.3,<4.7|^4.10",
|
||||
"paragonie/hidden-string": "^1.0",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.3",
|
||||
"phpunit/phpunit": "^8.5|^9.5",
|
||||
"povils/phpmnd": "^2.2",
|
||||
"psalm/plugin-phpunit": "^0.10.0|^0.15.1",
|
||||
"roave/security-advisories": "dev-master",
|
||||
"sebastian/phpcpd": "^4.1|^6.0"
|
||||
},
|
||||
"scripts": {
|
||||
"static-analysis": [
|
||||
"parallel-lint .php-cs-fixer.dist.php src tests examples",
|
||||
"phpcpd src tests",
|
||||
"composer-require-checker check --config-file=composer-require-checker.config.json ./composer.json",
|
||||
"phpmnd ./ --exclude=./.github/ --exclude=./examples/ --exclude=./vendor/ --non-zero-exit-on-violation --hint",
|
||||
"php-cs-fixer fix --allow-risky=yes --no-interaction --dry-run -v",
|
||||
"psalm --show-info=false"
|
||||
],
|
||||
"tests": [
|
||||
"@static-analysis",
|
||||
"phpunit --testdox"
|
||||
]
|
||||
},
|
||||
"suggest": {
|
||||
"ext-fileinfo": "To facilitate IncomingMailAttachment::getFileInfo() auto-detection"
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"PhpImap\\": "tests/unit"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PhpImap\\": "src/PhpImap"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Example: Get and parse all emails which match the subject "part of the subject" with saving their attachments.
|
||||
*
|
||||
* @author Sebastian Krätzig <info@ts3-tools.info>
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__.'/../vendor/autoload.php';
|
||||
|
||||
use PhpImap\Exceptions\ConnectionException;
|
||||
use PhpImap\Mailbox;
|
||||
|
||||
$mailbox = new Mailbox(
|
||||
'{imap.gmail.com:993/imap/ssl}INBOX', // IMAP server and mailbox folder
|
||||
'some@gmail.com', // Username for the before configured mailbox
|
||||
'*********', // Password for the before configured username
|
||||
__DIR__, // Directory, where attachments will be saved (optional)
|
||||
'US-ASCII' // Server encoding (optional)
|
||||
);
|
||||
|
||||
try {
|
||||
$mail_ids = $mailbox->searchMailbox('SUBJECT "part of the subject"');
|
||||
} catch (ConnectionException $ex) {
|
||||
exit('IMAP connection failed: '.$ex->getMessage());
|
||||
} catch (Exception $ex) {
|
||||
exit('An error occured: '.$ex->getMessage());
|
||||
}
|
||||
|
||||
foreach ($mail_ids as $mail_id) {
|
||||
echo "+------ P A R S I N G ------+\n";
|
||||
|
||||
$email = $mailbox->getMail(
|
||||
$mail_id, // ID of the email, you want to get
|
||||
false // Do NOT mark emails as seen (optional)
|
||||
);
|
||||
|
||||
echo 'from-name: '.(string) ($email->fromName ?? $email->fromAddress)."\n";
|
||||
echo 'from-email: '.(string) $email->fromAddress."\n";
|
||||
echo 'to: '.(string) $email->toString."\n";
|
||||
echo 'subject: '.(string) $email->subject."\n";
|
||||
echo 'message_id: '.(string) $email->messageId."\n";
|
||||
|
||||
echo 'mail has attachments? ';
|
||||
if ($email->hasAttachments()) {
|
||||
echo "Yes\n";
|
||||
} else {
|
||||
echo "No\n";
|
||||
}
|
||||
|
||||
if (!empty($email->getAttachments())) {
|
||||
echo \count($email->getAttachments())." attachements\n";
|
||||
}
|
||||
if ($email->textHtml) {
|
||||
echo "Message HTML:\n".$email->textHtml;
|
||||
} else {
|
||||
echo "Message Plain:\n".$email->textPlain;
|
||||
}
|
||||
|
||||
if (!empty($email->autoSubmitted)) {
|
||||
// Mark email as "read" / "seen"
|
||||
$mailbox->markMailAsRead($mail_id);
|
||||
echo "+------ IGNORING: Auto-Reply ------+\n";
|
||||
}
|
||||
|
||||
if (!empty($email_content->precedence)) {
|
||||
// Mark email as "read" / "seen"
|
||||
$mailbox->markMailAsRead($mail_id);
|
||||
echo "+------ IGNORING: Non-Delivery Report/Receipt ------+\n";
|
||||
}
|
||||
}
|
||||
|
||||
$mailbox->disconnect();
|
||||
@@ -1,84 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Example: Get and parse all emails without saving their attachments.
|
||||
*
|
||||
* @author Sebastian Krätzig <info@ts3-tools.info>
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__.'/../vendor/autoload.php';
|
||||
|
||||
use PhpImap\Exceptions\ConnectionException;
|
||||
use PhpImap\Mailbox;
|
||||
|
||||
$mailbox = new Mailbox(
|
||||
'{imap.gmail.com:993/imap/ssl}INBOX', // IMAP server and mailbox folder
|
||||
'some@gmail.com', // Username for the before configured mailbox
|
||||
'*********', // Password for the before configured username
|
||||
null, // Directory, where attachments will be saved (optional)
|
||||
'US-ASCII' // Server encoding (optional)
|
||||
);
|
||||
|
||||
// OR
|
||||
$mailbox = new Mailbox(
|
||||
'{imap.gmail.com:993/imap/ssl}INBOX', // IMAP server and mailbox folder
|
||||
'some@gmail.com', // Username for the before configured mailbox
|
||||
'*********' // Password for the before configured username
|
||||
);
|
||||
|
||||
// If you haven't defined the server encoding (charset) in 'new Mailbox()', you can change it any time
|
||||
$mailbox->setServerEncoding('US-ASCII');
|
||||
|
||||
try {
|
||||
$mail_ids = $mailbox->searchMailbox('UNSEEN');
|
||||
} catch (ConnectionException $ex) {
|
||||
exit('IMAP connection failed: '.$ex->getMessage());
|
||||
} catch (Exception $ex) {
|
||||
exit('An error occured: '.$ex->getMessage());
|
||||
}
|
||||
|
||||
foreach ($mail_ids as $mail_id) {
|
||||
echo "+------ P A R S I N G ------+\n";
|
||||
|
||||
$email = $mailbox->getMail(
|
||||
$mail_id, // ID of the email, you want to get
|
||||
false // Do NOT mark emails as seen (optional)
|
||||
);
|
||||
|
||||
echo 'from-name: '.(string) ($email->fromName ?? $email->fromAddress)."\n";
|
||||
echo 'from-email: '.(string) $email->fromAddress."\n";
|
||||
echo 'to: '.(string) $email->toString."\n";
|
||||
echo 'subject: '.(string) $email->subject."\n";
|
||||
echo 'message_id: '.(string) $email->messageId."\n";
|
||||
|
||||
echo 'mail has attachments? ';
|
||||
if ($email->hasAttachments()) {
|
||||
echo "Yes\n";
|
||||
} else {
|
||||
echo "No\n";
|
||||
}
|
||||
|
||||
if (!empty($email->getAttachments())) {
|
||||
echo \count($email->getAttachments())." attachements\n";
|
||||
}
|
||||
if ($email->textHtml) {
|
||||
echo "Message HTML:\n".$email->textHtml;
|
||||
} else {
|
||||
echo "Message Plain:\n".$email->textPlain;
|
||||
}
|
||||
|
||||
if (!empty($email->autoSubmitted)) {
|
||||
// Mark email as "read" / "seen"
|
||||
$mailbox->markMailAsRead($mail_id);
|
||||
echo "+------ IGNORING: Auto-Reply ------+\n";
|
||||
}
|
||||
|
||||
if (!empty($email_content->precedence)) {
|
||||
// Mark email as "read" / "seen"
|
||||
$mailbox->markMailAsRead($mail_id);
|
||||
echo "+------ IGNORING: Non-Delivery Report/Receipt ------+\n";
|
||||
}
|
||||
}
|
||||
|
||||
$mailbox->disconnect();
|
||||
@@ -1,74 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Example: Get and parse all unseen emails with saving their attachments.
|
||||
*
|
||||
* @author Sebastian Krätzig <info@ts3-tools.info>
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__.'/../vendor/autoload.php';
|
||||
|
||||
use PhpImap\Exceptions\ConnectionException;
|
||||
use PhpImap\Mailbox;
|
||||
|
||||
$mailbox = new Mailbox(
|
||||
'{imap.gmail.com:993/imap/ssl}INBOX', // IMAP server and mailbox folder
|
||||
'some@gmail.com', // Username for the before configured mailbox
|
||||
'*********', // Password for the before configured username
|
||||
__DIR__, // Directory, where attachments will be saved (optional)
|
||||
'US-ASCII' // Server encoding (optional)
|
||||
);
|
||||
|
||||
try {
|
||||
$mail_ids = $mailbox->searchMailbox('UNSEEN');
|
||||
} catch (ConnectionException $ex) {
|
||||
exit('IMAP connection failed: '.$ex->getErrors('first'));
|
||||
} catch (Exception $ex) {
|
||||
exit('An error occured: '.$ex->getMessage());
|
||||
}
|
||||
|
||||
foreach ($mail_ids as $mail_id) {
|
||||
echo "+------ P A R S I N G ------+\n";
|
||||
|
||||
$email = $mailbox->getMail(
|
||||
$mail_id, // ID of the email, you want to get
|
||||
false // Do NOT mark emails as seen (optional)
|
||||
);
|
||||
|
||||
echo 'from-name: '.(string) ($email->fromName ?? $email->fromAddress)."\n";
|
||||
echo 'from-email: '.(string) $email->fromAddress."\n";
|
||||
echo 'to: '.(string) $email->toString."\n";
|
||||
echo 'subject: '.(string) $email->subject."\n";
|
||||
echo 'message_id: '.(string) $email->messageId."\n";
|
||||
|
||||
echo 'mail has attachments? ';
|
||||
if ($email->hasAttachments()) {
|
||||
echo "Yes\n";
|
||||
} else {
|
||||
echo "No\n";
|
||||
}
|
||||
|
||||
if (!empty($email->getAttachments())) {
|
||||
echo \count($email->getAttachments())." attachements\n";
|
||||
}
|
||||
if ($email->textHtml) {
|
||||
echo "Message HTML:\n".$email->textHtml;
|
||||
} else {
|
||||
echo "Message Plain:\n".$email->textPlain;
|
||||
}
|
||||
|
||||
if (!empty($email->autoSubmitted)) {
|
||||
// Mark email as "read" / "seen"
|
||||
$mailbox->markMailAsRead($mail_id);
|
||||
echo "+------ IGNORING: Auto-Reply ------+\n";
|
||||
}
|
||||
|
||||
if (!empty($email_content->precedence)) {
|
||||
// Mark email as "read" / "seen"
|
||||
$mailbox->markMailAsRead($mail_id);
|
||||
echo "+------ IGNORING: Non-Delivery Report/Receipt ------+\n";
|
||||
}
|
||||
}
|
||||
|
||||
$mailbox->disconnect();
|
||||
@@ -1,92 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Example: Get and parse all unseen emails with saving their attachments one by one.
|
||||
*
|
||||
* @author Sebastian Krätzig <info@ts3-tools.info>
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__.'/../vendor/autoload.php';
|
||||
|
||||
use PhpImap\Exceptions\ConnectionException;
|
||||
use PhpImap\Mailbox;
|
||||
|
||||
$mailbox = new Mailbox(
|
||||
'{imap.gmail.com:993/imap/ssl}INBOX', // IMAP server and mailbox folder
|
||||
'some@gmail.com', // Username for the before configured mailbox
|
||||
'*********' // Password for the before configured username
|
||||
);
|
||||
|
||||
try {
|
||||
$mail_ids = $mailbox->searchMailbox('UNSEEN');
|
||||
} catch (ConnectionException $ex) {
|
||||
exit('IMAP connection failed: '.$ex->getMessage());
|
||||
} catch (Exception $ex) {
|
||||
exit('An error occured: '.$ex->getMessage());
|
||||
}
|
||||
|
||||
foreach ($mail_ids as $mail_id) {
|
||||
echo "+------ P A R S I N G ------+\n";
|
||||
|
||||
$email = $mailbox->getMail(
|
||||
$mail_id, // ID of the email, you want to get
|
||||
false // Do NOT mark emails as seen (optional)
|
||||
);
|
||||
|
||||
echo 'from-name: '.(string) ($email->fromName ?? $email->fromAddress)."\n";
|
||||
echo 'from-email: '.(string) $email->fromAddress."\n";
|
||||
echo 'to: '.(string) $email->toString."\n";
|
||||
echo 'subject: '.(string) $email->subject."\n";
|
||||
echo 'message_id: '.(string) $email->messageId."\n";
|
||||
|
||||
echo 'mail has attachments? ';
|
||||
if ($email->hasAttachments()) {
|
||||
echo "Yes\n";
|
||||
} else {
|
||||
echo "No\n";
|
||||
}
|
||||
|
||||
if (!empty($email->getAttachments())) {
|
||||
echo \count($email->getAttachments())." attachements\n";
|
||||
}
|
||||
|
||||
// Save attachments one by one
|
||||
if (!$mailbox->getAttachmentsIgnore()) {
|
||||
$attachments = $email->getAttachments();
|
||||
|
||||
foreach ($attachments as $attachment) {
|
||||
echo '--> Saving '.(string) $attachment->name.'...';
|
||||
|
||||
// Set individually filePath for each single attachment
|
||||
// In this case, every file will get the current Unix timestamp
|
||||
$attachment->setFilePath(__DIR__.'/files/'.\time());
|
||||
|
||||
if ($attachment->saveToDisk()) {
|
||||
echo "OK, saved!\n";
|
||||
} else {
|
||||
echo "ERROR, could not save!\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($email->textHtml) {
|
||||
echo "Message HTML:\n".$email->textHtml;
|
||||
} else {
|
||||
echo "Message Plain:\n".$email->textPlain;
|
||||
}
|
||||
|
||||
if (!empty($email->autoSubmitted)) {
|
||||
// Mark email as "read" / "seen"
|
||||
$mailbox->markMailAsRead($mail_id);
|
||||
echo "+------ IGNORING: Auto-Reply ------+\n";
|
||||
}
|
||||
|
||||
if (!empty($email_content->precedence)) {
|
||||
// Mark email as "read" / "seen"
|
||||
$mailbox->markMailAsRead($mail_id);
|
||||
echo "+------ IGNORING: Non-Delivery Report/Receipt ------+\n";
|
||||
}
|
||||
}
|
||||
|
||||
$mailbox->disconnect();
|
||||
27
vendor/php-imap/php-imap/phpunit.xml
vendored
27
vendor/php-imap/php-imap/phpunit.xml
vendored
@@ -1,27 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
bootstrap="vendor/autoload.php"
|
||||
verbose="true"
|
||||
stopOnError="false"
|
||||
stopOnFailure="false"
|
||||
stopOnIncomplete="false"
|
||||
stopOnSkipped="false"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
colors="true"
|
||||
forceCoversAnnotation="false"
|
||||
processIsolation="false"
|
||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
|
||||
<coverage>
|
||||
<include>
|
||||
<directory>src</directory>
|
||||
</include>
|
||||
</coverage>
|
||||
<testsuites>
|
||||
<testsuite name="php-imap Tests">
|
||||
<directory>tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
||||
57
vendor/php-imap/php-imap/psalm.baseline.xml
vendored
57
vendor/php-imap/php-imap/psalm.baseline.xml
vendored
@@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<files psalm-version="3.12.2@7c7ebd068f8acaba211d4a2c707c4ba90874fa26">
|
||||
<file src="examples/get_and_parse_all_emails_without_saving_attachments.php">
|
||||
<UnusedVariable occurrences="1">
|
||||
<code>$mailbox</code>
|
||||
</UnusedVariable>
|
||||
</file>
|
||||
<file src="src/PhpImap/Imap.php">
|
||||
<DocblockTypeContradiction occurrences="3">
|
||||
<code>\is_int($section)</code>
|
||||
<code>!\is_string($section) && !\is_int($section)</code>
|
||||
<code>\is_resource($maybe)</code>
|
||||
</DocblockTypeContradiction>
|
||||
</file>
|
||||
<file src="src/PhpImap/Mailbox.php">
|
||||
<DocblockTypeContradiction occurrences="2">
|
||||
<code>\in_array($imapSearchOption, $supported_options, true)</code>
|
||||
<code>\in_array($key, $supported_params, true)</code>
|
||||
</DocblockTypeContradiction>
|
||||
<InvalidArgument occurrences="3">
|
||||
<code>$element->charset</code>
|
||||
<code>$element->text</code>
|
||||
<code>$element->text</code>
|
||||
</InvalidArgument>
|
||||
<PossiblyUnusedMethod occurrences="24">
|
||||
<code>setConnectionRetry</code>
|
||||
<code>setConnectionRetryDelay</code>
|
||||
<code>setExpungeOnDisconnect</code>
|
||||
<code>renameMailbox</code>
|
||||
<code>getListingFolders</code>
|
||||
<code>searchMailboxFrom</code>
|
||||
<code>searchMailboxFromDisableServerEncoding</code>
|
||||
<code>searchMailboxMergeResults</code>
|
||||
<code>searchMailboxMergeResultsDisableServerEncoding</code>
|
||||
<code>saveMail</code>
|
||||
<code>moveMail</code>
|
||||
<code>copyMail</code>
|
||||
<code>markMailAsUnread</code>
|
||||
<code>markMailAsImportant</code>
|
||||
<code>markMailsAsRead</code>
|
||||
<code>markMailsAsUnread</code>
|
||||
<code>markMailsAsImportant</code>
|
||||
<code>getMailboxHeaders</code>
|
||||
<code>getMailboxInfo</code>
|
||||
<code>getQuotaLimit</code>
|
||||
<code>getQuotaUsage</code>
|
||||
<code>getSubscribedMailboxes</code>
|
||||
<code>subscribeMailbox</code>
|
||||
<code>unsubscribeMailbox</code>
|
||||
</PossiblyUnusedMethod>
|
||||
</file>
|
||||
<file src="tests/unit/MailboxTest.php">
|
||||
<InvalidArgument occurrences="1">
|
||||
<code>self::ANYTHING</code>
|
||||
</InvalidArgument>
|
||||
</file>
|
||||
</files>
|
||||
37
vendor/php-imap/php-imap/psalm.xml
vendored
37
vendor/php-imap/php-imap/psalm.xml
vendored
@@ -1,37 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<psalm
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
name="Psalm for php-imap"
|
||||
useDocblockTypes="true"
|
||||
errorLevel="1"
|
||||
strictBinaryOperands="false"
|
||||
rememberPropertyAssignmentsAfterCall="true"
|
||||
checkForThrowsDocblock="false"
|
||||
throwExceptionOnError="0"
|
||||
findUnusedCode="false"
|
||||
ensureArrayStringOffsetsExist="true"
|
||||
ensureArrayIntOffsetsExist="true"
|
||||
resolveFromConfigFile="true"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config config.xsd"
|
||||
limitMethodComplexity="true"
|
||||
errorBaseline="./psalm.baseline.xml"
|
||||
cacheDirectory="./psalm/cache/"
|
||||
findUnusedPsalmSuppress="true"
|
||||
>
|
||||
<projectFiles>
|
||||
<file name="./.php-cs-fixer.dist.php"/>
|
||||
<directory name="src"/>
|
||||
<ignoreFiles>
|
||||
<directory name="tests"/>
|
||||
<directory name="examples"/>
|
||||
<directory name="vendor"/>
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
|
||||
<issueHandlers>
|
||||
</issueHandlers>
|
||||
<plugins>
|
||||
<pluginClass class="Psalm\PhpUnitPlugin\Plugin"/>
|
||||
</plugins>
|
||||
</psalm>
|
||||
@@ -1,126 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap;
|
||||
|
||||
use const ENC8BIT;
|
||||
use const ENCBASE64;
|
||||
use const ENCBINARY;
|
||||
use const ENCQUOTEDPRINTABLE;
|
||||
|
||||
/**
|
||||
* @see https://github.com/barbushin/php-imap
|
||||
*
|
||||
* @author nickl- http://github.com/nickl-
|
||||
*/
|
||||
class DataPartInfo
|
||||
{
|
||||
public const TEXT_PLAIN = 0;
|
||||
|
||||
public const TEXT_HTML = 1;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @readonly
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @var int|mixed
|
||||
*
|
||||
* @readonly
|
||||
*/
|
||||
public $encoding;
|
||||
|
||||
/** @var string|null */
|
||||
public $charset;
|
||||
|
||||
/**
|
||||
* @var 0|string
|
||||
*
|
||||
* @readonly
|
||||
*/
|
||||
public $part;
|
||||
|
||||
/**
|
||||
* @var Mailbox
|
||||
*
|
||||
* @readonly
|
||||
*/
|
||||
public $mail;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @readonly
|
||||
*/
|
||||
public $options;
|
||||
|
||||
/** @var string|null */
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @param 0|string $part
|
||||
* @param int|mixed $encoding
|
||||
*/
|
||||
public function __construct(Mailbox $mail, int $id, $part, $encoding, int $options)
|
||||
{
|
||||
$this->mail = $mail;
|
||||
$this->id = $id;
|
||||
$this->part = $part;
|
||||
$this->encoding = $encoding;
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
public function fetch(): string
|
||||
{
|
||||
if (0 === $this->part) {
|
||||
$this->data = Imap::body($this->mail->getImapStream(), $this->id, $this->options);
|
||||
} else {
|
||||
if (null !== $this->data) {
|
||||
return $this->data;
|
||||
}
|
||||
$this->data = Imap::fetchbody($this->mail->getImapStream(), $this->id, $this->part, $this->options);
|
||||
}
|
||||
|
||||
return $this->decodeAfterFetch($this->data);
|
||||
}
|
||||
|
||||
public function decodeAfterFetch(string $data): string
|
||||
{
|
||||
switch ($this->encoding) {
|
||||
case ENC8BIT:
|
||||
$this->data = \imap_utf8((string) $data);
|
||||
break;
|
||||
case ENCBINARY:
|
||||
$this->data = \imap_binary((string) $data);
|
||||
break;
|
||||
case ENCBASE64:
|
||||
$this->data = \base64_decode((string) $data, false);
|
||||
break;
|
||||
case ENCQUOTEDPRINTABLE:
|
||||
$this->data = \quoted_printable_decode((string) $data);
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->convertEncodingAfterFetch();
|
||||
}
|
||||
|
||||
protected function convertEncodingAfterFetch(): string
|
||||
{
|
||||
if (isset($this->charset) && !empty(\trim($this->charset))) {
|
||||
$this->data = $this->mail->decodeMimeStr(
|
||||
(string) $this->data // Data to convert
|
||||
);
|
||||
|
||||
$this->data = $this->mail->convertToUtf8(
|
||||
$this->data,
|
||||
$this->charset
|
||||
);
|
||||
}
|
||||
|
||||
return (null === $this->data) ? '' : $this->data;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* @see https://github.com/barbushin/php-imap
|
||||
*
|
||||
* @author Barbushin Sergey http://linkedin.com/in/barbushin
|
||||
*/
|
||||
class ConnectionException extends Exception
|
||||
{
|
||||
public function __construct(array $message, int $code = 0, Exception $previous = null)
|
||||
{
|
||||
parent::__construct(json_encode($message), $code, $previous);
|
||||
}
|
||||
|
||||
public function getErrors(string $select = 'first')
|
||||
{
|
||||
$message = $this->getMessage();
|
||||
|
||||
switch (strtolower($select)) {
|
||||
case 'all':
|
||||
return json_decode($message);
|
||||
break;
|
||||
default:
|
||||
case 'first':
|
||||
$message = json_decode($message);
|
||||
|
||||
return $message[0];
|
||||
break;
|
||||
case 'last':
|
||||
$message = json_decode($message);
|
||||
|
||||
return $message[\count($message) - 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* @see https://github.com/barbushin/php-imap
|
||||
*
|
||||
* @author Barbushin Sergey http://linkedin.com/in/barbushin
|
||||
*/
|
||||
class InvalidParameterException extends Exception
|
||||
{
|
||||
}
|
||||
1163
vendor/php-imap/php-imap/src/PhpImap/Imap.php
vendored
1163
vendor/php-imap/php-imap/src/PhpImap/Imap.php
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,247 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap;
|
||||
|
||||
use const FILEINFO_MIME_TYPE;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* The PhpImap IncomingMail class.
|
||||
*
|
||||
* @author Barbushin Sergey http://linkedin.com/in/barbushin
|
||||
*
|
||||
* @see https://github.com/barbushin/php-imap
|
||||
*
|
||||
* @property string $textPlain lazy plain message body
|
||||
* @property string $textHtml lazy html message body
|
||||
*/
|
||||
class IncomingMail extends IncomingMailHeader
|
||||
{
|
||||
/**
|
||||
* @var IncomingMailAttachment[]
|
||||
*/
|
||||
protected $attachments = [];
|
||||
|
||||
/** @var bool */
|
||||
protected $hasAttachments = false;
|
||||
|
||||
/**
|
||||
* @var DataPartInfo[][]
|
||||
*
|
||||
* @psalm-var array{0:list<DataPartInfo>, 1:list<DataPartInfo>}
|
||||
*/
|
||||
protected $dataInfo = [[], []];
|
||||
|
||||
/** @var string|null */
|
||||
private $textPlain;
|
||||
|
||||
/** @var string|null */
|
||||
private $textHtml;
|
||||
|
||||
/**
|
||||
* __get() is utilized for reading data from inaccessible (protected
|
||||
* or private) or non-existing properties.
|
||||
*
|
||||
* @param string $name Name of the property (eg. textPlain)
|
||||
*
|
||||
* @return string Value of the property (eg. Plain text message)
|
||||
*/
|
||||
public function __get(string $name): string
|
||||
{
|
||||
$type = false;
|
||||
if ('textPlain' == $name) {
|
||||
$type = DataPartInfo::TEXT_PLAIN;
|
||||
}
|
||||
if ('textHtml' == $name) {
|
||||
$type = DataPartInfo::TEXT_HTML;
|
||||
}
|
||||
if (('textPlain' === $name || 'textHtml' === $name) && isset($this->$name)) {
|
||||
return (string) $this->$name;
|
||||
}
|
||||
if (false === $type) {
|
||||
\trigger_error("Undefined property: IncomingMail::$name");
|
||||
}
|
||||
if (!isset($this->$name)) {
|
||||
$this->$name = '';
|
||||
}
|
||||
foreach ($this->dataInfo[$type] as $data) {
|
||||
$this->$name .= \trim($data->fetch());
|
||||
}
|
||||
|
||||
/** @var string */
|
||||
return $this->$name;
|
||||
}
|
||||
|
||||
/**
|
||||
* The method __isset() is triggered by calling isset() or empty()
|
||||
* on inaccessible (protected or private) or non-existing properties.
|
||||
*
|
||||
* @param string $name Name of the property (eg. textPlain)
|
||||
*
|
||||
* @return bool True, if property is set or empty
|
||||
*/
|
||||
public function __isset(string $name): bool
|
||||
{
|
||||
self::__get($name);
|
||||
|
||||
return isset($this->$name);
|
||||
}
|
||||
|
||||
public function setHeader(IncomingMailHeader $header): void
|
||||
{
|
||||
/** @psalm-var array<string, scalar|array|object|null> */
|
||||
$array = \get_object_vars($header);
|
||||
foreach ($array as $property => $value) {
|
||||
$this->$property = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DataPartInfo::TEXT_PLAIN|DataPartInfo::TEXT_HTML $type
|
||||
*/
|
||||
public function addDataPartInfo(DataPartInfo $dataInfo, int $type): void
|
||||
{
|
||||
$this->dataInfo[$type][] = $dataInfo;
|
||||
}
|
||||
|
||||
public function addAttachment(IncomingMailAttachment $attachment): void
|
||||
{
|
||||
if (!\is_string($attachment->id)) {
|
||||
throw new InvalidArgumentException('Argument 1 passed to '.__METHOD__.'() does not have an id specified!');
|
||||
}
|
||||
$this->attachments[$attachment->id] = $attachment;
|
||||
|
||||
$this->setHasAttachments(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets property $hasAttachments.
|
||||
*
|
||||
* @param bool $hasAttachments True, if IncomingMail[] has one or more attachments
|
||||
*/
|
||||
public function setHasAttachments(bool $hasAttachments): void
|
||||
{
|
||||
$this->hasAttachments = $hasAttachments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns, if the mail has attachments or not.
|
||||
*
|
||||
* @return bool true or false
|
||||
*/
|
||||
public function hasAttachments(): bool
|
||||
{
|
||||
return $this->hasAttachments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return IncomingMailAttachment[]
|
||||
*/
|
||||
public function getAttachments(): array
|
||||
{
|
||||
return $this->attachments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id The attachment id
|
||||
*/
|
||||
public function removeAttachment(string $id): bool
|
||||
{
|
||||
if (!isset($this->attachments[$id])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unset($this->attachments[$id]);
|
||||
|
||||
$this->setHasAttachments([] !== $this->attachments);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of internal HTML links placeholders.
|
||||
*
|
||||
* @return array attachmentId => link placeholder
|
||||
*
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getInternalLinksPlaceholders(): array
|
||||
{
|
||||
$fetchedHtml = $this->__get('textHtml');
|
||||
|
||||
$match = \preg_match_all('/=["\'](ci?d:([\w\.%*@-]+))["\']/i', $fetchedHtml, $matches);
|
||||
|
||||
/** @psalm-var array{1:list<string>, 2:list<string>} */
|
||||
$matches = $matches;
|
||||
|
||||
return $match ? \array_combine($matches[2], $matches[1]) : [];
|
||||
}
|
||||
|
||||
public function replaceInternalLinks(string $baseUri): string
|
||||
{
|
||||
$baseUri = \rtrim($baseUri, '\\/').'/';
|
||||
$fetchedHtml = $this->textHtml;
|
||||
$search = [];
|
||||
$replace = [];
|
||||
foreach ($this->getInternalLinksPlaceholders() as $attachmentId => $placeholder) {
|
||||
foreach ($this->attachments as $attachment) {
|
||||
if ($attachment->contentId == $attachmentId) {
|
||||
if (!\is_string($attachment->id)) {
|
||||
throw new InvalidArgumentException('Argument 1 passed to '.__METHOD__.'() does not have an id specified!');
|
||||
}
|
||||
$search[] = $placeholder;
|
||||
$replace[] = $baseUri.\basename($this->attachments[$attachment->id]->filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @psalm-var string */
|
||||
return \str_replace($search, $replace, $fetchedHtml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Embed inline image attachments as base64 to allow for
|
||||
* email html to display inline images automatically.
|
||||
*/
|
||||
public function embedImageAttachments(): void
|
||||
{
|
||||
$fetchedHtml = $this->__get('textHtml');
|
||||
|
||||
\preg_match_all("/\bcid:[^'\"\s]{1,256}/mi", $fetchedHtml, $matches);
|
||||
|
||||
if (isset($matches[0]) && \is_array($matches[0]) && \count($matches[0])) {
|
||||
/** @var list<string> */
|
||||
$matches = $matches[0];
|
||||
$attachments = $this->getAttachments();
|
||||
foreach ($matches as $match) {
|
||||
$cid = \str_replace('cid:', '', $match);
|
||||
|
||||
foreach ($attachments as $attachment) {
|
||||
/**
|
||||
* Inline images can contain a "Content-Disposition: inline", but only a "Content-ID" is also enough.
|
||||
* See https://github.com/barbushin/php-imap/issues/569.
|
||||
*/
|
||||
if ($attachment->contentId == $cid || 'inline' == \mb_strtolower((string) $attachment->disposition)) {
|
||||
$contents = $attachment->getContents();
|
||||
$contentType = $attachment->getFileInfo(FILEINFO_MIME_TYPE);
|
||||
|
||||
if (!\strstr($contentType, 'image')) {
|
||||
continue;
|
||||
} elseif (!\is_string($attachment->id)) {
|
||||
throw new InvalidArgumentException('Argument 1 passed to '.__METHOD__.'() does not have an id specified!');
|
||||
}
|
||||
|
||||
$base64encoded = \base64_encode($contents);
|
||||
$replacement = 'data:'.$contentType.';base64, '.$base64encoded;
|
||||
|
||||
$this->textHtml = \str_replace($match, $replacement, $this->textHtml);
|
||||
|
||||
$this->removeAttachment($attachment->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap;
|
||||
|
||||
use const FILEINFO_NONE;
|
||||
use finfo;
|
||||
use UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* @see https://github.com/barbushin/php-imap
|
||||
*
|
||||
* @author Barbushin Sergey http://linkedin.com/in/barbushin
|
||||
*
|
||||
* @property string|false|null $filePath lazy attachment data file
|
||||
*
|
||||
* @psalm-type fileinfoconst = 0|2|16|1024|1040|8|32|128|256|16777216
|
||||
*/
|
||||
class IncomingMailAttachment
|
||||
{
|
||||
/** @var string|null */
|
||||
public $id;
|
||||
|
||||
/** @var string|null */
|
||||
public $contentId;
|
||||
|
||||
/** @var int|null */
|
||||
public $type;
|
||||
|
||||
/** @var int|null */
|
||||
public $encoding;
|
||||
|
||||
/** @var string|null */
|
||||
public $subtype;
|
||||
|
||||
/** @var string|null */
|
||||
public $description;
|
||||
|
||||
/** @var string|null */
|
||||
public $name;
|
||||
|
||||
/** @var int|null */
|
||||
public $sizeInBytes;
|
||||
|
||||
/** @var string|null */
|
||||
public $disposition;
|
||||
|
||||
/** @var string|null */
|
||||
public $charset;
|
||||
|
||||
/** @var bool|null */
|
||||
public $emlOrigin;
|
||||
|
||||
/** @var string|null */
|
||||
public $fileInfoRaw;
|
||||
|
||||
/** @var string|null */
|
||||
public $fileInfo;
|
||||
|
||||
/** @var string|null */
|
||||
public $mime;
|
||||
|
||||
/** @var string|null */
|
||||
public $mimeEncoding;
|
||||
|
||||
/** @var string|null */
|
||||
public $fileExtension;
|
||||
|
||||
/** @var string|null */
|
||||
public $mimeType;
|
||||
|
||||
/** @var string|null */
|
||||
private $file_path;
|
||||
|
||||
/** @var DataPartInfo|null */
|
||||
private $dataInfo;
|
||||
|
||||
/** @var string|null */
|
||||
private $filePath;
|
||||
|
||||
/**
|
||||
* @return false|string
|
||||
*/
|
||||
public function __get(string $name)
|
||||
{
|
||||
if ('filePath' !== $name) {
|
||||
\trigger_error("Undefined property: IncomingMailAttachment::$name");
|
||||
}
|
||||
|
||||
if (!isset($this->file_path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->filePath = $this->file_path;
|
||||
|
||||
if (@\file_exists($this->file_path)) {
|
||||
return $this->filePath;
|
||||
}
|
||||
|
||||
return $this->filePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the file path.
|
||||
*
|
||||
* @param string $filePath File path incl. file name and optional extension
|
||||
*/
|
||||
public function setFilePath(string $filePath): void
|
||||
{
|
||||
$this->file_path = $filePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data part info.
|
||||
*
|
||||
* @param DataPartInfo $dataInfo Date info (file content)
|
||||
*/
|
||||
public function addDataPartInfo(DataPartInfo $dataInfo): void
|
||||
{
|
||||
$this->dataInfo = $dataInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets information about a file.
|
||||
*
|
||||
* @param int $fileinfo_const Any predefined constant. See https://www.php.net/manual/en/fileinfo.constants.php
|
||||
*
|
||||
* @psalm-param fileinfoconst $fileinfo_const
|
||||
*/
|
||||
public function getFileInfo(int $fileinfo_const = FILEINFO_NONE): string
|
||||
{
|
||||
$finfo = new finfo($fileinfo_const);
|
||||
|
||||
return $finfo->buffer($this->getContents());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file content.
|
||||
*/
|
||||
public function getContents(): string
|
||||
{
|
||||
if (null === $this->dataInfo) {
|
||||
throw new UnexpectedValueException(static::class.'::$dataInfo has not been set by calling '.self::class.'::addDataPartInfo()');
|
||||
}
|
||||
|
||||
return $this->dataInfo->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the attachment object on the disk.
|
||||
*
|
||||
* @return bool True, if it could save the attachment on the disk
|
||||
*/
|
||||
public function saveToDisk(): bool
|
||||
{
|
||||
if (null === $this->dataInfo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (false === \file_put_contents($this->__get('filePath'), $this->dataInfo->fetch())) {
|
||||
unset($this->filePath, $this->file_path);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap;
|
||||
|
||||
/**
|
||||
* @see https://github.com/barbushin/php-imap
|
||||
*
|
||||
* @author Barbushin Sergey http://linkedin.com/in/barbushin
|
||||
*/
|
||||
class IncomingMailHeader
|
||||
{
|
||||
/** @var int|null The IMAP message ID - not the "Message-ID:"-header of the email */
|
||||
public $id;
|
||||
|
||||
/** @var string|null */
|
||||
public $imapPath;
|
||||
|
||||
/** @var string|null */
|
||||
public $mailboxFolder;
|
||||
|
||||
/** @var bool */
|
||||
public $isSeen = false;
|
||||
|
||||
/** @var bool */
|
||||
public $isAnswered = false;
|
||||
|
||||
/** @var bool */
|
||||
public $isRecent = false;
|
||||
|
||||
/** @var bool */
|
||||
public $isFlagged = false;
|
||||
|
||||
/** @var bool */
|
||||
public $isDeleted = false;
|
||||
|
||||
/** @var bool */
|
||||
public $isDraft = false;
|
||||
|
||||
/** @var string|null */
|
||||
public $date;
|
||||
|
||||
/** @var string|null */
|
||||
public $headersRaw;
|
||||
|
||||
/** @var object|null */
|
||||
public $headers;
|
||||
|
||||
/** @var string|null */
|
||||
public $mimeVersion;
|
||||
|
||||
/** @var string|null */
|
||||
public $xVirusScanned;
|
||||
|
||||
/** @var string|null */
|
||||
public $organization;
|
||||
|
||||
/** @var string|null */
|
||||
public $contentType;
|
||||
|
||||
/** @var string|null */
|
||||
public $xMailer;
|
||||
|
||||
/** @var string|null */
|
||||
public $contentLanguage;
|
||||
|
||||
/** @var string|null */
|
||||
public $xSenderIp;
|
||||
|
||||
/** @var string|null */
|
||||
public $priority;
|
||||
|
||||
/** @var string|null */
|
||||
public $importance;
|
||||
|
||||
/** @var string|null */
|
||||
public $sensitivity;
|
||||
|
||||
/** @var string|null */
|
||||
public $autoSubmitted;
|
||||
|
||||
/** @var string|null */
|
||||
public $precedence;
|
||||
|
||||
/** @var string|null */
|
||||
public $failedRecipients;
|
||||
|
||||
/** @var string|null */
|
||||
public $subject;
|
||||
|
||||
/** @var string|null */
|
||||
public $fromHost;
|
||||
|
||||
/** @var string|null */
|
||||
public $fromName;
|
||||
|
||||
/** @var string|null */
|
||||
public $fromAddress;
|
||||
|
||||
/** @var string|null */
|
||||
public $senderHost;
|
||||
|
||||
/** @var string|null */
|
||||
public $senderName;
|
||||
|
||||
/** @var string|null */
|
||||
public $senderAddress;
|
||||
|
||||
/** @var string|null */
|
||||
public $xOriginalTo;
|
||||
|
||||
/**
|
||||
* @var (string|null)[]
|
||||
*
|
||||
* @psalm-var array<string, string|null>
|
||||
*/
|
||||
public $to = [];
|
||||
|
||||
/** @var string|null */
|
||||
public $toString;
|
||||
|
||||
/**
|
||||
* @var (string|null)[]
|
||||
*
|
||||
* @psalm-var array<string, string|null>
|
||||
*/
|
||||
public $cc = [];
|
||||
|
||||
/** @var string|null */
|
||||
public $ccString;
|
||||
|
||||
/**
|
||||
* @var (string|null)[]
|
||||
*
|
||||
* @psalm-var array<string, string|null>
|
||||
*/
|
||||
public $bcc = [];
|
||||
|
||||
/**
|
||||
* @var (string|null)[]
|
||||
*
|
||||
* @psalm-var array<string, string|null>
|
||||
*/
|
||||
public $replyTo = [];
|
||||
|
||||
/** @var string|null */
|
||||
public $messageId;
|
||||
}
|
||||
2069
vendor/php-imap/php-imap/src/PhpImap/Mailbox.php
vendored
2069
vendor/php-imap/php-imap/src/PhpImap/Mailbox.php
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,210 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Live Mailbox - PHPUnit tests.
|
||||
*
|
||||
* Runs tests on a live mailbox
|
||||
*
|
||||
* @author BAPCLTD-Marv
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap;
|
||||
|
||||
use Generator;
|
||||
use ParagonIE\HiddenString\HiddenString;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* @psalm-type MAILBOX_ARGS = array{
|
||||
* 0:HiddenString,
|
||||
* 1:HiddenString,
|
||||
* 2:HiddenString,
|
||||
* 3:string,
|
||||
* 4?:string
|
||||
* }
|
||||
* @psalm-type COMPOSE_ENVELOPE = array{
|
||||
* subject?:string
|
||||
* }
|
||||
* @psalm-type COMPOSE_BODY = list<array{
|
||||
* type?:int,
|
||||
* encoding?:int,
|
||||
* charset?:string,
|
||||
* subtype?:string,
|
||||
* description?:string,
|
||||
* 'disposition.type'?:string,
|
||||
* 'type.parameters'?:array{name:string},
|
||||
* 'contents.data'?:string,
|
||||
* id?:string,
|
||||
* disposition?:array{filename:string}
|
||||
* }>
|
||||
*/
|
||||
abstract class AbstractLiveMailboxTest extends TestCase
|
||||
{
|
||||
use LiveMailboxTestingTrait;
|
||||
|
||||
/**
|
||||
* @psalm-return Generator<empty, empty, mixed, void>
|
||||
*/
|
||||
public function ComposeProvider(): Generator
|
||||
{
|
||||
yield from [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-return Generator<int, array{
|
||||
* 0:MAILBOX_ARGS,
|
||||
* 1:COMPOSE_ENVELOPE,
|
||||
* 2:COMPOSE_BODY,
|
||||
* 3:string,
|
||||
* 4:bool
|
||||
* }, mixed, void>
|
||||
*/
|
||||
public function AppendProvider(): Generator
|
||||
{
|
||||
foreach ($this->MailBoxProvider() as $mailbox_args) {
|
||||
foreach ($this->ComposeProvider() as $compose_args) {
|
||||
[$envelope, $body, $expected_compose_result] = $compose_args;
|
||||
|
||||
yield [$mailbox_args, $envelope, $body, $expected_compose_result, false];
|
||||
}
|
||||
|
||||
foreach ($this->ComposeProvider() as $compose_args) {
|
||||
[$envelope, $body, $expected_compose_result] = $compose_args;
|
||||
|
||||
yield [$mailbox_args, $envelope, $body, $expected_compose_result, true];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider AppendProvider
|
||||
*
|
||||
* @group live
|
||||
*
|
||||
* @depends testGetImapStream
|
||||
* @depends testMailCompose
|
||||
*
|
||||
* @psalm-param MAILBOX_ARGS $mailbox_args
|
||||
* @psalm-param COMPOSE_ENVELOPE $envelope
|
||||
* @psalm-param COMPOSE_BODY $body
|
||||
*/
|
||||
public function testAppend(
|
||||
array $mailbox_args,
|
||||
array $envelope,
|
||||
array $body,
|
||||
string $_expected_compose_result,
|
||||
bool $pre_compose
|
||||
): void {
|
||||
if ($this->MaybeSkipAppendTest($envelope)) {
|
||||
return;
|
||||
}
|
||||
|
||||
[$search_criteria] = $this->SubjectSearchCriteriaAndSubject($envelope);
|
||||
|
||||
[$mailbox, $remove_mailbox, $path] = $this->getMailboxFromArgs(
|
||||
$mailbox_args
|
||||
);
|
||||
|
||||
/** @var Throwable|null */
|
||||
$exception = null;
|
||||
|
||||
$mailboxDeleted = false;
|
||||
|
||||
try {
|
||||
$search = $mailbox->searchMailbox($search_criteria);
|
||||
|
||||
$this->assertCount(
|
||||
0,
|
||||
$search,
|
||||
(
|
||||
'If a subject was found,'.
|
||||
' then the message is insufficiently unique to assert that'.
|
||||
' a newly-appended message was actually created.'
|
||||
)
|
||||
);
|
||||
|
||||
$message = [$envelope, $body];
|
||||
|
||||
if ($pre_compose) {
|
||||
$message = Imap::mail_compose($envelope, $body);
|
||||
}
|
||||
|
||||
$mailbox->appendMessageToMailbox($message);
|
||||
|
||||
$search = $mailbox->searchMailbox($search_criteria);
|
||||
|
||||
$this->assertCount(
|
||||
1,
|
||||
$search,
|
||||
(
|
||||
'If a subject was not found, '.
|
||||
' then Mailbox::appendMessageToMailbox() failed'.
|
||||
' despite not throwing an exception.'
|
||||
)
|
||||
);
|
||||
|
||||
$mailbox->deleteMail($search[0]);
|
||||
|
||||
$mailbox->expungeDeletedMails();
|
||||
|
||||
$mailbox->switchMailbox($path->getString());
|
||||
$mailbox->deleteMailbox($remove_mailbox);
|
||||
$mailboxDeleted = true;
|
||||
|
||||
$this->assertCount(
|
||||
0,
|
||||
$mailbox->searchMailbox($search_criteria),
|
||||
(
|
||||
'If a subject was found,'.
|
||||
' then the message is was not expunged as requested.'
|
||||
)
|
||||
);
|
||||
} catch (Throwable $ex) {
|
||||
$exception = $ex;
|
||||
} finally {
|
||||
$mailbox->switchMailbox($path->getString());
|
||||
if (!$mailboxDeleted) {
|
||||
$mailbox->deleteMailbox($remove_mailbox);
|
||||
}
|
||||
$mailbox->disconnect();
|
||||
}
|
||||
|
||||
if (null !== $exception) {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subject search criteria and subject.
|
||||
*
|
||||
* @psalm-param array{subject?:mixed} $envelope
|
||||
*
|
||||
* @psalm-return array{0:string, 1:string}
|
||||
*/
|
||||
protected function SubjectSearchCriteriaAndSubject(array $envelope): array
|
||||
{
|
||||
/** @var string|null */
|
||||
$subject = $envelope['subject'] ?? null;
|
||||
|
||||
$this->assertIsString($subject);
|
||||
|
||||
$search_criteria = \sprintf('SUBJECT "%s"', $subject);
|
||||
|
||||
/** @psalm-var array{0:string, 1:string} */
|
||||
return [$search_criteria, $subject];
|
||||
}
|
||||
|
||||
protected function MaybeSkipAppendTest(array $envelope): bool
|
||||
{
|
||||
if (!isset($envelope['subject'])) {
|
||||
$this->markTestSkipped(
|
||||
'Cannot search for message by subject, no subject specified!'
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap\Fixtures;
|
||||
|
||||
use PhpImap\DataPartInfo as Base;
|
||||
|
||||
class DataPartInfo extends Base
|
||||
{
|
||||
/** @var string|null */
|
||||
protected $data;
|
||||
|
||||
public function fetch(): string
|
||||
{
|
||||
return $this->decodeAfterFetch($this->data);
|
||||
}
|
||||
|
||||
public function setData(string $data = null): void
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap\Fixtures;
|
||||
|
||||
use const FILEINFO_MIME_TYPE;
|
||||
use const FILEINFO_NONE;
|
||||
use PhpImap\IncomingMailAttachment as Base;
|
||||
|
||||
class IncomingMailAttachment extends Base
|
||||
{
|
||||
/** @var string|null */
|
||||
public $override_getFileInfo_mime_type = null;
|
||||
|
||||
public function getFileInfo(int $fileinfo_const = FILEINFO_NONE): string
|
||||
{
|
||||
if (
|
||||
FILEINFO_MIME_TYPE === $fileinfo_const &&
|
||||
isset($this->override_getFileInfo_mime_type)
|
||||
) {
|
||||
return $this->override_getFileInfo_mime_type;
|
||||
}
|
||||
|
||||
return parent::getFileInfo($fileinfo_const);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap\Fixtures;
|
||||
|
||||
use PhpImap\Mailbox as Base;
|
||||
|
||||
class Mailbox extends Base
|
||||
{
|
||||
public function getImapPassword(): string
|
||||
{
|
||||
return $this->imapPassword;
|
||||
}
|
||||
|
||||
public function getImapOptions(): int
|
||||
{
|
||||
return $this->imapOptions;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 74 B |
Binary file not shown.
|
Before Width: | Height: | Size: 34 B |
152
vendor/php-imap/php-imap/tests/unit/ImapTest.php
vendored
152
vendor/php-imap/php-imap/tests/unit/ImapTest.php
vendored
@@ -1,152 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @author BAPCLTD-Marv
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap;
|
||||
|
||||
use Generator;
|
||||
use ParagonIE\HiddenString\HiddenString;
|
||||
use PhpImap\Exceptions\ConnectionException;
|
||||
use PHPUnit\Framework\TestCase as Base;
|
||||
use const SORTARRIVAL;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* @psalm-type MAILBOX_ARGS = array{
|
||||
* 0:HiddenString,
|
||||
* 1:HiddenString,
|
||||
* 2:HiddenString,
|
||||
* 3:string,
|
||||
* 4?:string
|
||||
* }
|
||||
* @psalm-type PSALM_OPEN_ARGS = array{
|
||||
* 0:HiddenString,
|
||||
* 1:HiddenString,
|
||||
* 2:HiddenString,
|
||||
* 3:int,
|
||||
* 4:int,
|
||||
* 5:array{DISABLE_AUTHENTICATOR:string}|array<empty, empty>
|
||||
* } $args
|
||||
*/
|
||||
class ImapTest extends Base
|
||||
{
|
||||
use LiveMailboxTestingTrait;
|
||||
|
||||
/**
|
||||
* @psalm-return Generator<'CI ENV with invalid password'|'empty mailbox/username/password', array{0: ConnectionException::class, 1: '/^[AUTHENTICATIONFAILED]/'|'Can't open mailbox : no such mailbox', 2: array{0: HiddenString, 1: HiddenString, 2: HiddenString, 3: 0, 4: 0, 5: array<empty, empty>}, 3?: true}, mixed, void>
|
||||
*/
|
||||
public function OpenFailure(): Generator
|
||||
{
|
||||
yield 'empty mailbox/username/password' => [
|
||||
ConnectionException::class,
|
||||
'Can\'t open mailbox : no such mailbox',
|
||||
[
|
||||
new HiddenString(''),
|
||||
new HiddenString(''),
|
||||
new HiddenString(''),
|
||||
0,
|
||||
0,
|
||||
[],
|
||||
],
|
||||
];
|
||||
|
||||
$imapPath = \getenv('PHPIMAP_IMAP_PATH');
|
||||
$login = \getenv('PHPIMAP_LOGIN');
|
||||
$password = \getenv('PHPIMAP_PASSWORD');
|
||||
|
||||
if (\is_string($imapPath) && \is_string($login) && \is_string($password)) {
|
||||
yield 'CI ENV with invalid password' => [
|
||||
ConnectionException::class,
|
||||
'/^\[AUTHENTICATIONFAILED\].*/',
|
||||
[
|
||||
new HiddenString($imapPath, true, true),
|
||||
new HiddenString($login, true, true),
|
||||
new HiddenString(\strrev($password), true, true),
|
||||
0,
|
||||
0,
|
||||
[],
|
||||
],
|
||||
true,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider OpenFailure
|
||||
*
|
||||
* @psalm-param class-string<Throwable> $exception
|
||||
* @psalm-param PSALM_OPEN_ARGS $args
|
||||
*/
|
||||
public function testOpenFailure(
|
||||
string $exception,
|
||||
string $message,
|
||||
array $args,
|
||||
bool $message_as_regex = false
|
||||
): void {
|
||||
$this->expectException($exception);
|
||||
|
||||
if ($message_as_regex) {
|
||||
$this->expectExceptionMessageMatches($message);
|
||||
} else {
|
||||
$this->expectExceptionMessage($message);
|
||||
}
|
||||
|
||||
Imap::open(
|
||||
$args[0]->getString(),
|
||||
$args[1]->getString(),
|
||||
$args[2]->getString(),
|
||||
$args[3],
|
||||
$args[4],
|
||||
$args[5]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider MailBoxProvider
|
||||
*
|
||||
* @group live
|
||||
*/
|
||||
public function testSortEmpty(
|
||||
HiddenString $path,
|
||||
HiddenString $login,
|
||||
HiddenString $password
|
||||
): void {
|
||||
[$mailbox, $remove_mailbox, $path] = $this->getMailboxFromArgs([
|
||||
$path,
|
||||
$login,
|
||||
$password,
|
||||
\sys_get_temp_dir(),
|
||||
]);
|
||||
|
||||
/** @var Throwable|null */
|
||||
$exception = null;
|
||||
|
||||
$mailboxDeleted = false;
|
||||
|
||||
try {
|
||||
$this->assertSame(
|
||||
[],
|
||||
Imap::sort(
|
||||
$mailbox->getImapStream(),
|
||||
SORTARRIVAL,
|
||||
false,
|
||||
0
|
||||
)
|
||||
);
|
||||
} catch (Throwable $ex) {
|
||||
$exception = $ex;
|
||||
} finally {
|
||||
$mailbox->switchMailbox($path->getString());
|
||||
if (!$mailboxDeleted) {
|
||||
$mailbox->deleteMailbox($remove_mailbox);
|
||||
}
|
||||
$mailbox->disconnect();
|
||||
}
|
||||
|
||||
if (null !== $exception) {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @author BAPCLTD-Marv
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap;
|
||||
|
||||
use const DATE_RFC3339;
|
||||
use const ENCOTHER;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class IncomingMailTest extends TestCase
|
||||
{
|
||||
public function testSetHeader(): void
|
||||
{
|
||||
$mail = new IncomingMail();
|
||||
$header = new IncomingMailHeader();
|
||||
|
||||
$mail->id = 1;
|
||||
$header->id = 2;
|
||||
|
||||
$mail->isDraft = true;
|
||||
$header->isDraft = false;
|
||||
|
||||
$mail->date = \date(DATE_RFC3339, 0);
|
||||
$header->date = \date(DATE_RFC3339, 60 * 60 * 24);
|
||||
|
||||
$mail->setHeader($header);
|
||||
|
||||
foreach (
|
||||
[
|
||||
'id',
|
||||
'isDraft',
|
||||
'date',
|
||||
] as $property
|
||||
) {
|
||||
/** @var scalar|array|object|resource|null */
|
||||
$headerPropertyValue = $header->$property;
|
||||
$this->assertSame($headerPropertyValue, $mail->$property);
|
||||
}
|
||||
}
|
||||
|
||||
public function testDataPartInfo(): void
|
||||
{
|
||||
$mail = new IncomingMail();
|
||||
$mailbox = new Mailbox('', '', '');
|
||||
|
||||
$data_part = new Fixtures\DataPartInfo($mailbox, 1, 0, ENCOTHER, 0);
|
||||
$data_part->setData('foo');
|
||||
|
||||
$this->assertSame('foo', $data_part->fetch());
|
||||
|
||||
$mail->addDataPartInfo($data_part, DataPartInfo::TEXT_PLAIN);
|
||||
|
||||
$this->assertSame('foo', $mail->textPlain);
|
||||
|
||||
$this->assertTrue($mail->__isset('textPlain'));
|
||||
}
|
||||
|
||||
public function testAttachments(): void
|
||||
{
|
||||
$mail = new IncomingMail();
|
||||
|
||||
$this->assertFalse($mail->hasAttachments());
|
||||
$this->assertSame([], $mail->getAttachments());
|
||||
|
||||
$attachments = [
|
||||
new IncomingMailAttachment(),
|
||||
];
|
||||
|
||||
foreach ($attachments as $i => $attachment) {
|
||||
$attachment->id = (string) $i;
|
||||
$mail->addAttachment($attachment);
|
||||
}
|
||||
|
||||
$this->assertTrue($mail->hasAttachments());
|
||||
$this->assertSame($attachments, $mail->getAttachments());
|
||||
|
||||
foreach ($attachments as $attachment) {
|
||||
$this->assertIsString($attachment->id);
|
||||
$this->assertTrue($mail->removeAttachment($attachment->id));
|
||||
}
|
||||
|
||||
$this->assertFalse($mail->hasAttachments());
|
||||
$this->assertSame([], $mail->getAttachments());
|
||||
|
||||
foreach ($attachments as $attachment) {
|
||||
$this->assertIsString($attachment->id);
|
||||
$this->assertFalse($mail->removeAttachment($attachment->id));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Live Mailbox - PHPUnit tests.
|
||||
*
|
||||
* Runs tests on a live mailbox
|
||||
*
|
||||
* @author BAPCLTD-Marv
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class Issue509Test extends TestCase
|
||||
{
|
||||
public const base64 =
|
||||
'vsiz58fPvcq0z7HuLiC05MDlx9jB1rzFvK0gsKi758fVtM+02S4NCsDMt7EgwM/AuiC16b7uILq7
|
||||
wPvAzCC++L3AtM+02S4NCsDMwM8gvu62u7DUIMfPvcO0wsH2ILHDsd3H1bTPtNkuDQrBprChIMik
|
||||
vcMgsPi9xMD7wLi3ziCw7b/rtce++r3AtM+x7j8NCg0KU2VudCBmcm9tIE1haWw8aHR0cHM6Ly9n
|
||||
by5taWNyb3NvZnQuY29tL2Z3bGluay8/TGlua0lkPTU1MDk4Nj4gZm9yIFdpbmRvd3MgMTANCg0K
|
||||
RnJvbTogQ2xvdWR3b3JrZXJzIEFnZW50cyBLUjxtYWlsdG86am9icy5rckBjbG91ZHdvcmtlcnMu
|
||||
Y29tcGFueT4NClNlbnQ6IEZyaWRheSwgTWF5IDIyLCAyMDIwIDg6NDkgUE0NClRvOiBjYXNleWN1
|
||||
bGxlbjE3QGhvdG1haWwuY29tPG1haWx0bzpjYXNleWN1bGxlbjE3QGhvdG1haWwuY29tPg0KU3Vi
|
||||
amVjdDogQ2xvdWR3b3JrZXJzIENvbXBhbnktIFlvdXIgQXBwbGljYXRpb24NCg0Kvsiz58fPvcq0
|
||||
z7HuLg0KtOe757+hvK0gsPjB9sfRIL73uau/oSDB9r/4x9jB1rzFvK0gsKi758fVtM+02S4gwMy/
|
||||
oSC068fYILyzuO215biuwNq46SC02cC9sPogsLC9wLTPtNkuDQq/wrbzwM4gwNu+97DJseIgxL+5
|
||||
wrTPxry/obytILDtsLTAzCC6uLO7tMIguN68vMH2v6EgtOvH2CC05MfPtMIgsM3AzCDB1r73uavA
|
||||
1LTPtNkuILTnu+fAxyC/wMbbt7kgwMzFzbXpwLogxMTHu8XNt84gxvfF0MC7IMXrx9gguN68vMH2
|
||||
v6EgtOTH1bTPtNkuIL/CtvPAzsC4t84gv+6/tbXHtMIgvve5q8DMuOcgvu618LyttefB9iDExMe7
|
||||
xc2/zSDA/MDaILHiseK3ziDAz8fYvt8gx9W0z7TZLg0KDQqw7bC0wMcgv+WxuCDD5sG3v6Egv+y8
|
||||
sb3Dx9i+3yDHz7TCILi4xa0gtOvIrSCzu7/rwMcgvPbAp7ChILP0wLogvPbB2MDUtM+02S4gwKW7
|
||||
58DMxq6/oSCw+MH2x9G06yC3ziwgwMzAzCC068fRILHNx8/AxyChsL+tuLAgxcK1tb/NIMD7sdjA
|
||||
+8DOILi2wL2wocH8obHAzCDHyr/kx9W0z7TZLg0KDQrAzL+hILTrx9ggvsuw7SCw6L3DtMIgsM3A
|
||||
zCDBwbTZsO0gu/2wosfVtM+02S4guN68vMH2IMfPs6q05yAwLjnAr7fOwNS0z7TZLg0Ksd6/qbTC
|
||||
ILjFtN4gw8osIDEwwM8gvve5q8DPILO7v6EgUGF5cGFswMyzqiDAusfgILzbsd0sIL/4x8+0wiC5
|
||||
5r3EwLi3ziDB9rHetcu0z7TZLiDAzLexIMDPwLsgx9i6uLzMsMWzqiC16b7uuri9xSDA+8DMIMDW
|
||||
wLi9xbChv+Q/DQqxw7Hdx9Egu+fH18DMIMDWwLi46SC+8MGmtecgwfq5rsfYwda9yr3Dv8AhILCo
|
||||
u+fH1bTPtNkuDQoNCg0KRG9uZ2h5dW4gS2ltDQoNCkNMT1VEV09SS0VSUyBDT01QQU5ZDQoNCsOk
|
||||
v+vGwA0KDQpGb246ICs0NCAoMCkgMjA4MDgwNjU3MQ0KDQoxMjggQ2Fubm9uIFdvcmtzaG9wcyBD
|
||||
YW5ub24gRHJpdmUNCkUxNCA0QVMgTG9uZG9uDQp3d3cuY2xvdWR3b3JrZXJzLmNvbXBhbnkNCg0K
|
||||
DQo=';
|
||||
|
||||
public const sha256 =
|
||||
'5656f5f8a872b8989ba3aaecdfbdc6311bf4c5e0219c27b3b004ce83d8ffd6f3';
|
||||
|
||||
public function testDecode(): void
|
||||
{
|
||||
$mailbox = new Mailbox('', '', '');
|
||||
|
||||
$mailbox->decodeMimeStrDefaultCharset = 'EUC-KR';
|
||||
$decoded = $mailbox->decodeMimeStr(\base64_decode(self::base64));
|
||||
|
||||
$this->assertSame(self::sha256, \hash('sha256', $decoded));
|
||||
}
|
||||
}
|
||||
184
vendor/php-imap/php-imap/tests/unit/Issue519Test.php
vendored
184
vendor/php-imap/php-imap/tests/unit/Issue519Test.php
vendored
@@ -1,184 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Live Mailbox - PHPUnit tests.
|
||||
*
|
||||
* Runs tests on a live mailbox
|
||||
*
|
||||
* @author BAPCLTD-Marv
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap;
|
||||
|
||||
use const ENC8BIT;
|
||||
use const ENCBASE64;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use const TYPEIMAGE;
|
||||
|
||||
class Issue519Test extends TestCase
|
||||
{
|
||||
public const HEADER_VALUES = [
|
||||
'inline',
|
||||
'Inline',
|
||||
'iNline',
|
||||
'INline',
|
||||
'inLine',
|
||||
'InLine',
|
||||
'iNLine',
|
||||
'INLine',
|
||||
'inlIne',
|
||||
'InlIne',
|
||||
'iNlIne',
|
||||
'INlIne',
|
||||
'inLIne',
|
||||
'InLIne',
|
||||
'iNLIne',
|
||||
'INLIne',
|
||||
'inliNe',
|
||||
'InliNe',
|
||||
'iNliNe',
|
||||
'INliNe',
|
||||
'inLiNe',
|
||||
'InLiNe',
|
||||
'iNLiNe',
|
||||
'INLiNe',
|
||||
'inlINe',
|
||||
'InlINe',
|
||||
'iNlINe',
|
||||
'INlINe',
|
||||
'inLINe',
|
||||
'InLINe',
|
||||
'iNLINe',
|
||||
'INLINe',
|
||||
'inlinE',
|
||||
'InlinE',
|
||||
'iNlinE',
|
||||
'INlinE',
|
||||
'inLinE',
|
||||
'InLinE',
|
||||
'iNLinE',
|
||||
'INLinE',
|
||||
'inlInE',
|
||||
'InlInE',
|
||||
'iNlInE',
|
||||
'INlInE',
|
||||
'inLInE',
|
||||
'InLInE',
|
||||
'iNLInE',
|
||||
'INLInE',
|
||||
'inliNE',
|
||||
'InliNE',
|
||||
'iNliNE',
|
||||
'INliNE',
|
||||
'inLiNE',
|
||||
'InLiNE',
|
||||
'iNLiNE',
|
||||
'INLiNE',
|
||||
'inlINE',
|
||||
'InlINE',
|
||||
'iNlINE',
|
||||
'INlINE',
|
||||
'inLINE',
|
||||
'InLINE',
|
||||
'iNLINE',
|
||||
'INLINE',
|
||||
];
|
||||
|
||||
public const CID = 'cid:foo.jpg';
|
||||
|
||||
public const ID = 'foo.jpg';
|
||||
|
||||
public const SUBTYPE = 'jpeg';
|
||||
|
||||
public const SIZE_IN_BYTES = 0;
|
||||
|
||||
public const HTML = 'foo.html';
|
||||
|
||||
public const HTML_EMBED = '<img src="data:image/jpeg;base64, ">';
|
||||
|
||||
public const MIME_TYPE = 'image/jpeg';
|
||||
|
||||
public const EXPECTED_ATTACHMENT_COUNT = 1;
|
||||
|
||||
public const EXPECTED_ATTACHMENT_COUNT_AFTER_EMBED = 0;
|
||||
|
||||
/**
|
||||
* @psalm-return array<string, array{0: string}>
|
||||
*
|
||||
* @return string[][]
|
||||
*/
|
||||
public function provider(): array
|
||||
{
|
||||
$out = [];
|
||||
|
||||
foreach (self::HEADER_VALUES as $value) {
|
||||
$out[$value] = [$value];
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provider
|
||||
*/
|
||||
public function test(string $header_value): void
|
||||
{
|
||||
$mailbox = new Mailbox('', '', '');
|
||||
$mail = new IncomingMail();
|
||||
$attachment = new Fixtures\IncomingMailAttachment();
|
||||
$part = new Fixtures\DataPartInfo(
|
||||
$mailbox,
|
||||
0,
|
||||
0,
|
||||
ENCBASE64,
|
||||
0
|
||||
);
|
||||
|
||||
$html = new Fixtures\DataPartInfo(
|
||||
$mailbox,
|
||||
0,
|
||||
0,
|
||||
ENC8BIT,
|
||||
0
|
||||
);
|
||||
|
||||
$html_string = '<img src="'.self::CID.'">';
|
||||
|
||||
$html->setData($html_string);
|
||||
$part->setData('');
|
||||
|
||||
$attachment->id = self::ID;
|
||||
$attachment->contentId = self::ID;
|
||||
$attachment->type = TYPEIMAGE;
|
||||
$attachment->encoding = ENCBASE64;
|
||||
$attachment->subtype = self::SUBTYPE;
|
||||
$attachment->description = self::ID;
|
||||
$attachment->name = self::ID;
|
||||
$attachment->sizeInBytes = self::SIZE_IN_BYTES;
|
||||
$attachment->disposition = $header_value;
|
||||
$attachment->override_getFileInfo_mime_type = self::MIME_TYPE;
|
||||
|
||||
$attachment->addDataPartInfo($part);
|
||||
|
||||
$mail->addDataPartInfo($html, DataPartInfo::TEXT_HTML);
|
||||
$mail->addAttachment($attachment);
|
||||
|
||||
$this->assertTrue($mail->hasAttachments());
|
||||
|
||||
$this->assertCount(
|
||||
self::EXPECTED_ATTACHMENT_COUNT,
|
||||
$mail->getAttachments()
|
||||
);
|
||||
|
||||
$this->assertSame($html_string, $mail->textHtml);
|
||||
|
||||
$mail->embedImageAttachments();
|
||||
|
||||
$this->assertCount(
|
||||
self::EXPECTED_ATTACHMENT_COUNT_AFTER_EMBED,
|
||||
$mail->getAttachments()
|
||||
);
|
||||
|
||||
$this->assertSame(self::HTML_EMBED, $mail->textHtml);
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Live Mailbox - PHPUnit tests.
|
||||
*
|
||||
* Runs tests on a live mailbox
|
||||
*
|
||||
* @author BAPCLTD-Marv
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap;
|
||||
|
||||
use Generator;
|
||||
use ParagonIE\HiddenString\HiddenString;
|
||||
use const TYPETEXT;
|
||||
|
||||
/**
|
||||
* @psalm-type MAILBOX_ARGS = array{
|
||||
* 0:HiddenString,
|
||||
* 1:HiddenString,
|
||||
* 2:HiddenString,
|
||||
* 3:string,
|
||||
* 4?:string
|
||||
* }
|
||||
* @psalm-type COMPOSE_ENVELOPE = array{
|
||||
* subject?:string
|
||||
* }
|
||||
* @psalm-type COMPOSE_BODY = list<array{
|
||||
* type?:int,
|
||||
* encoding?:int,
|
||||
* charset?:string,
|
||||
* subtype?:string,
|
||||
* description?:string,
|
||||
* disposition?:array{filename:string}
|
||||
* }>
|
||||
*/
|
||||
class LiveMailboxIssue250Test extends AbstractLiveMailboxTest
|
||||
{
|
||||
/**
|
||||
* @psalm-return Generator<int, array{0: array{subject: string}, 1: array{0: array{type: 0, 'contents.data': 'test'}}, 2: string}, mixed, void>
|
||||
*/
|
||||
public function ComposeProvider(): Generator
|
||||
{
|
||||
$random_subject = 'barbushin/php-imap#250 测试: '.\bin2hex(\random_bytes(16));
|
||||
|
||||
yield [
|
||||
['subject' => $random_subject],
|
||||
[
|
||||
[
|
||||
'type' => TYPETEXT,
|
||||
'contents.data' => 'test',
|
||||
],
|
||||
],
|
||||
(
|
||||
'Subject: '.$random_subject."\r\n".
|
||||
'MIME-Version: 1.0'."\r\n".
|
||||
'Content-Type: TEXT/PLAIN; CHARSET=US-ASCII'."\r\n".
|
||||
"\r\n".
|
||||
'test'."\r\n"
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider AppendProvider
|
||||
*
|
||||
* @group live
|
||||
* @group live-issue-250
|
||||
*
|
||||
* @psalm-param MAILBOX_ARGS $mailbox_args
|
||||
* @psalm-param COMPOSE_ENVELOPE $envelope
|
||||
* @psalm-param COMPOSE_BODY $body
|
||||
*/
|
||||
public function testAppend(
|
||||
array $mailbox_args,
|
||||
array $envelope,
|
||||
array $body,
|
||||
string $expected_compose_result,
|
||||
bool $pre_compose
|
||||
): void {
|
||||
parent::testAppend(
|
||||
$mailbox_args,
|
||||
$envelope,
|
||||
$body,
|
||||
$expected_compose_result,
|
||||
$pre_compose
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Live Mailbox - PHPUnit tests.
|
||||
*
|
||||
* Runs tests on a live mailbox
|
||||
*
|
||||
* @author BAPCLTD-Marv
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap;
|
||||
|
||||
use Exception;
|
||||
use ParagonIE\HiddenString\HiddenString;
|
||||
use const TYPEMULTIPART;
|
||||
use const TYPETEXT;
|
||||
|
||||
/**
|
||||
* @psalm-type MAILBOX_ARGS = array{
|
||||
* 0:HiddenString,
|
||||
* 1:HiddenString,
|
||||
* 2:HiddenString,
|
||||
* 3:string,
|
||||
* 4?:string
|
||||
* }
|
||||
*/
|
||||
class LiveMailboxIssue490Test extends AbstractLiveMailboxTest
|
||||
{
|
||||
/**
|
||||
* @dataProvider MailBoxProvider
|
||||
*
|
||||
* @group live
|
||||
* @group live-issue-490
|
||||
*/
|
||||
public function testGetTextAttachments(
|
||||
HiddenString $imapPath,
|
||||
HiddenString $login,
|
||||
HiddenString $password,
|
||||
string $attachmentsDir,
|
||||
string $serverEncoding = 'UTF-8'
|
||||
): void {
|
||||
[$mailbox, $remove_mailbox] = $this->getMailbox(
|
||||
$imapPath,
|
||||
$login,
|
||||
$password,
|
||||
$attachmentsDir,
|
||||
$serverEncoding
|
||||
);
|
||||
|
||||
$exception = null;
|
||||
|
||||
try {
|
||||
$envelope = [
|
||||
'subject' => 'barbushin/php-imap#501: '.\bin2hex(\random_bytes(16)),
|
||||
];
|
||||
|
||||
[$search_criteria] = $this->SubjectSearchCriteriaAndSubject(
|
||||
$envelope
|
||||
);
|
||||
|
||||
$search = $mailbox->searchMailbox($search_criteria);
|
||||
|
||||
$this->assertCount(
|
||||
0,
|
||||
$search,
|
||||
(
|
||||
'If a subject was found,'.
|
||||
' then the message is insufficiently unique to assert that'.
|
||||
' a newly-appended message was actually created.'
|
||||
)
|
||||
);
|
||||
|
||||
$message = Imap::mail_compose(
|
||||
$envelope,
|
||||
[
|
||||
[
|
||||
'type' => TYPEMULTIPART,
|
||||
],
|
||||
[
|
||||
'type' => TYPETEXT,
|
||||
'contents.data' => 'foo',
|
||||
],
|
||||
[
|
||||
'type' => TYPEMULTIPART,
|
||||
'subtype' => 'plain',
|
||||
'description' => 'bar.txt',
|
||||
'disposition.type' => 'attachment',
|
||||
'disposition' => ['filename' => 'bar.txt'],
|
||||
'type.parameters' => ['name' => 'bar.txt'],
|
||||
'contents.data' => 'bar',
|
||||
],
|
||||
[
|
||||
'type' => TYPEMULTIPART,
|
||||
'subtype' => 'plain',
|
||||
'description' => 'baz.txt',
|
||||
'disposition.type' => 'attachment',
|
||||
'disposition' => ['filename' => 'baz.txt'],
|
||||
'type.parameters' => ['name' => 'baz.txt'],
|
||||
'contents.data' => 'baz',
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$mailbox->appendMessageToMailbox($message);
|
||||
|
||||
$search = $mailbox->searchMailbox($search_criteria);
|
||||
|
||||
$this->assertCount(
|
||||
1,
|
||||
$search,
|
||||
(
|
||||
'If a subject was not found, '.
|
||||
' then Mailbox::appendMessageToMailbox() failed'.
|
||||
' despite not throwing an exception.'
|
||||
)
|
||||
);
|
||||
|
||||
$mail = $mailbox->getMail($search[0], false);
|
||||
|
||||
$this->assertSame('foo', $mail->textPlain);
|
||||
|
||||
$attachments = $mail->getAttachments();
|
||||
$keys = \array_keys($attachments);
|
||||
|
||||
$this->assertCount(2, $attachments);
|
||||
|
||||
$this->assertSame('bar', $attachments[$keys[0]]->getContents());
|
||||
$this->assertSame('baz', $attachments[$keys[1]]->getContents());
|
||||
} catch (Exception $ex) {
|
||||
$exception = $ex;
|
||||
} finally {
|
||||
$mailbox->switchMailbox($imapPath->getString());
|
||||
$mailbox->deleteMailbox($remove_mailbox);
|
||||
$mailbox->disconnect();
|
||||
}
|
||||
|
||||
if (null !== $exception) {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Live Mailbox - PHPUnit tests.
|
||||
*
|
||||
* Runs tests on a live mailbox
|
||||
*
|
||||
* @author BAPCLTD-Marv
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap;
|
||||
|
||||
use Exception;
|
||||
use ParagonIE\HiddenString\HiddenString;
|
||||
use const TYPETEXT;
|
||||
|
||||
/**
|
||||
* @psalm-type MAILBOX_ARGS = array{
|
||||
* 0:HiddenString,
|
||||
* 1:HiddenString,
|
||||
* 2:HiddenString,
|
||||
* 3:string,
|
||||
* 4?:string
|
||||
* }
|
||||
*/
|
||||
class LiveMailboxIssue501Test extends AbstractLiveMailboxTest
|
||||
{
|
||||
/**
|
||||
* @group offline
|
||||
* @group offline-issue-501
|
||||
*/
|
||||
public function testDecodeMimeStrEmpty(): void
|
||||
{
|
||||
$this->assertSame([], \imap_mime_header_decode(''));
|
||||
|
||||
// example credentials nabbed from MailboxTest::testConstructorTrimsPossibleVariables()
|
||||
$imapPath = ' {imap.example.com:993/imap/ssl}INBOX ';
|
||||
$login = ' php-imap@example.com';
|
||||
$password = ' v3rY!53cEt&P4sSWöRd$';
|
||||
// directory names can contain spaces before AND after on Linux/Unix systems. Windows trims these spaces automatically.
|
||||
$attachmentsDir = '.';
|
||||
$serverEncoding = 'UTF-8 ';
|
||||
|
||||
$mailbox = new Mailbox($imapPath, $login, $password, $attachmentsDir, $serverEncoding);
|
||||
|
||||
$this->assertSame('', $mailbox->decodeMimeStr(''));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider MailBoxProvider
|
||||
*
|
||||
* @group live
|
||||
* @group live-issue-501
|
||||
*/
|
||||
public function testGetEmptyBody(
|
||||
HiddenString $imapPath,
|
||||
HiddenString $login,
|
||||
HiddenString $password,
|
||||
string $attachmentsDir,
|
||||
string $serverEncoding = 'UTF-8'
|
||||
): void {
|
||||
[$mailbox, $remove_mailbox] = $this->getMailbox(
|
||||
$imapPath,
|
||||
$login,
|
||||
$password,
|
||||
$attachmentsDir,
|
||||
$serverEncoding
|
||||
);
|
||||
|
||||
$exception = null;
|
||||
|
||||
try {
|
||||
$envelope = [
|
||||
'subject' => 'barbushin/php-imap#501: '.\bin2hex(\random_bytes(16)),
|
||||
];
|
||||
|
||||
[$search_criteria] = $this->SubjectSearchCriteriaAndSubject(
|
||||
$envelope
|
||||
);
|
||||
|
||||
$search = $mailbox->searchMailbox($search_criteria);
|
||||
|
||||
$this->assertCount(
|
||||
0,
|
||||
$search,
|
||||
(
|
||||
'If a subject was found,'.
|
||||
' then the message is insufficiently unique to assert that'.
|
||||
' a newly-appended message was actually created.'
|
||||
)
|
||||
);
|
||||
|
||||
$mailbox->appendMessageToMailbox(Imap::mail_compose(
|
||||
$envelope,
|
||||
[
|
||||
[
|
||||
'type' => TYPETEXT,
|
||||
'contents.data' => '',
|
||||
],
|
||||
]
|
||||
));
|
||||
|
||||
$search = $mailbox->searchMailbox($search_criteria);
|
||||
|
||||
$this->assertCount(
|
||||
1,
|
||||
$search,
|
||||
(
|
||||
'If a subject was not found, '.
|
||||
' then Mailbox::appendMessageToMailbox() failed'.
|
||||
' despite not throwing an exception.'
|
||||
)
|
||||
);
|
||||
|
||||
$mail = $mailbox->getMail($search[0], false);
|
||||
|
||||
$this->assertSame('', $mail->textPlain);
|
||||
} catch (Exception $ex) {
|
||||
$exception = $ex;
|
||||
} finally {
|
||||
$mailbox->switchMailbox($imapPath->getString());
|
||||
$mailbox->deleteMailbox($remove_mailbox);
|
||||
$mailbox->disconnect();
|
||||
}
|
||||
|
||||
if (null !== $exception) {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,258 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Live Mailbox - PHPUnit tests.
|
||||
*
|
||||
* Runs tests on a live mailbox
|
||||
*
|
||||
* @author BAPCLTD-Marv
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap;
|
||||
|
||||
use const ENCBASE64;
|
||||
use ParagonIE\HiddenString\HiddenString;
|
||||
use Throwable;
|
||||
use const TYPEIMAGE;
|
||||
use const TYPEMULTIPART;
|
||||
use const TYPETEXT;
|
||||
|
||||
/**
|
||||
* @psalm-import-type COMPOSE_ENVELOPE from AbstractLiveMailboxTest
|
||||
*/
|
||||
class LiveMailboxIssue514Test extends AbstractLiveMailboxTest
|
||||
{
|
||||
/**
|
||||
* @dataProvider MailBoxProvider
|
||||
*
|
||||
* @group live
|
||||
* @group issue-514
|
||||
*/
|
||||
public function testEmbed(
|
||||
HiddenString $imapPath,
|
||||
HiddenString $login,
|
||||
HiddenString $password,
|
||||
string $attachmentsDir,
|
||||
string $serverEncoding = 'UTF-8'
|
||||
): void {
|
||||
/** @var Throwable|null */
|
||||
$exception = null;
|
||||
|
||||
$mailboxDeleted = false;
|
||||
|
||||
/** @psalm-var COMPOSE_ENVELOPE */
|
||||
$envelope = [
|
||||
'subject' => 'barbushin/php-imap#514--'.\bin2hex(\random_bytes(16)),
|
||||
];
|
||||
|
||||
[$search_criteria] = $this->SubjectSearchCriteriaAndSubject($envelope);
|
||||
|
||||
$body = [
|
||||
[
|
||||
'type' => TYPEMULTIPART,
|
||||
],
|
||||
[
|
||||
'type' => TYPETEXT,
|
||||
'subtype' => 'plain',
|
||||
'contents.data' => 'foo',
|
||||
],
|
||||
[
|
||||
'type' => TYPETEXT,
|
||||
'subtype' => 'html',
|
||||
'contents.data' => \implode('', [
|
||||
'<img alt="png" width="5" height="1" src="cid:foo.png">',
|
||||
'<img alt="webp" width="5" height="1" src="cid:foo.webp">',
|
||||
]),
|
||||
],
|
||||
[
|
||||
'type' => TYPEIMAGE,
|
||||
'subtype' => 'png',
|
||||
'encoding' => ENCBASE64,
|
||||
'id' => 'foo.png',
|
||||
'description' => 'foo.png',
|
||||
'disposition' => ['filename' => 'foo.png'],
|
||||
'disposition.type' => 'inline',
|
||||
'type.parameters' => ['name' => 'foo.png'],
|
||||
'contents.data' => \base64_encode(
|
||||
\file_get_contents(__DIR__.'/Fixtures/rgbkw5x1.png')
|
||||
),
|
||||
],
|
||||
[
|
||||
'type' => TYPEIMAGE,
|
||||
'subtype' => 'webp',
|
||||
'encoding' => ENCBASE64,
|
||||
'id' => 'foo.webp',
|
||||
'description' => 'foo.webp',
|
||||
'disposition' => ['filename' => 'foo.webp'],
|
||||
'disposition.type' => 'inline',
|
||||
'type.parameters' => ['name' => 'foo.webp'],
|
||||
'contents.data' => \base64_encode(
|
||||
\file_get_contents(__DIR__.'/Fixtures/rgbkw5x1.webp')
|
||||
),
|
||||
],
|
||||
];
|
||||
|
||||
$message = Imap::mail_compose(
|
||||
$envelope,
|
||||
$body
|
||||
);
|
||||
|
||||
[$mailbox, $remove_mailbox, $path] = $this->getMailboxFromArgs([
|
||||
$imapPath,
|
||||
$login,
|
||||
$password,
|
||||
$attachmentsDir,
|
||||
$serverEncoding,
|
||||
]);
|
||||
|
||||
$result = null;
|
||||
|
||||
try {
|
||||
$search = $mailbox->searchMailbox($search_criteria);
|
||||
|
||||
$this->assertCount(
|
||||
0,
|
||||
$search,
|
||||
(
|
||||
'If a subject was found,'.
|
||||
' then the message is insufficiently unique to assert that'.
|
||||
' a newly-appended message was actually created.'
|
||||
)
|
||||
);
|
||||
|
||||
$mailbox->appendMessageToMailbox($message);
|
||||
|
||||
$search = $mailbox->searchMailbox($search_criteria);
|
||||
|
||||
$this->assertCount(
|
||||
1,
|
||||
$search,
|
||||
(
|
||||
'If a subject was not found, '.
|
||||
' then Mailbox::appendMessageToMailbox() failed'.
|
||||
' despite not throwing an exception.'
|
||||
)
|
||||
);
|
||||
|
||||
$result = $mailbox->getMail($search[0], false);
|
||||
|
||||
/** @var array<string, int> */
|
||||
$counts = [];
|
||||
|
||||
foreach ($result->getAttachments() as $attachment) {
|
||||
if (!isset($counts[(string) $attachment->contentId])) {
|
||||
$counts[(string) $attachment->contentId] = 0;
|
||||
}
|
||||
|
||||
++$counts[(string) $attachment->contentId];
|
||||
}
|
||||
|
||||
$this->assertCount(
|
||||
2,
|
||||
$counts,
|
||||
(
|
||||
'counts should only contain foo.png and foo.webp, found: '.
|
||||
\implode(
|
||||
', ',
|
||||
\array_keys($counts)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
foreach ($counts as $cid => $count) {
|
||||
$this->assertSame(
|
||||
1,
|
||||
$count,
|
||||
$cid.' had '.(string) $count.', expected 1.'
|
||||
);
|
||||
}
|
||||
|
||||
$this->assertSame(
|
||||
'foo',
|
||||
$result->textPlain,
|
||||
'plain text body did not match expected result!'
|
||||
);
|
||||
|
||||
$embedded = \implode('', [
|
||||
'<img alt="png" width="5" height="1" src="',
|
||||
'data:image/png; charset=binary;base64, ',
|
||||
$body[3]['contents.data'],
|
||||
'">',
|
||||
'<img alt="webp" width="5" height="1" src="',
|
||||
'data:image/webp; charset=binary;base64, ',
|
||||
$body[4]['contents.data'],
|
||||
'">',
|
||||
]);
|
||||
|
||||
$this->assertSame(
|
||||
[
|
||||
'foo.png' => 'cid:foo.png',
|
||||
'foo.webp' => 'cid:foo.webp',
|
||||
],
|
||||
$result->getInternalLinksPlaceholders(),
|
||||
'Internal link placeholders did not match expected result!'
|
||||
);
|
||||
|
||||
$replaced = \implode('', [
|
||||
'<img alt="png" width="5" height="1" src="',
|
||||
'foo.png',
|
||||
'">',
|
||||
'<img alt="webp" width="5" height="1" src="',
|
||||
'foo.webp',
|
||||
'">',
|
||||
]);
|
||||
|
||||
foreach ($result->getAttachments() as $attachment) {
|
||||
if ('foo.png' === $attachment->contentId) {
|
||||
$replaced = \str_replace(
|
||||
'foo.png',
|
||||
'/'.\basename($attachment->filePath),
|
||||
$replaced
|
||||
);
|
||||
} elseif ('foo.webp' === $attachment->contentId) {
|
||||
$replaced = \str_replace(
|
||||
'foo.webp',
|
||||
'/'.\basename($attachment->filePath),
|
||||
$replaced
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertSame(
|
||||
$replaced,
|
||||
$result->replaceInternalLinks(''),
|
||||
'replaced html body did not match expected result!'
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
$body[2]['contents.data'],
|
||||
$result->textHtml,
|
||||
'unembeded html body did not match expected result!'
|
||||
);
|
||||
|
||||
$result->embedImageAttachments();
|
||||
|
||||
$this->assertSame(
|
||||
$embedded,
|
||||
$result->textHtml,
|
||||
'embeded html body did not match expected result!'
|
||||
);
|
||||
|
||||
$mailbox->deleteMail($search[0]);
|
||||
} catch (Throwable $ex) {
|
||||
$exception = $ex;
|
||||
} finally {
|
||||
$mailbox->switchMailbox($path->getString());
|
||||
|
||||
if (!$mailboxDeleted) {
|
||||
$mailbox->deleteMailbox($remove_mailbox);
|
||||
}
|
||||
|
||||
$mailbox->disconnect();
|
||||
}
|
||||
|
||||
if (null !== $exception) {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Live Mailbox - PHPUnit tests.
|
||||
*
|
||||
* Runs tests on a live mailbox
|
||||
*
|
||||
* @author Sebi94nbg
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap;
|
||||
|
||||
use const ENCQUOTEDPRINTABLE;
|
||||
use Generator;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class LiveMailboxStringDecodingConvertingTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Provides data for testing string decoding.
|
||||
*/
|
||||
public function stringDecodeProvider(): Generator
|
||||
{
|
||||
yield 'Issue #250 iso-8859-1' => [
|
||||
ENCQUOTEDPRINTABLE,
|
||||
'iso-8859-1',
|
||||
'mountainguan',
|
||||
'mountainguan',
|
||||
'e94a37111edb29a8d3f6078dc4810953964f19562613cf2bd15e21b69d30822a',
|
||||
];
|
||||
|
||||
yield 'Issue #250 utf-7' => [
|
||||
ENCQUOTEDPRINTABLE,
|
||||
'utf-7',
|
||||
'+bUuL1Q-',
|
||||
'测试',
|
||||
'6aa8f49cc992dfd75a114269ed26de0ad6d4e7d7a70d9c8afb3d7a57a88a73ed',
|
||||
];
|
||||
|
||||
yield 'Issue #250 utf-7 with chinese' => [
|
||||
ENCQUOTEDPRINTABLE,
|
||||
'utf-7',
|
||||
'mountainguan+bUuL1Q-',
|
||||
'mountainguan测试',
|
||||
'62a5022b682b7e02bda8d18424fa06501cdd71cce2832e95129673f63da2e177',
|
||||
];
|
||||
|
||||
yield 'Issue #250 utf-8 with chinese' => [
|
||||
ENCQUOTEDPRINTABLE,
|
||||
'utf-8',
|
||||
'mountainguan=E6=B5=8B=E8=AF=95',
|
||||
'mountainguan测试',
|
||||
'62a5022b682b7e02bda8d18424fa06501cdd71cce2832e95129673f63da2e177',
|
||||
];
|
||||
|
||||
yield 'Issue #657' => [
|
||||
ENCQUOTEDPRINTABLE,
|
||||
'iso-8859-2',
|
||||
'=EC=B9=E8=F8=BE=FD=E1=ED=E9',
|
||||
'ěščřžýáíé',
|
||||
'a05e42c7e14de716cd501e135f3f5e49545f71069de316a1e9f7bb153f9a7356',
|
||||
];
|
||||
|
||||
yield 'Emoji utf-8' => [
|
||||
ENCQUOTEDPRINTABLE,
|
||||
'utf-8',
|
||||
'Some subject here =F0=9F=98=98',
|
||||
'Some subject here 😘',
|
||||
'da66c62e7e82316b8b543f52f1ecc4415c4dc93bc87e2239ee5f98bdf00a8c50',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that string decoding and converting works as expected.
|
||||
*
|
||||
* @dataProvider stringDecodeProvider
|
||||
*/
|
||||
public function testStringDecode(int $encoding, string $charset, string $iso_8859_2, string $utf8, string $sha256): void
|
||||
{
|
||||
$mailbox = new Mailbox('', '', '');
|
||||
|
||||
$dataInfo = new DataPartInfo($mailbox, 1337, '', $encoding, 0);
|
||||
$dataInfo->charset = $charset;
|
||||
|
||||
$decoded = $dataInfo->decodeAfterFetch($iso_8859_2);
|
||||
|
||||
$this->assertSame($utf8, $decoded);
|
||||
|
||||
$this->assertSame($sha256, \hash('sha256', $decoded));
|
||||
}
|
||||
}
|
||||
@@ -1,678 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Live Mailbox - PHPUnit tests.
|
||||
*
|
||||
* Runs tests on a live mailbox
|
||||
*
|
||||
* @author BAPCLTD-Marv
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap;
|
||||
|
||||
use function date;
|
||||
use const ENCBASE64;
|
||||
use Generator;
|
||||
use ParagonIE\HiddenString\HiddenString;
|
||||
use const SORTARRIVAL;
|
||||
use Throwable;
|
||||
use const TYPEAPPLICATION;
|
||||
use const TYPEMULTIPART;
|
||||
use const TYPETEXT;
|
||||
|
||||
/**
|
||||
* @psalm-type MAILBOX_ARGS = array{
|
||||
* 0:HiddenString,
|
||||
* 1:HiddenString,
|
||||
* 2:HiddenString,
|
||||
* 3:string,
|
||||
* 4?:string
|
||||
* }
|
||||
* @psalm-type COMPOSE_ENVELOPE = array{
|
||||
* subject?:string
|
||||
* }
|
||||
* @psalm-type COMPOSE_BODY = list<array{
|
||||
* type?:int,
|
||||
* encoding?:int,
|
||||
* charset?:string,
|
||||
* subtype?:string,
|
||||
* description?:string,
|
||||
* disposition?:array{filename:string}
|
||||
* }>
|
||||
*
|
||||
* @todo see @todo of Imap::mail_compose()
|
||||
*/
|
||||
class LiveMailboxTest extends AbstractLiveMailboxTest
|
||||
{
|
||||
public const RANDOM_MAILBOX_SAMPLE_SIZE = 3;
|
||||
|
||||
public const ISSUE_EXPECTED_ATTACHMENT_COUNT = [
|
||||
448 => 1,
|
||||
391 => 2,
|
||||
];
|
||||
|
||||
/**
|
||||
* @dataProvider MailBoxProvider
|
||||
*
|
||||
* @group live
|
||||
*/
|
||||
public function testGetImapStream(HiddenString $imapPath, HiddenString $login, HiddenString $password, string $attachmentsDir, string $serverEncoding = 'UTF-8'): void
|
||||
{
|
||||
[$mailbox, $remove_mailbox] = $this->getMailbox(
|
||||
$imapPath,
|
||||
$login,
|
||||
$password,
|
||||
$attachmentsDir,
|
||||
$serverEncoding
|
||||
);
|
||||
|
||||
/** @var Throwable|null */
|
||||
$exception = null;
|
||||
|
||||
try {
|
||||
$mailbox->getImapStream();
|
||||
$this->assertTrue($mailbox->hasImapStream());
|
||||
|
||||
$mailboxes = $mailbox->getMailboxes();
|
||||
\shuffle($mailboxes);
|
||||
|
||||
$mailboxes = \array_values($mailboxes);
|
||||
|
||||
$limit = \min(\count($mailboxes), self::RANDOM_MAILBOX_SAMPLE_SIZE);
|
||||
|
||||
for ($i = 0; $i < $limit; ++$i) {
|
||||
$this->assertIsArray($mailboxes[$i]);
|
||||
$this->assertTrue(isset($mailboxes[$i]['shortpath']));
|
||||
$this->assertIsString($mailboxes[$i]['shortpath']);
|
||||
$mailbox->switchMailbox($mailboxes[$i]['shortpath']);
|
||||
|
||||
$check = $mailbox->checkMailbox();
|
||||
|
||||
foreach ([
|
||||
'Date',
|
||||
'Driver',
|
||||
'Mailbox',
|
||||
'Nmsgs',
|
||||
'Recent',
|
||||
] as $expectedProperty) {
|
||||
$this->assertTrue(\property_exists($check, $expectedProperty));
|
||||
}
|
||||
|
||||
$this->assertIsString($check->Date, 'Date property of Mailbox::checkMailbox() result was not a string!');
|
||||
|
||||
$unix = \strtotime($check->Date);
|
||||
|
||||
if (false === $unix && \preg_match('/[+-]\d{1,2}:?\d{2} \([^\)]+\)$/', $check->Date)) {
|
||||
/** @var int */
|
||||
$pos = \strrpos($check->Date, '(');
|
||||
|
||||
// Although the date property is likely RFC2822-compliant, it will not be parsed by strtotime()
|
||||
$unix = \strtotime(\substr($check->Date, 0, $pos));
|
||||
}
|
||||
|
||||
$this->assertIsInt($unix, 'Date property of Mailbox::checkMailbox() result was not a valid date!');
|
||||
$this->assertTrue(\in_array($check->Driver, ['POP3', 'IMAP', 'NNTP', 'pop3', 'imap', 'nntp'], true), 'Driver property of Mailbox::checkMailbox() result was not of an expected value!');
|
||||
$this->assertIsInt($check->Nmsgs, 'Nmsgs property of Mailbox::checkMailbox() result was not of an expected type!');
|
||||
$this->assertIsInt($check->Recent, 'Recent property of Mailbox::checkMailbox() result was not of an expected type!');
|
||||
|
||||
$status = $mailbox->statusMailbox();
|
||||
|
||||
foreach ([
|
||||
'messages',
|
||||
'recent',
|
||||
'unseen',
|
||||
'uidnext',
|
||||
'uidvalidity',
|
||||
] as $expectedProperty) {
|
||||
$this->assertTrue(\property_exists($status, $expectedProperty));
|
||||
}
|
||||
|
||||
$this->assertSame($check->Nmsgs, $mailbox->countMails(), 'Mailbox::checkMailbox()->Nmsgs did not match Mailbox::countMails()!');
|
||||
}
|
||||
} catch (Throwable $ex) {
|
||||
$exception = $ex;
|
||||
} finally {
|
||||
$mailbox->switchMailbox($imapPath->getString());
|
||||
$mailbox->deleteMailbox($remove_mailbox);
|
||||
$mailbox->disconnect();
|
||||
}
|
||||
|
||||
if (null !== $exception) {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-return Generator<int, array{0: array{subject: string}, 1: array{0: array{type: 0|1|3, 'contents.data'?: string, encoding?: 3, subtype?: 'octet-stream', description?: '.gitignore'|'gitignore.', 'disposition.type'?: 'attachment', disposition?: array{filename: '.gitignore'|'gitignore.'}, 'type.parameters'?: array{name: '.gitignore'|'gitignore.'}}, 1?: array{type: 0, 'contents.data': 'test'}, 2?: array{type: 3, encoding: 3, subtype: 'octet-stream', description: 'foo.bin', 'disposition.type': 'attachment', disposition: array{filename: 'foo.bin'}, 'type.parameters': array{name: 'foo.bin'}, 'contents.data': string}, 3?: array{type: 3, encoding: 3, subtype: 'octet-stream', description: 'foo.bin', 'disposition.type': 'attachment', disposition: array{filename: 'foo.bin'}, 'type.parameters': array{name: 'foo.bin'}, 'contents.data': string}}, 2: string}, mixed, void>
|
||||
*/
|
||||
public function ComposeProvider(): Generator
|
||||
{
|
||||
$random_subject = 'test: '.\bin2hex(\random_bytes(16));
|
||||
|
||||
yield [
|
||||
['subject' => $random_subject],
|
||||
[
|
||||
[
|
||||
'type' => TYPETEXT,
|
||||
'contents.data' => 'test',
|
||||
],
|
||||
],
|
||||
(
|
||||
'Subject: '.$random_subject."\r\n".
|
||||
'MIME-Version: 1.0'."\r\n".
|
||||
'Content-Type: TEXT/PLAIN; CHARSET=US-ASCII'."\r\n".
|
||||
"\r\n".
|
||||
'test'."\r\n"
|
||||
),
|
||||
];
|
||||
|
||||
$random_subject = 'barbushin/php-imap#448: dot first:'.\bin2hex(\random_bytes(16));
|
||||
|
||||
yield [
|
||||
['subject' => $random_subject],
|
||||
[
|
||||
[
|
||||
'type' => TYPEAPPLICATION,
|
||||
'encoding' => ENCBASE64,
|
||||
'subtype' => 'octet-stream',
|
||||
'description' => '.gitignore',
|
||||
'disposition.type' => 'attachment',
|
||||
'disposition' => ['filename' => '.gitignore'],
|
||||
'type.parameters' => ['name' => '.gitignore'],
|
||||
'contents.data' => \base64_encode(
|
||||
\file_get_contents(__DIR__.'/../../.gitignore')
|
||||
),
|
||||
],
|
||||
],
|
||||
(
|
||||
'Subject: '.$random_subject."\r\n".
|
||||
'MIME-Version: 1.0'."\r\n".
|
||||
'Content-Type: APPLICATION/octet-stream; name=.gitignore'."\r\n".
|
||||
'Content-Transfer-Encoding: BASE64'."\r\n".
|
||||
'Content-Description: .gitignore'."\r\n".
|
||||
'Content-Disposition: attachment; filename=.gitignore'."\r\n".
|
||||
"\r\n".
|
||||
\base64_encode(
|
||||
\file_get_contents(__DIR__.'/../../.gitignore')
|
||||
)."\r\n"
|
||||
),
|
||||
];
|
||||
|
||||
$random_subject = 'barbushin/php-imap#448: dot last: '.\bin2hex(\random_bytes(16));
|
||||
|
||||
yield [
|
||||
['subject' => $random_subject],
|
||||
[
|
||||
[
|
||||
'type' => TYPEAPPLICATION,
|
||||
'encoding' => ENCBASE64,
|
||||
'subtype' => 'octet-stream',
|
||||
'description' => 'gitignore.',
|
||||
'disposition.type' => 'attachment',
|
||||
'disposition' => ['filename' => 'gitignore.'],
|
||||
'type.parameters' => ['name' => 'gitignore.'],
|
||||
'contents.data' => \base64_encode(
|
||||
\file_get_contents(__DIR__.'/../../.gitignore')
|
||||
),
|
||||
],
|
||||
],
|
||||
(
|
||||
'Subject: '.$random_subject."\r\n".
|
||||
'MIME-Version: 1.0'."\r\n".
|
||||
'Content-Type: APPLICATION/octet-stream; name=gitignore.'."\r\n".
|
||||
'Content-Transfer-Encoding: BASE64'."\r\n".
|
||||
'Content-Description: gitignore.'."\r\n".
|
||||
'Content-Disposition: attachment; filename=gitignore.'."\r\n".
|
||||
"\r\n".
|
||||
\base64_encode(
|
||||
\file_get_contents(__DIR__.'/../../.gitignore')
|
||||
)."\r\n"
|
||||
),
|
||||
];
|
||||
|
||||
$random_subject = 'barbushin/php-imap#391: '.\bin2hex(\random_bytes(16));
|
||||
|
||||
$random_attachment_a = \base64_encode(\random_bytes(16));
|
||||
$random_attachment_b = \base64_encode(\random_bytes(16));
|
||||
|
||||
yield [
|
||||
['subject' => $random_subject],
|
||||
[
|
||||
[
|
||||
'type' => TYPEMULTIPART,
|
||||
],
|
||||
[
|
||||
'type' => TYPETEXT,
|
||||
'contents.data' => 'test',
|
||||
],
|
||||
[
|
||||
'type' => TYPEAPPLICATION,
|
||||
'encoding' => ENCBASE64,
|
||||
'subtype' => 'octet-stream',
|
||||
'description' => 'foo.bin',
|
||||
'disposition.type' => 'attachment',
|
||||
'disposition' => ['filename' => 'foo.bin'],
|
||||
'type.parameters' => ['name' => 'foo.bin'],
|
||||
'contents.data' => $random_attachment_a,
|
||||
],
|
||||
[
|
||||
'type' => TYPEAPPLICATION,
|
||||
'encoding' => ENCBASE64,
|
||||
'subtype' => 'octet-stream',
|
||||
'description' => 'foo.bin',
|
||||
'disposition.type' => 'attachment',
|
||||
'disposition' => ['filename' => 'foo.bin'],
|
||||
'type.parameters' => ['name' => 'foo.bin'],
|
||||
'contents.data' => $random_attachment_b,
|
||||
],
|
||||
],
|
||||
(
|
||||
'Subject: '.$random_subject."\r\n".
|
||||
'MIME-Version: 1.0'."\r\n".
|
||||
'Content-Type: MULTIPART/MIXED; BOUNDARY="{{REPLACE_BOUNDARY_HERE}}"'."\r\n".
|
||||
"\r\n".
|
||||
'--{{REPLACE_BOUNDARY_HERE}}'."\r\n".
|
||||
'Content-Type: TEXT/PLAIN; CHARSET=US-ASCII'."\r\n".
|
||||
"\r\n".
|
||||
'test'."\r\n".
|
||||
'--{{REPLACE_BOUNDARY_HERE}}'."\r\n".
|
||||
'Content-Type: APPLICATION/octet-stream; name=foo.bin'."\r\n".
|
||||
'Content-Transfer-Encoding: BASE64'."\r\n".
|
||||
'Content-Description: foo.bin'."\r\n".
|
||||
'Content-Disposition: attachment; filename=foo.bin'."\r\n".
|
||||
"\r\n".
|
||||
$random_attachment_a."\r\n".
|
||||
'--{{REPLACE_BOUNDARY_HERE}}'."\r\n".
|
||||
'Content-Type: APPLICATION/octet-stream; name=foo.bin'."\r\n".
|
||||
'Content-Transfer-Encoding: BASE64'."\r\n".
|
||||
'Content-Description: foo.bin'."\r\n".
|
||||
'Content-Disposition: attachment; filename=foo.bin'."\r\n".
|
||||
"\r\n".
|
||||
$random_attachment_b."\r\n".
|
||||
'--{{REPLACE_BOUNDARY_HERE}}--'."\r\n"
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider ComposeProvider
|
||||
*
|
||||
* @group compose
|
||||
*
|
||||
* @psalm-param COMPOSE_ENVELOPE $envelope
|
||||
* @psalm-param COMPOSE_BODY $body
|
||||
*/
|
||||
public function testMailCompose(array $envelope, array $body, string $expected_result): void
|
||||
{
|
||||
$actual_result = Imap::mail_compose($envelope, $body);
|
||||
|
||||
$expected_result = $this->ReplaceBoundaryHere(
|
||||
$expected_result,
|
||||
$actual_result
|
||||
);
|
||||
|
||||
$this->assertSame($expected_result, $actual_result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider AppendProvider
|
||||
*
|
||||
* @group live
|
||||
*
|
||||
* @depends testAppend
|
||||
*
|
||||
* @psalm-param MAILBOX_ARGS $mailbox_args
|
||||
* @psalm-param COMPOSE_ENVELOPE $envelope
|
||||
* @psalm-param COMPOSE_BODY $body
|
||||
*/
|
||||
public function testAppendNudgesMailboxCount(
|
||||
array $mailbox_args,
|
||||
array $envelope,
|
||||
array $body,
|
||||
string $_expected_compose_result,
|
||||
bool $pre_compose
|
||||
): void {
|
||||
if ($this->MaybeSkipAppendTest($envelope)) {
|
||||
return;
|
||||
}
|
||||
|
||||
[$search_criteria] = $this->SubjectSearchCriteriaAndSubject($envelope);
|
||||
|
||||
[$mailbox, $remove_mailbox, $path] = $this->getMailboxFromArgs(
|
||||
$mailbox_args
|
||||
);
|
||||
|
||||
$count = $mailbox->countMails();
|
||||
|
||||
$message = [$envelope, $body];
|
||||
|
||||
if ($pre_compose) {
|
||||
$message = Imap::mail_compose($envelope, $body);
|
||||
}
|
||||
|
||||
$search = $mailbox->searchMailbox($search_criteria);
|
||||
|
||||
$this->assertCount(
|
||||
0,
|
||||
$search,
|
||||
(
|
||||
'If a subject was found,'.
|
||||
' then the message is insufficiently unique to assert that'.
|
||||
' a newly-appended message was actually created.'
|
||||
)
|
||||
);
|
||||
|
||||
$mailbox->appendMessageToMailbox($message);
|
||||
|
||||
$search = $mailbox->searchMailbox($search_criteria);
|
||||
|
||||
$this->assertCount(
|
||||
1,
|
||||
$search,
|
||||
(
|
||||
'If a subject was not found, '.
|
||||
' then Mailbox::appendMessageToMailbox() failed'.
|
||||
' despite not throwing an exception.'
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
$count + 1,
|
||||
$mailbox->countMails(),
|
||||
(
|
||||
'If the message count did not increase'.
|
||||
' then either the message was not appended,'.
|
||||
' or a mesage was removed while the test was running.'
|
||||
)
|
||||
);
|
||||
|
||||
$mailbox->deleteMail($search[0]);
|
||||
|
||||
$mailbox->expungeDeletedMails();
|
||||
|
||||
$mailbox->switchMailbox($path->getString());
|
||||
$mailbox->deleteMailbox($remove_mailbox);
|
||||
|
||||
$this->assertCount(
|
||||
0,
|
||||
$mailbox->searchMailbox($search_criteria),
|
||||
(
|
||||
'If a subject was found,'.
|
||||
' then the message is was not expunged as requested.'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider AppendProvider
|
||||
*
|
||||
* @group live
|
||||
*
|
||||
* @depends testAppend
|
||||
*
|
||||
* @psalm-param MAILBOX_ARGS $mailbox_args
|
||||
* @psalm-param COMPOSE_ENVELOPE $envelope
|
||||
* @psalm-param COMPOSE_BODY $body
|
||||
*/
|
||||
public function testAppendSingleSearchMatchesSort(
|
||||
array $mailbox_args,
|
||||
array $envelope,
|
||||
array $body,
|
||||
string $_expected_compose_result,
|
||||
bool $pre_compose
|
||||
): void {
|
||||
if ($this->MaybeSkipAppendTest($envelope)) {
|
||||
return;
|
||||
}
|
||||
|
||||
[$search_criteria] = $this->SubjectSearchCriteriaAndSubject($envelope);
|
||||
|
||||
[$mailbox, $remove_mailbox, $path] = $this->getMailboxFromArgs(
|
||||
$mailbox_args
|
||||
);
|
||||
|
||||
$message = [$envelope, $body];
|
||||
|
||||
if ($pre_compose) {
|
||||
$message = Imap::mail_compose($envelope, $body);
|
||||
}
|
||||
|
||||
$search = $mailbox->searchMailbox($search_criteria);
|
||||
|
||||
$this->assertCount(
|
||||
0,
|
||||
$search,
|
||||
(
|
||||
'If a subject was found,'.
|
||||
' then the message is insufficiently unique to assert that'.
|
||||
' a newly-appended message was actually created.'
|
||||
)
|
||||
);
|
||||
|
||||
$mailbox->appendMessageToMailbox($message);
|
||||
|
||||
$search = $mailbox->searchMailbox($search_criteria);
|
||||
|
||||
$this->assertCount(
|
||||
1,
|
||||
$search,
|
||||
(
|
||||
'If a subject was not found, '.
|
||||
' then Mailbox::appendMessageToMailbox() failed'.
|
||||
' despite not throwing an exception.'
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
$search,
|
||||
$mailbox->sortMails(SORTARRIVAL, true, $search_criteria)
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
$search,
|
||||
$mailbox->sortMails(SORTARRIVAL, false, $search_criteria)
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
$search,
|
||||
$mailbox->sortMails(SORTARRIVAL, false, $search_criteria, 'UTF-8')
|
||||
);
|
||||
|
||||
$this->assertTrue(\in_array(
|
||||
$search[0],
|
||||
$mailbox->sortMails(SORTARRIVAL, false, null),
|
||||
true
|
||||
));
|
||||
|
||||
$mailbox->deleteMail($search[0]);
|
||||
|
||||
$mailbox->expungeDeletedMails();
|
||||
|
||||
$mailbox->switchMailbox($path->getString());
|
||||
$mailbox->deleteMailbox($remove_mailbox);
|
||||
|
||||
$this->assertCount(
|
||||
0,
|
||||
$mailbox->searchMailbox($search_criteria),
|
||||
(
|
||||
'If a subject was found,'.
|
||||
' then the message is was not expunged as requested.'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider AppendProvider
|
||||
*
|
||||
* @group live
|
||||
*
|
||||
* @depends testAppend
|
||||
*
|
||||
* @psalm-param MAILBOX_ARGS $mailbox_args
|
||||
* @psalm-param COMPOSE_ENVELOPE $envelope
|
||||
* @psalm-param COMPOSE_BODY $body
|
||||
*/
|
||||
public function testAppendRetrievalMatchesExpected(
|
||||
array $mailbox_args,
|
||||
array $envelope,
|
||||
array $body,
|
||||
string $expected_compose_result,
|
||||
bool $pre_compose
|
||||
): void {
|
||||
if ($this->MaybeSkipAppendTest($envelope)) {
|
||||
return;
|
||||
}
|
||||
|
||||
[$search_criteria, $search_subject] = $this->SubjectSearchCriteriaAndSubject($envelope);
|
||||
|
||||
[$mailbox, $remove_mailbox, $path] = $this->getMailboxFromArgs(
|
||||
$mailbox_args
|
||||
);
|
||||
|
||||
$message = [$envelope, $body];
|
||||
|
||||
if ($pre_compose) {
|
||||
$message = Imap::mail_compose($envelope, $body);
|
||||
}
|
||||
|
||||
$search = $mailbox->searchMailbox($search_criteria);
|
||||
|
||||
$this->assertCount(
|
||||
0,
|
||||
$search,
|
||||
(
|
||||
'If a subject was found,'.
|
||||
' then the message is insufficiently unique to assert that'.
|
||||
' a newly-appended message was actually created.'
|
||||
)
|
||||
);
|
||||
|
||||
$mailbox->appendMessageToMailbox($message);
|
||||
|
||||
$search = $mailbox->searchMailbox($search_criteria);
|
||||
|
||||
$this->assertCount(
|
||||
1,
|
||||
$search,
|
||||
(
|
||||
'If a subject was not found, '.
|
||||
' then Mailbox::appendMessageToMailbox() failed'.
|
||||
' despite not throwing an exception.'
|
||||
)
|
||||
);
|
||||
|
||||
$actual_result = $mailbox->getMailMboxFormat($search[0]);
|
||||
|
||||
$this->assertSame(
|
||||
$this->ReplaceBoundaryHere(
|
||||
$expected_compose_result,
|
||||
$actual_result
|
||||
),
|
||||
$actual_result
|
||||
);
|
||||
|
||||
$actual_result = $mailbox->getRawMail($search[0]);
|
||||
|
||||
$this->assertSame(
|
||||
$this->ReplaceBoundaryHere(
|
||||
$expected_compose_result,
|
||||
$actual_result
|
||||
),
|
||||
$actual_result
|
||||
);
|
||||
|
||||
$mail = $mailbox->getMail($search[0], false);
|
||||
|
||||
$this->assertSame(
|
||||
$search_subject,
|
||||
$mail->subject,
|
||||
(
|
||||
'If a retrieved mail did not have a matching subject'.
|
||||
' despite being found via search,'.
|
||||
' then something has gone wrong.'
|
||||
)
|
||||
);
|
||||
|
||||
$info = $mailbox->getMailsInfo($search);
|
||||
|
||||
$this->assertCount(1, $info);
|
||||
|
||||
$this->assertSame(
|
||||
$search_subject,
|
||||
$info[0]->subject,
|
||||
(
|
||||
'If a retrieved mail did not have a matching subject'.
|
||||
' despite being found via search,'.
|
||||
' then something has gone wrong.'
|
||||
)
|
||||
);
|
||||
|
||||
if (1 === \preg_match(
|
||||
'/^barbushin\/php-imap#(448|391):/',
|
||||
$envelope['subject'] ?? '',
|
||||
$matches
|
||||
)) {
|
||||
$this->assertTrue($mail->hasAttachments());
|
||||
|
||||
$attachments = $mail->getAttachments();
|
||||
|
||||
$this->assertCount(self::ISSUE_EXPECTED_ATTACHMENT_COUNT[
|
||||
(int) $matches[1]],
|
||||
$attachments
|
||||
);
|
||||
|
||||
if ('448' === $matches[1]) {
|
||||
$this->assertSame(
|
||||
\file_get_contents(__DIR__.'/../../.gitignore'),
|
||||
\current($attachments)->getContents()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$mailbox->deleteMail($search[0]);
|
||||
|
||||
$mailbox->expungeDeletedMails();
|
||||
|
||||
$mailbox->switchMailbox($path->getString());
|
||||
$mailbox->deleteMailbox($remove_mailbox);
|
||||
|
||||
$this->assertCount(
|
||||
0,
|
||||
$mailbox->searchMailbox($search_criteria),
|
||||
(
|
||||
'If a subject was found,'.
|
||||
' then the message is was not expunged as requested.'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $expected_result
|
||||
* @param string $actual_result
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
protected function ReplaceBoundaryHere(
|
||||
$expected_result,
|
||||
$actual_result
|
||||
) {
|
||||
if (
|
||||
1 === \preg_match('/{{REPLACE_BOUNDARY_HERE}}/', $expected_result) &&
|
||||
1 === \preg_match(
|
||||
'/Content-Type: MULTIPART\/MIXED; BOUNDARY="([^"]+)"/',
|
||||
$actual_result,
|
||||
$matches
|
||||
)
|
||||
) {
|
||||
$expected_result = \str_replace(
|
||||
'{{REPLACE_BOUNDARY_HERE}}',
|
||||
$matches[1],
|
||||
$expected_result
|
||||
);
|
||||
}
|
||||
|
||||
return $expected_result;
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Live Mailbox - PHPUnit tests.
|
||||
*
|
||||
* Runs tests on a live mailbox
|
||||
*
|
||||
* @author BAPCLTD-Marv
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap;
|
||||
|
||||
use ParagonIE\HiddenString\HiddenString;
|
||||
|
||||
/**
|
||||
* @psalm-type MAILBOX_ARGS = array{
|
||||
* 0:HiddenString,
|
||||
* 1:HiddenString,
|
||||
* 2:HiddenString,
|
||||
* 3:string,
|
||||
* 4?:string
|
||||
* }
|
||||
*/
|
||||
trait LiveMailboxTestingTrait
|
||||
{
|
||||
/**
|
||||
* Provides constructor arguments for a live mailbox.
|
||||
*
|
||||
* @psalm-return array{'CI ENV'?: array{0: \ParagonIE\HiddenString\HiddenString, 1: \ParagonIE\HiddenString\HiddenString, 2: \ParagonIE\HiddenString\HiddenString, 3: string}}
|
||||
*
|
||||
* @return (\ParagonIE\HiddenString\HiddenString|string)[][]
|
||||
*/
|
||||
public function MailBoxProvider(): array
|
||||
{
|
||||
$sets = [];
|
||||
|
||||
$imapPath = \getenv('PHPIMAP_IMAP_PATH');
|
||||
$login = \getenv('PHPIMAP_LOGIN');
|
||||
$password = \getenv('PHPIMAP_PASSWORD');
|
||||
|
||||
if (\is_string($imapPath) && \is_string($login) && \is_string($password)) {
|
||||
$sets['CI ENV'] = [new HiddenString($imapPath), new HiddenString($login), new HiddenString($password, true, true), \sys_get_temp_dir()];
|
||||
}
|
||||
|
||||
return $sets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get instance of Mailbox, pre-set to a random mailbox.
|
||||
*
|
||||
* @param string $attachmentsDir
|
||||
* @param string $serverEncoding
|
||||
*
|
||||
* @return (Mailbox|\ParagonIE\HiddenString\HiddenString|string)[]
|
||||
*
|
||||
* @psalm-return array{0: Mailbox, 1: string, 2: \ParagonIE\HiddenString\HiddenString}
|
||||
*/
|
||||
protected function getMailbox(HiddenString $imapPath, HiddenString $login, HiddenString $password, $attachmentsDir, $serverEncoding = 'UTF-8'): array
|
||||
{
|
||||
$mailbox = new Mailbox($imapPath->getString(), $login->getString(), $password->getString(), $attachmentsDir, $serverEncoding);
|
||||
|
||||
$random = 'test-box-'.\date('c').\bin2hex(\random_bytes(4));
|
||||
|
||||
$mailbox->createMailbox($random);
|
||||
|
||||
$mailbox->switchMailbox($random, false);
|
||||
|
||||
return [$mailbox, $random, $imapPath];
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-param MAILBOX_ARGS $mailbox_args
|
||||
*
|
||||
* @return mixed[]
|
||||
*
|
||||
* @psalm-return array{0:Mailbox, 1:string, 2:HiddenString}
|
||||
*/
|
||||
protected function getMailboxFromArgs(array $mailbox_args): array
|
||||
{
|
||||
[$path, $username, $password, $attachments_dir] = $mailbox_args;
|
||||
|
||||
return $this->getMailbox(
|
||||
$path,
|
||||
$username,
|
||||
$password,
|
||||
$attachments_dir,
|
||||
$mailbox_args[4] ?? 'UTF-8'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Live Mailbox - PHPUnit tests.
|
||||
*
|
||||
* Runs tests on a live mailbox
|
||||
*
|
||||
* @author BAPCLTD-Marv
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap;
|
||||
|
||||
use Generator;
|
||||
use ParagonIE\HiddenString\HiddenString;
|
||||
|
||||
/**
|
||||
* @psalm-type MAILBOX_ARGS = array{
|
||||
* 0:HiddenString,
|
||||
* 1:HiddenString,
|
||||
* 2:HiddenString,
|
||||
* 3:string,
|
||||
* 4?:string
|
||||
* }
|
||||
*/
|
||||
class LiveMailboxWithManualSetupTest extends AbstractLiveMailboxTest
|
||||
{
|
||||
/**
|
||||
* @psalm-return Generator<int, array{0: '.issue-499.Éléments envoyés'}, mixed, void>
|
||||
*/
|
||||
public function RelativeToRootPathProvider(): Generator
|
||||
{
|
||||
yield [
|
||||
'.issue-499.Éléments envoyés',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-return Generator<int, array{0: array{0: HiddenString, 1: HiddenString, 2: HiddenString, 3: string, 4?: string}}, mixed, void>
|
||||
*/
|
||||
public function statusProviderAbsolutePath(): Generator
|
||||
{
|
||||
foreach ($this->RelativeToRootPathProvider() as $path_args) {
|
||||
foreach ($this->MailBoxProvider() as $args) {
|
||||
$args[0] = new HiddenString($args[0]->getString().$path_args[0]);
|
||||
|
||||
yield [$args];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the status of an absolute mailbox path set from the Mailbox constructor.
|
||||
*
|
||||
* @dataProvider statusProviderAbsolutePath
|
||||
*
|
||||
* @group live
|
||||
* @group live-manual
|
||||
*
|
||||
* @psalm-param MAILBOX_ARGS $mailbox_args
|
||||
*/
|
||||
public function testAbsolutePathStatusFromConstruction(
|
||||
array $mailbox_args
|
||||
): void {
|
||||
[$mailbox] = $this->getMailboxFromArgs($mailbox_args);
|
||||
|
||||
$mailbox->statusMailbox();
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
}
|
||||
814
vendor/php-imap/php-imap/tests/unit/MailboxTest.php
vendored
814
vendor/php-imap/php-imap/tests/unit/MailboxTest.php
vendored
@@ -1,814 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Mailbox - PHPUnit tests.
|
||||
*
|
||||
* @author Sebastian Kraetzig <sebastian-kraetzig@gmx.de>
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpImap;
|
||||
|
||||
use const CL_EXPUNGE;
|
||||
use DateTime;
|
||||
use Generator;
|
||||
use const IMAP_CLOSETIMEOUT;
|
||||
use const IMAP_OPENTIMEOUT;
|
||||
use const IMAP_READTIMEOUT;
|
||||
use const IMAP_WRITETIMEOUT;
|
||||
use const OP_ANONYMOUS;
|
||||
use const OP_DEBUG;
|
||||
use const OP_HALFOPEN;
|
||||
use const OP_PROTOTYPE;
|
||||
use const OP_READONLY;
|
||||
use const OP_SECURE;
|
||||
use const OP_SHORTCACHE;
|
||||
use const OP_SILENT;
|
||||
use PhpImap\Exceptions\InvalidParameterException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use const SE_FREE;
|
||||
use const SE_UID;
|
||||
|
||||
final class MailboxTest extends TestCase
|
||||
{
|
||||
public const ANYTHING = 0;
|
||||
|
||||
/**
|
||||
* Holds the imap path.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $imapPath = '{imap.example.com:993/imap/ssl/novalidate-cert}INBOX';
|
||||
|
||||
/**
|
||||
* Holds the imap username.
|
||||
*
|
||||
* @var string|email
|
||||
*
|
||||
* @psalm-var string
|
||||
*/
|
||||
private $login = 'php-imap@example.com';
|
||||
|
||||
/**
|
||||
* Holds the imap user password.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $password = 'v3rY!53cEt&P4sSWöRd$';
|
||||
|
||||
/**
|
||||
* Holds the relative name of the directory, where email attachments will be saved.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $attachmentsDir = '.';
|
||||
|
||||
/**
|
||||
* Holds the server encoding setting.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $serverEncoding = 'UTF-8';
|
||||
|
||||
/**
|
||||
* Test, that the constructor trims possible variables
|
||||
* Leading and ending spaces are not even possible in some variables.
|
||||
*/
|
||||
public function testConstructorTrimsPossibleVariables(): void
|
||||
{
|
||||
$imapPath = ' {imap.example.com:993/imap/ssl}INBOX ';
|
||||
$login = ' php-imap@example.com';
|
||||
$password = ' v3rY!53cEt&P4sSWöRd$';
|
||||
// directory names can contain spaces before AND after on Linux/Unix systems. Windows trims these spaces automatically.
|
||||
$attachmentsDir = '.';
|
||||
$serverEncoding = 'UTF-8 ';
|
||||
|
||||
$mailbox = new Fixtures\Mailbox($imapPath, $login, $password, $attachmentsDir, $serverEncoding);
|
||||
|
||||
$this->assertSame('{imap.example.com:993/imap/ssl}INBOX', $mailbox->getImapPath());
|
||||
$this->assertSame('php-imap@example.com', $mailbox->getLogin());
|
||||
$this->assertSame(' v3rY!53cEt&P4sSWöRd$', $mailbox->getImapPassword());
|
||||
$this->assertSame(\realpath('.'), $mailbox->getAttachmentsDir());
|
||||
$this->assertSame('UTF-8', $mailbox->getServerEncoding());
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-return non-empty-list<array{0: 'UTF-8'|'Windows-1251'|'Windows-1252'}>
|
||||
*
|
||||
* @return string[][]
|
||||
*/
|
||||
public function SetAndGetServerEncodingProvider(): array
|
||||
{
|
||||
$data = [
|
||||
['UTF-8'],
|
||||
];
|
||||
|
||||
$supported = \mb_list_encodings();
|
||||
|
||||
foreach (
|
||||
[
|
||||
'Windows-1251',
|
||||
'Windows-1252',
|
||||
] as $perhaps
|
||||
) {
|
||||
if (
|
||||
\in_array(\trim($perhaps), $supported, true) ||
|
||||
\in_array(\strtoupper(\trim($perhaps)), $supported, true)
|
||||
) {
|
||||
$data[] = [$perhaps];
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, that the server encoding can be set.
|
||||
*
|
||||
* @dataProvider SetAndGetServerEncodingProvider
|
||||
*/
|
||||
public function testSetAndGetServerEncoding(string $encoding): void
|
||||
{
|
||||
$mailbox = $this->getMailbox();
|
||||
|
||||
$mailbox->setServerEncoding($encoding);
|
||||
|
||||
$encoding = \strtoupper(\trim($encoding));
|
||||
|
||||
$this->assertEquals($mailbox->getServerEncoding(), $encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, that server encoding is set to a default value.
|
||||
*/
|
||||
public function testServerEncodingHasDefaultSetting(): void
|
||||
{
|
||||
// Default character encoding should be set
|
||||
$mailbox = new Mailbox($this->imapPath, $this->login, $this->password, $this->attachmentsDir);
|
||||
$this->assertSame('UTF-8', $mailbox->getServerEncoding());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, that server encoding that all functions uppers the server encoding setting.
|
||||
*/
|
||||
public function testServerEncodingUppersSetting(): void
|
||||
{
|
||||
// Server encoding should be always upper formatted
|
||||
$mailbox = new Mailbox($this->imapPath, $this->login, $this->password, $this->attachmentsDir, 'utf-8');
|
||||
$this->assertSame('UTF-8', $mailbox->getServerEncoding());
|
||||
|
||||
$mailbox = new Mailbox($this->imapPath, $this->login, $this->password, $this->attachmentsDir, 'UTF7-IMAP');
|
||||
$mailbox->setServerEncoding('uTf-8');
|
||||
$this->assertSame('UTF-8', $mailbox->getServerEncoding());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testing server encodings.
|
||||
*
|
||||
* @return (bool|string)[][]
|
||||
*
|
||||
* @psalm-return array{UTF-7: array{0: true, 1: 'UTF-7'}, UTF7-IMAP: array{0: true, 1: 'UTF7-IMAP'}, UTF-8: array{0: true, 1: 'UTF-8'}, ASCII: array{0: true, 1: 'ASCII'}, US-ASCII: array{0: true, 1: 'US-ASCII'}, ISO-8859-1: array{0: true, 1: 'ISO-8859-1'}, UTF7: array{0: false, 1: 'UTF7'}, UTF-7-IMAP: array{0: false, 1: 'UTF-7-IMAP'}, UTF-7IMAP: array{0: false, 1: 'UTF-7IMAP'}, UTF8: array{0: false, 1: 'UTF8'}, USASCII: array{0: false, 1: 'USASCII'}, ASC11: array{0: false, 1: 'ASC11'}, ISO-8859-0: array{0: false, 1: 'ISO-8859-0'}, ISO-8855-1: array{0: false, 1: 'ISO-8855-1'}, ISO-8859: array{0: false, 1: 'ISO-8859'}}
|
||||
*/
|
||||
public function serverEncodingProvider(): array
|
||||
{
|
||||
return [
|
||||
// Supported encodings
|
||||
'UTF-7' => [true, 'UTF-7'],
|
||||
'UTF7-IMAP' => [true, 'UTF7-IMAP'],
|
||||
'UTF-8' => [true, 'UTF-8'],
|
||||
'ASCII' => [true, 'ASCII'],
|
||||
'US-ASCII' => [true, 'US-ASCII'],
|
||||
'ISO-8859-1' => [true, 'ISO-8859-1'],
|
||||
// NOT supported encodings
|
||||
'UTF7' => [false, 'UTF7'],
|
||||
'UTF-7-IMAP' => [false, 'UTF-7-IMAP'],
|
||||
'UTF-7IMAP' => [false, 'UTF-7IMAP'],
|
||||
'UTF8' => [false, 'UTF8'],
|
||||
'USASCII' => [false, 'USASCII'],
|
||||
'ASC11' => [false, 'ASC11'],
|
||||
'ISO-8859-0' => [false, 'ISO-8859-0'],
|
||||
'ISO-8855-1' => [false, 'ISO-8855-1'],
|
||||
'ISO-8859' => [false, 'ISO-8859'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, that server encoding only can use supported character encodings.
|
||||
*
|
||||
* @dataProvider serverEncodingProvider
|
||||
*/
|
||||
public function testServerEncodingOnlyUseSupportedSettings(bool $bool, string $encoding): void
|
||||
{
|
||||
$mailbox = $this->getMailbox();
|
||||
|
||||
if ($bool) {
|
||||
$mailbox->setServerEncoding($encoding);
|
||||
$this->assertEquals($encoding, $mailbox->getServerEncoding());
|
||||
} else {
|
||||
$this->expectException(InvalidParameterException::class);
|
||||
$mailbox->setServerEncoding($encoding);
|
||||
$this->assertNotEquals($encoding, $mailbox->getServerEncoding());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, that the IMAP search option has a default value
|
||||
* 1 => SE_UID
|
||||
* 2 => SE_FREE.
|
||||
*/
|
||||
public function testImapSearchOptionHasADefault(): void
|
||||
{
|
||||
$this->assertEquals($this->getMailbox()->getImapSearchOption(), 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, that the IMAP search option can be changed
|
||||
* 1 => SE_UID
|
||||
* 2 => SE_FREE.
|
||||
*/
|
||||
public function testSetAndGetImapSearchOption(): void
|
||||
{
|
||||
$mailbox = $this->getMailbox();
|
||||
|
||||
$mailbox->setImapSearchOption(SE_FREE);
|
||||
$this->assertEquals($mailbox->getImapSearchOption(), 2);
|
||||
|
||||
$this->expectException(InvalidParameterException::class);
|
||||
$mailbox->setImapSearchOption(self::ANYTHING);
|
||||
|
||||
$mailbox->setImapSearchOption(SE_UID);
|
||||
$this->assertEquals($mailbox->getImapSearchOption(), 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, that the imap login can be retrieved.
|
||||
*/
|
||||
public function testGetLogin(): void
|
||||
{
|
||||
$this->assertEquals($this->getMailbox()->getLogin(), 'php-imap@example.com');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, that the path delimiter has a default value.
|
||||
*/
|
||||
public function testPathDelimiterHasADefault(): void
|
||||
{
|
||||
$this->assertNotEmpty($this->getMailbox()->getPathDelimiter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testing path delimiter.
|
||||
*
|
||||
* @psalm-return array{0: array{0: '0'}, 1: array{0: '1'}, 2: array{0: '2'}, 3: array{0: '3'}, 4: array{0: '4'}, 5: array{0: '5'}, 6: array{0: '6'}, 7: array{0: '7'}, 8: array{0: '8'}, 9: array{0: '9'}, a: array{0: 'a'}, b: array{0: 'b'}, c: array{0: 'c'}, d: array{0: 'd'}, e: array{0: 'e'}, f: array{0: 'f'}, g: array{0: 'g'}, h: array{0: 'h'}, i: array{0: 'i'}, j: array{0: 'j'}, k: array{0: 'k'}, l: array{0: 'l'}, m: array{0: 'm'}, n: array{0: 'n'}, o: array{0: 'o'}, p: array{0: 'p'}, q: array{0: 'q'}, r: array{0: 'r'}, s: array{0: 's'}, t: array{0: 't'}, u: array{0: 'u'}, v: array{0: 'v'}, w: array{0: 'w'}, x: array{0: 'x'}, y: array{0: 'y'}, z: array{0: 'z'}, !: array{0: '!'}, '\\': array{0: '\'}, $: array{0: '$'}, %: array{0: '%'}, §: array{0: '§'}, &: array{0: '&'}, /: array{0: '/'}, (: array{0: '('}, ): array{0: ')'}, =: array{0: '='}, #: array{0: '#'}, ~: array{0: '~'}, *: array{0: '*'}, +: array{0: '+'}, ,: array{0: ','}, ;: array{0: ';'}, '.': array{0: '.'}, ':': array{0: ':'}, <: array{0: '<'}, >: array{0: '>'}, |: array{0: '|'}, _: array{0: '_'}}
|
||||
*
|
||||
* @return string[][]
|
||||
*/
|
||||
public function pathDelimiterProvider(): array
|
||||
{
|
||||
return [
|
||||
'0' => ['0'],
|
||||
'1' => ['1'],
|
||||
'2' => ['2'],
|
||||
'3' => ['3'],
|
||||
'4' => ['4'],
|
||||
'5' => ['5'],
|
||||
'6' => ['6'],
|
||||
'7' => ['7'],
|
||||
'8' => ['8'],
|
||||
'9' => ['9'],
|
||||
'a' => ['a'],
|
||||
'b' => ['b'],
|
||||
'c' => ['c'],
|
||||
'd' => ['d'],
|
||||
'e' => ['e'],
|
||||
'f' => ['f'],
|
||||
'g' => ['g'],
|
||||
'h' => ['h'],
|
||||
'i' => ['i'],
|
||||
'j' => ['j'],
|
||||
'k' => ['k'],
|
||||
'l' => ['l'],
|
||||
'm' => ['m'],
|
||||
'n' => ['n'],
|
||||
'o' => ['o'],
|
||||
'p' => ['p'],
|
||||
'q' => ['q'],
|
||||
'r' => ['r'],
|
||||
's' => ['s'],
|
||||
't' => ['t'],
|
||||
'u' => ['u'],
|
||||
'v' => ['v'],
|
||||
'w' => ['w'],
|
||||
'x' => ['x'],
|
||||
'y' => ['y'],
|
||||
'z' => ['z'],
|
||||
'!' => ['!'],
|
||||
'\\' => ['\\'],
|
||||
'$' => ['$'],
|
||||
'%' => ['%'],
|
||||
'§' => ['§'],
|
||||
'&' => ['&'],
|
||||
'/' => ['/'],
|
||||
'(' => ['('],
|
||||
')' => [')'],
|
||||
'=' => ['='],
|
||||
'#' => ['#'],
|
||||
'~' => ['~'],
|
||||
'*' => ['*'],
|
||||
'+' => ['+'],
|
||||
',' => [','],
|
||||
';' => [';'],
|
||||
'.' => ['.'],
|
||||
':' => [':'],
|
||||
'<' => ['<'],
|
||||
'>' => ['>'],
|
||||
'|' => ['|'],
|
||||
'_' => ['_'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, that the path delimiter is checked for supported chars.
|
||||
*
|
||||
* @dataProvider pathDelimiterProvider
|
||||
*/
|
||||
public function testPathDelimiterIsBeingChecked(string $str): void
|
||||
{
|
||||
$supported_delimiters = ['.', '/'];
|
||||
|
||||
$mailbox = $this->getMailbox();
|
||||
|
||||
if (\in_array($str, $supported_delimiters)) {
|
||||
$this->assertTrue($mailbox->validatePathDelimiter($str));
|
||||
} else {
|
||||
$this->expectException(InvalidParameterException::class);
|
||||
$mailbox->setPathDelimiter($str);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, that the path delimiter can be set.
|
||||
*/
|
||||
public function testSetAndGetPathDelimiter(): void
|
||||
{
|
||||
$mailbox = $this->getMailbox();
|
||||
|
||||
$mailbox->setPathDelimiter('.');
|
||||
$this->assertEquals($mailbox->getPathDelimiter(), '.');
|
||||
|
||||
$mailbox->setPathDelimiter('/');
|
||||
$this->assertEquals($mailbox->getPathDelimiter(), '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, that the attachments are not ignored by default.
|
||||
*/
|
||||
public function testGetAttachmentsAreNotIgnoredByDefault(): void
|
||||
{
|
||||
$this->assertEquals($this->getMailbox()->getAttachmentsIgnore(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testing attachments ignore.
|
||||
*
|
||||
* @psalm-return array<string, array{0:bool}>
|
||||
*/
|
||||
public function attachmentsIgnoreProvider(): array
|
||||
{
|
||||
/** @psalm-var array<string, array{0:bool}> */
|
||||
return [
|
||||
'true' => [true],
|
||||
'false' => [false],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, that attachments can be ignored and only valid values are accepted.
|
||||
*
|
||||
* @dataProvider attachmentsIgnoreProvider
|
||||
*/
|
||||
public function testSetAttachmentsIgnore(bool $paramValue): void
|
||||
{
|
||||
$mailbox = $this->getMailbox();
|
||||
$mailbox->setAttachmentsIgnore($paramValue);
|
||||
$this->assertEquals($mailbox->getAttachmentsIgnore(), $paramValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testing encoding.
|
||||
*
|
||||
* @psalm-return array{Avañe’ẽ: array{0: 'Avañe’ẽ'}, azərbaycanca: array{0: 'azərbaycanca'}, Bokmål: array{0: 'Bokmål'}, chiCheŵa: array{0: 'chiCheŵa'}, Deutsch: array{0: 'Deutsch'}, 'U.S. English': array{0: 'U.S. English'}, français: array{0: 'français'}, 'Éléments envoyés': array{0: 'Éléments envoyés'}, føroyskt: array{0: 'føroyskt'}, Kĩmĩrũ: array{0: 'Kĩmĩrũ'}, Kɨlaangi: array{0: 'Kɨlaangi'}, oʼzbekcha: array{0: 'oʼzbekcha'}, Plattdüütsch: array{0: 'Plattdüütsch'}, română: array{0: 'română'}, Sängö: array{0: 'Sängö'}, 'Tiếng Việt': array{0: 'Tiếng Việt'}, ɔl-Maa: array{0: 'ɔl-Maa'}, Ελληνικά: array{0: 'Ελληνικά'}, Ўзбек: array{0: 'Ўзбек'}, Азәрбајҹан: array{0: 'Азәрбајҹан'}, Српски: array{0: 'Српски'}, русский: array{0: 'русский'}, 'ѩзыкъ словѣньскъ': array{0: 'ѩзыкъ словѣньскъ'}, العربية: array{0: 'العربية'}, नेपाली: array{0: 'नेपाली'}, 日本語: array{0: '日本語'}, 简体中文: array{0: '简体中文'}, 繁體中文: array{0: '繁體中文'}, 한국어: array{0: '한국어'}, ąčęėįšųūžĄČĘĖĮŠŲŪŽ: array{0: 'ąčęėįšųūžĄČĘĖĮŠŲŪŽ'}}
|
||||
*
|
||||
* @return string[][]
|
||||
*/
|
||||
public function encodingTestStringsProvider(): array
|
||||
{
|
||||
return [
|
||||
'Avañe’ẽ' => ['Avañe’ẽ'], // Guaraní
|
||||
'azərbaycanca' => ['azərbaycanca'], // Azerbaijani (Latin)
|
||||
'Bokmål' => ['Bokmål'], // Norwegian Bokmål
|
||||
'chiCheŵa' => ['chiCheŵa'], // Chewa
|
||||
'Deutsch' => ['Deutsch'], // German
|
||||
'U.S. English' => ['U.S. English'], // U.S. English
|
||||
'français' => ['français'], // French
|
||||
'Éléments envoyés' => ['Éléments envoyés'], // issue 499
|
||||
'føroyskt' => ['føroyskt'], // Faroese
|
||||
'Kĩmĩrũ' => ['Kĩmĩrũ'], // Kimîîru
|
||||
'Kɨlaangi' => ['Kɨlaangi'], // Langi
|
||||
'oʼzbekcha' => ['oʼzbekcha'], // Uzbek (Latin)
|
||||
'Plattdüütsch' => ['Plattdüütsch'], // Low German
|
||||
'română' => ['română'], // Romanian
|
||||
'Sängö' => ['Sängö'], // Sango
|
||||
'Tiếng Việt' => ['Tiếng Việt'], // Vietnamese
|
||||
'ɔl-Maa' => ['ɔl-Maa'], // Masai
|
||||
'Ελληνικά' => ['Ελληνικά'], // Greek
|
||||
'Ўзбек' => ['Ўзбек'], // Uzbek (Cyrillic)
|
||||
'Азәрбајҹан' => ['Азәрбајҹан'], // Azerbaijani (Cyrillic)
|
||||
'Српски' => ['Српски'], // Serbian (Cyrillic)
|
||||
'русский' => ['русский'], // Russian
|
||||
'ѩзыкъ словѣньскъ' => ['ѩзыкъ словѣньскъ'], // Church Slavic
|
||||
'العربية' => ['العربية'], // Arabic
|
||||
'नेपाली' => ['नेपाली'], // Nepali
|
||||
'日本語' => ['日本語'], // Japanese
|
||||
'简体中文' => ['简体中文'], // Chinese (Simplified)
|
||||
'繁體中文' => ['繁體中文'], // Chinese (Traditional)
|
||||
'한국어' => ['한국어'], // Korean
|
||||
'ąčęėįšųūžĄČĘĖĮŠŲŪŽ' => ['ąčęėįšųūžĄČĘĖĮŠŲŪŽ'], // Lithuanian letters
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, that strings encoded to UTF-7 can be decoded back to UTF-8.
|
||||
*
|
||||
* @dataProvider encodingTestStringsProvider
|
||||
*/
|
||||
public function testEncodingToUtf7DecodeBackToUtf8(string $str): void
|
||||
{
|
||||
$mailbox = $this->getMailbox();
|
||||
|
||||
$utf7_encoded_str = $mailbox->encodeStringToUtf7Imap($str);
|
||||
$utf8_decoded_str = $mailbox->decodeStringFromUtf7ImapToUtf8($utf7_encoded_str);
|
||||
|
||||
$this->assertEquals($utf8_decoded_str, $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, that strings encoded to UTF-7 can be decoded back to UTF-8.
|
||||
*
|
||||
* @dataProvider encodingTestStringsProvider
|
||||
*/
|
||||
public function testMimeDecodingReturnsCorrectValues(string $str): void
|
||||
{
|
||||
$this->assertEquals($this->getMailbox()->decodeMimeStr($str), $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testing parsing datetimes.
|
||||
*
|
||||
* @psalm-return array{'Sun, 14 Aug 2005 16:13:03 +0000 (CEST)': array{0: '2005-08-14T16:13:03+00:00', 1: 1124035983}, 'Sun, 14 Aug 2005 16:13:03 +0000': array{0: '2005-08-14T16:13:03+00:00', 1: 1124035983}, 'Sun, 14 Aug 2005 16:13:03 +1000 (CEST)': array{0: '2005-08-14T06:13:03+00:00', 1: 1123999983}, 'Sun, 14 Aug 2005 16:13:03 +1000': array{0: '2005-08-14T06:13:03+00:00', 1: 1123999983}, 'Sun, 14 Aug 2005 16:13:03 -1000': array{0: '2005-08-15T02:13:03+00:00', 1: 1124071983}, 'Sun, 14 Aug 2005 16:13:03 +1100 (CEST)': array{0: '2005-08-14T05:13:03+00:00', 1: 1123996383}, 'Sun, 14 Aug 2005 16:13:03 +1100': array{0: '2005-08-14T05:13:03+00:00', 1: 1123996383}, 'Sun, 14 Aug 2005 16:13:03 -1100': array{0: '2005-08-15T03:13:03+00:00', 1: 1124075583}, '14 Aug 2005 16:13:03 +1000 (CEST)': array{0: '2005-08-14T06:13:03+00:00', 1: 1123999983}, '14 Aug 2005 16:13:03 +1000': array{0: '2005-08-14T06:13:03+00:00', 1: 1123999983}, '14 Aug 2005 16:13:03 -1000': array{0: '2005-08-15T02:13:03+00:00', 1: 1124071983}}
|
||||
*
|
||||
* @return (int|string)[][]
|
||||
*/
|
||||
public function datetimeProvider(): array
|
||||
{
|
||||
return [
|
||||
'Sun, 14 Aug 2005 16:13:03 +0000 (CEST)' => ['2005-08-14T16:13:03+00:00', 1124035983],
|
||||
'Sun, 14 Aug 2005 16:13:03 +0000' => ['2005-08-14T16:13:03+00:00', 1124035983],
|
||||
|
||||
'Sun, 14 Aug 2005 16:13:03 +1000 (CEST)' => ['2005-08-14T06:13:03+00:00', 1123999983],
|
||||
'Sun, 14 Aug 2005 16:13:03 +1000' => ['2005-08-14T06:13:03+00:00', 1123999983],
|
||||
'Sun, 14 Aug 2005 16:13:03 -1000' => ['2005-08-15T02:13:03+00:00', 1124071983],
|
||||
|
||||
'Sun, 14 Aug 2005 16:13:03 +1100 (CEST)' => ['2005-08-14T05:13:03+00:00', 1123996383],
|
||||
'Sun, 14 Aug 2005 16:13:03 +1100' => ['2005-08-14T05:13:03+00:00', 1123996383],
|
||||
'Sun, 14 Aug 2005 16:13:03 -1100' => ['2005-08-15T03:13:03+00:00', 1124075583],
|
||||
|
||||
'14 Aug 2005 16:13:03 +1000 (CEST)' => ['2005-08-14T06:13:03+00:00', 1123999983],
|
||||
'14 Aug 2005 16:13:03 +1000' => ['2005-08-14T06:13:03+00:00', 1123999983],
|
||||
'14 Aug 2005 16:13:03 -1000' => ['2005-08-15T02:13:03+00:00', 1124071983],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, different datetimes conversions using differents timezones.
|
||||
*
|
||||
* @dataProvider datetimeProvider
|
||||
*/
|
||||
public function testParsedDateDifferentTimeZones(string $dateToParse, int $epochToCompare): void
|
||||
{
|
||||
$parsedDt = $this->getMailbox()->parseDateTime($dateToParse);
|
||||
$parsedDateTime = new DateTime($parsedDt);
|
||||
$this->assertEquals((int) $parsedDateTime->format('U'), $epochToCompare);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testing parsing invalid / unparseable datetimes.
|
||||
*
|
||||
* @psalm-return array{'Sun, 14 Aug 2005 16:13:03 +9000 (CEST)': array{0: 'Sun, 14 Aug 2005 16:13:03 +9000 (CEST)'}, 'Sun, 14 Aug 2005 16:13:03 +9000': array{0: 'Sun, 14 Aug 2005 16:13:03 +9000'}, 'Sun, 14 Aug 2005 16:13:03 -9000': array{0: 'Sun, 14 Aug 2005 16:13:03 -9000'}}
|
||||
*
|
||||
* @return string[][]
|
||||
*/
|
||||
public function invalidDatetimeProvider(): array
|
||||
{
|
||||
return [
|
||||
'Sun, 14 Aug 2005 16:13:03 +9000 (CEST)' => ['Sun, 14 Aug 2005 16:13:03 +9000 (CEST)'],
|
||||
'Sun, 14 Aug 2005 16:13:03 +9000' => ['Sun, 14 Aug 2005 16:13:03 +9000'],
|
||||
'Sun, 14 Aug 2005 16:13:03 -9000' => ['Sun, 14 Aug 2005 16:13:03 -9000'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, different invalid / unparseable datetimes conversions.
|
||||
*
|
||||
* @dataProvider invalidDatetimeProvider
|
||||
*/
|
||||
public function testParsedDateWithUnparseableDateTime(string $dateToParse): void
|
||||
{
|
||||
$parsedDt = $this->getMailbox()->parseDateTime($dateToParse);
|
||||
$this->assertEquals($parsedDt, $dateToParse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, parsed datetime being emtpy the header date.
|
||||
*/
|
||||
public function testParsedDateTimeWithEmptyHeaderDate(): void
|
||||
{
|
||||
$this->expectException(InvalidParameterException::class);
|
||||
$this->getMailbox()->parseDateTime('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testing mime encoding.
|
||||
*
|
||||
* @return string[][]
|
||||
*
|
||||
* @psalm-return array{0: array{0: '=?iso-8859-1?Q?Sebastian_Kr=E4tzig?= <sebastian.kraetzig@example.com>', 1: 'Sebastian Krätzig <sebastian.kraetzig@example.com>'}, 1: array{0: '=?iso-8859-1?Q?Sebastian_Kr=E4tzig?=', 1: 'Sebastian Krätzig'}, 2: array{0: 'sebastian.kraetzig', 1: 'sebastian.kraetzig'}, 3: array{0: '=?US-ASCII?Q?Keith_Moore?= <km@ab.example.edu>', 1: 'Keith Moore <km@ab.example.edu>'}, 4: array{0: ' ', 1: ' '}, 5: array{0: '=?ISO-8859-1?Q?Max_J=F8rn_Simsen?= <max.joern.s@example.dk>', 1: 'Max Jørn Simsen <max.joern.s@example.dk>'}, 6: array{0: '=?ISO-8859-1?Q?Andr=E9?= Muster <andre.muster@vm1.ulg.ac.be>', 1: 'André Muster <andre.muster@vm1.ulg.ac.be>'}, 7: array{0: '=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?= =?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=', 1: 'If you can read this you understand the example.'}, 8: array{0: '', 1: ''}}
|
||||
*/
|
||||
public function mimeEncodingProvider(): array
|
||||
{
|
||||
return [
|
||||
['=?iso-8859-1?Q?Sebastian_Kr=E4tzig?= <sebastian.kraetzig@example.com>', 'Sebastian Krätzig <sebastian.kraetzig@example.com>'],
|
||||
['=?iso-8859-1?Q?Sebastian_Kr=E4tzig?=', 'Sebastian Krätzig'],
|
||||
['sebastian.kraetzig', 'sebastian.kraetzig'],
|
||||
['=?US-ASCII?Q?Keith_Moore?= <km@ab.example.edu>', 'Keith Moore <km@ab.example.edu>'],
|
||||
[' ', ' '],
|
||||
['=?ISO-8859-1?Q?Max_J=F8rn_Simsen?= <max.joern.s@example.dk>', 'Max Jørn Simsen <max.joern.s@example.dk>'],
|
||||
['=?ISO-8859-1?Q?Andr=E9?= Muster <andre.muster@vm1.ulg.ac.be>', 'André Muster <andre.muster@vm1.ulg.ac.be>'],
|
||||
['=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?= =?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=', 'If you can read this you understand the example.'],
|
||||
['', ''], // barbushin/php-imap#501
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, that mime encoding returns correct strings.
|
||||
*
|
||||
* @dataProvider mimeEncodingProvider
|
||||
*/
|
||||
public function testMimeEncoding(string $str, string $expected): void
|
||||
{
|
||||
$mailbox = $this->getMailbox();
|
||||
|
||||
$this->assertEquals($mailbox->decodeMimeStr($str), $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testing timeouts.
|
||||
*
|
||||
* @psalm-return array<string, array{0:'assertNull'|'expectException', 1:int, 2:list<1|2|3|4>}>
|
||||
*/
|
||||
public function timeoutsProvider(): array
|
||||
{
|
||||
/** @psalm-var array<string, array{0:'assertNull'|'expectException', 1:int, 2:list<int>}> */
|
||||
return [
|
||||
'array(IMAP_OPENTIMEOUT)' => ['assertNull', 1, [IMAP_OPENTIMEOUT]],
|
||||
'array(IMAP_READTIMEOUT)' => ['assertNull', 1, [IMAP_READTIMEOUT]],
|
||||
'array(IMAP_WRITETIMEOUT)' => ['assertNull', 1, [IMAP_WRITETIMEOUT]],
|
||||
'array(IMAP_CLOSETIMEOUT)' => ['assertNull', 1, [IMAP_CLOSETIMEOUT]],
|
||||
'array(IMAP_OPENTIMEOUT, IMAP_READTIMEOUT, IMAP_WRITETIMEOUT, IMAP_CLOSETIMEOUT)' => ['assertNull', 1, [IMAP_OPENTIMEOUT, IMAP_READTIMEOUT, IMAP_WRITETIMEOUT, IMAP_CLOSETIMEOUT]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, that only supported timeouts can be set.
|
||||
*
|
||||
* @dataProvider timeoutsProvider
|
||||
*
|
||||
* @param int[] $types
|
||||
*
|
||||
* @psalm-param 'assertNull'|'expectException' $assertMethod
|
||||
* @psalm-param list<1|2|3|4> $types
|
||||
*/
|
||||
public function testSetTimeouts(string $assertMethod, int $timeout, array $types): void
|
||||
{
|
||||
$mailbox = $this->getMailbox();
|
||||
|
||||
if ('expectException' == $assertMethod) {
|
||||
$this->expectException(InvalidParameterException::class);
|
||||
$mailbox->setTimeouts($timeout, $types);
|
||||
} else {
|
||||
$this->assertNull($mailbox->setTimeouts($timeout, $types));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testing connection args.
|
||||
*
|
||||
* @psalm-return Generator<string, array{0: 'assertNull'|'expectException', 1: int, 2: 0, 3: array<empty, empty>}, mixed, void>
|
||||
*/
|
||||
public function connectionArgsProvider(): Generator
|
||||
{
|
||||
yield from [
|
||||
'readonly, disable gssapi' => ['assertNull', OP_READONLY, 0, ['DISABLE_AUTHENTICATOR' => 'GSSAPI']],
|
||||
'anonymous, disable gssapi' => ['assertNull', OP_ANONYMOUS, 0, ['DISABLE_AUTHENTICATOR' => 'GSSAPI']],
|
||||
'half open, disable gssapi' => ['assertNull', OP_HALFOPEN, 0, ['DISABLE_AUTHENTICATOR' => 'GSSAPI']],
|
||||
'expunge on close, disable gssapi' => ['assertNull', CL_EXPUNGE, 0, ['DISABLE_AUTHENTICATOR' => 'GSSAPI']],
|
||||
'debug, disable gssapi' => ['assertNull', OP_DEBUG, 0, ['DISABLE_AUTHENTICATOR' => 'GSSAPI']],
|
||||
'short cache, disable gssapi' => ['assertNull', OP_SHORTCACHE, 0, ['DISABLE_AUTHENTICATOR' => 'GSSAPI']],
|
||||
'silent, disable gssapi' => ['assertNull', OP_SILENT, 0, ['DISABLE_AUTHENTICATOR' => 'GSSAPI']],
|
||||
'return driver prototype, disable gssapi' => ['assertNull', OP_PROTOTYPE, 0, ['DISABLE_AUTHENTICATOR' => 'GSSAPI']],
|
||||
'don\'t do non-secure authentication, disable gssapi' => ['assertNull', OP_SECURE, 0, ['DISABLE_AUTHENTICATOR' => 'GSSAPI']],
|
||||
'readonly, disable gssapi, 1 retry' => ['assertNull', OP_READONLY, 1, ['DISABLE_AUTHENTICATOR' => 'GSSAPI']],
|
||||
'readonly, disable gssapi, 3 retries' => ['assertNull', OP_READONLY, 3, ['DISABLE_AUTHENTICATOR' => 'GSSAPI']],
|
||||
'readonly, disable gssapi, 12 retries' => ['assertNull', OP_READONLY, 12, ['DISABLE_AUTHENTICATOR' => 'GSSAPI']],
|
||||
'readonly debug, disable gssapi' => ['assertNull', OP_READONLY | OP_DEBUG, 0, ['DISABLE_AUTHENTICATOR' => 'GSSAPI']],
|
||||
'readonly, -1 retries' => ['expectException', OP_READONLY, -1, ['DISABLE_AUTHENTICATOR' => 'GSSAPI']],
|
||||
'readonly, -3 retries' => ['expectException', OP_READONLY, -3, ['DISABLE_AUTHENTICATOR' => 'GSSAPI']],
|
||||
'readonly, -12 retries' => ['expectException', OP_READONLY, -12, ['DISABLE_AUTHENTICATOR' => 'GSSAPI']],
|
||||
'readonly, null options' => ['expectException', OP_READONLY, 0, [null]],
|
||||
];
|
||||
|
||||
/** @psalm-var list<array{0:int, 1:string}> */
|
||||
$options = [
|
||||
[OP_DEBUG, 'debug'], // 1
|
||||
[OP_READONLY, 'readonly'], // 2
|
||||
[OP_ANONYMOUS, 'anonymous'], // 4
|
||||
[OP_SHORTCACHE, 'short cache'], // 8
|
||||
[OP_SILENT, 'silent'], // 16
|
||||
[OP_PROTOTYPE, 'return driver prototype'], // 32
|
||||
[OP_HALFOPEN, 'half-open'], // 64
|
||||
[OP_SECURE, 'don\'t do non-secure authnetication'], // 256
|
||||
[CL_EXPUNGE, 'expunge on close'], // 32768
|
||||
];
|
||||
|
||||
foreach ($options as $i => $option) {
|
||||
$value = $option[0];
|
||||
|
||||
for ($j = $i + 1; $j < \count($options); ++$j) {
|
||||
$value |= $options[$j][0];
|
||||
|
||||
$fields = [];
|
||||
|
||||
foreach ($options as $option) {
|
||||
if (0 !== ($value & $option[0])) {
|
||||
$fields[] = $option[1];
|
||||
}
|
||||
}
|
||||
|
||||
$key = \implode(', ', $fields);
|
||||
|
||||
yield $key => ['assertNull', $value, 0, []];
|
||||
yield ('INVALID + '.$key) => ['expectException', $value | 128, 0, []];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, that only supported and valid connection args can be set.
|
||||
*
|
||||
* @dataProvider connectionArgsProvider
|
||||
*
|
||||
* @psalm-param array{DISABLE_AUTHENTICATOR?:string}|array<empty, empty> $param
|
||||
*/
|
||||
public function testSetConnectionArgs(string $assertMethod, int $option, int $retriesNum, array $param = null): void
|
||||
{
|
||||
$mailbox = $this->getMailbox();
|
||||
|
||||
if ('expectException' == $assertMethod) {
|
||||
$this->expectException(InvalidParameterException::class);
|
||||
$mailbox->setConnectionArgs($option, $retriesNum, $param);
|
||||
$this->assertSame($option, $mailbox->getImapOptions());
|
||||
} elseif ('assertNull' == $assertMethod) {
|
||||
$this->assertNull($mailbox->setConnectionArgs($option, $retriesNum, $param));
|
||||
}
|
||||
|
||||
$mailbox->disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testing mime string decoding.
|
||||
*
|
||||
* @psalm-return array{'<bde36ec8-9710-47bc-9ea3-bf0425078e33@php.imap>': array{0: '<bde36ec8-9710-47bc-9ea3-bf0425078e33@php.imap>', 1: '<bde36ec8-9710-47bc-9ea3-bf0425078e33@php.imap>'}, '<CAKBqNfyKo+ZXtkz6DUAHw6FjmsDjWDB-pvHkJy6kwO82jTbkNA@mail.gmail.com>': array{0: '<CAKBqNfyKo+ZXtkz6DUAHw6FjmsDjWDB-pvHkJy6kwO82jTbkNA@mail.gmail.com>', 1: '<CAKBqNfyKo+ZXtkz6DUAHw6FjmsDjWDB-pvHkJy6kwO82jTbkNA@mail.gmail.com>'}, '<CAE78dO7vwnd_rkozHLZ5xSUnFEQA9fymcYREW2cwQ8DA2v7BTA@mail.gmail.com>': array{0: '<CAE78dO7vwnd_rkozHLZ5xSUnFEQA9fymcYREW2cwQ8DA2v7BTA@mail.gmail.com>', 1: '<CAE78dO7vwnd_rkozHLZ5xSUnFEQA9fymcYREW2cwQ8DA2v7BTA@mail.gmail.com>'}, '<CAE78dO7vwnd_rkozHLZ5xSU-=nFE_QA9+fymcYREW2cwQ8DA2v7BTA@mail.gmail.com>': array{0: '<CAE78dO7vwnd_rkozHLZ5xSU-=nFE_QA9+fymcYREW2cwQ8DA2v7BTA@mail.gmail.com>', 1: '<CAE78dO7vwnd_rkozHLZ5xSU-=nFE_QA9+fymcYREW2cwQ8DA2v7BTA@mail.gmail.com>'}, 'Some subject here 😘': array{0: '=?UTF-8?q?Some_subject_here_?= =?UTF-8?q?=F0=9F=98=98?=', 1: 'Some subject here 😘'}, mountainguan测试: array{0: '=?UTF-8?Q?mountainguan=E6=B5=8B=E8=AF=95?=', 1: 'mountainguan测试'}, 'This is the Euro symbol \'\'.': array{0: 'This is the Euro symbol ''.', 1: 'This is the Euro symbol ''.'}, 'Some subject here 😘 US-ASCII': array{0: '=?UTF-8?q?Some_subject_here_?= =?UTF-8?q?=F0=9F=98=98?=', 1: 'Some subject here 😘', 2: 'US-ASCII'}, 'mountainguan测试 US-ASCII': array{0: '=?UTF-8?Q?mountainguan=E6=B5=8B=E8=AF=95?=', 1: 'mountainguan测试', 2: 'US-ASCII'}, 'مقتطفات من: صن تزو. \"فن الحرب\". كتب أبل. Something': array{0: 'مقتطفات من: صن تزو. "فن الحرب". كتب أبل. Something', 1: 'مقتطفات من: صن تزو. "فن الحرب". كتب أبل. Something'}, '(事件单编号:TESTA-111111)(通报)入口有陌生人': array{0: '=?utf-8?b?KOS6i+S7tuWNlee8luWPtzpURVNUQS0xMTExMTEpKOmAmuaKpSnl?= =?utf-8?b?haXlj6PmnInpmYznlJ/kuro=?=', 1: '(事件单编号:TESTA-111111)(通报)入口有陌生人'}}
|
||||
*
|
||||
* @return string[][]
|
||||
*/
|
||||
public function mimeStrDecodingProvider(): array
|
||||
{
|
||||
return [
|
||||
'<bde36ec8-9710-47bc-9ea3-bf0425078e33@php.imap>' => ['<bde36ec8-9710-47bc-9ea3-bf0425078e33@php.imap>', '<bde36ec8-9710-47bc-9ea3-bf0425078e33@php.imap>'],
|
||||
'<CAKBqNfyKo+ZXtkz6DUAHw6FjmsDjWDB-pvHkJy6kwO82jTbkNA@mail.gmail.com>' => ['<CAKBqNfyKo+ZXtkz6DUAHw6FjmsDjWDB-pvHkJy6kwO82jTbkNA@mail.gmail.com>', '<CAKBqNfyKo+ZXtkz6DUAHw6FjmsDjWDB-pvHkJy6kwO82jTbkNA@mail.gmail.com>'],
|
||||
'<CAE78dO7vwnd_rkozHLZ5xSUnFEQA9fymcYREW2cwQ8DA2v7BTA@mail.gmail.com>' => ['<CAE78dO7vwnd_rkozHLZ5xSUnFEQA9fymcYREW2cwQ8DA2v7BTA@mail.gmail.com>', '<CAE78dO7vwnd_rkozHLZ5xSUnFEQA9fymcYREW2cwQ8DA2v7BTA@mail.gmail.com>'],
|
||||
'<CAE78dO7vwnd_rkozHLZ5xSU-=nFE_QA9+fymcYREW2cwQ8DA2v7BTA@mail.gmail.com>' => ['<CAE78dO7vwnd_rkozHLZ5xSU-=nFE_QA9+fymcYREW2cwQ8DA2v7BTA@mail.gmail.com>', '<CAE78dO7vwnd_rkozHLZ5xSU-=nFE_QA9+fymcYREW2cwQ8DA2v7BTA@mail.gmail.com>'],
|
||||
'Some subject here 😘' => ['=?UTF-8?q?Some_subject_here_?= =?UTF-8?q?=F0=9F=98=98?=', 'Some subject here 😘'],
|
||||
'mountainguan测试' => ['=?UTF-8?Q?mountainguan=E6=B5=8B=E8=AF=95?=', 'mountainguan测试'],
|
||||
"This is the Euro symbol ''." => ["This is the Euro symbol ''.", "This is the Euro symbol ''."],
|
||||
'Some subject here 😘 US-ASCII' => ['=?UTF-8?q?Some_subject_here_?= =?UTF-8?q?=F0=9F=98=98?=', 'Some subject here 😘', 'US-ASCII'],
|
||||
'mountainguan测试 US-ASCII' => ['=?UTF-8?Q?mountainguan=E6=B5=8B=E8=AF=95?=', 'mountainguan测试', 'US-ASCII'],
|
||||
'مقتطفات من: صن تزو. "فن الحرب". كتب أبل. Something' => ['مقتطفات من: صن تزو. "فن الحرب". كتب أبل. Something', 'مقتطفات من: صن تزو. "فن الحرب". كتب أبل. Something'],
|
||||
'(事件单编号:TESTA-111111)(通报)入口有陌生人' => ['=?utf-8?b?KOS6i+S7tuWNlee8luWPtzpURVNUQS0xMTExMTEpKOmAmuaKpSnl?= =?utf-8?b?haXlj6PmnInpmYznlJ/kuro=?=', '(事件单编号:TESTA-111111)(通报)入口有陌生人'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test, that decoding mime strings return unchanged / not broken strings.
|
||||
*
|
||||
* @dataProvider mimeStrDecodingProvider
|
||||
*/
|
||||
public function testDecodeMimeStr(string $str, string $expectedStr, string $serverEncoding = 'utf-8'): void
|
||||
{
|
||||
$mailbox = $this->getMailbox();
|
||||
|
||||
$mailbox->setServerEncoding($serverEncoding);
|
||||
$this->assertEquals($mailbox->decodeMimeStr($str), $expectedStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testing base64 string decoding.
|
||||
*
|
||||
* @psalm-return array{0: array{0: 'bm8tcmVwbHlAZXhhbXBsZS5jb20=', 1: 'no-reply@example.com'}, 1: array{0: 'TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=', 1: 'Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.'}, 2: array{0: 'SSBjYW4gZWF0IGdsYXNzIGFuZCBpdCBkb2VzIG5vdCBodXJ0IG1lLg==', 1: 'I can eat glass and it does not hurt me.'}, 3: array{0: '77u/4KSV4KS+4KSa4KSCIOCktuCkleCljeCkqOCli+CkruCljeCkr+CkpOCljeCkpOClgeCkruCljSDgpaQg4KSo4KWL4KSq4KS54KS/4KSo4KS44KWN4KSk4KS/IOCkruCkvuCkruCljSDgpaU=', 1: 'काचं शक्नोम्यत्तुम् । नोपहिनस्ति माम् ॥'}, 4: array{0: 'SmUgcGV1eCBtYW5nZXIgZHUgdmVycmUsIMOnYSBuZSBtZSBmYWl0IHBhcyBtYWwu', 1: 'Je peux manger du verre, ça ne me fait pas mal.'}, 5: array{0: 'UG90IHPEgyBtxINuw6JuYyBzdGljbMSDIMiZaSBlYSBudSBtxIMgcsSDbmXImXRlLg==', 1: 'Pot să mănânc sticlă și ea nu mă rănește.'}, 6: array{0: '5oiR6IO95ZCe5LiL546755KD6ICM5LiN5YK36Lqr6auU44CC', 1: '我能吞下玻璃而不傷身體。'}}
|
||||
*
|
||||
* @return string[][]
|
||||
*/
|
||||
public function Base64DecodeProvider(): array
|
||||
{
|
||||
return [
|
||||
['bm8tcmVwbHlAZXhhbXBsZS5jb20=', 'no-reply@example.com'],
|
||||
['TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=', 'Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.'],
|
||||
['SSBjYW4gZWF0IGdsYXNzIGFuZCBpdCBkb2VzIG5vdCBodXJ0IG1lLg==', 'I can eat glass and it does not hurt me.'],
|
||||
['77u/4KSV4KS+4KSa4KSCIOCktuCkleCljeCkqOCli+CkruCljeCkr+CkpOCljeCkpOClgeCkruCljSDgpaQg4KSo4KWL4KSq4KS54KS/4KSo4KS44KWN4KSk4KS/IOCkruCkvuCkruCljSDgpaU=', 'काचं शक्नोम्यत्तुम् । नोपहिनस्ति माम् ॥'],
|
||||
['SmUgcGV1eCBtYW5nZXIgZHUgdmVycmUsIMOnYSBuZSBtZSBmYWl0IHBhcyBtYWwu', 'Je peux manger du verre, ça ne me fait pas mal.'],
|
||||
['UG90IHPEgyBtxINuw6JuYyBzdGljbMSDIMiZaSBlYSBudSBtxIMgcsSDbmXImXRlLg==', 'Pot să mănânc sticlă și ea nu mă rănește.'],
|
||||
['5oiR6IO95ZCe5LiL546755KD6ICM5LiN5YK36Lqr6auU44CC', '我能吞下玻璃而不傷身體。'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider Base64DecodeProvider
|
||||
*/
|
||||
public function testBase64Decode(string $input, string $expected): void
|
||||
{
|
||||
$this->assertSame($expected, \imap_base64(\preg_replace('~[^a-zA-Z0-9+=/]+~s', '', $input)));
|
||||
$this->assertSame($expected, \base64_decode($input, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-return array{0: array{0: string, 1: '', 2: Exceptions\InvalidParameterException::class, 3: 'setAttachmentsDir() expects a string as first parameter!'}, 1: array{0: string, 1: ' ', 2: Exceptions\InvalidParameterException::class, 3: 'setAttachmentsDir() expects a string as first parameter!'}, 2: array{0: string, 1: string, 2: Exceptions\InvalidParameterException::class, 3: string}}
|
||||
*
|
||||
* @return string[][]
|
||||
*/
|
||||
public function attachmentDirFailureProvider(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
__DIR__,
|
||||
'',
|
||||
InvalidParameterException::class,
|
||||
'setAttachmentsDir() expects a string as first parameter!',
|
||||
],
|
||||
[
|
||||
__DIR__,
|
||||
' ',
|
||||
InvalidParameterException::class,
|
||||
'setAttachmentsDir() expects a string as first parameter!',
|
||||
],
|
||||
[
|
||||
__DIR__,
|
||||
__FILE__,
|
||||
InvalidParameterException::class,
|
||||
'Directory "'.__FILE__.'" not found',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that setting the attachments directory fails when expected.
|
||||
*
|
||||
* @dataProvider attachmentDirFailureProvider
|
||||
*
|
||||
* @psalm-param class-string<\Exception> $expectedException
|
||||
*/
|
||||
public function testAttachmentDirFailure(string $initialDir, string $attachmentsDir, string $expectedException, string $expectedExceptionMessage): void
|
||||
{
|
||||
$mailbox = new Mailbox('', '', '', $initialDir);
|
||||
|
||||
$this->assertSame(\trim($initialDir), $mailbox->getAttachmentsDir());
|
||||
|
||||
$this->expectException($expectedException);
|
||||
$this->expectExceptionMessage($expectedExceptionMessage);
|
||||
|
||||
$mailbox->setAttachmentsDir($attachmentsDir);
|
||||
}
|
||||
|
||||
protected function getMailbox(): Fixtures\Mailbox
|
||||
{
|
||||
return new Fixtures\Mailbox($this->imapPath, $this->login, $this->password, $this->attachmentsDir, $this->serverEncoding);
|
||||
}
|
||||
}
|
||||
4
vendor/phpmailer/phpmailer/README.md
vendored
4
vendor/phpmailer/phpmailer/README.md
vendored
@@ -47,7 +47,7 @@ This software is distributed under the [LGPL 2.1](http://www.gnu.org/licenses/lg
|
||||
PHPMailer is available on [Packagist](https://packagist.org/packages/phpmailer/phpmailer) (using semantic versioning), and installation via [Composer](https://getcomposer.org) is the recommended way to install PHPMailer. Just add this line to your `composer.json` file:
|
||||
|
||||
```json
|
||||
"phpmailer/phpmailer": "^6.8.0"
|
||||
"phpmailer/phpmailer": "^6.8.1"
|
||||
```
|
||||
|
||||
or run
|
||||
@@ -150,7 +150,7 @@ PHPMailer defaults to English, but in the [language](https://github.com/PHPMaile
|
||||
$mail->setLanguage('fr', '/optional/path/to/language/directory/');
|
||||
```
|
||||
|
||||
We welcome corrections and new languages – if you're looking for corrections, run the [PHPMailerLangTest.php](https://github.com/PHPMailer/PHPMailer/tree/master/test/PHPMailerLangTest.php) script in the tests folder and it will show any missing translations.
|
||||
We welcome corrections and new languages – if you're looking for corrections, run the [Language/TranslationCompletenessTest.php](https://github.com/PHPMailer/PHPMailer/blob/master/test/Language/TranslationCompletenessTest.php) script in the tests folder and it will show any missing translations.
|
||||
|
||||
## Documentation
|
||||
Start reading at the [GitHub wiki](https://github.com/PHPMailer/PHPMailer/wiki). If you're having trouble, head for [the troubleshooting guide](https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting) as it's frequently updated.
|
||||
|
||||
2
vendor/phpmailer/phpmailer/VERSION
vendored
2
vendor/phpmailer/phpmailer/VERSION
vendored
@@ -1 +1 @@
|
||||
6.8.0
|
||||
6.8.1
|
||||
@@ -20,7 +20,6 @@ $PHPMAILER_LANG['instantiate'] = 'mail-funktion luonti epäonnistui.';
|
||||
$PHPMAILER_LANG['mailer_not_supported'] = 'postivälitintyyppiä ei tueta.';
|
||||
$PHPMAILER_LANG['provide_address'] = 'Aseta vähintään yksi vastaanottajan sähköpostiosoite.';
|
||||
$PHPMAILER_LANG['recipients_failed'] = 'SMTP-virhe: seuraava vastaanottaja osoite on virheellinen.';
|
||||
$PHPMAILER_LANG['encoding'] = 'Tuntematon koodaustyyppi: ';
|
||||
//$PHPMAILER_LANG['signing'] = 'Signing Error: ';
|
||||
//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
|
||||
//$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
|
||||
|
||||
@@ -35,4 +35,3 @@ $PHPMAILER_LANG['smtp_connect_failed'] = 'La fonction SMTP connect() a échoué
|
||||
$PHPMAILER_LANG['smtp_detail'] = 'Détails : ';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'Erreur du serveur SMTP : ';
|
||||
$PHPMAILER_LANG['variable_set'] = 'Impossible d’initialiser ou de réinitialiser une variable : ';
|
||||
$PHPMAILER_LANG['extension_missing'] = 'Extension manquante : ';
|
||||
|
||||
@@ -24,7 +24,6 @@ $PHPMAILER_LANG['invalid_address'] = '发送失败,电子邮箱地址是
|
||||
$PHPMAILER_LANG['mailer_not_supported'] = '发信客户端不被支持。';
|
||||
$PHPMAILER_LANG['provide_address'] = '必须提供至少一个收件人地址。';
|
||||
$PHPMAILER_LANG['recipients_failed'] = 'SMTP 错误:收件人地址错误:';
|
||||
$PHPMAILER_LANG['signing'] = '登录失败:';
|
||||
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP服务器连接失败。';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'SMTP服务器出错:';
|
||||
$PHPMAILER_LANG['variable_set'] = '无法设置或重置变量:';
|
||||
|
||||
@@ -80,9 +80,7 @@ class DSNConfigurator
|
||||
$config = $this->parseUrl($dsn);
|
||||
|
||||
if (false === $config || !isset($config['scheme']) || !isset($config['host'])) {
|
||||
throw new Exception(
|
||||
sprintf('Malformed DSN: "%s".', $dsn)
|
||||
);
|
||||
throw new Exception('Malformed DSN');
|
||||
}
|
||||
|
||||
if (isset($config['query'])) {
|
||||
|
||||
6
vendor/phpmailer/phpmailer/src/PHPMailer.php
vendored
6
vendor/phpmailer/phpmailer/src/PHPMailer.php
vendored
@@ -750,7 +750,7 @@ class PHPMailer
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const VERSION = '6.8.0';
|
||||
const VERSION = '6.8.1';
|
||||
|
||||
/**
|
||||
* Error severity: message only, continue processing.
|
||||
@@ -1571,6 +1571,10 @@ class PHPMailer
|
||||
|
||||
//Validate From, Sender, and ConfirmReadingTo addresses
|
||||
foreach (['From', 'Sender', 'ConfirmReadingTo'] as $address_kind) {
|
||||
if ($this->{$address_kind} === null) {
|
||||
$this->{$address_kind} = '';
|
||||
continue;
|
||||
}
|
||||
$this->{$address_kind} = trim($this->{$address_kind});
|
||||
if (empty($this->{$address_kind})) {
|
||||
continue;
|
||||
|
||||
2
vendor/phpmailer/phpmailer/src/POP3.php
vendored
2
vendor/phpmailer/phpmailer/src/POP3.php
vendored
@@ -46,7 +46,7 @@ class POP3
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const VERSION = '6.8.0';
|
||||
const VERSION = '6.8.1';
|
||||
|
||||
/**
|
||||
* Default POP3 port number.
|
||||
|
||||
6
vendor/phpmailer/phpmailer/src/SMTP.php
vendored
6
vendor/phpmailer/phpmailer/src/SMTP.php
vendored
@@ -35,7 +35,7 @@ class SMTP
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const VERSION = '6.8.0';
|
||||
const VERSION = '6.8.1';
|
||||
|
||||
/**
|
||||
* SMTP line break constant.
|
||||
@@ -704,7 +704,7 @@ class SMTP
|
||||
* Send an SMTP DATA command.
|
||||
* Issues a data command and sends the msg_data to the server,
|
||||
* finalizing the mail transaction. $msg_data is the message
|
||||
* that is to be send with the headers. Each header needs to be
|
||||
* that is to be sent with the headers. Each header needs to be
|
||||
* on a single line followed by a <CRLF> with the message headers
|
||||
* and the message body being separated by an additional <CRLF>.
|
||||
* Implements RFC 821: DATA <CRLF>.
|
||||
@@ -732,7 +732,7 @@ class SMTP
|
||||
$lines = explode("\n", str_replace(["\r\n", "\r"], "\n", $msg_data));
|
||||
|
||||
/* To distinguish between a complete RFC822 message and a plain message body, we check if the first field
|
||||
* of the first line (':' separated) does not contain a space then it _should_ be a header and we will
|
||||
* of the first line (':' separated) does not contain a space then it _should_ be a header, and we will
|
||||
* process all lines before a blank line as headers.
|
||||
*/
|
||||
|
||||
|
||||
203
vendor/tinymce/tinymce/CHANGELOG.md
vendored
203
vendor/tinymce/tinymce/CHANGELOG.md
vendored
@@ -6,19 +6,202 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## Unreleased
|
||||
|
||||
## 6.7.0 - 2023-08-30
|
||||
|
||||
### Added
|
||||
- New `help_accessibility` option displays the keyboard shortcut to open the in-application help in the status bar. #TINY-9379
|
||||
- Added a new `InsertNewBlockBefore` command which inserts an empty block before the block containing the current selection. #TINY-10022
|
||||
- Added a new `InsertNewBlockAfter` command which inserts an empty block after the block containing the current selection. #TINY-10022
|
||||
|
||||
### Improved
|
||||
- Adding a newline after a table would, in some specific cases, not work. #TINY-9863
|
||||
- Menus now have a slight margin at the top and bottom to more clearly separate them from the frame edge. #TINY-9978
|
||||
- Updated **More** toolbar button tooltip text from *More...* to *Reveal or hide additional toolbar items*. #TINY-9629
|
||||
- Where multiple case sensitive variants of a translation key are provided, they will now all be preserved in the translation object instead of just the lowercase variant. #TINY-10115
|
||||
- Improved screen reader announcements of the column and row selection in the grid presented by the **Table** menu and toolbar item. #TINY-10140
|
||||
- Improved the keyboard focus visibility for links inside dialogs. #TINY-10124
|
||||
|
||||
### Changed
|
||||
- Change `UndoLevelType` from `enum` to union type so that it is easier to use. #TINY-9764
|
||||
- The pattern replacement removed spaces if they were contained within a tag that only contained a space and the text to replace. #TINY-9744
|
||||
- If loading content CSS takes more than 500ms, the editor will be set to an *in progress* state until the CSS is ready. #TINY-10008
|
||||
|
||||
### Fixed
|
||||
- Applying an ordered or unordered list to a selected checklist incorrectly turned the list into paragraphs. #TINY-9975
|
||||
- Returning an empty string in a custom context menu update function resulted in a small white line appearing on right-click and the browser-native context menu would not present. #TINY-9842
|
||||
- For sufficiently long URLs and sufficiently wide windows, URL autocompletion hid middle portions of the URL from view. #TINY-10017
|
||||
- Numeric input in toolbar items did not disable when a switching from edit to read-only mode. #TINY-10129
|
||||
- The Quick Toolbars plugin showed text alignment buttons on pagebreaks. #TINY-10054
|
||||
- Creating lists in empty blocks sometimes, and incorrectly, converted adjacent block elements into list items. #TINY-10136
|
||||
- Creating a list from multiple `<div>` elements only created a partial list. #TINY-9872
|
||||
- Tab navigation incorrectly stopped around `iframe` dialog components. #TINY-9815
|
||||
- It was possible to delete the sole empty block immediately before a `<details>` element if it was nested within another `<details>` element. #TINY-9965
|
||||
- Deleting `<li>` elements that only contained `<br>` tags sometimes caused a crash. #TINY-6888
|
||||
- It was possible to remove the `<summary>` element from a `<details>` element by dragging and dropping. #TINY-9960
|
||||
- It was possible to break `<summary>` elements if content containing block elements was dragged-and-dropped inside them. #TINY-9960
|
||||
- Contents were not removed from the drag start source if dragging and dropping internally into a transparent block element. #TINY-9960
|
||||
- Using the Media plugin unexpectedly changed `<script>` tags in the editor body to `<image>` tags. #TINY-10007
|
||||
- In some circumstances, pressing the **Enter** key scrolled the entire page. #TINY-9828
|
||||
- The border styles of a table were incorrectly split into a longhand form after table dialog updates. #TINY-9843
|
||||
- Links in **Help → Help → Plugins** and **Help → Help → Version** were not navigable by keyboard. #TINY-10071
|
||||
- Fixed the inability to insert content next to the `<details>` element when it is the first or last content element. Pressing the **Up** or **Down** arrow key now inserts a block element before or after the `<details>` element. #TINY-9827
|
||||
- An empty element with a `contenteditable="true"` attribute within a noneditable root was deleted when the Backspace key was pressed. #TINY-10011
|
||||
- The `color_cols` option was not respected when set to the value 5 with a custom `color_map` specified. #TINY-10126
|
||||
- In Safari on macOS, deleting backwards within a `<summary>` element removed the entire `<details>` element if it had no other content. #TINY-10123
|
||||
|
||||
## 6.6.2 - 2023-08-09
|
||||
|
||||
### Fixed
|
||||
- An "Uncaught TypeError: Cannot read properties of null" error would sometimes be thrown when updating the content of a `streamContent: true` iframe dialog component. #TINY-10128
|
||||
|
||||
## 6.6.1 - 2023-08-02
|
||||
|
||||
### Added
|
||||
- Restored filtering option, `pad_empty_with_br`. Set to `true` to pad empty block elements with `<br>` tags instead of the ` ` character entity. #TINY-9861
|
||||
|
||||
### Improved
|
||||
- When Safari is the host browser, content updates for iframe dialog components with `streamContent: true` set are now throttled to 500ms intervals. #TINY-10097
|
||||
|
||||
### Changed
|
||||
- API comments/documentation: a markup typo and run-on sentences both corrected. #TINY-10073
|
||||
|
||||
### Fixed
|
||||
- On Safari and Firefox, scroll positions were not always maintained when updating the content of a `streamContent: true` iframe dialog component. #TINY-10078
|
||||
- On Safari, iframe dialog components did not consistently autoscroll to the end of the scrollable area when `streamContent: true` was set. #TINY-10109
|
||||
- Scrolling behavior was inconsistent when updating a `streamContent: true` iframe dialog component with content lacking an HTML document type declaration. #TINY-10110
|
||||
- A warning message was sometimes printed to the browser console when closing a dialog that contained an iframe component. #TINY-10070
|
||||
- Lists could not be created within editable areas nested inside non-editable areas. #TINY-10000
|
||||
- On Safari and Firefox, the border around `iframe` dialog components did not highlight when focused. #TINY-10101
|
||||
- Right-clicking on an image in a non-editable context opened the Image context menu. #TINY-10016
|
||||
- The `color_cols` option was not respected when a custom `color_map` was defined. #TINY-10098
|
||||
- The `color_cols` options were were not rounded to the nearest number when set to a decimal number. #TINY-9737
|
||||
|
||||
## 6.6.0 - 2023-07-12
|
||||
|
||||
### Added
|
||||
- Added a new property value — `bottom` — for inline dialog configurations that anchors the dialog to the bottom of the editor. #TINY-9888
|
||||
- Added a new property — `persistent` — for inline dialog configurations that will stop the dialog closing when clicking away from it. #TINY-9991
|
||||
- New `ai`, `ai-prompt` and `send` icons. #TINY-9942
|
||||
- Added a new property — `streamContent` — for the `iframe` dialog component. This causes `setData()` to update content without reloading the frame, and end scroll positions will be maintained as new content streams in. #TINY-10032
|
||||
- AI Assistant plugin toolbar items added to the default toolbar and AI Assistant plugin menu items added to the default menu bar. #TINY-9939
|
||||
- Added a new property — `border` — for the `iframe` dialog component that allows a border to be added. #TINY-10049
|
||||
- Added a new property — `align` — for the label dialog component that controls text alignment. #TINY-10058
|
||||
|
||||
### Improved
|
||||
- When defining a modal or inline dialog, if the buttons property is an empty array, or is not defined at all, the footer will now no longer be rendered. #TINY-9996
|
||||
- The `iframe` dialog component now has a minimum height of 200px. #TINY-10059
|
||||
- Improved detection of scrollable containers when the `ui_mode: 'split'` option is set. #TINY-9385
|
||||
|
||||
### Changed
|
||||
- The icon in an `alertbanner` dialog component is no longer clickable if the _URL_ field is not specified. #TINY-10013
|
||||
|
||||
### Fixed
|
||||
- Fixed an issue that caused the inline dialog `size` setting to have no effect. #TINY-10015
|
||||
- Fixed an issue that prevented the close button from being clicked when the dialog was blocked. #TINY-10056
|
||||
|
||||
## 6.5.1 - 2023-06-19
|
||||
|
||||
### Fixed
|
||||
- Fixed a regression where pasting an image url would result in the url being inserted as plain text instead of the image being inserted. #TINY-9997
|
||||
- It was not possible to press space to insert a space character inside a summary element on Firefox. #TINY-9964
|
||||
|
||||
## 6.5.0 - 2023-06-12
|
||||
|
||||
### Added
|
||||
- Support for the `h` hash parameter in Vimeo video URLs in the Media plugin. #TINY-9830
|
||||
- New `table_merge_content_on_paste` option which disables the merging behaviour when pasting a table inside an existing table. #TINY-9808
|
||||
- New optional `defaultExpandedIds` and `onToggleExpand` options to the `tree` component config. #TINY-9653
|
||||
- New optional `defaultSelectedId` option to the `tree` component config. #TINY-9715
|
||||
- New `accordion` plugin with the `InsertAccordion` command. #TINY-9730
|
||||
- New `accordion` and `accordion-toggle` icons. #TINY-9789
|
||||
- New `details_initial_state` and `details_serialized_state` options. #TINY-9732
|
||||
- New `init_content_sync` option that initializes the editor iframe using `document.write` instead of `srcdoc`. #TINY-9818
|
||||
- New `newdocument_content` option that sets the content presented in the editor on choosing *File -> New document* or pressing the *New document* toolbar button. #TINY-9839
|
||||
- New `editable_root` option that can be set to `false` to prevent editing of the editor’s root element. #TINY-9839
|
||||
- New `editor.setEditableRoot` API that sets the editable state of the editor root element. #TINY-9839
|
||||
- New `editor.hasEditableRoot` API that returns `true` or `false` depending on the editable state of the editor root element. #TINY-9839
|
||||
- New `EditableRootStateChange` event that gets dispatched when the state of the editable root is changed. #TINY-9839
|
||||
- Added Oxide styles for `dl`, `dt`, `dd`, `ol`, and `strong` elements in dialog body content. #TINY-9919
|
||||
|
||||
### Improved
|
||||
- Screen readers can now announce highlighted items listed in the Link dialog’s link combobox. #TINY-9280
|
||||
- The `icon` field for a dialog’s footer `togglebutton` is no longer mandatory. #TINY-9757
|
||||
- Toolbar buttons and menu items now present as disabled when they cannot be used because a selected element has a `contenteditable="false"` attribute. #TINY-9669
|
||||
- Help text displayed at *Help -> Help -> Keyboard Navigation* re-written. #DOC-1936
|
||||
- Translations added for Help text displayed at *Help > Help > Keyboard Navigation*. #TINY-9633
|
||||
- For word count purposes these characters are now considered punctuation marks: *$*, *~*, *+*, *|*, *№*, and *`*. They no longer increase a document’s word count. #TINY-8122
|
||||
- Updated the `codesample` plugin dialog and the `template` plugin dialog to use the `listbox` component to match other dialogs. #TINY-9630
|
||||
- If the selection contains more than one table cell, Quickbar toolbars are now positioned in the middle of the selection horizontally. #TINY-8297
|
||||
- Exposed `dataTransfer` property of drag and drop events for elements with a `contenteditable="false"` attribute. #TINY-9601
|
||||
- Screen readers now announce instructions for resizing the editor using arrow keys, when the resize handle is focused. #TINY-9793
|
||||
- Dialog `tabpanel` tab labels are now allowed to word wrap for better readability with long labels. #TINY-9947
|
||||
- Added newlines before and after `details` elements in the output HTML. #TINY-9959
|
||||
- Added padding for empty `summary` elements so that they can be properly edited. #TINY-9959
|
||||
|
||||
### Changed
|
||||
- The `caption`, `address` and `dt` elements no longer incorrectly allow non-inline child elements when the editor schema is set to _HTML 4_. #TINY-9768
|
||||
- SVG icons for back and foreground colors now use `class` instead of `id` to identify SVG elements that should change color. #TINY-9844
|
||||
- Anchor tag elements — `<a>` — no longer incorrectly allow non-inline child elements when the editor schema is set to _HTML 4_. #TINY-9805
|
||||
- Help dialog was restored to `medium` width for better readability. #TINY-9947
|
||||
|
||||
### Fixed
|
||||
- Right-clicking on a merge tag instance presented different highlighting depending on the host browser. #TINY-9848
|
||||
- When macOS was the host operating system, pressing *Command+backspace* did not add an undo level. #TINY-8910
|
||||
- *Ctrl+backspace* and *Ctrl+delete* did not restore the correct insertion point position after a redo operation. #TINY-8910
|
||||
- In the `tree` component, a selected item in a directory would not stay selected after collapsing the directory. #TINY-9715
|
||||
- Enabling or Disabling checkboxes would not set the correct classes and attributes. #TINY-4189
|
||||
- Entering a newline would, in some setups, place the insertion point in the wrong paragraph. #TINY-9822
|
||||
- Redial would, in some situations, cause select elements not to have an initial value selected when they should have. #TINY-9679
|
||||
- The Table toolbar was visible even if the table was within a host element with a `contenteditable="false"` attribute set. #TINY-9664
|
||||
- Quickbar toolbars were incorrectly shown for elements with a `contenteditable="false"` attribute set in a root with a `contenteditable="false"` attribute set. #TINY-9460
|
||||
- When Chrome was the host browser, adding a newline when the insertion point was placed after a table could, in some specific situations, not generate the expected newline. #TINY-9813
|
||||
- Show the calculated height and width of Media Embed elements in the `media` plugin dialog. #TINY-8714
|
||||
- Removing an image that failed to upload from an empty paragraph left the paragraph without a padding `<br>` tag. #TINY-9696
|
||||
- Allow a Media Embed element to be correctly resized when using the `media` plugin dialog by converting the Media Embed element to a standalone iframe. #TINY-8714
|
||||
- In some circumstances, an inline alert in the _Search and Replace_ dialog persisted when it was not necessary. #TINY-9704
|
||||
- Context toolbars displayed the incorrect status for the `advlist` plugin buttons. #TINY-9680
|
||||
- In Safari running on iOS, Korean characters merged onto the previous line upon typing after inserting a newline by pressing Enter. #TINY-9746
|
||||
- Initiating the editor with a table as the first element resulted in resize handles being displayed around the table even when the editor did not have focus. #TINY-9748
|
||||
- If the insertion point was between two images, pressing the Backspace key would, in some situations, delete the image after the insertion point instead of the image before the insertion point. #TINY-9807
|
||||
- Directionality commands could set the `dir` attribute on elements with a `contenteditable="false"` attribute set when these elements were within a root with a `contenteditable="false"` attribute set. #TINY-9662
|
||||
- The content of the dialog body could not be scrolled. #TINY-9668
|
||||
- Some toolbar items, when in a not-enabled state, did not render the `not-allowed` mouse pointer. #TINY-9758
|
||||
- Formats were incorrectly applied to the closest editable element if the selection was in a `contenteditable="false"` context. #TINY-9678
|
||||
- Formats were incorrectly removed from the closest editable element if the selection was in a `contenteditable="false"` context. #TINY-9678
|
||||
- Formatter API, `canApply`, was not returning `false` when the selection was in a `contenteditable="false"` context. #TINY-9678
|
||||
- When dragging image elements and dropping the image in the editor the `dragend` event would sometimes not fire when Firefox was the host browser. #TINY-9694
|
||||
- It was possible to remove links in noneditable contents with the `unlink` editor command. #TINY-9739
|
||||
- Direction was not visually changing when using the Directionality plugin on an element which had the `direction` CSS property set. #TINY-9314
|
||||
- Whitespace between transparent elements was incorrectly converted into empty paragraphs. #TINY-9761
|
||||
- Popups were not constrained within the scrollable container when in a shadow root. #TINY-9743
|
||||
- Pressing arrow keys inside RTL elements would move the insertion point in an incorrect direction when moving over elements with the `contenteditable` attribute set to `false`. #TINY-9565
|
||||
- Inserting two tables consecutively without focus in the editor resulted in the second table being inserted at the wrong position. #TINY-3909
|
||||
- Pasting content into the editor did not fire `beforeinput` and `input` events. #TINY-9829
|
||||
- In some cases, exiting a `blockquote` element could fail when the insertion point was positioned at the end of the `blockquote`. #TINY-9794
|
||||
- Templates containing an `<html>` tag were not parsed before being rendered for preview. #TINY-9867
|
||||
- Typing after deleting formatted content could remove a space at the start of the typing. #TINY-9310
|
||||
- Invalid markup in Notification and Dialog close buttons. #TINY-9849
|
||||
- In dialogs, an incorrect `aria-describedby` attribute caused the dialog body to be announced when using a screen reader. #TINY-9816
|
||||
- The sticky toolbar did not render correctly when transitioning from the custom editor view to the main view. #TINY-9814
|
||||
- Saving the Table Properties dialog after changing properties unrelated to cells would overwrite cell properties set by the Cell Properties dialog. #TINY-9837
|
||||
- Fixed the constrained bounds calculation for dismissal of the toolbar when using `toolbar_location: 'bottom'`. #TINY-9718
|
||||
- Pressing the Backspace or Delete key when the insertion point was within a `details` element resulted in broken markup. #TINY-9884
|
||||
- Making the selection into a list did not work if the selection included a block element with a `contenteditable="false"` attribute. #TINY-9823
|
||||
- Inserting elements in the middle of the summary caused two summaries to appear within `details` elements. #TINY-9885
|
||||
|
||||
## 6.4.2 - 2023-04-26
|
||||
|
||||
### Fixed
|
||||
- The editor would display a notification error when it fails to retirieve a blob image uri. #TINY-9604
|
||||
- Menu buttons would have the Tabstopping behaviour in toolbar. #TINY-9723
|
||||
- The `urlinput` dialog component would not open the typeahead dropdown when the input value was reset to an empty string. #TINY-9717
|
||||
- Redial would in some situations cause select elements not to have an initial value selected when they should have. #TINY-9679
|
||||
- Fixed the mouse pointer style from a text cursor to a default arrow pointer when hovering over the tree dialog component items. #TINY-9692
|
||||
- Enabled variant of togglable `tox-button` and `tox-button--secondary` now supports `hover`/`active`/`focus`/`disabled` states. #TINY-9713
|
||||
- Setting an invalid unit in the `fontsizeinput` would change it do the default value instead of reverting it back to the previous valid value. #TINY-9754
|
||||
- The editor displayed a notification error when it failed to retrieve a blob image uri. #TINY-9604
|
||||
- Tab navigation no longer incorrectly stops at menu buttons within toolbar groups. #TINY-9723
|
||||
- The `urlinput` dialog component would not open the type-ahead dropdown when the input value was reset to an empty string. #TINY-9717
|
||||
- Redial would, in some circumstances, cause elements to not have an initial value selected when they should have. #TINY-9679
|
||||
- When hovering over tree dialog components the mouse pointer rendered incorrectly. #TINY-9692
|
||||
- The `tox-button` and `tox-button-secondary` buttons now support the `hover`, `active`, `focus`, and `disabled` states. #TINY-9713
|
||||
- Setting an invalid unit in the `fontsizeinput` changed it to the default value instead of reverting it to the previous, and valid, value. #TINY-9754
|
||||
- Selection was not correctly scrolled horizontally into view when using the `selection.scrollIntoView` API. #TINY-9747
|
||||
- Context toolbars displayed the incorrect status for the `advlist` plugin buttons. #TINY-9680
|
||||
- The image would not be inserted when using the `quickimage` button on Chrome. #TINY-9769
|
||||
- The contextual toolbar displayed the status of Advanced List Premium plugin icons incorrectly. #TINY-9680
|
||||
- The `quickimage` toolbar button failed to insert images selected from the local computer when running on Google Chrome for macOS. #TINY-9769
|
||||
|
||||
## 6.4.1 - 2023-03-29
|
||||
|
||||
@@ -111,6 +294,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Opening a menu button in the footer of a dialog after a redial threw an error. #TINY-9686
|
||||
- After closing a view, the `more...` toolbar button disappeared if the editor had `toolbar_mode: 'sliding'` and the toolbar was opened. #TINY-9419
|
||||
- Inline dialogs would open partially off screen when the toolbar had a small width. #TINY-9588
|
||||
- The `autoresize` plugin would cause infinite resizing when `content_css` was set to `document`. #TINY-8872
|
||||
|
||||
## 6.3.2 - 2023-02-22
|
||||
|
||||
@@ -165,7 +349,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- A newline could not be inserted when the selection was restored from a bookmark after an inline element with a `contenteditable="false"` attribute. #TINY-9194
|
||||
- The global `tinymce.dom.styleSheetLoader` was not affected by the `content_css_cors` option. #TINY-6037
|
||||
- The caret was moved to the previous line when a text pattern executed a `mceInsertContent` command on Enter key when running on Firefox. #TINY-9193
|
||||
- The `autoresize` plugin used to cause infinite resize when `content_css` is set to `document`. #TINY-8872
|
||||
|
||||
## 6.2.0 - 2022-09-08
|
||||
|
||||
|
||||
2
vendor/tinymce/tinymce/composer.json
vendored
2
vendor/tinymce/tinymce/composer.json
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tinymce/tinymce",
|
||||
"version": "6.4.2",
|
||||
"version": "6.7.0",
|
||||
"description": "Web based JavaScript HTML WYSIWYG editor control.",
|
||||
"license": [
|
||||
"MIT-only"
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
tinymce.IconManager.add('default', {
|
||||
icons: {
|
||||
'accessibility-check': '<svg width="24" height="24"><path d="M12 2a2 2 0 0 1 2 2 2 2 0 0 1-2 2 2 2 0 0 1-2-2c0-1.1.9-2 2-2Zm8 7h-5v12c0 .6-.4 1-1 1a1 1 0 0 1-1-1v-5c0-.6-.4-1-1-1a1 1 0 0 0-1 1v5c0 .6-.4 1-1 1a1 1 0 0 1-1-1V9H4a1 1 0 1 1 0-2h16c.6 0 1 .4 1 1s-.4 1-1 1Z" fill-rule="nonzero"/></svg>',
|
||||
'accordion-toggle': '<svg width="24" height="24"><path fill-rule="evenodd" clip-rule="evenodd" d="M12 15c0-.6.4-1 1-1h6c.6 0 1 .4 1 1s-.4 1-1 1h-6a1 1 0 0 1-1-1Z"/><path opacity=".2" fill-rule="evenodd" clip-rule="evenodd" d="M4 15c0-.6.4-1 1-1h6c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 0 1-1-1Z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M12 19c0-.6.4-1 1-1h6c.6 0 1 .4 1 1s-.4 1-1 1h-6a1 1 0 0 1-1-1Z"/><path opacity=".2" fill-rule="evenodd" clip-rule="evenodd" d="M4 19c0-.6.4-1 1-1h6c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 0 1-1-1Z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M12.3 7.3a1 1 0 0 1 1.4 0L16 9.6l2.3-2.3a1 1 0 1 1 1.4 1.4L16 12.4l-3.7-3.7a1 1 0 0 1 0-1.4ZM4.3 11.7a1 1 0 0 1 0-1.4L6.6 8 4.3 5.7a1 1 0 0 1 1.4-1.4L9.4 8l-3.7 3.7a1 1 0 0 1-1.4 0Z"/></svg>',
|
||||
'accordion': '<svg width="24" height="24"><rect x="12" y="7" width="10" height="2" rx="1"/><rect x="12" y="11" width="10" height="2" rx="1"/><rect x="12" y="15" width="6" height="2" rx="1"/><path fill-rule="evenodd" clip-rule="evenodd" d="M2.3 7.3a1 1 0 0 1 1.4 0L6 9.6l2.3-2.3a1 1 0 0 1 1.4 1.4L6 12.4 2.3 8.7a1 1 0 0 1 0-1.4Z"/></svg>',
|
||||
'action-next': '<svg width="24" height="24"><path fill-rule="nonzero" d="M5.7 7.3a1 1 0 0 0-1.4 1.4l7.7 7.7 7.7-7.7a1 1 0 1 0-1.4-1.4L12 13.6 5.7 7.3Z"/></svg>',
|
||||
'action-prev': '<svg width="24" height="24"><path fill-rule="nonzero" d="M18.3 15.7a1 1 0 0 0 1.4-1.4L12 6.6l-7.7 7.7a1 1 0 0 0 1.4 1.4L12 9.4l6.3 6.3Z"/></svg>',
|
||||
'addtag': '<svg width="24" height="24"><path fill-rule="evenodd" clip-rule="evenodd" d="M15 5a2 2 0 0 1 1.6.8L21 12l-4.4 6.2a2 2 0 0 1-1.6.8h-3v-2h3l3.5-5L15 7H5v3H3V7c0-1.1.9-2 2-2h10Z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M6 12a1 1 0 0 0-1 1v2H3a1 1 0 1 0 0 2h2v2a1 1 0 1 0 2 0v-2h2a1 1 0 1 0 0-2H7v-2c0-.6-.4-1-1-1Z"/></svg>',
|
||||
'ai-prompt': '<svg width="24" height="24"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M15 6.7a1 1 0 0 0-1.4 0l-9.9 10a1 1 0 0 0 0 1.3l2.1 2.1c.4.4 1 .4 1.4 0l10-9.9c.3-.3.3-1 0-1.4l-2.2-2Zm1.4 2.8-2-2-3 2.7 2.2 2.2 2.8-2.9Z"/><path d="m18.5 7.3-.7-1.5-1.5-.8 1.5-.7.7-1.5.7 1.5 1.5.7-1.5.8-.7 1.5ZM18.5 16.5l-.7-1.6-1.5-.7 1.5-.7.7-1.6.7 1.6 1.5.7-1.5.7-.7 1.6ZM9.7 7.3 9 5.8 7.5 5 9 4.3l.7-1.5.7 1.5L12 5l-1.5.8-.7 1.5Z"/></g><defs><clipPath id="a"><path d="M0 0h24v24H0z"/></clipPath></defs></svg>',
|
||||
'ai': '<svg width="24" height="24"><path fill-rule="evenodd" clip-rule="evenodd" d="M5 3a3 3 0 0 0-3 3v12a3 3 0 0 0 3 3h14a3 3 0 0 0 3-3V6a3 3 0 0 0-3-3H5Zm6.8 11.5.5 1.2a68.3 68.3 0 0 0 .7 1.1l.4.1c.3 0 .5 0 .7-.3.2-.1.3-.3.3-.6l-.3-1-2.6-6.2a20.4 20.4 0 0 0-.5-1.3l-.5-.4-.7-.2c-.2 0-.5 0-.6.2-.2 0-.4.2-.5.4l-.3.6-.3.7L5.7 15l-.2.6-.1.4c0 .3 0 .5.3.7l.6.2c.3 0 .5 0 .7-.2l.4-1 .5-1.2h3.9ZM9.8 9l1.5 4h-3l1.5-4Zm5.6-.9v7.6c0 .4 0 .7.2 1l.7.2c.3 0 .6 0 .8-.3l.2-.9V8.1c0-.4 0-.7-.2-.9a1 1 0 0 0-.8-.3c-.2 0-.5.1-.7.3l-.2 1Z"/></svg>',
|
||||
'align-center': '<svg width="24" height="24"><path d="M5 5h14c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 1 1 0-2Zm3 4h8c.6 0 1 .4 1 1s-.4 1-1 1H8a1 1 0 1 1 0-2Zm0 8h8c.6 0 1 .4 1 1s-.4 1-1 1H8a1 1 0 0 1 0-2Zm-3-4h14c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 0 1 0-2Z" fill-rule="evenodd"/></svg>',
|
||||
'align-justify': '<svg width="24" height="24"><path d="M5 5h14c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 1 1 0-2Zm0 4h14c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 1 1 0-2Zm0 4h14c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 0 1 0-2Zm0 4h14c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 0 1 0-2Z" fill-rule="evenodd"/></svg>',
|
||||
'align-left': '<svg width="24" height="24"><path d="M5 5h14c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 1 1 0-2Zm0 4h8c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 1 1 0-2Zm0 8h8c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 0 1 0-2Zm0-4h14c.6 0 1 .4 1 1s-.4 1-1 1H5a1 1 0 0 1 0-2Z" fill-rule="evenodd"/></svg>',
|
||||
@@ -64,7 +68,7 @@ tinymce.IconManager.add('default', {
|
||||
'gallery': '<svg width="24" height="24"><path fill-rule="nonzero" d="m5 15.7 2.3-2.2c.3-.3.7-.3 1 0L11 16l5.1-5c.3-.4.8-.4 1 0l2 1.9V8H5v7.7ZM5 18V19h3l1.8-1.9-2-2L5 17.9Zm14-3-2.5-2.4-6.4 6.5H19v-4ZM4 6h16c.6 0 1 .4 1 1v13c0 .6-.4 1-1 1H4a1 1 0 0 1-1-1V7c0-.6.4-1 1-1Zm6 7a2 2 0 1 1 0-4 2 2 0 0 1 0 4ZM4.5 4h15a.5.5 0 1 1 0 1h-15a.5.5 0 0 1 0-1Zm2-2h11a.5.5 0 1 1 0 1h-11a.5.5 0 0 1 0-1Z"/></svg>',
|
||||
'gamma': '<svg width="24" height="24"><path d="M4 3h16c.6 0 1 .4 1 1v16c0 .6-.4 1-1 1H4a1 1 0 0 1-1-1V4c0-.6.4-1 1-1Zm1 2v14h14V5H5Zm6.5 11.8V14L9.2 8.7a5.1 5.1 0 0 0-.4-.8l-.1-.2H8v-1l.3-.1.3-.1h.7a1 1 0 0 1 .6.5l.1.3a8.5 8.5 0 0 1 .3.6l1.9 4.6 2-5.2a1 1 0 0 1 1-.6.5.5 0 0 1 .5.6L13 14v2.8a.7.7 0 0 1-1.4 0Z" fill-rule="nonzero"/></svg>',
|
||||
'help': '<svg width="24" height="24"><g fill-rule="evenodd"><path d="M12 5.5a6.5 6.5 0 0 0-6 9 6.3 6.3 0 0 0 1.4 2l1 1a6.3 6.3 0 0 0 3.6 1 6.5 6.5 0 0 0 6-9 6.3 6.3 0 0 0-1.4-2l-1-1a6.3 6.3 0 0 0-3.6-1ZM12 4a7.8 7.8 0 0 1 5.7 2.3A8 8 0 1 1 12 4Z"/><path d="M9.6 9.7a.7.7 0 0 1-.7-.8c0-1.1 1.5-1.8 3.2-1.8 1.8 0 3.2.8 3.2 2.4 0 1.4-.4 2.1-1.5 2.8-.2 0-.3.1-.3.2a2 2 0 0 0-.8.8.8.8 0 0 1-1.4-.6c.3-.7.8-1 1.3-1.5l.4-.2c.7-.4.8-.6.8-1.5 0-.5-.6-.9-1.7-.9-.5 0-1 .1-1.4.3-.2 0-.3.1-.3.2v-.2c0 .4-.4.8-.8.8Z" fill-rule="nonzero"/><circle cx="12" cy="16" r="1"/></g></svg>',
|
||||
'highlight-bg-color': '<svg width="24" height="24"><g fill-rule="evenodd"><path id="tox-icon-highlight-bg-color__color" d="M3 18h18v3H3z"/><path fill-rule="nonzero" d="M7.7 16.7H3l3.3-3.3-.7-.8L10.2 8l4 4.1-4 4.2c-.2.2-.6.2-.8 0l-.6-.7-1.1 1.1zm5-7.5L11 7.4l3-2.9a2 2 0 0 1 2.6 0L18 6c.7.7.7 2 0 2.7l-2.9 2.9-1.8-1.8-.5-.6"/></g></svg>',
|
||||
'highlight-bg-color': '<svg width="24" height="24"><g fill-rule="evenodd"><path class="tox-icon-highlight-bg-color__color" d="M3 18h18v3H3z"/><path fill-rule="nonzero" d="M7.7 16.7H3l3.3-3.3-.7-.8L10.2 8l4 4.1-4 4.2c-.2.2-.6.2-.8 0l-.6-.7-1.1 1.1zm5-7.5L11 7.4l3-2.9a2 2 0 0 1 2.6 0L18 6c.7.7.7 2 0 2.7l-2.9 2.9-1.8-1.8-.5-.6"/></g></svg>',
|
||||
'home': '<svg width="24" height="24"><path fill-rule="nonzero" d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/></svg>',
|
||||
'horizontal-rule': '<svg width="24" height="24"><path d="M4 11h16v2H4z" fill-rule="evenodd"/></svg>',
|
||||
'image-options': '<svg width="24" height="24"><path d="M6 10a2 2 0 0 0-2 2c0 1.1.9 2 2 2a2 2 0 0 0 2-2 2 2 0 0 0-2-2Zm12 0a2 2 0 0 0-2 2c0 1.1.9 2 2 2a2 2 0 0 0 2-2 2 2 0 0 0-2-2Zm-6 0a2 2 0 0 0-2 2c0 1.1.9 2 2 2a2 2 0 0 0 2-2 2 2 0 0 0-2-2Z" fill-rule="nonzero"/></svg>',
|
||||
@@ -134,6 +138,7 @@ tinymce.IconManager.add('default', {
|
||||
'search': '<svg width="24" height="24"><path d="M16 17.3a8 8 0 1 1 1.4-1.4l4.3 4.4a1 1 0 0 1-1.4 1.4l-4.4-4.3Zm-5-.3a6 6 0 1 0 0-12 6 6 0 0 0 0 12Z" fill-rule="nonzero"/></svg>',
|
||||
'select-all': '<svg width="24" height="24"><path d="M3 5h2V3a2 2 0 0 0-2 2Zm0 8h2v-2H3v2Zm4 8h2v-2H7v2ZM3 9h2V7H3v2Zm10-6h-2v2h2V3Zm6 0v2h2a2 2 0 0 0-2-2ZM5 21v-2H3c0 1.1.9 2 2 2Zm-2-4h2v-2H3v2ZM9 3H7v2h2V3Zm2 18h2v-2h-2v2Zm8-8h2v-2h-2v2Zm0 8a2 2 0 0 0 2-2h-2v2Zm0-12h2V7h-2v2Zm0 8h2v-2h-2v2Zm-4 4h2v-2h-2v2Zm0-16h2V3h-2v2ZM7 17h10V7H7v10Zm2-8h6v6H9V9Z" fill-rule="nonzero"/></svg>',
|
||||
'selected': '<svg width="24" height="24"><path fill-rule="nonzero" d="M6 4h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2Zm3.6 10.9L7 12.3a.7.7 0 0 0-1 1L9.6 17 18 8.6a.7.7 0 0 0 0-1 .7.7 0 0 0-1 0l-7.4 7.3Z"/></svg>',
|
||||
'send': '<svg width="24" height="24"><path fill-rule="evenodd" clip-rule="evenodd" d="m13.3 22 7-18.3-18.3 7L9 15l4.3 7ZM18 6.8l-.7-.7L9.4 14l.7.7L18 6.8Z"/></svg>',
|
||||
'settings': '<svg width="24" height="24"><path d="M11 6h8c.6 0 1 .4 1 1s-.4 1-1 1h-8v.3c0 .2 0 .3-.2.5l-.6.2H7.8c-.3 0-.4 0-.6-.2a.7.7 0 0 1-.2-.6V8H5a1 1 0 1 1 0-2h2v-.3c0-.2 0-.3.2-.5l.5-.2h2.5c.3 0 .4 0 .6.2l.2.5V6ZM8 8h2V6H8v2Zm9 2.8v.2h2c.6 0 1 .4 1 1s-.4 1-1 1h-2v.3c0 .2 0 .3-.2.5l-.6.2h-2.4c-.3 0-.4 0-.6-.2a.7.7 0 0 1-.2-.6V13H5a1 1 0 0 1 0-2h8v-.3c0-.2 0-.3.2-.5l.6-.2h2.4c.3 0 .4 0 .6.2l.2.6ZM14 13h2v-2h-2v2Zm-3 2.8v.2h8c.6 0 1 .4 1 1s-.4 1-1 1h-8v.3c0 .2 0 .3-.2.5l-.6.2H7.8c-.3 0-.4 0-.6-.2a.7.7 0 0 1-.2-.6V18H5a1 1 0 0 1 0-2h2v-.3c0-.2 0-.3.2-.5l.5-.2h2.5c.3 0 .4 0 .6.2l.2.6ZM8 18h2v-2H8v2Z" fill-rule="evenodd"/></svg>',
|
||||
'sharpen': '<svg width="24" height="24"><path d="m16 6 4 4-8 9-8-9 4-4h8Zm-4 10.2 5.5-6.2-.1-.1H12v-.3h5.1l-.2-.2H12V9h4.6l-.2-.2H12v-.3h4.1l-.2-.2H12V8h3.6l-.2-.2H8.7L6.5 10l.1.1H12v.3H6.9l.2.2H12v.3H7.3l.2.2H12v.3H7.7l.3.2h4v.3H8.2l.2.2H12v.3H8.6l.3.2H12v.3H9l.3.2H12v.3H9.5l.2.2H12v.3h-2l.2.2H12v.3h-1.6l.2.2H12v.3h-1.1l.2.2h.9v.3h-.7l.2.2h.5v.3h-.3l.3.2Z" fill-rule="evenodd"/></svg>',
|
||||
'sourcecode': '<svg width="24" height="24"><g fill-rule="nonzero"><path d="M9.8 15.7c.3.3.3.8 0 1-.3.4-.9.4-1.2 0l-4.4-4.1a.8.8 0 0 1 0-1.2l4.4-4.2c.3-.3.9-.3 1.2 0 .3.3.3.8 0 1.1L6 12l3.8 3.7ZM14.2 15.7c-.3.3-.3.8 0 1 .4.4.9.4 1.2 0l4.4-4.1c.3-.3.3-.9 0-1.2l-4.4-4.2a.8.8 0 0 0-1.2 0c-.3.3-.3.8 0 1.1L18 12l-3.8 3.7Z"/></g></svg>',
|
||||
@@ -165,7 +170,7 @@ tinymce.IconManager.add('default', {
|
||||
'template-add': '<svg width="24" height="24"><path fill-rule="evenodd" clip-rule="evenodd" d="M9 12v4H5a2 2 0 0 0-2 2v3h9.3a6 6 0 0 1-.3-2H5v-1h7a6 6 0 0 1 .8-2H11v-5l-.8-.6a3 3 0 1 1 3.6 0l-.8.6v4.7a6 6 0 0 1 2-1.9V12a5 5 0 1 0-6 0Z"/><path d="M18 15c.5 0 1 .4 1 .9V18h2a1 1 0 0 1 .1 2H19v2a1 1 0 0 1-2 .1V20h-2a1 1 0 0 1-.1-2H17v-2c0-.6.4-1 1-1Z"/></svg>',
|
||||
'template': '<svg width="24" height="24"><path d="M19 19v-1H5v1h14ZM9 16v-4a5 5 0 1 1 6 0v4h4a2 2 0 0 1 2 2v3H3v-3c0-1.1.9-2 2-2h4Zm4 0v-5l.8-.6a3 3 0 1 0-3.6 0l.8.6v5h2Z" fill-rule="nonzero"/></svg>',
|
||||
'temporary-placeholder': '<svg width="24" height="24"><g fill-rule="evenodd"><path d="M9 7.6V6h2.5V4.5a.5.5 0 1 1 1 0V6H15v1.6a8 8 0 1 1-6 0Zm-2.6 5.3a.5.5 0 0 0 .3.6c.3 0 .6 0 .6-.3l.1-.2a5 5 0 0 1 3.3-2.8c.3-.1.4-.4.4-.6-.1-.3-.4-.5-.6-.4a6 6 0 0 0-4.1 3.7Z"/><circle cx="14" cy="4" r="1"/><circle cx="12" cy="2" r="1"/><circle cx="10" cy="4" r="1"/></g></svg>',
|
||||
'text-color': '<svg width="24" height="24"><g fill-rule="evenodd"><path id="tox-icon-text-color__color" d="M3 18h18v3H3z"/><path d="M8.7 16h-.8a.5.5 0 0 1-.5-.6l2.7-9c.1-.3.3-.4.5-.4h2.8c.2 0 .4.1.5.4l2.7 9a.5.5 0 0 1-.5.6h-.8a.5.5 0 0 1-.4-.4l-.7-2.2c0-.3-.3-.4-.5-.4h-3.4c-.2 0-.4.1-.5.4l-.7 2.2c0 .3-.2.4-.4.4Zm2.6-7.6-.6 2a.5.5 0 0 0 .5.6h1.6a.5.5 0 0 0 .5-.6l-.6-2c0-.3-.3-.4-.5-.4h-.4c-.2 0-.4.1-.5.4Z"/></g></svg>',
|
||||
'text-color': '<svg width="24" height="24"><g fill-rule="evenodd"><path class="tox-icon-text-color__color" d="M3 18h18v3H3z"/><path d="M8.7 16h-.8a.5.5 0 0 1-.5-.6l2.7-9c.1-.3.3-.4.5-.4h2.8c.2 0 .4.1.5.4l2.7 9a.5.5 0 0 1-.5.6h-.8a.5.5 0 0 1-.4-.4l-.7-2.2c0-.3-.3-.4-.5-.4h-3.4c-.2 0-.4.1-.5.4l-.7 2.2c0 .3-.2.4-.4.4Zm2.6-7.6-.6 2a.5.5 0 0 0 .5.6h1.6a.5.5 0 0 0 .5-.6l-.6-2c0-.3-.3-.4-.5-.4h-.4c-.2 0-.4.1-.5.4Z"/></g></svg>',
|
||||
'text-size-decrease': '<svg width="24" height="24"><path fill-rule="evenodd" clip-rule="evenodd" d="M14 5a1 1 0 1 1 0 2h-4v11a1 1 0 1 1-2 0V7H4a1 1 0 0 1 0-2h10ZM14 12a1 1 0 1 0 0 2h6a1 1 0 1 0 0-2h-6Z"/></svg>',
|
||||
'text-size-increase': '<svg width="24" height="24"><path fill-rule="evenodd" clip-rule="evenodd" d="M14 5a1 1 0 1 1 0 2h-4v11a1 1 0 1 1-2 0V7H4a1 1 0 0 1 0-2h10ZM17 9a1 1 0 0 0-1 1v2h-2a1 1 0 1 0 0 2h2v2a1 1 0 1 0 2 0v-2h2a1 1 0 1 0 0-2h-2v-2c0-.6-.4-1-1-1Z"/></svg>',
|
||||
'toc': '<svg width="24" height="24"><path d="M5 5c.6 0 1 .4 1 1s-.4 1-1 1a1 1 0 1 1 0-2Zm3 0h11c.6 0 1 .4 1 1s-.4 1-1 1H8a1 1 0 1 1 0-2Zm-3 8c.6 0 1 .4 1 1s-.4 1-1 1a1 1 0 0 1 0-2Zm3 0h11c.6 0 1 .4 1 1s-.4 1-1 1H8a1 1 0 0 1 0-2Zm0-4c.6 0 1 .4 1 1s-.4 1-1 1a1 1 0 1 1 0-2Zm3 0h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2Zm-3 8c.6 0 1 .4 1 1s-.4 1-1 1a1 1 0 0 1 0-2Zm3 0h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2Z" fill-rule="evenodd"/></svg>',
|
||||
|
||||
File diff suppressed because one or more lines are too long
267
vendor/tinymce/tinymce/models/dom/model.js
vendored
267
vendor/tinymce/tinymce/models/dom/model.js
vendored
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
|
||||
(function () {
|
||||
@@ -2356,6 +2356,140 @@
|
||||
};
|
||||
const fromDom = nodes => map$1(nodes, SugarElement.fromDom);
|
||||
|
||||
const option = name => editor => editor.options.get(name);
|
||||
const defaultWidth = '100%';
|
||||
const getPixelForcedWidth = editor => {
|
||||
var _a;
|
||||
const dom = editor.dom;
|
||||
const parentBlock = (_a = dom.getParent(editor.selection.getStart(), dom.isBlock)) !== null && _a !== void 0 ? _a : editor.getBody();
|
||||
return getInner(SugarElement.fromDom(parentBlock)) + 'px';
|
||||
};
|
||||
const determineDefaultTableStyles = (editor, defaultStyles) => {
|
||||
if (isTableResponsiveForced(editor) || !shouldStyleWithCss(editor)) {
|
||||
return defaultStyles;
|
||||
} else if (isTablePixelsForced(editor)) {
|
||||
return {
|
||||
...defaultStyles,
|
||||
width: getPixelForcedWidth(editor)
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...defaultStyles,
|
||||
width: defaultWidth
|
||||
};
|
||||
}
|
||||
};
|
||||
const determineDefaultTableAttributes = (editor, defaultAttributes) => {
|
||||
if (isTableResponsiveForced(editor) || shouldStyleWithCss(editor)) {
|
||||
return defaultAttributes;
|
||||
} else if (isTablePixelsForced(editor)) {
|
||||
return {
|
||||
...defaultAttributes,
|
||||
width: getPixelForcedWidth(editor)
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...defaultAttributes,
|
||||
width: defaultWidth
|
||||
};
|
||||
}
|
||||
};
|
||||
const register = editor => {
|
||||
const registerOption = editor.options.register;
|
||||
registerOption('table_clone_elements', { processor: 'string[]' });
|
||||
registerOption('table_use_colgroups', {
|
||||
processor: 'boolean',
|
||||
default: true
|
||||
});
|
||||
registerOption('table_header_type', {
|
||||
processor: value => {
|
||||
const valid = contains$2([
|
||||
'section',
|
||||
'cells',
|
||||
'sectionCells',
|
||||
'auto'
|
||||
], value);
|
||||
return valid ? {
|
||||
value,
|
||||
valid
|
||||
} : {
|
||||
valid: false,
|
||||
message: 'Must be one of: section, cells, sectionCells or auto.'
|
||||
};
|
||||
},
|
||||
default: 'section'
|
||||
});
|
||||
registerOption('table_sizing_mode', {
|
||||
processor: 'string',
|
||||
default: 'auto'
|
||||
});
|
||||
registerOption('table_default_attributes', {
|
||||
processor: 'object',
|
||||
default: { border: '1' }
|
||||
});
|
||||
registerOption('table_default_styles', {
|
||||
processor: 'object',
|
||||
default: { 'border-collapse': 'collapse' }
|
||||
});
|
||||
registerOption('table_column_resizing', {
|
||||
processor: value => {
|
||||
const valid = contains$2([
|
||||
'preservetable',
|
||||
'resizetable'
|
||||
], value);
|
||||
return valid ? {
|
||||
value,
|
||||
valid
|
||||
} : {
|
||||
valid: false,
|
||||
message: 'Must be preservetable, or resizetable.'
|
||||
};
|
||||
},
|
||||
default: 'preservetable'
|
||||
});
|
||||
registerOption('table_resize_bars', {
|
||||
processor: 'boolean',
|
||||
default: true
|
||||
});
|
||||
registerOption('table_style_by_css', {
|
||||
processor: 'boolean',
|
||||
default: true
|
||||
});
|
||||
registerOption('table_merge_content_on_paste', {
|
||||
processor: 'boolean',
|
||||
default: true
|
||||
});
|
||||
};
|
||||
const getTableCloneElements = editor => {
|
||||
return Optional.from(editor.options.get('table_clone_elements'));
|
||||
};
|
||||
const hasTableObjectResizing = editor => {
|
||||
const objectResizing = editor.options.get('object_resizing');
|
||||
return contains$2(objectResizing.split(','), 'table');
|
||||
};
|
||||
const getTableHeaderType = option('table_header_type');
|
||||
const getTableColumnResizingBehaviour = option('table_column_resizing');
|
||||
const isPreserveTableColumnResizing = editor => getTableColumnResizingBehaviour(editor) === 'preservetable';
|
||||
const isResizeTableColumnResizing = editor => getTableColumnResizingBehaviour(editor) === 'resizetable';
|
||||
const getTableSizingMode = option('table_sizing_mode');
|
||||
const isTablePercentagesForced = editor => getTableSizingMode(editor) === 'relative';
|
||||
const isTablePixelsForced = editor => getTableSizingMode(editor) === 'fixed';
|
||||
const isTableResponsiveForced = editor => getTableSizingMode(editor) === 'responsive';
|
||||
const hasTableResizeBars = option('table_resize_bars');
|
||||
const shouldStyleWithCss = option('table_style_by_css');
|
||||
const shouldMergeContentOnPaste = option('table_merge_content_on_paste');
|
||||
const getTableDefaultAttributes = editor => {
|
||||
const options = editor.options;
|
||||
const defaultAttributes = options.get('table_default_attributes');
|
||||
return options.isSet('table_default_attributes') ? defaultAttributes : determineDefaultTableAttributes(editor, defaultAttributes);
|
||||
};
|
||||
const getTableDefaultStyles = editor => {
|
||||
const options = editor.options;
|
||||
const defaultStyles = options.get('table_default_styles');
|
||||
return options.isSet('table_default_styles') ? defaultStyles : determineDefaultTableStyles(editor, defaultStyles);
|
||||
};
|
||||
const tableUseColumnGroup = option('table_use_colgroups');
|
||||
|
||||
const closest = target => closest$1(target, '[contenteditable]');
|
||||
const isEditable$1 = (element, assumeEditable = false) => {
|
||||
if (inBody(element)) {
|
||||
@@ -2904,7 +3038,7 @@
|
||||
return name(content) !== 'meta';
|
||||
});
|
||||
const isTable = isTag('table');
|
||||
if (elements.length === 1 && isTable(elements[0])) {
|
||||
if (shouldMergeContentOnPaste(editor) && elements.length === 1 && isTable(elements[0])) {
|
||||
e.preventDefault();
|
||||
const doc = SugarElement.fromDom(editor.getDoc());
|
||||
const generators = paste$1(doc);
|
||||
@@ -4639,135 +4773,6 @@
|
||||
style: true
|
||||
};
|
||||
|
||||
const option = name => editor => editor.options.get(name);
|
||||
const defaultWidth = '100%';
|
||||
const getPixelForcedWidth = editor => {
|
||||
var _a;
|
||||
const dom = editor.dom;
|
||||
const parentBlock = (_a = dom.getParent(editor.selection.getStart(), dom.isBlock)) !== null && _a !== void 0 ? _a : editor.getBody();
|
||||
return getInner(SugarElement.fromDom(parentBlock)) + 'px';
|
||||
};
|
||||
const determineDefaultTableStyles = (editor, defaultStyles) => {
|
||||
if (isTableResponsiveForced(editor) || !shouldStyleWithCss(editor)) {
|
||||
return defaultStyles;
|
||||
} else if (isTablePixelsForced(editor)) {
|
||||
return {
|
||||
...defaultStyles,
|
||||
width: getPixelForcedWidth(editor)
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...defaultStyles,
|
||||
width: defaultWidth
|
||||
};
|
||||
}
|
||||
};
|
||||
const determineDefaultTableAttributes = (editor, defaultAttributes) => {
|
||||
if (isTableResponsiveForced(editor) || shouldStyleWithCss(editor)) {
|
||||
return defaultAttributes;
|
||||
} else if (isTablePixelsForced(editor)) {
|
||||
return {
|
||||
...defaultAttributes,
|
||||
width: getPixelForcedWidth(editor)
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...defaultAttributes,
|
||||
width: defaultWidth
|
||||
};
|
||||
}
|
||||
};
|
||||
const register = editor => {
|
||||
const registerOption = editor.options.register;
|
||||
registerOption('table_clone_elements', { processor: 'string[]' });
|
||||
registerOption('table_use_colgroups', {
|
||||
processor: 'boolean',
|
||||
default: true
|
||||
});
|
||||
registerOption('table_header_type', {
|
||||
processor: value => {
|
||||
const valid = contains$2([
|
||||
'section',
|
||||
'cells',
|
||||
'sectionCells',
|
||||
'auto'
|
||||
], value);
|
||||
return valid ? {
|
||||
value,
|
||||
valid
|
||||
} : {
|
||||
valid: false,
|
||||
message: 'Must be one of: section, cells, sectionCells or auto.'
|
||||
};
|
||||
},
|
||||
default: 'section'
|
||||
});
|
||||
registerOption('table_sizing_mode', {
|
||||
processor: 'string',
|
||||
default: 'auto'
|
||||
});
|
||||
registerOption('table_default_attributes', {
|
||||
processor: 'object',
|
||||
default: { border: '1' }
|
||||
});
|
||||
registerOption('table_default_styles', {
|
||||
processor: 'object',
|
||||
default: { 'border-collapse': 'collapse' }
|
||||
});
|
||||
registerOption('table_column_resizing', {
|
||||
processor: value => {
|
||||
const valid = contains$2([
|
||||
'preservetable',
|
||||
'resizetable'
|
||||
], value);
|
||||
return valid ? {
|
||||
value,
|
||||
valid
|
||||
} : {
|
||||
valid: false,
|
||||
message: 'Must be preservetable, or resizetable.'
|
||||
};
|
||||
},
|
||||
default: 'preservetable'
|
||||
});
|
||||
registerOption('table_resize_bars', {
|
||||
processor: 'boolean',
|
||||
default: true
|
||||
});
|
||||
registerOption('table_style_by_css', {
|
||||
processor: 'boolean',
|
||||
default: true
|
||||
});
|
||||
};
|
||||
const getTableCloneElements = editor => {
|
||||
return Optional.from(editor.options.get('table_clone_elements'));
|
||||
};
|
||||
const hasTableObjectResizing = editor => {
|
||||
const objectResizing = editor.options.get('object_resizing');
|
||||
return contains$2(objectResizing.split(','), 'table');
|
||||
};
|
||||
const getTableHeaderType = option('table_header_type');
|
||||
const getTableColumnResizingBehaviour = option('table_column_resizing');
|
||||
const isPreserveTableColumnResizing = editor => getTableColumnResizingBehaviour(editor) === 'preservetable';
|
||||
const isResizeTableColumnResizing = editor => getTableColumnResizingBehaviour(editor) === 'resizetable';
|
||||
const getTableSizingMode = option('table_sizing_mode');
|
||||
const isTablePercentagesForced = editor => getTableSizingMode(editor) === 'relative';
|
||||
const isTablePixelsForced = editor => getTableSizingMode(editor) === 'fixed';
|
||||
const isTableResponsiveForced = editor => getTableSizingMode(editor) === 'responsive';
|
||||
const hasTableResizeBars = option('table_resize_bars');
|
||||
const shouldStyleWithCss = option('table_style_by_css');
|
||||
const getTableDefaultAttributes = editor => {
|
||||
const options = editor.options;
|
||||
const defaultAttributes = options.get('table_default_attributes');
|
||||
return options.isSet('table_default_attributes') ? defaultAttributes : determineDefaultTableAttributes(editor, defaultAttributes);
|
||||
};
|
||||
const getTableDefaultStyles = editor => {
|
||||
const options = editor.options;
|
||||
const defaultStyles = options.get('table_default_styles');
|
||||
return options.isSet('table_default_styles') ? defaultStyles : determineDefaultTableStyles(editor, defaultStyles);
|
||||
};
|
||||
const tableUseColumnGroup = option('table_use_colgroups');
|
||||
|
||||
const get$5 = (editor, table) => {
|
||||
if (isTablePercentagesForced(editor)) {
|
||||
return TableSize.percentageSize(table);
|
||||
|
||||
File diff suppressed because one or more lines are too long
2
vendor/tinymce/tinymce/package.json
vendored
2
vendor/tinymce/tinymce/package.json
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tinymce",
|
||||
"version": "6.4.2",
|
||||
"version": "6.7.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/tinymce/tinymce.git",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
|
||||
(function () {
|
||||
@@ -162,7 +162,7 @@
|
||||
const isWithinNonEditable = (editor, element) => element !== null && !editor.dom.isEditable(element);
|
||||
const isWithinNonEditableList = (editor, element) => {
|
||||
const parentList = editor.dom.getParent(element, 'ol,ul,dl');
|
||||
return isWithinNonEditable(editor, parentList);
|
||||
return isWithinNonEditable(editor, parentList) && editor.selection.isEditable();
|
||||
};
|
||||
const setNodeChangeHandler = (editor, nodeChangeHandler) => {
|
||||
const initialNode = editor.selection.getNode();
|
||||
@@ -184,7 +184,7 @@
|
||||
const updateButtonState = (editor, parents) => {
|
||||
const element = editor.selection.getStart(true);
|
||||
api.setActive(inList(editor, parents, nodeName));
|
||||
api.setEnabled(!isWithinNonEditableList(editor, element));
|
||||
api.setEnabled(!isWithinNonEditableList(editor, element) && editor.selection.isEditable());
|
||||
};
|
||||
const nodeChangeHandler = e => updateButtonState(editor, e.parents);
|
||||
return setNodeChangeHandler(editor, nodeChangeHandler);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=(t,e,s)=>{const r="UL"===e?"InsertUnorderedList":"InsertOrderedList";t.execCommand(r,!1,!1===s?null:{"list-style-type":s})},s=t=>e=>e.options.get(t),r=s("advlist_number_styles"),n=s("advlist_bullet_styles"),l=t=>null==t,i=t=>!l(t);var o=tinymce.util.Tools.resolve("tinymce.util.Tools");class a{constructor(t,e){this.tag=t,this.value=e}static some(t){return new a(!0,t)}static none(){return a.singletonNone}fold(t,e){return this.tag?e(this.value):t()}isSome(){return this.tag}isNone(){return!this.tag}map(t){return this.tag?a.some(t(this.value)):a.none()}bind(t){return this.tag?t(this.value):a.none()}exists(t){return this.tag&&t(this.value)}forall(t){return!this.tag||t(this.value)}filter(t){return!this.tag||t(this.value)?this:a.none()}getOr(t){return this.tag?this.value:t}or(t){return this.tag?this:t}getOrThunk(t){return this.tag?this.value:t()}orThunk(t){return this.tag?this:t()}getOrDie(t){if(this.tag)return this.value;throw new Error(null!=t?t:"Called getOrDie on None")}static from(t){return i(t)?a.some(t):a.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(t){this.tag&&t(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}a.singletonNone=new a(!1);const u=t=>e=>i(e)&&t.test(e.nodeName),d=u(/^(OL|UL|DL)$/),g=u(/^(TH|TD)$/),c=t=>l(t)||"default"===t?"":t,h=(t,e)=>s=>((t,e)=>{const s=t.selection.getNode();return e({parents:t.dom.getParents(s),element:s}),t.on("NodeChange",e),()=>t.off("NodeChange",e)})(t,(r=>((t,r)=>{const n=t.selection.getStart(!0);s.setActive(((t,e,s)=>((t,e,s)=>{for(let e=0,n=t.length;e<n;e++){const n=t[e];if(d(r=n)&&!/\btox\-/.test(r.className))return a.some(n);if(s(n,e))break}var r;return a.none()})(e,0,g).exists((e=>e.nodeName===s&&((t,e)=>t.dom.isChildOf(e,t.getBody()))(t,e))))(t,r,e)),s.setEnabled(!((t,e)=>{const s=t.dom.getParent(e,"ol,ul,dl");return((t,e)=>null!==e&&!t.dom.isEditable(e))(t,s)})(t,n))})(t,r.parents))),m=(t,s,r,n,l,i)=>{i.length>1?((t,s,r,n,l,i)=>{t.ui.registry.addSplitButton(s,{tooltip:r,icon:"OL"===l?"ordered-list":"unordered-list",presets:"listpreview",columns:3,fetch:t=>{t(o.map(i,(t=>{const e="OL"===l?"num":"bull",s="disc"===t||"decimal"===t?"default":t,r=c(t),n=(t=>t.replace(/\-/g," ").replace(/\b\w/g,(t=>t.toUpperCase())))(t);return{type:"choiceitem",value:r,icon:"list-"+e+"-"+s,text:n}})))},onAction:()=>t.execCommand(n),onItemAction:(s,r)=>{e(t,l,r)},select:e=>{const s=(t=>{const e=t.dom.getParent(t.selection.getNode(),"ol,ul"),s=t.dom.getStyle(e,"listStyleType");return a.from(s)})(t);return s.map((t=>e===t)).getOr(!1)},onSetup:h(t,l)})})(t,s,r,n,l,i):((t,s,r,n,l,i)=>{t.ui.registry.addToggleButton(s,{active:!1,tooltip:r,icon:"OL"===l?"ordered-list":"unordered-list",onSetup:h(t,l),onAction:()=>t.queryCommandState(n)||""===i?t.execCommand(n):e(t,l,i)})})(t,s,r,n,l,c(i[0]))};t.add("advlist",(t=>{t.hasPlugin("lists")?((t=>{const e=t.options.register;e("advlist_number_styles",{processor:"string[]",default:"default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman".split(",")}),e("advlist_bullet_styles",{processor:"string[]",default:"default,circle,square".split(",")})})(t),(t=>{m(t,"numlist","Numbered list","InsertOrderedList","OL",r(t)),m(t,"bullist","Bullet list","InsertUnorderedList","UL",n(t))})(t),(t=>{t.addCommand("ApplyUnorderedListStyle",((s,r)=>{e(t,"UL",r["list-style-type"])})),t.addCommand("ApplyOrderedListStyle",((s,r)=>{e(t,"OL",r["list-style-type"])}))})(t)):console.error("Please use the Lists plugin together with the Advanced List plugin.")}))}();
|
||||
!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=(t,e,s)=>{const r="UL"===e?"InsertUnorderedList":"InsertOrderedList";t.execCommand(r,!1,!1===s?null:{"list-style-type":s})},s=t=>e=>e.options.get(t),r=s("advlist_number_styles"),n=s("advlist_bullet_styles"),i=t=>null==t,l=t=>!i(t);var o=tinymce.util.Tools.resolve("tinymce.util.Tools");class a{constructor(t,e){this.tag=t,this.value=e}static some(t){return new a(!0,t)}static none(){return a.singletonNone}fold(t,e){return this.tag?e(this.value):t()}isSome(){return this.tag}isNone(){return!this.tag}map(t){return this.tag?a.some(t(this.value)):a.none()}bind(t){return this.tag?t(this.value):a.none()}exists(t){return this.tag&&t(this.value)}forall(t){return!this.tag||t(this.value)}filter(t){return!this.tag||t(this.value)?this:a.none()}getOr(t){return this.tag?this.value:t}or(t){return this.tag?this:t}getOrThunk(t){return this.tag?this.value:t()}orThunk(t){return this.tag?this:t()}getOrDie(t){if(this.tag)return this.value;throw new Error(null!=t?t:"Called getOrDie on None")}static from(t){return l(t)?a.some(t):a.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(t){this.tag&&t(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}a.singletonNone=new a(!1);const u=t=>e=>l(e)&&t.test(e.nodeName),d=u(/^(OL|UL|DL)$/),g=u(/^(TH|TD)$/),c=t=>i(t)||"default"===t?"":t,h=(t,e)=>s=>((t,e)=>{const s=t.selection.getNode();return e({parents:t.dom.getParents(s),element:s}),t.on("NodeChange",e),()=>t.off("NodeChange",e)})(t,(r=>((t,r)=>{const n=t.selection.getStart(!0);s.setActive(((t,e,s)=>((t,e,s)=>{for(let e=0,n=t.length;e<n;e++){const n=t[e];if(d(r=n)&&!/\btox\-/.test(r.className))return a.some(n);if(s(n,e))break}var r;return a.none()})(e,0,g).exists((e=>e.nodeName===s&&((t,e)=>t.dom.isChildOf(e,t.getBody()))(t,e))))(t,r,e)),s.setEnabled(!((t,e)=>{const s=t.dom.getParent(e,"ol,ul,dl");return((t,e)=>null!==e&&!t.dom.isEditable(e))(t,s)&&t.selection.isEditable()})(t,n)&&t.selection.isEditable())})(t,r.parents))),m=(t,s,r,n,i,l)=>{l.length>1?((t,s,r,n,i,l)=>{t.ui.registry.addSplitButton(s,{tooltip:r,icon:"OL"===i?"ordered-list":"unordered-list",presets:"listpreview",columns:3,fetch:t=>{t(o.map(l,(t=>{const e="OL"===i?"num":"bull",s="disc"===t||"decimal"===t?"default":t,r=c(t),n=(t=>t.replace(/\-/g," ").replace(/\b\w/g,(t=>t.toUpperCase())))(t);return{type:"choiceitem",value:r,icon:"list-"+e+"-"+s,text:n}})))},onAction:()=>t.execCommand(n),onItemAction:(s,r)=>{e(t,i,r)},select:e=>{const s=(t=>{const e=t.dom.getParent(t.selection.getNode(),"ol,ul"),s=t.dom.getStyle(e,"listStyleType");return a.from(s)})(t);return s.map((t=>e===t)).getOr(!1)},onSetup:h(t,i)})})(t,s,r,n,i,l):((t,s,r,n,i,l)=>{t.ui.registry.addToggleButton(s,{active:!1,tooltip:r,icon:"OL"===i?"ordered-list":"unordered-list",onSetup:h(t,i),onAction:()=>t.queryCommandState(n)||""===l?t.execCommand(n):e(t,i,l)})})(t,s,r,n,i,c(l[0]))};t.add("advlist",(t=>{t.hasPlugin("lists")?((t=>{const e=t.options.register;e("advlist_number_styles",{processor:"string[]",default:"default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman".split(",")}),e("advlist_bullet_styles",{processor:"string[]",default:"default,circle,square".split(",")})})(t),(t=>{m(t,"numlist","Numbered list","InsertOrderedList","OL",r(t)),m(t,"bullist","Bullet list","InsertUnorderedList","UL",n(t))})(t),(t=>{t.addCommand("ApplyUnorderedListStyle",((s,r)=>{e(t,"UL",r["list-style-type"])})),t.addCommand("ApplyOrderedListStyle",((s,r)=>{e(t,"OL",r["list-style-type"])}))})(t)):console.error("Please use the Lists plugin together with the Advanced List plugin.")}))}();
|
||||
24
vendor/tinymce/tinymce/plugins/anchor/plugin.js
vendored
24
vendor/tinymce/tinymce/plugins/anchor/plugin.js
vendored
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
|
||||
(function () {
|
||||
@@ -164,18 +164,36 @@
|
||||
});
|
||||
};
|
||||
|
||||
const onSetupEditable = editor => api => {
|
||||
const nodeChanged = () => {
|
||||
api.setEnabled(editor.selection.isEditable());
|
||||
};
|
||||
editor.on('NodeChange', nodeChanged);
|
||||
nodeChanged();
|
||||
return () => {
|
||||
editor.off('NodeChange', nodeChanged);
|
||||
};
|
||||
};
|
||||
const register = editor => {
|
||||
const onAction = () => editor.execCommand('mceAnchor');
|
||||
editor.ui.registry.addToggleButton('anchor', {
|
||||
icon: 'bookmark',
|
||||
tooltip: 'Anchor',
|
||||
onAction,
|
||||
onSetup: buttonApi => editor.selection.selectorChangedWithUnbind('a:not([href])', buttonApi.setActive).unbind
|
||||
onSetup: buttonApi => {
|
||||
const unbindSelectorChanged = editor.selection.selectorChangedWithUnbind('a:not([href])', buttonApi.setActive).unbind;
|
||||
const unbindEditableChanged = onSetupEditable(editor)(buttonApi);
|
||||
return () => {
|
||||
unbindSelectorChanged();
|
||||
unbindEditableChanged();
|
||||
};
|
||||
}
|
||||
});
|
||||
editor.ui.registry.addMenuItem('anchor', {
|
||||
icon: 'bookmark',
|
||||
text: 'Anchor...',
|
||||
onAction
|
||||
onAction,
|
||||
onSetup: onSetupEditable(editor)
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.dom.RangeUtils"),o=tinymce.util.Tools.resolve("tinymce.util.Tools");const n=("allow_html_in_named_anchor",e=>e.options.get("allow_html_in_named_anchor"));const a="a:not([href])",r=e=>!e,i=e=>e.getAttribute("id")||e.getAttribute("name")||"",l=e=>(e=>"a"===e.nodeName.toLowerCase())(e)&&!e.getAttribute("href")&&""!==i(e),s=e=>e.dom.getParent(e.selection.getStart(),a),d=(e,a)=>{const r=s(e);r?((e,t,o)=>{o.removeAttribute("name"),o.id=t,e.addVisual(),e.undoManager.add()})(e,a,r):((e,a)=>{e.undoManager.transact((()=>{n(e)||e.selection.collapse(!0),e.selection.isCollapsed()?e.insertContent(e.dom.createHTML("a",{id:a})):((e=>{const n=e.dom;t(n).walk(e.selection.getRng(),(e=>{o.each(e,(e=>{var t;l(t=e)&&!t.firstChild&&n.remove(e,!1)}))}))})(e),e.formatter.remove("namedAnchor",void 0,void 0,!0),e.formatter.apply("namedAnchor",{value:a}),e.addVisual())}))})(e,a),e.focus()},c=e=>(e=>r(e.attr("href"))&&!r(e.attr("id")||e.attr("name")))(e)&&!e.firstChild,m=e=>t=>{for(let o=0;o<t.length;o++){const n=t[o];c(n)&&n.attr("contenteditable",e)}};e.add("anchor",(e=>{(e=>{(0,e.options.register)("allow_html_in_named_anchor",{processor:"boolean",default:!1})})(e),(e=>{e.on("PreInit",(()=>{e.parser.addNodeFilter("a",m("false")),e.serializer.addNodeFilter("a",m(null))}))})(e),(e=>{e.addCommand("mceAnchor",(()=>{(e=>{const t=(e=>{const t=s(e);return t?i(t):""})(e);e.windowManager.open({title:"Anchor",size:"normal",body:{type:"panel",items:[{name:"id",type:"input",label:"ID",placeholder:"example"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{id:t},onSubmit:t=>{((e,t)=>/^[A-Za-z][A-Za-z0-9\-:._]*$/.test(t)?(d(e,t),!0):(e.windowManager.alert("ID should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores."),!1))(e,t.getData().id)&&t.close()}})})(e)}))})(e),(e=>{const t=()=>e.execCommand("mceAnchor");e.ui.registry.addToggleButton("anchor",{icon:"bookmark",tooltip:"Anchor",onAction:t,onSetup:t=>e.selection.selectorChangedWithUnbind("a:not([href])",t.setActive).unbind}),e.ui.registry.addMenuItem("anchor",{icon:"bookmark",text:"Anchor...",onAction:t})})(e),e.on("PreInit",(()=>{(e=>{e.formatter.register("namedAnchor",{inline:"a",selector:a,remove:"all",split:!0,deep:!0,attributes:{id:"%value"},onmatch:(e,t,o)=>l(e)})})(e)}))}))}();
|
||||
!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.dom.RangeUtils"),o=tinymce.util.Tools.resolve("tinymce.util.Tools");const n=("allow_html_in_named_anchor",e=>e.options.get("allow_html_in_named_anchor"));const a="a:not([href])",r=e=>!e,i=e=>e.getAttribute("id")||e.getAttribute("name")||"",l=e=>(e=>"a"===e.nodeName.toLowerCase())(e)&&!e.getAttribute("href")&&""!==i(e),s=e=>e.dom.getParent(e.selection.getStart(),a),d=(e,a)=>{const r=s(e);r?((e,t,o)=>{o.removeAttribute("name"),o.id=t,e.addVisual(),e.undoManager.add()})(e,a,r):((e,a)=>{e.undoManager.transact((()=>{n(e)||e.selection.collapse(!0),e.selection.isCollapsed()?e.insertContent(e.dom.createHTML("a",{id:a})):((e=>{const n=e.dom;t(n).walk(e.selection.getRng(),(e=>{o.each(e,(e=>{var t;l(t=e)&&!t.firstChild&&n.remove(e,!1)}))}))})(e),e.formatter.remove("namedAnchor",void 0,void 0,!0),e.formatter.apply("namedAnchor",{value:a}),e.addVisual())}))})(e,a),e.focus()},c=e=>(e=>r(e.attr("href"))&&!r(e.attr("id")||e.attr("name")))(e)&&!e.firstChild,m=e=>t=>{for(let o=0;o<t.length;o++){const n=t[o];c(n)&&n.attr("contenteditable",e)}},u=e=>t=>{const o=()=>{t.setEnabled(e.selection.isEditable())};return e.on("NodeChange",o),o(),()=>{e.off("NodeChange",o)}};e.add("anchor",(e=>{(e=>{(0,e.options.register)("allow_html_in_named_anchor",{processor:"boolean",default:!1})})(e),(e=>{e.on("PreInit",(()=>{e.parser.addNodeFilter("a",m("false")),e.serializer.addNodeFilter("a",m(null))}))})(e),(e=>{e.addCommand("mceAnchor",(()=>{(e=>{const t=(e=>{const t=s(e);return t?i(t):""})(e);e.windowManager.open({title:"Anchor",size:"normal",body:{type:"panel",items:[{name:"id",type:"input",label:"ID",placeholder:"example"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{id:t},onSubmit:t=>{((e,t)=>/^[A-Za-z][A-Za-z0-9\-:._]*$/.test(t)?(d(e,t),!0):(e.windowManager.alert("ID should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores."),!1))(e,t.getData().id)&&t.close()}})})(e)}))})(e),(e=>{const t=()=>e.execCommand("mceAnchor");e.ui.registry.addToggleButton("anchor",{icon:"bookmark",tooltip:"Anchor",onAction:t,onSetup:t=>{const o=e.selection.selectorChangedWithUnbind("a:not([href])",t.setActive).unbind,n=u(e)(t);return()=>{o(),n()}}}),e.ui.registry.addMenuItem("anchor",{icon:"bookmark",text:"Anchor...",onAction:t,onSetup:u(e)})})(e),e.on("PreInit",(()=>{(e=>{e.formatter.register("namedAnchor",{inline:"a",selector:a,remove:"all",split:!0,deep:!0,attributes:{id:"%value"},onmatch:(e,t,o)=>l(e)})})(e)}))}))}();
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
|
||||
(function () {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>t.options.get(e),n=t("autolink_pattern"),o=t("link_default_target"),r=t("link_default_protocol"),a=t("allow_unsafe_link_target"),s=("string",e=>"string"===(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(n=o=e,(r=String).prototype.isPrototypeOf(n)||(null===(a=o.constructor)||void 0===a?void 0:a.name)===r.name)?"string":t;var n,o,r,a})(e));const l=(void 0,e=>undefined===e);const i=e=>!(e=>null==e)(e),c=Object.hasOwnProperty,d=e=>"\ufeff"===e;var u=tinymce.util.Tools.resolve("tinymce.dom.TextSeeker");const f=e=>/^[(\[{ \u00a0]$/.test(e),g=(e,t,n)=>{for(let o=t-1;o>=0;o--){const t=e.charAt(o);if(!d(t)&&n(t))return o}return-1},m=(e,t)=>{var o;const a=e.schema.getVoidElements(),s=n(e),{dom:i,selection:d}=e;if(null!==i.getParent(d.getNode(),"a[href]"))return null;const m=d.getRng(),k=u(i,(e=>{return i.isBlock(e)||(t=a,n=e.nodeName.toLowerCase(),c.call(t,n))||"false"===i.getContentEditable(e);var t,n})),{container:p,offset:y}=((e,t)=>{let n=e,o=t;for(;1===n.nodeType&&n.childNodes[o];)n=n.childNodes[o],o=3===n.nodeType?n.data.length:n.childNodes.length;return{container:n,offset:o}})(m.endContainer,m.endOffset),h=null!==(o=i.getParent(p,i.isBlock))&&void 0!==o?o:i.getRoot(),w=k.backwards(p,y+t,((e,t)=>{const n=e.data,o=g(n,t,(r=f,e=>!r(e)));var r,a;return-1===o||(a=n[o],/[?!,.;:]/.test(a))?o:o+1}),h);if(!w)return null;let v=w.container;const _=k.backwards(w.container,w.offset,((e,t)=>{v=e;const n=g(e.data,t,f);return-1===n?n:n+1}),h),A=i.createRng();_?A.setStart(_.container,_.offset):A.setStart(v,0),A.setEnd(w.container,w.offset);const C=A.toString().replace(/\uFEFF/g,"").match(s);if(C){let t=C[0];return $="www.",(b=t).length>=$.length&&b.substr(0,0+$.length)===$?t=r(e)+"://"+t:((e,t,n=0,o)=>{const r=e.indexOf(t,n);return-1!==r&&(!!l(o)||r+t.length<=o)})(t,"@")&&!(e=>/^([A-Za-z][A-Za-z\d.+-]*:\/\/)|mailto:/.test(e))(t)&&(t="mailto:"+t),{rng:A,url:t}}var b,$;return null},k=(e,t)=>{const{dom:n,selection:r}=e,{rng:l,url:i}=t,c=r.getBookmark();r.setRng(l);const d="createlink",u={command:d,ui:!1,value:i};if(!e.dispatch("BeforeExecCommand",u).isDefaultPrevented()){e.getDoc().execCommand(d,!1,i),e.dispatch("ExecCommand",u);const t=o(e);if(s(t)){const o=r.getNode();n.setAttrib(o,"target",t),"_blank"!==t||a(e)||n.setAttrib(o,"rel","noopener")}}r.moveToBookmark(c),e.nodeChanged()},p=e=>{const t=m(e,-1);i(t)&&k(e,t)},y=p;e.add("autolink",(e=>{(e=>{const t=e.options.register;t("autolink_pattern",{processor:"regexp",default:new RegExp("^"+/(?:[A-Za-z][A-Za-z\d.+-]{0,14}:\/\/(?:[-.~*+=!&;:'%@?^${}(),\w]+@)?|www\.|[-;:&=+$,.\w]+@)[A-Za-z\d-]+(?:\.[A-Za-z\d-]+)*(?::\d+)?(?:\/(?:[-.~*+=!;:'%@$(),\/\w]*[-~*+=%@$()\/\w])?)?(?:\?(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?(?:#(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?/g.source+"$","i")}),t("link_default_target",{processor:"string"}),t("link_default_protocol",{processor:"string",default:"https"})})(e),(e=>{e.on("keydown",(t=>{13!==t.keyCode||t.isDefaultPrevented()||(e=>{const t=m(e,0);i(t)&&k(e,t)})(e)})),e.on("keyup",(t=>{32===t.keyCode?p(e):(48===t.keyCode&&t.shiftKey||221===t.keyCode)&&y(e)}))})(e)}))}();
|
||||
!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>t.options.get(e),n=t("autolink_pattern"),o=t("link_default_target"),r=t("link_default_protocol"),a=t("allow_unsafe_link_target"),s=("string",e=>"string"===(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(n=o=e,(r=String).prototype.isPrototypeOf(n)||(null===(a=o.constructor)||void 0===a?void 0:a.name)===r.name)?"string":t;var n,o,r,a})(e));const l=(void 0,e=>undefined===e);const i=e=>!(e=>null==e)(e),c=Object.hasOwnProperty,d=e=>"\ufeff"===e;var u=tinymce.util.Tools.resolve("tinymce.dom.TextSeeker");const f=e=>/^[(\[{ \u00a0]$/.test(e),g=(e,t,n)=>{for(let o=t-1;o>=0;o--){const t=e.charAt(o);if(!d(t)&&n(t))return o}return-1},m=(e,t)=>{var o;const a=e.schema.getVoidElements(),s=n(e),{dom:i,selection:d}=e;if(null!==i.getParent(d.getNode(),"a[href]"))return null;const m=d.getRng(),k=u(i,(e=>{return i.isBlock(e)||(t=a,n=e.nodeName.toLowerCase(),c.call(t,n))||"false"===i.getContentEditable(e);var t,n})),{container:p,offset:y}=((e,t)=>{let n=e,o=t;for(;1===n.nodeType&&n.childNodes[o];)n=n.childNodes[o],o=3===n.nodeType?n.data.length:n.childNodes.length;return{container:n,offset:o}})(m.endContainer,m.endOffset),w=null!==(o=i.getParent(p,i.isBlock))&&void 0!==o?o:i.getRoot(),h=k.backwards(p,y+t,((e,t)=>{const n=e.data,o=g(n,t,(r=f,e=>!r(e)));var r,a;return-1===o||(a=n[o],/[?!,.;:]/.test(a))?o:o+1}),w);if(!h)return null;let v=h.container;const _=k.backwards(h.container,h.offset,((e,t)=>{v=e;const n=g(e.data,t,f);return-1===n?n:n+1}),w),A=i.createRng();_?A.setStart(_.container,_.offset):A.setStart(v,0),A.setEnd(h.container,h.offset);const C=A.toString().replace(/\uFEFF/g,"").match(s);if(C){let t=C[0];return $="www.",(b=t).length>=4&&b.substr(0,4)===$?t=r(e)+"://"+t:((e,t,n=0,o)=>{const r=e.indexOf(t,n);return-1!==r&&(!!l(o)||r+t.length<=o)})(t,"@")&&!(e=>/^([A-Za-z][A-Za-z\d.+-]*:\/\/)|mailto:/.test(e))(t)&&(t="mailto:"+t),{rng:A,url:t}}var b,$;return null},k=(e,t)=>{const{dom:n,selection:r}=e,{rng:l,url:i}=t,c=r.getBookmark();r.setRng(l);const d="createlink",u={command:d,ui:!1,value:i};if(!e.dispatch("BeforeExecCommand",u).isDefaultPrevented()){e.getDoc().execCommand(d,!1,i),e.dispatch("ExecCommand",u);const t=o(e);if(s(t)){const o=r.getNode();n.setAttrib(o,"target",t),"_blank"!==t||a(e)||n.setAttrib(o,"rel","noopener")}}r.moveToBookmark(c),e.nodeChanged()},p=e=>{const t=m(e,-1);i(t)&&k(e,t)},y=p;e.add("autolink",(e=>{(e=>{const t=e.options.register;t("autolink_pattern",{processor:"regexp",default:new RegExp("^"+/(?:[A-Za-z][A-Za-z\d.+-]{0,14}:\/\/(?:[-.~*+=!&;:'%@?^${}(),\w]+@)?|www\.|[-;:&=+$,.\w]+@)[A-Za-z\d-]+(?:\.[A-Za-z\d-]+)*(?::\d+)?(?:\/(?:[-.~*+=!;:'%@$(),\/\w]*[-~*+=%@$()\/\w])?)?(?:\?(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?(?:#(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?/g.source+"$","i")}),t("link_default_target",{processor:"string"}),t("link_default_protocol",{processor:"string",default:"https"})})(e),(e=>{e.on("keydown",(t=>{13!==t.keyCode||t.isDefaultPrevented()||(e=>{const t=m(e,0);i(t)&&k(e,t)})(e)})),e.on("keyup",(t=>{32===t.keyCode?p(e):(48===t.keyCode&&t.shiftKey||221===t.keyCode)&&y(e)}))})(e)}))}();
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
|
||||
(function () {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.Env");const o=e=>t=>t.options.get(e),s=o("min_height"),i=o("max_height"),n=o("autoresize_overflow_padding"),r=o("autoresize_bottom_margin"),l=(e,t)=>{const o=e.getBody();o&&(o.style.overflowY=t?"":"hidden",t||(o.scrollTop=0))},g=(e,t,o,s)=>{var i;const n=parseInt(null!==(i=e.getStyle(t,o,s))&&void 0!==i?i:"",10);return isNaN(n)?0:n},a=(e,o,r,c)=>{var d;const f=e.dom,u=e.getDoc();if(!u)return;if((e=>e.plugins.fullscreen&&e.plugins.fullscreen.isFullscreen())(e))return void l(e,!0);const m=u.documentElement,h=c?c():n(e),p=null!==(d=s(e))&&void 0!==d?d:e.getElement().offsetHeight;let y=p;const S=g(f,m,"margin-top",!0),v=g(f,m,"margin-bottom",!0);let C=m.offsetHeight+S+v+h;C<0&&(C=0);const b=e.getContainer().offsetHeight-e.getContentAreaContainer().offsetHeight;C+b>p&&(y=C+b);const w=i(e);if(w&&y>w?(y=w,l(e,!0)):l(e,!1),y!==o.get()){const s=y-o.get();if(f.setStyle(e.getContainer(),"height",y+"px"),o.set(y),(e=>{e.dispatch("ResizeEditor")})(e),t.browser.isSafari()&&(t.os.isMacOS()||t.os.isiOS())){const t=e.getWin();t.scrollTo(t.pageXOffset,t.pageYOffset)}e.hasFocus()&&(e=>{if("setcontent"===(null==e?void 0:e.type.toLowerCase())){const t=e;return!0===t.selection||!0===t.paste}return!1})(r)&&e.selection.scrollIntoView(),(t.browser.isSafari()||t.browser.isChromium())&&s<0&&a(e,o,r,c)}};e.add("autoresize",(e=>{if((e=>{const t=e.options.register;t("autoresize_overflow_padding",{processor:"number",default:1}),t("autoresize_bottom_margin",{processor:"number",default:50})})(e),e.options.isSet("resize")||e.options.set("resize",!1),!e.inline){const o=(e=>{let t=0;return{get:()=>t,set:e=>{t=e}}})();((e,t)=>{e.addCommand("mceAutoResize",(()=>{a(e,t)}))})(e,o),((e,o)=>{let s,i,l=()=>r(e);e.on("init",(i=>{s=0;const r=n(e),g=e.dom;g.setStyles(e.getDoc().documentElement,{height:"auto"}),t.browser.isEdge()||t.browser.isIE()?g.setStyles(e.getBody(),{paddingLeft:r,paddingRight:r,"min-height":0}):g.setStyles(e.getBody(),{paddingLeft:r,paddingRight:r}),a(e,o,i,l),s+=1})),e.on("NodeChange SetContent keyup FullscreenStateChanged ResizeContent",(t=>{if(1===s)i=e.getContainer().offsetHeight,a(e,o,t,l),s+=1;else if(2===s){const t=i<e.getContainer().offsetHeight;if(t){const t=e.dom,o=e.getDoc();t.setStyles(o.documentElement,{"min-height":0}),t.setStyles(e.getBody(),{"min-height":"inherit"})}l=t?(0,()=>0):l,s+=1}else a(e,o,t,l)}))})(e,o)}}))}();
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
|
||||
(function () {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=("string",t=>"string"===(t=>{const e=typeof t;return null===t?"null":"object"===e&&Array.isArray(t)?"array":"object"===e&&(r=o=t,(a=String).prototype.isPrototypeOf(r)||(null===(s=o.constructor)||void 0===s?void 0:s.name)===a.name)?"string":e;var r,o,a,s})(t));const r=(void 0,t=>undefined===t);var o=tinymce.util.Tools.resolve("tinymce.util.Delay"),a=tinymce.util.Tools.resolve("tinymce.util.LocalStorage"),s=tinymce.util.Tools.resolve("tinymce.util.Tools");const n=t=>{const e=/^(\d+)([ms]?)$/.exec(t);return(e&&e[2]?{s:1e3,m:6e4}[e[2]]:1)*parseInt(t,10)},i=t=>e=>e.options.get(t),u=i("autosave_ask_before_unload"),l=i("autosave_restore_when_empty"),c=i("autosave_interval"),d=i("autosave_retention"),m=t=>{const e=document.location;return t.options.get("autosave_prefix").replace(/{path}/g,e.pathname).replace(/{query}/g,e.search).replace(/{hash}/g,e.hash).replace(/{id}/g,t.id)},v=(t,e)=>{if(r(e))return t.dom.isEmpty(t.getBody());{const r=s.trim(e);if(""===r)return!0;{const e=(new DOMParser).parseFromString(r,"text/html");return t.dom.isEmpty(e)}}},f=t=>{var e;const r=parseInt(null!==(e=a.getItem(m(t)+"time"))&&void 0!==e?e:"0",10)||0;return!((new Date).getTime()-r>d(t)&&(p(t,!1),1))},p=(t,e)=>{const r=m(t);a.removeItem(r+"draft"),a.removeItem(r+"time"),!1!==e&&(t=>{t.dispatch("RemoveDraft")})(t)},g=t=>{const e=m(t);!v(t)&&t.isDirty()&&(a.setItem(e+"draft",t.getContent({format:"raw",no_events:!0})),a.setItem(e+"time",(new Date).getTime().toString()),(t=>{t.dispatch("StoreDraft")})(t))},y=t=>{var e;const r=m(t);f(t)&&(t.setContent(null!==(e=a.getItem(r+"draft"))&&void 0!==e?e:"",{format:"raw"}),(t=>{t.dispatch("RestoreDraft")})(t))};var D=tinymce.util.Tools.resolve("tinymce.EditorManager");const h=t=>e=>{e.setEnabled(f(t));const r=()=>e.setEnabled(f(t));return t.on("StoreDraft RestoreDraft RemoveDraft",r),()=>t.off("StoreDraft RestoreDraft RemoveDraft",r)};t.add("autosave",(t=>((t=>{const r=t.options.register,o=t=>{const r=e(t);return r?{value:n(t),valid:r}:{valid:!1,message:"Must be a string."}};r("autosave_ask_before_unload",{processor:"boolean",default:!0}),r("autosave_prefix",{processor:"string",default:"tinymce-autosave-{path}{query}{hash}-{id}-"}),r("autosave_restore_when_empty",{processor:"boolean",default:!1}),r("autosave_interval",{processor:o,default:"30s"}),r("autosave_retention",{processor:o,default:"20m"})})(t),(t=>{t.editorManager.on("BeforeUnload",(t=>{let e;s.each(D.get(),(t=>{t.plugins.autosave&&t.plugins.autosave.storeDraft(),!e&&t.isDirty()&&u(t)&&(e=t.translate("You have unsaved changes are you sure you want to navigate away?"))})),e&&(t.preventDefault(),t.returnValue=e)}))})(t),(t=>{(t=>{const e=c(t);o.setEditorInterval(t,(()=>{g(t)}),e)})(t);const e=()=>{(t=>{t.undoManager.transact((()=>{y(t),p(t)})),t.focus()})(t)};t.ui.registry.addButton("restoredraft",{tooltip:"Restore last draft",icon:"restore-draft",onAction:e,onSetup:h(t)}),t.ui.registry.addMenuItem("restoredraft",{text:"Restore last draft",icon:"restore-draft",onAction:e,onSetup:h(t)})})(t),t.on("init",(()=>{l(t)&&t.dom.isEmpty(t.getBody())&&y(t)})),(t=>({hasDraft:()=>f(t),storeDraft:()=>g(t),restoreDraft:()=>y(t),removeDraft:e=>p(t,e),isEmpty:e=>v(t,e)}))(t))))}();
|
||||
18
vendor/tinymce/tinymce/plugins/charmap/plugin.js
vendored
18
vendor/tinymce/tinymce/plugins/charmap/plugin.js
vendored
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
|
||||
(function () {
|
||||
@@ -1616,17 +1616,29 @@
|
||||
});
|
||||
};
|
||||
|
||||
const onSetupEditable = editor => api => {
|
||||
const nodeChanged = () => {
|
||||
api.setEnabled(editor.selection.isEditable());
|
||||
};
|
||||
editor.on('NodeChange', nodeChanged);
|
||||
nodeChanged();
|
||||
return () => {
|
||||
editor.off('NodeChange', nodeChanged);
|
||||
};
|
||||
};
|
||||
const register = editor => {
|
||||
const onAction = () => editor.execCommand('mceShowCharmap');
|
||||
editor.ui.registry.addButton('charmap', {
|
||||
icon: 'insert-character',
|
||||
tooltip: 'Special character',
|
||||
onAction
|
||||
onAction,
|
||||
onSetup: onSetupEditable(editor)
|
||||
});
|
||||
editor.ui.registry.addMenuItem('charmap', {
|
||||
icon: 'insert-character',
|
||||
text: 'Special character...',
|
||||
onAction
|
||||
onAction,
|
||||
onSetup: onSetupEditable(editor)
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
|
||||
(function () {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
!function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("code",(e=>((e=>{e.addCommand("mceCodeEditor",(()=>{(e=>{const o=(e=>e.getContent({source_view:!0}))(e);e.windowManager.open({title:"Source Code",size:"large",body:{type:"panel",items:[{type:"textarea",name:"code"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{code:o},onSubmit:o=>{((e,o)=>{e.focus(),e.undoManager.transact((()=>{e.setContent(o)})),e.selection.setCursorLocation(),e.nodeChanged()})(e,o.getData().code),o.close()}})})(e)}))})(e),(e=>{const o=()=>e.execCommand("mceCodeEditor");e.ui.registry.addButton("code",{icon:"sourcecode",tooltip:"Source code",onAction:o}),e.ui.registry.addMenuItem("code",{icon:"sourcecode",text:"Source code",onAction:o})})(e),{})))}();
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
|
||||
(function () {
|
||||
@@ -10,6 +10,8 @@
|
||||
const isNullable = a => a === null || a === undefined;
|
||||
const isNonNullable = a => !isNullable(a);
|
||||
|
||||
const noop = () => {
|
||||
};
|
||||
const constant = value => {
|
||||
return () => {
|
||||
return value;
|
||||
@@ -1222,7 +1224,7 @@
|
||||
Prism.languages.css = {
|
||||
'comment': /\/\*[\s\S]*?\*\//,
|
||||
'atrule': {
|
||||
pattern: /@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,
|
||||
pattern: RegExp('@[\\w-](?:' + /[^;{\s"']|\s+(?!\s)/.source + '|' + string.source + ')*?' + /(?:;|(?=\s*\{))/.source),
|
||||
inside: {
|
||||
'rule': /^@[\w-]+/,
|
||||
'selector-function-argument': {
|
||||
@@ -1319,7 +1321,8 @@
|
||||
'operator': {
|
||||
pattern: /(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,
|
||||
lookbehind: true
|
||||
}
|
||||
},
|
||||
'constant': /\b[A-Z][A-Z_\d]+\b/
|
||||
});
|
||||
Prism.languages.insertBefore('java', 'string', {
|
||||
'triple-quoted-string': {
|
||||
@@ -1549,7 +1552,10 @@
|
||||
pattern: /^=/,
|
||||
alias: 'attr-equals'
|
||||
},
|
||||
/"|'/
|
||||
{
|
||||
pattern: /^(\s*)["']|["']$/,
|
||||
lookbehind: true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -2300,7 +2306,7 @@
|
||||
type: 'panel',
|
||||
items: [
|
||||
{
|
||||
type: 'selectbox',
|
||||
type: 'listbox',
|
||||
name: 'language',
|
||||
label: 'Language',
|
||||
items: languages
|
||||
@@ -2405,6 +2411,17 @@
|
||||
});
|
||||
};
|
||||
|
||||
const onSetupEditable = (editor, onChanged = noop) => api => {
|
||||
const nodeChanged = () => {
|
||||
api.setEnabled(editor.selection.isEditable());
|
||||
onChanged(api);
|
||||
};
|
||||
editor.on('NodeChange', nodeChanged);
|
||||
nodeChanged();
|
||||
return () => {
|
||||
editor.off('NodeChange', nodeChanged);
|
||||
};
|
||||
};
|
||||
const isCodeSampleSelection = editor => {
|
||||
const node = editor.selection.getStart();
|
||||
return editor.dom.is(node, 'pre[class*="language-"]');
|
||||
@@ -2415,18 +2432,15 @@
|
||||
icon: 'code-sample',
|
||||
tooltip: 'Insert/edit code sample',
|
||||
onAction,
|
||||
onSetup: api => {
|
||||
const nodeChangeHandler = () => {
|
||||
api.setActive(isCodeSampleSelection(editor));
|
||||
};
|
||||
editor.on('NodeChange', nodeChangeHandler);
|
||||
return () => editor.off('NodeChange', nodeChangeHandler);
|
||||
}
|
||||
onSetup: onSetupEditable(editor, api => {
|
||||
api.setActive(isCodeSampleSelection(editor));
|
||||
})
|
||||
});
|
||||
editor.ui.registry.addMenuItem('codesample', {
|
||||
text: 'Code sample...',
|
||||
icon: 'code-sample',
|
||||
onAction
|
||||
onAction,
|
||||
onSetup: onSetupEditable(editor)
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
|
||||
(function () {
|
||||
@@ -315,27 +315,36 @@
|
||||
return normalizedElement.getOr(element);
|
||||
};
|
||||
const isListItem = isTag('li');
|
||||
const setDir = (editor, dir) => {
|
||||
const selectedBlocks = editor.selection.getSelectedBlocks();
|
||||
if (selectedBlocks.length > 0) {
|
||||
each(selectedBlocks, block => {
|
||||
const blockElement = SugarElement.fromDom(block);
|
||||
const isBlockElementListItem = isListItem(blockElement);
|
||||
const normalizedBlock = getNormalizedBlock(blockElement, isBlockElementListItem);
|
||||
const normalizedBlockParent = getParentElement(normalizedBlock);
|
||||
normalizedBlockParent.each(parent => {
|
||||
const parentDirection = getDirection(parent);
|
||||
if (parentDirection !== dir) {
|
||||
set(normalizedBlock, 'dir', dir);
|
||||
} else if (getDirection(normalizedBlock) !== dir) {
|
||||
remove(normalizedBlock, 'dir');
|
||||
}
|
||||
if (isBlockElementListItem) {
|
||||
const listItems = children(normalizedBlock, 'li[dir]');
|
||||
each(listItems, listItem => remove(listItem, 'dir'));
|
||||
}
|
||||
});
|
||||
const setDirOnElements = (dom, blocks, dir) => {
|
||||
each(blocks, block => {
|
||||
const blockElement = SugarElement.fromDom(block);
|
||||
const isBlockElementListItem = isListItem(blockElement);
|
||||
const normalizedBlock = getNormalizedBlock(blockElement, isBlockElementListItem);
|
||||
const normalizedBlockParent = getParentElement(normalizedBlock);
|
||||
normalizedBlockParent.each(parent => {
|
||||
dom.setStyle(normalizedBlock.dom, 'direction', null);
|
||||
const parentDirection = getDirection(parent);
|
||||
if (parentDirection === dir) {
|
||||
remove(normalizedBlock, 'dir');
|
||||
} else {
|
||||
set(normalizedBlock, 'dir', dir);
|
||||
}
|
||||
if (getDirection(normalizedBlock) !== dir) {
|
||||
dom.setStyle(normalizedBlock.dom, 'direction', dir);
|
||||
}
|
||||
if (isBlockElementListItem) {
|
||||
const listItems = children(normalizedBlock, 'li[dir],li[style]');
|
||||
each(listItems, listItem => {
|
||||
remove(listItem, 'dir');
|
||||
dom.setStyle(listItem.dom, 'direction', null);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
const setDir = (editor, dir) => {
|
||||
if (editor.selection.isEditable()) {
|
||||
setDirOnElements(editor.dom, editor.selection.getSelectedBlocks(), dir);
|
||||
editor.nodeChanged();
|
||||
}
|
||||
};
|
||||
@@ -353,8 +362,10 @@
|
||||
const nodeChangeHandler = e => {
|
||||
const element = SugarElement.fromDom(e.element);
|
||||
api.setActive(getDirection(element) === dir);
|
||||
api.setEnabled(editor.selection.isEditable());
|
||||
};
|
||||
editor.on('NodeChange', nodeChangeHandler);
|
||||
api.setEnabled(editor.selection.isEditable());
|
||||
return () => editor.off('NodeChange', nodeChangeHandler);
|
||||
};
|
||||
const register = editor => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=t=>e=>typeof e===t,o=t=>"string"===(t=>{const e=typeof t;return null===t?"null":"object"===e&&Array.isArray(t)?"array":"object"===e&&(o=r=t,(n=String).prototype.isPrototypeOf(o)||(null===(i=r.constructor)||void 0===i?void 0:i.name)===n.name)?"string":e;var o,r,n,i})(t),r=e("boolean"),n=t=>!(t=>null==t)(t),i=e("function"),s=e("number"),l=(!1,()=>false);class a{constructor(t,e){this.tag=t,this.value=e}static some(t){return new a(!0,t)}static none(){return a.singletonNone}fold(t,e){return this.tag?e(this.value):t()}isSome(){return this.tag}isNone(){return!this.tag}map(t){return this.tag?a.some(t(this.value)):a.none()}bind(t){return this.tag?t(this.value):a.none()}exists(t){return this.tag&&t(this.value)}forall(t){return!this.tag||t(this.value)}filter(t){return!this.tag||t(this.value)?this:a.none()}getOr(t){return this.tag?this.value:t}or(t){return this.tag?this:t}getOrThunk(t){return this.tag?this.value:t()}orThunk(t){return this.tag?this:t()}getOrDie(t){if(this.tag)return this.value;throw new Error(null!=t?t:"Called getOrDie on None")}static from(t){return n(t)?a.some(t):a.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(t){this.tag&&t(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}a.singletonNone=new a(!1);const u=(t,e)=>{for(let o=0,r=t.length;o<r;o++)e(t[o],o)},c=t=>{if(null==t)throw new Error("Node cannot be null or undefined");return{dom:t}},d=c,h=(t,e)=>{const o=t.dom;if(1!==o.nodeType)return!1;{const t=o;if(void 0!==t.matches)return t.matches(e);if(void 0!==t.msMatchesSelector)return t.msMatchesSelector(e);if(void 0!==t.webkitMatchesSelector)return t.webkitMatchesSelector(e);if(void 0!==t.mozMatchesSelector)return t.mozMatchesSelector(e);throw new Error("Browser lacks native selectors")}};"undefined"!=typeof window?window:Function("return this;")();const m=t=>e=>(t=>t.dom.nodeType)(e)===t,g=m(1),f=m(3),v=m(9),p=m(11),y=(t,e)=>{t.dom.removeAttribute(e)},w=i(Element.prototype.attachShadow)&&i(Node.prototype.getRootNode)?t=>d(t.dom.getRootNode()):t=>v(t)?t:d(t.dom.ownerDocument),N=t=>d(t.dom.host),b=t=>{const e=f(t)?t.dom.parentNode:t.dom;if(null==e||null===e.ownerDocument)return!1;const o=e.ownerDocument;return(t=>{const e=w(t);return p(o=e)&&n(o.dom.host)?a.some(e):a.none();var o})(d(e)).fold((()=>o.body.contains(e)),(r=b,i=N,t=>r(i(t))));var r,i},S=t=>"rtl"===((t,e)=>{const o=t.dom,r=window.getComputedStyle(o).getPropertyValue(e);return""!==r||b(t)?r:((t,e)=>(t=>void 0!==t.style&&i(t.style.getPropertyValue))(t)?t.style.getPropertyValue(e):"")(o,e)})(t,"direction")?"rtl":"ltr",A=(t,e)=>((t,o)=>((t,e)=>{const o=[];for(let r=0,n=t.length;r<n;r++){const n=t[r];e(n,r)&&o.push(n)}return o})(((t,e)=>{const o=t.length,r=new Array(o);for(let n=0;n<o;n++){const o=t[n];r[n]=e(o,n)}return r})(t.dom.childNodes,d),(t=>h(t,e))))(t),T=("li",t=>g(t)&&"li"===t.dom.nodeName.toLowerCase());const C=(t,e)=>{const n=t.selection.getSelectedBlocks();n.length>0&&(u(n,(t=>{const n=d(t),c=T(n),m=((t,e)=>{return(e?(o=t,r="ol,ul",((t,e,o)=>{let n=t.dom;const s=i(o)?o:l;for(;n.parentNode;){n=n.parentNode;const t=d(n);if(h(t,r))return a.some(t);if(s(t))break}return a.none()})(o,0,n)):a.some(t)).getOr(t);var o,r,n})(n,c);var f;(f=m,(t=>a.from(t.dom.parentNode).map(d))(f).filter(g)).each((t=>{if(S(t)!==e?((t,e,n)=>{((t,e,n)=>{if(!(o(n)||r(n)||s(n)))throw console.error("Invalid call to Attribute.set. Key ",e,":: Value ",n,":: Element ",t),new Error("Attribute value was not simple");t.setAttribute(e,n+"")})(t.dom,e,n)})(m,"dir",e):S(m)!==e&&y(m,"dir"),c){const t=A(m,"li[dir]");u(t,(t=>y(t,"dir")))}}))})),t.nodeChanged())},D=(t,e)=>o=>{const r=t=>{const r=d(t.element);o.setActive(S(r)===e)};return t.on("NodeChange",r),()=>t.off("NodeChange",r)};t.add("directionality",(t=>{(t=>{t.addCommand("mceDirectionLTR",(()=>{C(t,"ltr")})),t.addCommand("mceDirectionRTL",(()=>{C(t,"rtl")}))})(t),(t=>{t.ui.registry.addToggleButton("ltr",{tooltip:"Left to right",icon:"ltr",onAction:()=>t.execCommand("mceDirectionLTR"),onSetup:D(t,"ltr")}),t.ui.registry.addToggleButton("rtl",{tooltip:"Right to left",icon:"rtl",onAction:()=>t.execCommand("mceDirectionRTL"),onSetup:D(t,"rtl")})})(t)}))}();
|
||||
!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=t=>e=>typeof e===t,o=t=>"string"===(t=>{const e=typeof t;return null===t?"null":"object"===e&&Array.isArray(t)?"array":"object"===e&&(o=r=t,(n=String).prototype.isPrototypeOf(o)||(null===(i=r.constructor)||void 0===i?void 0:i.name)===n.name)?"string":e;var o,r,n,i})(t),r=e("boolean"),n=t=>!(t=>null==t)(t),i=e("function"),s=e("number"),l=(!1,()=>false);class a{constructor(t,e){this.tag=t,this.value=e}static some(t){return new a(!0,t)}static none(){return a.singletonNone}fold(t,e){return this.tag?e(this.value):t()}isSome(){return this.tag}isNone(){return!this.tag}map(t){return this.tag?a.some(t(this.value)):a.none()}bind(t){return this.tag?t(this.value):a.none()}exists(t){return this.tag&&t(this.value)}forall(t){return!this.tag||t(this.value)}filter(t){return!this.tag||t(this.value)?this:a.none()}getOr(t){return this.tag?this.value:t}or(t){return this.tag?this:t}getOrThunk(t){return this.tag?this.value:t()}orThunk(t){return this.tag?this:t()}getOrDie(t){if(this.tag)return this.value;throw new Error(null!=t?t:"Called getOrDie on None")}static from(t){return n(t)?a.some(t):a.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(t){this.tag&&t(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}a.singletonNone=new a(!1);const u=(t,e)=>{for(let o=0,r=t.length;o<r;o++)e(t[o],o)},c=t=>{if(null==t)throw new Error("Node cannot be null or undefined");return{dom:t}},d=c,h=(t,e)=>{const o=t.dom;if(1!==o.nodeType)return!1;{const t=o;if(void 0!==t.matches)return t.matches(e);if(void 0!==t.msMatchesSelector)return t.msMatchesSelector(e);if(void 0!==t.webkitMatchesSelector)return t.webkitMatchesSelector(e);if(void 0!==t.mozMatchesSelector)return t.mozMatchesSelector(e);throw new Error("Browser lacks native selectors")}};"undefined"!=typeof window?window:Function("return this;")();const m=t=>e=>(t=>t.dom.nodeType)(e)===t,g=m(1),f=m(3),v=m(9),y=m(11),p=(t,e)=>{t.dom.removeAttribute(e)},w=i(Element.prototype.attachShadow)&&i(Node.prototype.getRootNode)?t=>d(t.dom.getRootNode()):t=>v(t)?t:d(t.dom.ownerDocument),b=t=>d(t.dom.host),N=t=>{const e=f(t)?t.dom.parentNode:t.dom;if(null==e||null===e.ownerDocument)return!1;const o=e.ownerDocument;return(t=>{const e=w(t);return y(o=e)&&n(o.dom.host)?a.some(e):a.none();var o})(d(e)).fold((()=>o.body.contains(e)),(r=N,i=b,t=>r(i(t))));var r,i},S=t=>"rtl"===((t,e)=>{const o=t.dom,r=window.getComputedStyle(o).getPropertyValue(e);return""!==r||N(t)?r:((t,e)=>(t=>void 0!==t.style&&i(t.style.getPropertyValue))(t)?t.style.getPropertyValue(e):"")(o,e)})(t,"direction")?"rtl":"ltr",A=(t,e)=>((t,o)=>((t,e)=>{const o=[];for(let r=0,n=t.length;r<n;r++){const n=t[r];e(n,r)&&o.push(n)}return o})(((t,e)=>{const o=t.length,r=new Array(o);for(let n=0;n<o;n++){const o=t[n];r[n]=e(o,n)}return r})(t.dom.childNodes,d),(t=>h(t,e))))(t),E=("li",t=>g(t)&&"li"===t.dom.nodeName.toLowerCase());const T=(t,e,n)=>{u(e,(e=>{const c=d(e),m=E(c),f=((t,e)=>{return(e?(o=t,r="ol,ul",((t,e,o)=>{let n=t.dom;const s=i(o)?o:l;for(;n.parentNode;){n=n.parentNode;const t=d(n);if(h(t,r))return a.some(t);if(s(t))break}return a.none()})(o,0,n)):a.some(t)).getOr(t);var o,r,n})(c,m);var v;(v=f,(t=>a.from(t.dom.parentNode).map(d))(v).filter(g)).each((e=>{if(t.setStyle(f.dom,"direction",null),S(e)===n?p(f,"dir"):((t,e,n)=>{((t,e,n)=>{if(!(o(n)||r(n)||s(n)))throw console.error("Invalid call to Attribute.set. Key ",e,":: Value ",n,":: Element ",t),new Error("Attribute value was not simple");t.setAttribute(e,n+"")})(t.dom,e,n)})(f,"dir",n),S(f)!==n&&t.setStyle(f.dom,"direction",n),m){const e=A(f,"li[dir],li[style]");u(e,(e=>{p(e,"dir"),t.setStyle(e.dom,"direction",null)}))}}))}))},C=(t,e)=>{t.selection.isEditable()&&(T(t.dom,t.selection.getSelectedBlocks(),e),t.nodeChanged())},D=(t,e)=>o=>{const r=r=>{const n=d(r.element);o.setActive(S(n)===e),o.setEnabled(t.selection.isEditable())};return t.on("NodeChange",r),o.setEnabled(t.selection.isEditable()),()=>t.off("NodeChange",r)};t.add("directionality",(t=>{(t=>{t.addCommand("mceDirectionLTR",(()=>{C(t,"ltr")})),t.addCommand("mceDirectionRTL",(()=>{C(t,"rtl")}))})(t),(t=>{t.ui.registry.addToggleButton("ltr",{tooltip:"Left to right",icon:"ltr",onAction:()=>t.execCommand("mceDirectionLTR"),onSetup:D(t,"ltr")}),t.ui.registry.addToggleButton("rtl",{tooltip:"Right to left",icon:"rtl",onAction:()=>t.execCommand("mceDirectionRTL"),onSetup:D(t,"rtl")})})(t)}))}();
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
|
||||
(function () {
|
||||
@@ -551,17 +551,29 @@
|
||||
});
|
||||
};
|
||||
|
||||
const onSetupEditable = editor => api => {
|
||||
const nodeChanged = () => {
|
||||
api.setEnabled(editor.selection.isEditable());
|
||||
};
|
||||
editor.on('NodeChange', nodeChanged);
|
||||
nodeChanged();
|
||||
return () => {
|
||||
editor.off('NodeChange', nodeChanged);
|
||||
};
|
||||
};
|
||||
const register = editor => {
|
||||
const onAction = () => editor.execCommand('mceEmoticons');
|
||||
editor.ui.registry.addButton('emoticons', {
|
||||
tooltip: 'Emojis',
|
||||
icon: 'emoji',
|
||||
onAction
|
||||
onAction,
|
||||
onSetup: onSetupEditable(editor)
|
||||
});
|
||||
editor.ui.registry.addMenuItem('emoticons', {
|
||||
text: 'Emojis...',
|
||||
icon: 'emoji',
|
||||
onAction
|
||||
onAction,
|
||||
onSetup: onSetupEditable(editor)
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* TinyMCE version 6.4.2 (2023-04-26)
|
||||
* TinyMCE version 6.7.0 (2023-08-30)
|
||||
*/
|
||||
|
||||
(function () {
|
||||
|
||||
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user