merge master in prod

This commit is contained in:
2020-09-08 12:00:45 +02:00
parent b925edaa9e
commit 3e5e731c2c
226 changed files with 8516 additions and 4149 deletions
+41
View File
@@ -1,3 +1,44 @@
# v3.0.9
## 06/08/2020
1. [](#improved)
* Disable password autocomplete in password field
* Don't save empty string in password field [#134](https://github.com/getgrav/grav-plugin-email/issues/134)
# v3.0.8
## 04/27/2020
1. [](#improved)
* Updated vendor library files
* Use Grav's Parsedown class
# v3.0.7
## 03/05/2020
1. [](#improved)
* Updated email validator library
1. [](#bugfix)
* Fixed `Invalid resource theme://` on CLI command `test-email` on Grav 1.6.21 and later versions [#128](https://github.com/getgrav/grav-plugin-email/issues/128)
# v3.0.6
## 02/11/2020
1. [](#improved)
* Updated email validator library
# v3.0.5
## 02/03/2020
1. [](#bugfix)
* Fixed a date in changelog (no other changes)
# v3.0.4
## 01/17/2020
1. [](#improved)
* Added ZOHO configuration example
* Updated SwiftMailer library for PHP 7.4 support
# v3.0.3
## 08/16/2019
+19
View File
@@ -159,6 +159,25 @@ mailer:
It's that easy!
#### ZOHO
ZOHO is a popular solution for hosted email due to it's great 'FREE' tier. It's paid options are also very reasonable and combined with the latest UI updates and outstanding security features, it's a solid email option.
In order to get ZOHO working with Grav, you need to send email via a user account. You can either use your users' password or generate an **App Password** via your ZOHO account (clicking on your avatar once logged in), then navigating to `Two Factor Authentication -> App Passwords -> Generate`. Just enter a unique app name (i.e. `Grav Website`).
NOTE: The SMTP host required can be found in `Settings -> Mail - > Mail Accounts -> POP/IMAP -> SMTP`. This will provide the SMTP server for this account (it may not be `imap.zoho.com` depending on what region you are in)
```
mailer:
engine: smtp
smtp:
server: smtp.zoho.com
port: 587
encryption: tls
user: 'ZOHO_EMAIL_ADDRESS'
password: 'ZOHO_EMAIL_PASSWORD'
```
#### Sendmail
Although not as reliable as SMTP not providing as much debug information, sendmail is a simple option as long as your hosting provider is not blocking the default SMTP port `25`:
+6 -3
View File
@@ -1,5 +1,7 @@
name: Email
version: 3.0.3
slug: email
type: plugin
version: 3.0.9
testing: false
description: Enables the emailing system for Grav
icon: envelope
@@ -18,6 +20,7 @@ dependencies:
form:
validation: loose
fields:
enabled:
type: hidden
@@ -168,13 +171,13 @@ form:
mailer.smtp.user:
type: text
size: medium
autocomplete: nope
autocomplete: 'off'
label: PLUGIN_EMAIL.SMTP_LOGIN_NAME
mailer.smtp.password:
type: password
size: medium
autocomplete: nope
autocomplete: 'new-password'
label: PLUGIN_EMAIL.SMTP_PASSWORD
sendmail_config:
+3 -2
View File
@@ -4,6 +4,7 @@ namespace Grav\Plugin\Email;
use Grav\Common\Config\Config;
use Grav\Common\Grav;
use Grav\Common\Language\Language;
use Grav\Common\Markdown\Parsedown;
use Grav\Common\Twig\Twig;
use Grav\Framework\Form\Interfaces\FormInterface;
use \Monolog\Logger;
@@ -178,7 +179,7 @@ class Email
$body = $twig->processString($value, $vars);
if ($params['process_markdown']) {
$parsedown = new \Parsedown();
$parsedown = new Parsedown();
$body = $parsedown->text($body);
}
@@ -202,7 +203,7 @@ class Email
$body = !empty($body_part['body']) ? $twig->processString($body_part['body'], $vars) : null;
if ($params['process_markdown']) {
$parsedown = new \Parsedown();
$parsedown = new Parsedown();
$body = $parsedown->text($body);
}
@@ -40,6 +40,11 @@ class ClearQueueFailuresCommand extends ConsoleCommand
*/
protected function serve()
{
// TODO: remove when requiring Grav 1.7+
if (method_exists($this, 'initializeGrav')) {
$this->initializeGrav();
}
$grav = Grav::instance();
$this->output->writeln('');
@@ -40,6 +40,11 @@ class FlushQueueCommand extends ConsoleCommand
*/
protected function serve()
{
// TODO: remove when requiring Grav 1.7+
if (method_exists($this, 'initializeGrav')) {
$this->initializeGrav();
}
$grav = Grav::instance();
$this->output->writeln('');
+5 -4
View File
@@ -59,6 +59,11 @@ class TestEmailCommand extends ConsoleCommand
*/
protected function serve()
{
// TODO: remove when requiring Grav 1.7+
if (method_exists($this, 'initializeGrav')) {
$this->initializeThemes();
}
$grav = Grav::instance();
$this->output->writeln('');
@@ -69,8 +74,6 @@ class TestEmailCommand extends ConsoleCommand
$this->output->writeln('');
require_once __DIR__ . '/../vendor/autoload.php';
$grav['Email'] = new Email();
$to = $this->input->getOption('to') ?: $grav['config']->get('plugins.email.to');
@@ -86,8 +89,6 @@ class TestEmailCommand extends ConsoleCommand
$body = $grav['language']->translate(['PLUGIN_EMAIL.TEST_EMAIL_BODY', $configuration]);
}
// This is the old way....
// $sent = EmailUtils::sendEmail($subject, $body, $email_to);
$sent = EmailUtils::sendEmail(['subject'=>$subject, 'body'=>$body, 'to'=>$to]);
if ($sent) {
+126 -60
View File
@@ -8,30 +8,35 @@
"packages": [
{
"name": "doctrine/lexer",
"version": "v1.0.1",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/lexer.git",
"reference": "83893c552fd2045dd78aef794c31e694c37c0b8c"
"reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c",
"reference": "83893c552fd2045dd78aef794c31e694c37c0b8c",
"url": "https://api.github.com/repos/doctrine/lexer/zipball/5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6",
"reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
"php": "^7.2"
},
"require-dev": {
"doctrine/coding-standard": "^6.0",
"phpstan/phpstan": "^0.11.8",
"phpunit/phpunit": "^8.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
"dev-master": "1.2.x-dev"
}
},
"autoload": {
"psr-0": {
"Doctrine\\Common\\Lexer\\": "lib/"
"psr-4": {
"Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -39,48 +44,52 @@
"MIT"
],
"authors": [
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
"homepage": "http://www.doctrine-project.org",
"description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
"homepage": "https://www.doctrine-project.org/projects/lexer.html",
"keywords": [
"annotations",
"docblock",
"lexer",
"parser"
"parser",
"php"
],
"time": "2014-09-09T13:34:57+00:00"
"time": "2019-10-30T14:39:59+00:00"
},
{
"name": "egulias/email-validator",
"version": "2.1.7",
"version": "2.1.17",
"source": {
"type": "git",
"url": "https://github.com/egulias/EmailValidator.git",
"reference": "709f21f92707308cdf8f9bcfa1af4cb26586521e"
"reference": "ade6887fd9bd74177769645ab5c474824f8a418a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/egulias/EmailValidator/zipball/709f21f92707308cdf8f9bcfa1af4cb26586521e",
"reference": "709f21f92707308cdf8f9bcfa1af4cb26586521e",
"url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ade6887fd9bd74177769645ab5c474824f8a418a",
"reference": "ade6887fd9bd74177769645ab5c474824f8a418a",
"shasum": ""
},
"require": {
"doctrine/lexer": "^1.0.1",
"php": ">= 5.5"
"php": ">=5.5",
"symfony/polyfill-intl-idn": "^1.10"
},
"require-dev": {
"dominicsayers/isemail": "dev-master",
"phpunit/phpunit": "^4.8.35||^5.7||^6.0",
"dominicsayers/isemail": "^3.0.7",
"phpunit/phpunit": "^4.8.36|^7.5.15",
"satooshi/php-coveralls": "^1.0.1"
},
"suggest": {
@@ -89,7 +98,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
"dev-master": "2.1.x-dev"
}
},
"autoload": {
@@ -115,20 +124,20 @@
"validation",
"validator"
],
"time": "2018-12-04T22:38:24+00:00"
"time": "2020-02-13T22:36:52+00:00"
},
{
"name": "swiftmailer/swiftmailer",
"version": "v6.2.0",
"version": "v6.2.3",
"source": {
"type": "git",
"url": "https://github.com/swiftmailer/swiftmailer.git",
"reference": "6fa3232ff9d3f8237c0fae4b7ff05e1baa4cd707"
"reference": "149cfdf118b169f7840bbe3ef0d4bc795d1780c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/6fa3232ff9d3f8237c0fae4b7ff05e1baa4cd707",
"reference": "6fa3232ff9d3f8237c0fae4b7ff05e1baa4cd707",
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/149cfdf118b169f7840bbe3ef0d4bc795d1780c9",
"reference": "149cfdf118b169f7840bbe3ef0d4bc795d1780c9",
"shasum": ""
},
"require": {
@@ -177,20 +186,20 @@
"mail",
"mailer"
],
"time": "2019-03-10T07:52:41+00:00"
"time": "2019-11-12T09:31:26+00:00"
},
{
"name": "symfony/polyfill-iconv",
"version": "v1.10.0",
"version": "v1.15.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-iconv.git",
"reference": "97001cfc283484c9691769f51cdf25259037eba2"
"reference": "ad6d62792bfbcfc385dd34b424d4fcf9712a32c8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/97001cfc283484c9691769f51cdf25259037eba2",
"reference": "97001cfc283484c9691769f51cdf25259037eba2",
"url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/ad6d62792bfbcfc385dd34b424d4fcf9712a32c8",
"reference": "ad6d62792bfbcfc385dd34b424d4fcf9712a32c8",
"shasum": ""
},
"require": {
@@ -202,7 +211,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
"dev-master": "1.15-dev"
}
},
"autoload": {
@@ -236,26 +245,40 @@
"portable",
"shim"
],
"time": "2018-09-21T06:26:08+00:00"
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-09T19:04:49+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.10.0",
"version": "v1.15.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "89de1d44f2c059b266f22c9cc9124ddc4cd0987a"
"reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/89de1d44f2c059b266f22c9cc9124ddc4cd0987a",
"reference": "89de1d44f2c059b266f22c9cc9124ddc4cd0987a",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf",
"reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"symfony/polyfill-mbstring": "^1.3",
"symfony/polyfill-php72": "^1.9"
"symfony/polyfill-php72": "^1.10"
},
"suggest": {
"ext-intl": "For best performance"
@@ -263,7 +286,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
"dev-master": "1.15-dev"
}
},
"autoload": {
@@ -279,13 +302,13 @@
"MIT"
],
"authors": [
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
},
{
"name": "Laurent Bassin",
"email": "laurent@bassin.info"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
@@ -298,20 +321,34 @@
"portable",
"shim"
],
"time": "2018-09-30T16:36:12+00:00"
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-09T19:04:49+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.10.0",
"version": "v1.15.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "c79c051f5b3a46be09205c73b80b346e4153e494"
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494",
"reference": "c79c051f5b3a46be09205c73b80b346e4153e494",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
"shasum": ""
},
"require": {
@@ -323,7 +360,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
"dev-master": "1.15-dev"
}
},
"autoload": {
@@ -357,20 +394,34 @@
"portable",
"shim"
],
"time": "2018-09-21T13:07:52+00:00"
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-09T19:04:49+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.10.0",
"version": "v1.15.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "9050816e2ca34a8e916c3a0ae8b9c2fccf68b631"
"reference": "37b0976c78b94856543260ce09b460a7bc852747"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9050816e2ca34a8e916c3a0ae8b9c2fccf68b631",
"reference": "9050816e2ca34a8e916c3a0ae8b9c2fccf68b631",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/37b0976c78b94856543260ce09b460a7bc852747",
"reference": "37b0976c78b94856543260ce09b460a7bc852747",
"shasum": ""
},
"require": {
@@ -379,7 +430,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
"dev-master": "1.15-dev"
}
},
"autoload": {
@@ -412,7 +463,21 @@
"portable",
"shim"
],
"time": "2018-09-21T13:07:52+00:00"
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-02-27T09:26:54+00:00"
}
],
"packages-dev": [],
@@ -424,5 +489,6 @@
"platform": {
"php": ">=7.1.3"
},
"platform-dev": []
"platform-dev": [],
"plugin-api-version": "1.1.0"
}
+24
View File
@@ -1,6 +1,7 @@
<?php
namespace Grav\Plugin;
use Grav\Common\Data\Data;
use Grav\Common\Plugin;
use Grav\Plugin\Email\Email;
use RocketTheme\Toolbox\Event\Event;
@@ -22,6 +23,7 @@ class EmailPlugin extends Plugin
'onFormProcessed' => ['onFormProcessed', 0],
'onTwigTemplatePaths' => ['onTwigTemplatePaths', 0],
'onSchedulerInitialized' => ['onSchedulerInitialized', 0],
'onAdminSave' => ['onAdminSave', 0],
];
}
@@ -48,6 +50,28 @@ class EmailPlugin extends Plugin
$twig->twig_paths[] = __DIR__ . '/templates';
}
/**
* Force compile during save if admin plugin save
*
* @param Event $event
*/
public function onAdminSave(Event $event)
{
/** @var Data $obj */
$obj = $event['object'];
if ($obj instanceof Data && $obj->blueprints()->getFilename() === 'email/blueprints') {
$current_pw = $this->grav['config']->get('plugins.email.mailer.smtp.password');
$new_pw = $obj->get('mailer.smtp.password');
if (!empty($current_pw) && empty($new_pw)) {
$obj->set('mailer.smtp.password', $current_pw);
}
}
}
/**
* Send email when processing the form data.
*
+2 -2
View File
@@ -279,7 +279,7 @@ class ClassLoader
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
@@ -377,7 +377,7 @@ class ClassLoader
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath.'\\';
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
+1 -1
View File
@@ -8,7 +8,7 @@ $baseDir = dirname($vendorDir);
return array(
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
'def43f6c87e4f8dfd0c9e1b1bab14fe8' => $vendorDir . '/symfony/polyfill-iconv/bootstrap.php',
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
'def43f6c87e4f8dfd0c9e1b1bab14fe8' => $vendorDir . '/symfony/polyfill-iconv/bootstrap.php',
'2c102faa651ef8ea5874edb585946bce' => $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php',
);
@@ -6,5 +6,4 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/lib'),
);
+1
View File
@@ -13,4 +13,5 @@ return array(
'Grav\\Plugin\\Email\\' => array($baseDir . '/classes'),
'Grav\\Plugin\\Console\\' => array($baseDir . '/cli'),
'Egulias\\EmailValidator\\' => array($vendorDir . '/egulias/email-validator/EmailValidator'),
'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/lib/Doctrine/Common/Lexer'),
);
+3
View File
@@ -13,6 +13,9 @@ class ComposerAutoloaderInitdec5d78def1384d1f20996ded9d7efbf
}
}
/**
* @return \Composer\Autoload\ClassLoader
*/
public static function getLoader()
{
if (null !== self::$loader) {
+7 -10
View File
@@ -9,8 +9,8 @@ class ComposerStaticInitdec5d78def1384d1f20996ded9d7efbf
public static $files = array (
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
'def43f6c87e4f8dfd0c9e1b1bab14fe8' => __DIR__ . '/..' . '/symfony/polyfill-iconv/bootstrap.php',
'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
'def43f6c87e4f8dfd0c9e1b1bab14fe8' => __DIR__ . '/..' . '/symfony/polyfill-iconv/bootstrap.php',
'2c102faa651ef8ea5874edb585946bce' => __DIR__ . '/..' . '/swiftmailer/swiftmailer/lib/swift_required.php',
);
@@ -31,6 +31,10 @@ class ComposerStaticInitdec5d78def1384d1f20996ded9d7efbf
array (
'Egulias\\EmailValidator\\' => 23,
),
'D' =>
array (
'Doctrine\\Common\\Lexer\\' => 22,
),
);
public static $prefixDirsPsr4 = array (
@@ -62,15 +66,9 @@ class ComposerStaticInitdec5d78def1384d1f20996ded9d7efbf
array (
0 => __DIR__ . '/..' . '/egulias/email-validator/EmailValidator',
),
);
public static $prefixesPsr0 = array (
'D' =>
'Doctrine\\Common\\Lexer\\' =>
array (
'Doctrine\\Common\\Lexer\\' =>
array (
0 => __DIR__ . '/..' . '/doctrine/lexer/lib',
),
0 => __DIR__ . '/..' . '/doctrine/lexer/lib/Doctrine/Common/Lexer',
),
);
@@ -83,7 +81,6 @@ class ComposerStaticInitdec5d78def1384d1f20996ded9d7efbf
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInitdec5d78def1384d1f20996ded9d7efbf::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitdec5d78def1384d1f20996ded9d7efbf::$prefixDirsPsr4;
$loader->prefixesPsr0 = ComposerStaticInitdec5d78def1384d1f20996ded9d7efbf::$prefixesPsr0;
$loader->classMap = ComposerStaticInitdec5d78def1384d1f20996ded9d7efbf::$classMap;
}, null, ClassLoader::class);
+131 -66
View File
@@ -1,33 +1,38 @@
[
{
"name": "doctrine/lexer",
"version": "v1.0.1",
"version_normalized": "1.0.1.0",
"version": "1.2.0",
"version_normalized": "1.2.0.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/lexer.git",
"reference": "83893c552fd2045dd78aef794c31e694c37c0b8c"
"reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c",
"reference": "83893c552fd2045dd78aef794c31e694c37c0b8c",
"url": "https://api.github.com/repos/doctrine/lexer/zipball/5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6",
"reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
"php": "^7.2"
},
"time": "2014-09-09T13:34:57+00:00",
"require-dev": {
"doctrine/coding-standard": "^6.0",
"phpstan/phpstan": "^0.11.8",
"phpunit/phpunit": "^8.2"
},
"time": "2019-10-30T14:39:59+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
"dev-master": "1.2.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-0": {
"Doctrine\\Common\\Lexer\\": "lib/"
"psr-4": {
"Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -35,58 +40,62 @@
"MIT"
],
"authors": [
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
"homepage": "http://www.doctrine-project.org",
"description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
"homepage": "https://www.doctrine-project.org/projects/lexer.html",
"keywords": [
"annotations",
"docblock",
"lexer",
"parser"
"parser",
"php"
]
},
{
"name": "egulias/email-validator",
"version": "2.1.7",
"version_normalized": "2.1.7.0",
"version": "2.1.17",
"version_normalized": "2.1.17.0",
"source": {
"type": "git",
"url": "https://github.com/egulias/EmailValidator.git",
"reference": "709f21f92707308cdf8f9bcfa1af4cb26586521e"
"reference": "ade6887fd9bd74177769645ab5c474824f8a418a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/egulias/EmailValidator/zipball/709f21f92707308cdf8f9bcfa1af4cb26586521e",
"reference": "709f21f92707308cdf8f9bcfa1af4cb26586521e",
"url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ade6887fd9bd74177769645ab5c474824f8a418a",
"reference": "ade6887fd9bd74177769645ab5c474824f8a418a",
"shasum": ""
},
"require": {
"doctrine/lexer": "^1.0.1",
"php": ">= 5.5"
"php": ">=5.5",
"symfony/polyfill-intl-idn": "^1.10"
},
"require-dev": {
"dominicsayers/isemail": "dev-master",
"phpunit/phpunit": "^4.8.35||^5.7||^6.0",
"dominicsayers/isemail": "^3.0.7",
"phpunit/phpunit": "^4.8.36|^7.5.15",
"satooshi/php-coveralls": "^1.0.1"
},
"suggest": {
"ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation"
},
"time": "2018-12-04T22:38:24+00:00",
"time": "2020-02-13T22:36:52+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
"dev-master": "2.1.x-dev"
}
},
"installation-source": "dist",
@@ -116,17 +125,17 @@
},
{
"name": "swiftmailer/swiftmailer",
"version": "v6.2.0",
"version_normalized": "6.2.0.0",
"version": "v6.2.3",
"version_normalized": "6.2.3.0",
"source": {
"type": "git",
"url": "https://github.com/swiftmailer/swiftmailer.git",
"reference": "6fa3232ff9d3f8237c0fae4b7ff05e1baa4cd707"
"reference": "149cfdf118b169f7840bbe3ef0d4bc795d1780c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/6fa3232ff9d3f8237c0fae4b7ff05e1baa4cd707",
"reference": "6fa3232ff9d3f8237c0fae4b7ff05e1baa4cd707",
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/149cfdf118b169f7840bbe3ef0d4bc795d1780c9",
"reference": "149cfdf118b169f7840bbe3ef0d4bc795d1780c9",
"shasum": ""
},
"require": {
@@ -144,7 +153,7 @@
"ext-intl": "Needed to support internationalized email addresses",
"true/punycode": "Needed to support internationalized email addresses, if ext-intl is not installed"
},
"time": "2019-03-10T07:52:41+00:00",
"time": "2019-11-12T09:31:26+00:00",
"type": "library",
"extra": {
"branch-alias": {
@@ -180,17 +189,17 @@
},
{
"name": "symfony/polyfill-iconv",
"version": "v1.10.0",
"version_normalized": "1.10.0.0",
"version": "v1.15.0",
"version_normalized": "1.15.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-iconv.git",
"reference": "97001cfc283484c9691769f51cdf25259037eba2"
"reference": "ad6d62792bfbcfc385dd34b424d4fcf9712a32c8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/97001cfc283484c9691769f51cdf25259037eba2",
"reference": "97001cfc283484c9691769f51cdf25259037eba2",
"url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/ad6d62792bfbcfc385dd34b424d4fcf9712a32c8",
"reference": "ad6d62792bfbcfc385dd34b424d4fcf9712a32c8",
"shasum": ""
},
"require": {
@@ -199,11 +208,11 @@
"suggest": {
"ext-iconv": "For best performance"
},
"time": "2018-09-21T06:26:08+00:00",
"time": "2020-03-09T19:04:49+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
"dev-master": "1.15-dev"
}
},
"installation-source": "dist",
@@ -237,36 +246,50 @@
"polyfill",
"portable",
"shim"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
]
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.10.0",
"version_normalized": "1.10.0.0",
"version": "v1.15.0",
"version_normalized": "1.15.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "89de1d44f2c059b266f22c9cc9124ddc4cd0987a"
"reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/89de1d44f2c059b266f22c9cc9124ddc4cd0987a",
"reference": "89de1d44f2c059b266f22c9cc9124ddc4cd0987a",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf",
"reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"symfony/polyfill-mbstring": "^1.3",
"symfony/polyfill-php72": "^1.9"
"symfony/polyfill-php72": "^1.10"
},
"suggest": {
"ext-intl": "For best performance"
},
"time": "2018-09-30T16:36:12+00:00",
"time": "2020-03-09T19:04:49+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
"dev-master": "1.15-dev"
}
},
"installation-source": "dist",
@@ -283,13 +306,13 @@
"MIT"
],
"authors": [
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
},
{
"name": "Laurent Bassin",
"email": "laurent@bassin.info"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
@@ -301,21 +324,35 @@
"polyfill",
"portable",
"shim"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
]
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.10.0",
"version_normalized": "1.10.0.0",
"version": "v1.15.0",
"version_normalized": "1.15.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "c79c051f5b3a46be09205c73b80b346e4153e494"
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494",
"reference": "c79c051f5b3a46be09205c73b80b346e4153e494",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
"shasum": ""
},
"require": {
@@ -324,11 +361,11 @@
"suggest": {
"ext-mbstring": "For best performance"
},
"time": "2018-09-21T13:07:52+00:00",
"time": "2020-03-09T19:04:49+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
"dev-master": "1.15-dev"
}
},
"installation-source": "dist",
@@ -362,31 +399,45 @@
"polyfill",
"portable",
"shim"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
]
},
{
"name": "symfony/polyfill-php72",
"version": "v1.10.0",
"version_normalized": "1.10.0.0",
"version": "v1.15.0",
"version_normalized": "1.15.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "9050816e2ca34a8e916c3a0ae8b9c2fccf68b631"
"reference": "37b0976c78b94856543260ce09b460a7bc852747"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9050816e2ca34a8e916c3a0ae8b9c2fccf68b631",
"reference": "9050816e2ca34a8e916c3a0ae8b9c2fccf68b631",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/37b0976c78b94856543260ce09b460a7bc852747",
"reference": "37b0976c78b94856543260ce09b460a7bc852747",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"time": "2018-09-21T13:07:52+00:00",
"time": "2020-02-27T09:26:54+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
"dev-master": "1.15-dev"
}
},
"installation-source": "dist",
@@ -419,6 +470,20 @@
"polyfill",
"portable",
"shim"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
]
}
]
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2006-2013 Doctrine Project
Copyright (c) 2006-2018 Doctrine Project
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
+4
View File
@@ -1,5 +1,9 @@
# Doctrine Lexer
Build Status: [![Build Status](https://travis-ci.org/doctrine/lexer.svg?branch=master)](https://travis-ci.org/doctrine/lexer)
Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.
This lexer is used in Doctrine Annotations and in Doctrine ORM (DQL).
https://www.doctrine-project.org/projects/lexer.html
+23 -6
View File
@@ -1,9 +1,15 @@
{
"name": "doctrine/lexer",
"type": "library",
"description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
"keywords": ["lexer", "parser"],
"homepage": "http://www.doctrine-project.org",
"description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
"keywords": [
"php",
"parser",
"lexer",
"annotations",
"docblock"
],
"homepage": "https://www.doctrine-project.org/projects/lexer.html",
"license": "MIT",
"authors": [
{"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"},
@@ -11,14 +17,25 @@
{"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"}
],
"require": {
"php": ">=5.3.2"
"php": "^7.2"
},
"require-dev": {
"doctrine/coding-standard": "^6.0",
"phpstan/phpstan": "^0.11.8",
"phpunit/phpunit": "^8.2"
},
"autoload": {
"psr-0": { "Doctrine\\Common\\Lexer\\": "lib/" }
"psr-4": { "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" }
},
"autoload-dev": {
"psr-4": { "Doctrine\\Tests\\": "tests/Doctrine" }
},
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
"dev-master": "1.2.x-dev"
}
},
"config": {
"sort-packages": true
}
}
@@ -1,31 +1,21 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
declare(strict_types=1);
namespace Doctrine\Common\Lexer;
use ReflectionClass;
use const PREG_SPLIT_DELIM_CAPTURE;
use const PREG_SPLIT_NO_EMPTY;
use const PREG_SPLIT_OFFSET_CAPTURE;
use function implode;
use function in_array;
use function preg_split;
use function sprintf;
use function substr;
/**
* Base class for writing simple lexers, i.e. for creating small DSLs.
*
* @since 2.0
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
abstract class AbstractLexer
{
@@ -47,36 +37,43 @@ abstract class AbstractLexer
*
* @var array
*/
private $tokens = array();
private $tokens = [];
/**
* Current lexer position in input string.
*
* @var integer
* @var int
*/
private $position = 0;
/**
* Current peek of current lexer position.
*
* @var integer
* @var int
*/
private $peek = 0;
/**
* The next token in the input.
*
* @var array
* @var array|null
*/
public $lookahead;
/**
* The last matched/seen token.
*
* @var array
* @var array|null
*/
public $token;
/**
* Composed regex for input parsing.
*
* @var string
*/
private $regex;
/**
* Sets the input data to be tokenized.
*
@@ -90,7 +87,7 @@ abstract class AbstractLexer
public function setInput($input)
{
$this->input = $input;
$this->tokens = array();
$this->tokens = [];
$this->reset();
$this->scan($input);
@@ -104,9 +101,9 @@ abstract class AbstractLexer
public function reset()
{
$this->lookahead = null;
$this->token = null;
$this->peek = 0;
$this->position = 0;
$this->token = null;
$this->peek = 0;
$this->position = 0;
}
/**
@@ -122,7 +119,7 @@ abstract class AbstractLexer
/**
* Resets the lexer position on the input to the given position.
*
* @param integer $position Position to place the lexical scanner.
* @param int $position Position to place the lexical scanner.
*
* @return void
*/
@@ -132,9 +129,9 @@ abstract class AbstractLexer
}
/**
* Retrieve the original lexer's input until a given position.
* Retrieve the original lexer's input until a given position.
*
* @param integer $position
* @param int $position
*
* @return string
*/
@@ -146,13 +143,13 @@ abstract class AbstractLexer
/**
* Checks whether a given token matches the current lookahead.
*
* @param integer|string $token
* @param int|string $token
*
* @return boolean
* @return bool
*/
public function isNextToken($token)
{
return null !== $this->lookahead && $this->lookahead['type'] === $token;
return $this->lookahead !== null && $this->lookahead['type'] === $token;
}
/**
@@ -160,23 +157,23 @@ abstract class AbstractLexer
*
* @param array $tokens
*
* @return boolean
* @return bool
*/
public function isNextTokenAny(array $tokens)
{
return null !== $this->lookahead && in_array($this->lookahead['type'], $tokens, true);
return $this->lookahead !== null && in_array($this->lookahead['type'], $tokens, true);
}
/**
* Moves to the next token in the input string.
*
* @return boolean
* @return bool
*/
public function moveNext()
{
$this->peek = 0;
$this->token = $this->lookahead;
$this->lookahead = (isset($this->tokens[$this->position]))
$this->peek = 0;
$this->token = $this->lookahead;
$this->lookahead = isset($this->tokens[$this->position])
? $this->tokens[$this->position++] : null;
return $this->lookahead !== null;
@@ -199,10 +196,10 @@ abstract class AbstractLexer
/**
* Checks if given value is identical to the given token.
*
* @param mixed $value
* @param integer $token
* @param mixed $value
* @param int|string $token
*
* @return boolean
* @return bool
*/
public function isA($value, $token)
{
@@ -218,9 +215,9 @@ abstract class AbstractLexer
{
if (isset($this->tokens[$this->position + $this->peek])) {
return $this->tokens[$this->position + $this->peek++];
} else {
return null;
}
return null;
}
/**
@@ -230,8 +227,9 @@ abstract class AbstractLexer
*/
public function glimpse()
{
$peek = $this->peek();
$peek = $this->peek();
$this->peek = 0;
return $peek;
}
@@ -244,10 +242,8 @@ abstract class AbstractLexer
*/
protected function scan($input)
{
static $regex;
if ( ! isset($regex)) {
$regex = sprintf(
if (! isset($this->regex)) {
$this->regex = sprintf(
'/(%s)|%s/%s',
implode(')|(', $this->getCatchablePatterns()),
implode('|', $this->getNonCatchablePatterns()),
@@ -255,32 +251,37 @@ abstract class AbstractLexer
);
}
$flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE;
$matches = preg_split($regex, $input, -1, $flags);
$flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE;
$matches = preg_split($this->regex, $input, -1, $flags);
if ($matches === false) {
// Work around https://bugs.php.net/78122
$matches = [[$input, 0]];
}
foreach ($matches as $match) {
// Must remain before 'value' assignment since it can change content
$type = $this->getType($match[0]);
$this->tokens[] = array(
$this->tokens[] = [
'value' => $match[0],
'type' => $type,
'position' => $match[1],
);
];
}
}
/**
* Gets the literal for a given token.
*
* @param integer $token
* @param int|string $token
*
* @return string
* @return int|string
*/
public function getLiteral($token)
{
$className = get_class($this);
$reflClass = new \ReflectionClass($className);
$className = static::class;
$reflClass = new ReflectionClass($className);
$constants = $reflClass->getConstants();
foreach ($constants as $name => $value) {
@@ -299,7 +300,7 @@ abstract class AbstractLexer
*/
protected function getModifiers()
{
return 'i';
return 'iu';
}
/**
@@ -321,7 +322,7 @@ abstract class AbstractLexer
*
* @param string $value
*
* @return integer
* @return int|string|null
*/
abstract protected function getType(&$value);
}
@@ -73,25 +73,73 @@ class EmailLexer extends AbstractLexer
'\0' => self::C_NUL,
);
/**
* @var bool
*/
protected $hasInvalidTokens = false;
protected $previous;
/**
* @var array
*
* @psalm-var array{value:string, type:null|int, position:int}|array<empty, empty>
*/
protected $previous = [];
/**
* The last matched/seen token.
*
* @var array
*
* @psalm-var array{value:string, type:null|int, position:int}
*/
public $token;
/**
* The next token in the input.
*
* @var array|null
*/
public $lookahead;
/**
* @psalm-var array{value:'', type:null, position:0}
*/
private static $nullToken = [
'value' => '',
'type' => null,
'position' => 0,
];
public function __construct()
{
$this->previous = $this->token = self::$nullToken;
$this->lookahead = null;
}
/**
* @return void
*/
public function reset()
{
$this->hasInvalidTokens = false;
parent::reset();
$this->previous = $this->token = self::$nullToken;
}
/**
* @return bool
*/
public function hasInvalidTokens()
{
return $this->hasInvalidTokens;
}
/**
* @param $type
* @param int $type
* @throws \UnexpectedValueException
* @return boolean
*
* @psalm-suppress InvalidScalarArgument
*/
public function find($type)
{
@@ -107,7 +155,7 @@ class EmailLexer extends AbstractLexer
/**
* getPrevious
*
* @return array token
* @return array
*/
public function getPrevious()
{
@@ -122,8 +170,10 @@ class EmailLexer extends AbstractLexer
public function moveNext()
{
$this->previous = $this->token;
$hasNext = parent::moveNext();
$this->token = $this->token ?: self::$nullToken;
return parent::moveNext();
return $hasNext;
}
/**
@@ -179,6 +229,11 @@ class EmailLexer extends AbstractLexer
return self::GENERIC;
}
/**
* @param string $value
*
* @return bool
*/
protected function isValid($value)
{
if (isset($this->charValue[$value])) {
@@ -189,7 +244,7 @@ class EmailLexer extends AbstractLexer
}
/**
* @param $value
* @param string $value
* @return bool
*/
protected function isNullType($value)
@@ -202,7 +257,7 @@ class EmailLexer extends AbstractLexer
}
/**
* @param $value
* @param string $value
* @return bool
*/
protected function isUTF8Invalid($value)
@@ -214,6 +269,9 @@ class EmailLexer extends AbstractLexer
return false;
}
/**
* @return string
*/
protected function getModifiers()
{
return 'iu';
@@ -17,11 +17,33 @@ class EmailParser
{
const EMAIL_MAX_LENGTH = 254;
protected $warnings;
/**
* @var array
*/
protected $warnings = [];
/**
* @var string
*/
protected $domainPart = '';
/**
* @var string
*/
protected $localPart = '';
/**
* @var EmailLexer
*/
protected $lexer;
/**
* @var LocalPart
*/
protected $localPartParser;
/**
* @var DomainPart
*/
protected $domainPartParser;
public function __construct(EmailLexer $lexer)
@@ -29,11 +51,10 @@ class EmailParser
$this->lexer = $lexer;
$this->localPartParser = new LocalPart($this->lexer);
$this->domainPartParser = new DomainPart($this->lexer);
$this->warnings = new \SplObjectStorage();
}
/**
* @param $str
* @param string $str
* @return array
*/
public function parse($str)
@@ -57,6 +78,9 @@ class EmailParser
return array('local' => $this->localPart, 'domain' => $this->domainPart);
}
/**
* @return Warning\Warning[]
*/
public function getWarnings()
{
$localPartWarnings = $this->localPartParser->getWarnings();
@@ -68,11 +92,17 @@ class EmailParser
return $this->warnings;
}
/**
* @return string
*/
public function getParsedDomainPart()
{
return $this->domainPart;
}
/**
* @param string $email
*/
protected function setParts($email)
{
$parts = explode('@', $email);
@@ -80,6 +110,9 @@ class EmailParser
$this->localPart = $parts[0];
}
/**
* @return bool
*/
protected function hasAtToken()
{
$this->lexer->moveNext();
@@ -13,12 +13,12 @@ class EmailValidator
private $lexer;
/**
* @var array
* @var Warning\Warning[]
*/
protected $warnings;
protected $warnings = [];
/**
* @var InvalidEmail
* @var InvalidEmail|null
*/
protected $error;
@@ -28,7 +28,7 @@ class EmailValidator
}
/**
* @param $email
* @param string $email
* @param EmailValidation $emailValidation
* @return bool
*/
@@ -58,7 +58,7 @@ class EmailValidator
}
/**
* @return InvalidEmail
* @return InvalidEmail|null
*/
public function getError()
{
@@ -2,7 +2,7 @@
namespace Egulias\EmailValidator\Exception;
class ExpectedQPair extends InvalidEmail
class ExpectingQPair extends InvalidEmail
{
const CODE = 136;
const REASON = "Expecting QPAIR";
@@ -2,8 +2,6 @@
namespace Egulias\EmailValidator\Exception;
use Egulias\EmailValidator\Exception\InvalidEmail;
class NoDNSRecord extends InvalidEmail
{
const CODE = 5;
@@ -35,27 +35,17 @@ use Egulias\EmailValidator\Warning\TLD;
class DomainPart extends Parser
{
const DOMAIN_MAX_LENGTH = 254;
/**
* @var string
*/
protected $domainPart = '';
public function parse($domainPart)
{
$this->lexer->moveNext();
if ($this->lexer->token['type'] === EmailLexer::S_DOT) {
throw new DotAtStart();
}
if ($this->lexer->token['type'] === EmailLexer::S_EMPTY) {
throw new NoDomainPart();
}
if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN) {
throw new DomainHyphened();
}
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
$this->warnings[DeprecatedComment::CODE] = new DeprecatedComment();
$this->parseDomainComments();
}
$this->performDomainStartChecks();
$domain = $this->doParseDomainPart();
@@ -77,11 +67,50 @@ class DomainPart extends Parser
$this->domainPart = $domain;
}
private function performDomainStartChecks()
{
$this->checkInvalidTokensAfterAT();
$this->checkEmptyDomain();
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
$this->warnings[DeprecatedComment::CODE] = new DeprecatedComment();
$this->parseDomainComments();
}
}
private function checkEmptyDomain()
{
$thereIsNoDomain = $this->lexer->token['type'] === EmailLexer::S_EMPTY ||
($this->lexer->token['type'] === EmailLexer::S_SP &&
!$this->lexer->isNextToken(EmailLexer::GENERIC));
if ($thereIsNoDomain) {
throw new NoDomainPart();
}
}
private function checkInvalidTokensAfterAT()
{
if ($this->lexer->token['type'] === EmailLexer::S_DOT) {
throw new DotAtStart();
}
if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN) {
throw new DomainHyphened();
}
}
/**
* @return string
*/
public function getDomainPart()
{
return $this->domainPart;
}
/**
* @param string $addressLiteral
* @param int $maxGroups
*/
public function checkIPV6Tag($addressLiteral, $maxGroups = 8)
{
$prev = $this->lexer->getPrevious();
@@ -125,6 +154,9 @@ class DomainPart extends Parser
}
}
/**
* @return string
*/
protected function doParseDomainPart()
{
$domain = '';
@@ -166,12 +198,12 @@ class DomainPart extends Parser
$domain .= $this->lexer->token['value'];
$this->lexer->moveNext();
} while ($this->lexer->token);
} while (null !== $this->lexer->token['type']);
return $domain;
}
private function checkNotAllowedChars($token)
private function checkNotAllowedChars(array $token)
{
$notAllowed = [EmailLexer::S_BACKSLASH => true, EmailLexer::S_SLASH=> true];
if (isset($notAllowed[$token['type']])) {
@@ -179,6 +211,9 @@ class DomainPart extends Parser
}
}
/**
* @return string|false
*/
protected function parseDomainLiteral()
{
if ($this->lexer->isNextToken(EmailLexer::S_COLON)) {
@@ -195,6 +230,9 @@ class DomainPart extends Parser
return $this->doParseDomainLiteral();
}
/**
* @return string|false
*/
protected function doParseDomainLiteral()
{
$IPv6TAG = false;
@@ -262,6 +300,11 @@ class DomainPart extends Parser
return $addressLiteral;
}
/**
* @param string $addressLiteral
*
* @return string|false
*/
protected function checkIPV4Tag($addressLiteral)
{
$matchesIP = array();
@@ -279,13 +322,13 @@ class DomainPart extends Parser
return false;
}
// Convert IPv4 part to IPv6 format for further testing
$addressLiteral = substr($addressLiteral, 0, $index) . '0:0';
$addressLiteral = substr($addressLiteral, 0, (int) $index) . '0:0';
}
return $addressLiteral;
}
protected function checkDomainPartExceptions($prev)
protected function checkDomainPartExceptions(array $prev)
{
$invalidDomainTokens = array(
EmailLexer::S_DQUOTE => true,
@@ -320,6 +363,9 @@ class DomainPart extends Parser
}
}
/**
* @return bool
*/
protected function hasBrackets()
{
if ($this->lexer->token['type'] !== EmailLexer::S_OPENBRACKET) {
@@ -335,7 +381,7 @@ class DomainPart extends Parser
return true;
}
protected function checkLabelLength($prev)
protected function checkLabelLength(array $prev)
{
if ($this->lexer->token['type'] === EmailLexer::S_DOT &&
$prev['type'] === EmailLexer::GENERIC &&
@@ -5,7 +5,6 @@ namespace Egulias\EmailValidator\Parser;
use Egulias\EmailValidator\Exception\DotAtEnd;
use Egulias\EmailValidator\Exception\DotAtStart;
use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\EmailValidator;
use Egulias\EmailValidator\Exception\ExpectingAT;
use Egulias\EmailValidator\Exception\ExpectingATEXT;
use Egulias\EmailValidator\Exception\UnclosedQuotedString;
@@ -20,9 +19,10 @@ class LocalPart extends Parser
$parseDQuote = true;
$closingQuote = false;
$openedParenthesis = 0;
$totalLength = 0;
while ($this->lexer->token['type'] !== EmailLexer::S_AT && $this->lexer->token) {
if ($this->lexer->token['type'] === EmailLexer::S_DOT && !$this->lexer->getPrevious()) {
while ($this->lexer->token['type'] !== EmailLexer::S_AT && null !== $this->lexer->token['type']) {
if ($this->lexer->token['type'] === EmailLexer::S_DOT && null === $this->lexer->getPrevious()['type']) {
throw new DotAtStart();
}
@@ -35,12 +35,13 @@ class LocalPart extends Parser
$this->parseComments();
$openedParenthesis += $this->getOpenedParenthesis();
}
if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) {
if ($openedParenthesis === 0) {
throw new UnopenedComment();
} else {
$openedParenthesis--;
}
$openedParenthesis--;
}
$this->checkConsecutiveDots();
@@ -58,15 +59,18 @@ class LocalPart extends Parser
$this->parseFWS();
}
$totalLength += strlen($this->lexer->token['value']);
$this->lexer->moveNext();
}
$prev = $this->lexer->getPrevious();
if (strlen($prev['value']) > LocalTooLong::LOCAL_PART_LENGTH) {
if ($totalLength > LocalTooLong::LOCAL_PART_LENGTH) {
$this->warnings[LocalTooLong::CODE] = new LocalTooLong();
}
}
/**
* @return bool
*/
protected function parseDoubleQuote()
{
$parseAgain = true;
@@ -86,7 +90,7 @@ class LocalPart extends Parser
$this->lexer->moveNext();
while ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE && $this->lexer->token) {
while ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE && null !== $this->lexer->token['type']) {
$parseAgain = false;
if (isset($special[$this->lexer->token['type']]) && $setSpecialsWarning) {
$this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS();
@@ -118,7 +122,10 @@ class LocalPart extends Parser
return $parseAgain;
}
protected function isInvalidToken($token, $closingQuote)
/**
* @param bool $closingQuote
*/
protected function isInvalidToken(array $token, $closingQuote)
{
$forbidden = array(
EmailLexer::S_COMMA,
@@ -8,7 +8,7 @@ use Egulias\EmailValidator\Exception\ConsecutiveDot;
use Egulias\EmailValidator\Exception\CRLFAtTheEnd;
use Egulias\EmailValidator\Exception\CRLFX2;
use Egulias\EmailValidator\Exception\CRNoLF;
use Egulias\EmailValidator\Exception\ExpectedQPair;
use Egulias\EmailValidator\Exception\ExpectingQPair;
use Egulias\EmailValidator\Exception\ExpectingATEXT;
use Egulias\EmailValidator\Exception\ExpectingCTEXT;
use Egulias\EmailValidator\Exception\UnclosedComment;
@@ -21,8 +21,19 @@ use Egulias\EmailValidator\Warning\QuotedString;
abstract class Parser
{
/**
* @var \Egulias\EmailValidator\Warning\Warning[]
*/
protected $warnings = [];
/**
* @var EmailLexer
*/
protected $lexer;
/**
* @var int
*/
protected $openedParenthesis = 0;
public function __construct(EmailLexer $lexer)
@@ -30,11 +41,17 @@ abstract class Parser
$this->lexer = $lexer;
}
/**
* @return \Egulias\EmailValidator\Warning\Warning[]
*/
public function getWarnings()
{
return $this->warnings;
}
/**
* @param string $str
*/
abstract public function parse($str);
/** @return int */
@@ -50,7 +67,7 @@ abstract class Parser
{
if (!($this->lexer->token['type'] === EmailLexer::INVALID
|| $this->lexer->token['type'] === EmailLexer::C_DEL)) {
throw new ExpectedQPair();
throw new ExpectingQPair();
}
$this->warnings[QuotedPart::CODE] =
@@ -80,6 +97,9 @@ abstract class Parser
}
}
/**
* @return bool
*/
protected function isUnclosedComment()
{
try {
@@ -122,6 +142,9 @@ abstract class Parser
}
}
/**
* @return bool
*/
protected function isFWS()
{
if ($this->escaped()) {
@@ -140,11 +163,14 @@ abstract class Parser
return false;
}
/**
* @return bool
*/
protected function escaped()
{
$previous = $this->lexer->getPrevious();
if ($previous['type'] === EmailLexer::S_BACKSLASH
if ($previous && $previous['type'] === EmailLexer::S_BACKSLASH
&&
$this->lexer->token['type'] !== EmailLexer::GENERIC
) {
@@ -154,6 +180,9 @@ abstract class Parser
return false;
}
/**
* @return bool
*/
protected function warnEscaping()
{
if ($this->lexer->token['type'] !== EmailLexer::S_BACKSLASH) {
@@ -174,6 +203,11 @@ abstract class Parser
}
/**
* @param bool $hasClosingQuote
*
* @return bool
*/
protected function checkDQUOTE($hasClosingQuote)
{
if ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE) {
@@ -15,13 +15,13 @@ class DNSCheckValidation implements EmailValidation
private $warnings = [];
/**
* @var InvalidEmail
* @var InvalidEmail|null
*/
private $error;
public function __construct()
{
if (!extension_loaded('intl')) {
if (!function_exists('idn_to_ascii')) {
throw new \LogicException(sprintf('The %s class requires the Intl extension.', __CLASS__));
}
}
@@ -49,6 +49,11 @@ class DNSCheckValidation implements EmailValidation
return $this->warnings;
}
/**
* @param string $host
*
* @return bool
*/
protected function checkDNS($host)
{
$variant = INTL_IDNA_VARIANT_2003;
@@ -6,6 +6,9 @@ use Exception;
class EmptyValidationList extends \InvalidArgumentException
{
/**
* @param int $code
*/
public function __construct($code = 0, Exception $previous = null)
{
parent::__construct("Empty validation list is not allowed", $code, $previous);
@@ -9,16 +9,22 @@ class MultipleErrors extends InvalidEmail
const CODE = 999;
const REASON = "Accumulated errors for multiple validations";
/**
* @var array
* @var InvalidEmail[]
*/
private $errors = [];
/**
* @param InvalidEmail[] $errors
*/
public function __construct(array $errors)
{
$this->errors = $errors;
parent::__construct();
}
/**
* @return InvalidEmail[]
*/
public function getErrors()
{
return $this->errors;
@@ -30,12 +30,12 @@ class MultipleValidationWithAnd implements EmailValidation
private $warnings = [];
/**
* @var MultipleErrors
* @var MultipleErrors|null
*/
private $error;
/**
* @var bool
* @var int
*/
private $mode;
@@ -79,6 +79,12 @@ class MultipleValidationWithAnd implements EmailValidation
return $result;
}
/**
* @param \Egulias\EmailValidator\Exception\InvalidEmail|null $possibleError
* @param \Egulias\EmailValidator\Exception\InvalidEmail[] $errors
*
* @return \Egulias\EmailValidator\Exception\InvalidEmail[]
*/
private function addNewError($possibleError, array $errors)
{
if (null !== $possibleError) {
@@ -88,13 +94,20 @@ class MultipleValidationWithAnd implements EmailValidation
return $errors;
}
/**
* @param bool $result
*
* @return bool
*/
private function shouldStop($result)
{
return !$result && $this->mode === self::STOP_ON_ERROR;
}
/**
* {@inheritdoc}
* Returns the validation errors.
*
* @return MultipleErrors|null
*/
public function getError()
{
@@ -9,7 +9,7 @@ use Egulias\EmailValidator\Validation\Error\RFCWarnings;
class NoRFCWarningsValidation extends RFCValidation
{
/**
* @var InvalidEmail
* @var InvalidEmail|null
*/
private $error;
@@ -9,7 +9,7 @@ use Egulias\EmailValidator\Exception\InvalidEmail;
class RFCValidation implements EmailValidation
{
/**
* @var EmailParser
* @var EmailParser|null
*/
private $parser;
@@ -19,7 +19,7 @@ class RFCValidation implements EmailValidation
private $warnings = [];
/**
* @var InvalidEmail
* @var InvalidEmail|null
*/
private $error;
@@ -10,7 +10,7 @@ use \Spoofchecker;
class SpoofCheckValidation implements EmailValidation
{
/**
* @var InvalidEmail
* @var InvalidEmail|null
*/
private $error;
@@ -21,6 +21,9 @@ class SpoofCheckValidation implements EmailValidation
}
}
/**
* @psalm-suppress InvalidArgument
*/
public function isValid($email, EmailLexer $emailLexer)
{
$checker = new Spoofchecker();
@@ -33,6 +36,9 @@ class SpoofCheckValidation implements EmailValidation
return $this->error === null;
}
/**
* @return InvalidEmail|null
*/
public function getError()
{
return $this->error;
@@ -6,6 +6,10 @@ class QuotedPart extends Warning
{
const CODE = 36;
/**
* @param scalar $prevToken
* @param scalar $postToken
*/
public function __construct($prevToken, $postToken)
{
$this->message = "Deprecated Quoted String found between $prevToken and $postToken";
@@ -6,6 +6,10 @@ class QuotedString extends Warning
{
const CODE = 11;
/**
* @param scalar $prevToken
* @param scalar $postToken
*/
public function __construct($prevToken, $postToken)
{
$this->message = "Quoted String found between $prevToken and $postToken";
@@ -5,19 +5,36 @@ namespace Egulias\EmailValidator\Warning;
abstract class Warning
{
const CODE = 0;
protected $message;
protected $rfcNumber;
/**
* @var string
*/
protected $message = '';
/**
* @var int
*/
protected $rfcNumber = 0;
/**
* @return string
*/
public function message()
{
return $this->message;
}
/**
* @return int
*/
public function code()
{
return self::CODE;
}
/**
* @return int
*/
public function RFCNumber()
{
return $this->rfcNumber;
@@ -1,5 +1,5 @@
# EmailValidator
[![Build Status](https://travis-ci.org/egulias/EmailValidator.png?branch=master)](https://travis-ci.org/egulias/EmailValidator) [![Coverage Status](https://coveralls.io/repos/egulias/EmailValidator/badge.png?branch=master)](https://coveralls.io/r/egulias/EmailValidator?branch=master) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/egulias/EmailValidator/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/egulias/EmailValidator/?branch=master) [![SensioLabsInsight](https://insight.sensiolabs.com/projects/22ba6692-9c02-42e5-a65d-1c5696bfffc6/small.png)](https://insight.sensiolabs.com/projects/22ba6692-9c02-42e5-a65d-1c5696bfffc6)
[![Build Status](https://travis-ci.org/egulias/EmailValidator.svg?branch=master)](https://travis-ci.org/egulias/EmailValidator) [![Coverage Status](https://coveralls.io/repos/egulias/EmailValidator/badge.svg?branch=master)](https://coveralls.io/r/egulias/EmailValidator?branch=master) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/egulias/EmailValidator/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/egulias/EmailValidator/?branch=master) [![SensioLabsInsight](https://insight.sensiolabs.com/projects/22ba6692-9c02-42e5-a65d-1c5696bfffc6/small.png)](https://insight.sensiolabs.com/projects/22ba6692-9c02-42e5-a65d-1c5696bfffc6)
=============================
## Suported RFCs ##
This library aims to support:
@@ -16,7 +16,7 @@ RFC 5321, 5322, 6530, 6531, 6532.
Run the command below to install via Composer
```shell
composer require egulias/email-validator "~2.1"
composer require egulias/email-validator
```
## Getting Started ##
@@ -2,7 +2,6 @@
"name": "egulias/email-validator",
"description": "A library for validating emails against several RFCs",
"homepage": "https://github.com/egulias/EmailValidator",
"type": "Library",
"keywords": ["email", "validation", "validator", "emailvalidation", "emailvalidator"],
"license": "MIT",
"authors": [
@@ -10,23 +9,18 @@
],
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
"dev-master": "2.1.x-dev"
}
},
"repositories": [
{
"type": "git",
"url": "https://github.com/dominicsayers/isemail"
}
],
"require": {
"php": ">= 5.5",
"doctrine/lexer": "^1.0.1"
"require": {
"php": ">=5.5",
"doctrine/lexer": "^1.0.1",
"symfony/polyfill-intl-idn": "^1.10"
},
"require-dev" : {
"require-dev": {
"satooshi/php-coveralls": "^1.0.1",
"phpunit/phpunit": "^4.8.35||^5.7||^6.0",
"dominicsayers/isemail": "dev-master"
"phpunit/phpunit": "^4.8.36|^7.5.15",
"dominicsayers/isemail": "^3.0.7"
},
"suggest": {
"ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation"
@@ -38,7 +32,7 @@
},
"autoload-dev": {
"psr-4": {
"Egulias\\Tests\\": "test"
"Egulias\\Tests\\": "Tests"
}
}
}
@@ -8,7 +8,6 @@
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="vendor/autoload.php"
>
<testsuites>
@@ -19,8 +18,8 @@
</testsuites>
<filter>
<blacklist>
<directory>./vendor</directory>
</blacklist>
<whitelist>
<directory>./EmailValidator/</directory>
</whitelist>
</filter>
</phpunit>
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="3.8.3@389af1bfc739bfdff3f9e3dc7bd6499aee51a831">
<file src="EmailValidator/EmailLexer.php">
<DocblockTypeContradiction occurrences="1">
<code>self::$nullToken</code>
</DocblockTypeContradiction>
</file>
<file src="EmailValidator/Parser/Parser.php">
<MissingReturnType occurrences="1">
<code>parse</code>
</MissingReturnType>
</file>
<file src="EmailValidator/Validation/SpoofCheckValidation.php">
<UndefinedClass occurrences="2">
<code>Spoofchecker</code>
<code>Spoofchecker</code>
</UndefinedClass>
</file>
</files>
@@ -0,0 +1,19 @@
<?xml version="1.0"?>
<psalm
requireVoidReturnType="false"
totallyTyped="false"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config ./vendor/vimeo/psalm/config.xsd"
errorBaseline="./psalm.baseline.xml"
>
<projectFiles>
<directory name="EmailValidator" />
<ignoreFiles>
<directory name="vendor" />
</ignoreFiles>
</projectFiles>
<issueHandlers>
</issueHandlers>
</psalm>
@@ -1,6 +1,22 @@
Changelog
=========
6.2.2 (2019-11-12)
------------------
* no changes
6.2.2 (2019-11-12)
------------------
* fixed cmopat with PHP 7.4
* fixed error message when connecting to a stream raises an error before connect()
6.2.1 (2019-04-21)
------------------
* reverted "deprecated Swift_CharacterStream_ArrayCharacterStream and Swift_CharacterStream_NgCharacterStream in favor of Swift_CharacterStream_CharacterStream"
6.2.0 (2019-03-10)
------------------
@@ -1,15 +0,0 @@
Swift Mailer
------------
Swift Mailer is a component based mailing solution for PHP 7.
It is released under the MIT license.
Homepage: https://swiftmailer.symfony.com/
Documentation: https://swiftmailer.symfony.com/docs/introduction.html
Bugs: https://github.com/swiftmailer/swiftmailer/issues
Repository: https://github.com/swiftmailer/swiftmailer
Swift Mailer is highly object-oriented by design and lends itself
to use in complex web application with a great deal of flexibility.
For full details on usage, see the documentation.
@@ -0,0 +1,19 @@
Swift Mailer
------------
Swift Mailer is a component based mailing solution for PHP 7.
It is released under the MIT license.
Swift Mailer is highly object-oriented by design and lends itself
to use in complex web application with a great deal of flexibility.
For full details on usage, read the [documentation](https://swiftmailer.symfony.com/docs/introduction.html).
Sponsors
--------
<div>
<a href="https://blackfire.io/docs/introduction?utm_source=swiftmailer&utm_medium=github_readme&utm_campaign=logo">
<img src="https://static.blackfire.io/assets/intemporals/logo/png/blackfire-io_secondary_horizontal_transparent.png?1" width="255px" alt="Blackfire.io">
</a>
</div>
@@ -520,9 +520,8 @@ Setting ``To:`` Recipients
or ``addTo()`` methods of the message.
To set ``To:`` recipients, create the message object using either ``new
Swift_Message( ... )`` or ``new Swift_Message( ... )``, then call the
``setTo()`` method with a complete array of addresses, or use the ``addTo()``
method to iteratively add recipients.
Swift_Message( ... )``, then call the ``setTo()`` method with a complete array
of addresses, or use the ``addTo()`` method to iteratively add recipients.
The ``setTo()`` method accepts input in various formats as described earlier in
this chapter. The ``addTo()`` method takes either one or two parameters. The
@@ -558,9 +557,8 @@ Setting ``Cc:`` Recipients
message.
To set ``Cc:`` recipients, create the message object using either ``new
Swift_Message( ... )`` or ``new Swift_Message( ... )``, then call the
``setCc()`` method with a complete array of addresses, or use the ``addCc()``
method to iteratively add recipients.
Swift_Message( ... )``, then call the ``setCc()`` method with a complete array
of addresses, or use the ``addCc()`` method to iteratively add recipients.
The ``setCc()`` method accepts input in various formats as described earlier in
this chapter. The ``addCc()`` method takes either one or two parameters. The
@@ -596,9 +594,8 @@ Setting ``Bcc:`` Recipients
it, and are set with the ``setBcc()`` or ``addBcc()`` methods of the message.
To set ``Bcc:`` recipients, create the message object using either ``new
Swift_Message( ... )`` or ``new Swift_Message( ... )``, then call the
``setBcc()`` method with a complete array of addresses, or use the ``addBcc()``
method to iteratively add recipients.
Swift_Message( ... )``, then call the ``setBcc()`` method with a complete array
of addresses, or use the ``addBcc()`` method to iteratively add recipients.
The ``setBcc()`` method accepts input in various formats as described earlier
in this chapter. The ``addBcc()`` method takes either one or two parameters.
@@ -15,7 +15,7 @@
*/
abstract class Swift
{
const VERSION = '6.2.0';
const VERSION = '6.2.3';
public static $initialized = false;
public static $inits = [];
@@ -8,8 +8,6 @@
* file that was distributed with this source code.
*/
@trigger_error(sprintf('The "%s" class is deprecated since Swiftmailer 6.2; use "%s" instead.', Swift_CharacterStream_ArrayCharacterStream::class, Swift_CharacterStream_CharacterStream::class), E_USER_DEPRECATED);
/**
* A CharacterStream implementation which stores characters in an internal array.
*
@@ -1,227 +0,0 @@
<?php
/*
* This file is part of SwiftMailer.
* (c) 2004-2009 Chris Corbyn
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* A CharacterStream implementation which stores characters in an internal array.
*
* @author Xavier De Cock <xdecock@gmail.com>
*/
class Swift_CharacterStream_CharacterStream implements Swift_CharacterStream
{
/**
* The char reader (lazy-loaded) for the current charset.
*
* @var Swift_CharacterReader
*/
private $charReader;
/**
* A factory for creating CharacterReader instances.
*
* @var Swift_CharacterReaderFactory
*/
private $charReaderFactory;
/**
* The character set this stream is using.
*
* @var string
*/
private $charset;
/**
* The data's stored as-is.
*
* @var string
*/
private $datas = '';
/**
* Number of bytes in the stream.
*
* @var int
*/
private $datasSize = 0;
/**
* Map.
*
* @var mixed
*/
private $map;
/**
* Map Type.
*
* @var int
*/
private $mapType = 0;
/**
* Number of characters in the stream.
*
* @var int
*/
private $charCount = 0;
/**
* Position in the stream.
*
* @var int
*/
private $currentPos = 0;
/**
* Constructor.
*
* @param string $charset
*/
public function __construct(Swift_CharacterReaderFactory $factory, $charset)
{
$this->setCharacterReaderFactory($factory);
$this->setCharacterSet($charset);
}
/* -- Changing parameters of the stream -- */
/**
* Set the character set used in this CharacterStream.
*
* @param string $charset
*/
public function setCharacterSet($charset)
{
$this->charset = $charset;
$this->charReader = null;
$this->mapType = 0;
}
/**
* Set the CharacterReaderFactory for multi charset support.
*/
public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory)
{
$this->charReaderFactory = $factory;
}
public function flushContents()
{
$this->datas = null;
$this->map = null;
$this->charCount = 0;
$this->currentPos = 0;
$this->datasSize = 0;
}
public function importByteStream(Swift_OutputByteStream $os)
{
$this->flushContents();
$blocks = 512;
$os->setReadPointer(0);
while (false !== ($read = $os->read($blocks))) {
$this->write($read);
}
}
public function importString($string)
{
$this->flushContents();
$this->write($string);
}
public function read($length)
{
if ($this->currentPos >= $this->charCount) {
return false;
}
$ret = false;
$length = ($this->currentPos + $length > $this->charCount) ? $this->charCount - $this->currentPos : $length;
switch ($this->mapType) {
case Swift_CharacterReader::MAP_TYPE_FIXED_LEN:
$len = $length * $this->map;
$ret = substr($this->datas,
$this->currentPos * $this->map,
$len);
$this->currentPos += $length;
break;
case Swift_CharacterReader::MAP_TYPE_INVALID:
$ret = '';
for (; $this->currentPos < $length; ++$this->currentPos) {
if (isset($this->map[$this->currentPos])) {
$ret .= '?';
} else {
$ret .= $this->datas[$this->currentPos];
}
}
break;
case Swift_CharacterReader::MAP_TYPE_POSITIONS:
$end = $this->currentPos + $length;
$end = $end > $this->charCount ? $this->charCount : $end;
$ret = '';
$start = 0;
if ($this->currentPos > 0) {
$start = $this->map['p'][$this->currentPos - 1];
}
$to = $start;
for (; $this->currentPos < $end; ++$this->currentPos) {
if (isset($this->map['i'][$this->currentPos])) {
$ret .= substr($this->datas, $start, $to - $start).'?';
$start = $this->map['p'][$this->currentPos];
} else {
$to = $this->map['p'][$this->currentPos];
}
}
$ret .= substr($this->datas, $start, $to - $start);
break;
}
return $ret;
}
public function readBytes($length)
{
$read = $this->read($length);
if (false !== $read) {
$ret = array_map('ord', str_split($read, 1));
return $ret;
}
return false;
}
public function setPointer($charOffset)
{
if ($this->charCount < $charOffset) {
$charOffset = $this->charCount;
}
$this->currentPos = $charOffset;
}
public function write($chars)
{
if (!isset($this->charReader)) {
$this->charReader = $this->charReaderFactory->getReaderFor(
$this->charset);
$this->map = [];
$this->mapType = $this->charReader->getMapType();
}
$ignored = '';
$this->datas .= $chars;
$this->charCount += $this->charReader->getCharPositions(substr($this->datas, $this->datasSize), $this->datasSize, $this->map, $ignored);
if (false !== $ignored) {
$this->datasSize = strlen($this->datas) - strlen($ignored);
} else {
$this->datasSize = strlen($this->datas);
}
}
}
@@ -8,13 +8,255 @@
* file that was distributed with this source code.
*/
@trigger_error(sprintf('The "%s" class is deprecated since Swiftmailer 6.2; use "%s" instead.', Swift_CharacterStream_NgCharacterStream::class, Swift_CharacterStream_CharacterStream::class), E_USER_DEPRECATED);
/**
* A CharacterStream implementation which stores characters in an internal array.
*
* @author Xavier De Cock <xdecock@gmail.com>
*/
class Swift_CharacterStream_NgCharacterStream extends Swift_CharacterStream_CharacterStream
class Swift_CharacterStream_NgCharacterStream implements Swift_CharacterStream
{
/**
* The char reader (lazy-loaded) for the current charset.
*
* @var Swift_CharacterReader
*/
private $charReader;
/**
* A factory for creating CharacterReader instances.
*
* @var Swift_CharacterReaderFactory
*/
private $charReaderFactory;
/**
* The character set this stream is using.
*
* @var string
*/
private $charset;
/**
* The data's stored as-is.
*
* @var string
*/
private $datas = '';
/**
* Number of bytes in the stream.
*
* @var int
*/
private $datasSize = 0;
/**
* Map.
*
* @var mixed
*/
private $map;
/**
* Map Type.
*
* @var int
*/
private $mapType = 0;
/**
* Number of characters in the stream.
*
* @var int
*/
private $charCount = 0;
/**
* Position in the stream.
*
* @var int
*/
private $currentPos = 0;
/**
* Constructor.
*
* @param string $charset
*/
public function __construct(Swift_CharacterReaderFactory $factory, $charset)
{
$this->setCharacterReaderFactory($factory);
$this->setCharacterSet($charset);
}
/* -- Changing parameters of the stream -- */
/**
* Set the character set used in this CharacterStream.
*
* @param string $charset
*/
public function setCharacterSet($charset)
{
$this->charset = $charset;
$this->charReader = null;
$this->mapType = 0;
}
/**
* Set the CharacterReaderFactory for multi charset support.
*/
public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory)
{
$this->charReaderFactory = $factory;
}
/**
* @see Swift_CharacterStream::flushContents()
*/
public function flushContents()
{
$this->datas = null;
$this->map = null;
$this->charCount = 0;
$this->currentPos = 0;
$this->datasSize = 0;
}
/**
* @see Swift_CharacterStream::importByteStream()
*/
public function importByteStream(Swift_OutputByteStream $os)
{
$this->flushContents();
$blocks = 512;
$os->setReadPointer(0);
while (false !== ($read = $os->read($blocks))) {
$this->write($read);
}
}
/**
* @see Swift_CharacterStream::importString()
*
* @param string $string
*/
public function importString($string)
{
$this->flushContents();
$this->write($string);
}
/**
* @see Swift_CharacterStream::read()
*
* @param int $length
*
* @return string
*/
public function read($length)
{
if ($this->currentPos >= $this->charCount) {
return false;
}
$ret = false;
$length = ($this->currentPos + $length > $this->charCount) ? $this->charCount - $this->currentPos : $length;
switch ($this->mapType) {
case Swift_CharacterReader::MAP_TYPE_FIXED_LEN:
$len = $length * $this->map;
$ret = substr($this->datas,
$this->currentPos * $this->map,
$len);
$this->currentPos += $length;
break;
case Swift_CharacterReader::MAP_TYPE_INVALID:
$ret = '';
for (; $this->currentPos < $length; ++$this->currentPos) {
if (isset($this->map[$this->currentPos])) {
$ret .= '?';
} else {
$ret .= $this->datas[$this->currentPos];
}
}
break;
case Swift_CharacterReader::MAP_TYPE_POSITIONS:
$end = $this->currentPos + $length;
$end = $end > $this->charCount ? $this->charCount : $end;
$ret = '';
$start = 0;
if ($this->currentPos > 0) {
$start = $this->map['p'][$this->currentPos - 1];
}
$to = $start;
for (; $this->currentPos < $end; ++$this->currentPos) {
if (isset($this->map['i'][$this->currentPos])) {
$ret .= substr($this->datas, $start, $to - $start).'?';
$start = $this->map['p'][$this->currentPos];
} else {
$to = $this->map['p'][$this->currentPos];
}
}
$ret .= substr($this->datas, $start, $to - $start);
break;
}
return $ret;
}
/**
* @see Swift_CharacterStream::readBytes()
*
* @param int $length
*
* @return int[]
*/
public function readBytes($length)
{
$read = $this->read($length);
if (false !== $read) {
$ret = array_map('ord', str_split($read, 1));
return $ret;
}
return false;
}
/**
* @see Swift_CharacterStream::setPointer()
*
* @param int $charOffset
*/
public function setPointer($charOffset)
{
if ($this->charCount < $charOffset) {
$charOffset = $this->charCount;
}
$this->currentPos = $charOffset;
}
/**
* @see Swift_CharacterStream::write()
*
* @param string $chars
*/
public function write($chars)
{
if (!isset($this->charReader)) {
$this->charReader = $this->charReaderFactory->getReaderFor(
$this->charset);
$this->map = [];
$this->mapType = $this->charReader->getMapType();
}
$ignored = '';
$this->datas .= $chars;
$this->charCount += $this->charReader->getCharPositions(substr($this->datas, $this->datasSize), $this->datasSize, $this->map, $ignored);
if (false !== $ignored) {
$this->datasSize = strlen($this->datas) - strlen($ignored);
} else {
$this->datasSize = strlen($this->datas);
}
}
}
@@ -264,13 +264,16 @@ class Swift_Transport_StreamBuffer extends Swift_ByteStream_AbstractFilterableIn
$options = array_merge($options, $this->params['stream_context_options']);
}
$streamContext = stream_context_create($options);
$this->stream = @stream_socket_client($host.':'.$this->params['port'], $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $streamContext);
if (false === $this->stream) {
throw new Swift_TransportException(
'Connection could not be established with host '.$this->params['host'].
' ['.$errstr.' #'.$errno.']'
);
set_error_handler(function ($type, $msg) {
throw new Swift_TransportException('Connection could not be established with host '.$this->params['host'].' :'.$msg);
});
try {
$this->stream = stream_socket_client($host.':'.$this->params['port'], $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $streamContext);
} finally {
restore_error_handler();
}
if (!empty($this->params['blocking'])) {
stream_set_blocking($this->stream, 1);
} else {
@@ -84,7 +84,7 @@ Swift_DependencyContainer::getInstance()
->withDependencies(['mime.charstream'])
->register('mime.charstream')
->asNewInstanceOf('Swift_CharacterStream_CharacterStream')
->asNewInstanceOf('Swift_CharacterStream_NgCharacterStream')
->withDependencies(['mime.characterreaderfactory', 'properties.charset'])
->register('mime.bytecanonicalizer')
@@ -173,7 +173,7 @@ function generateUpToDateMimeArray()
ksort($valid_mime_types);
// combine mime types and extensions array
$output = "$preamble\$swift_mime_types = array(\n ".implode($valid_mime_types, ",\n ")."\n);";
$output = "$preamble\$swift_mime_types = array(\n ".implode(",\n ", $valid_mime_types)."\n);";
// write mime_types.php config file
@file_put_contents('./mime_types.php', $output);
@@ -20,7 +20,7 @@ class Swift_Encoder_QpEncoderAcceptanceTest extends \PHPUnit\Framework\TestCase
}
$encoding = $encodingDir;
$charStream = new Swift_CharacterStream_CharacterStream(
$charStream = new Swift_CharacterStream_ArrayCharacterStream(
$this->factory, $encoding);
$encoder = new Swift_Encoder_QpEncoder($charStream);
@@ -20,7 +20,7 @@ class Swift_Encoder_Rfc2231EncoderAcceptanceTest extends \PHPUnit\Framework\Test
}
$encoding = $encodingDir;
$charStream = new Swift_CharacterStream_CharacterStream(
$charStream = new Swift_CharacterStream_ArrayCharacterStream(
$this->factory, $encoding);
$encoder = new Swift_Encoder_Rfc2231Encoder($charStream);
@@ -18,10 +18,10 @@ class Swift_Mime_AttachmentAcceptanceTest extends \PHPUnit\Framework\TestCase
$this->contentEncoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder();
$headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(
new Swift_CharacterStream_CharacterStream($factory, 'utf-8')
new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
);
$paramEncoder = new Swift_Encoder_Rfc2231Encoder(
new Swift_CharacterStream_CharacterStream($factory, 'utf-8')
new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
);
$this->emailValidator = new EmailValidator();
$this->idGenerator = new Swift_Mime_IdGenerator('example.com');
@@ -25,7 +25,7 @@ class Swift_Mime_ContentEncoder_QpContentEncoderAcceptanceTest extends \PHPUnit\
}
$encoding = $encodingDir;
$charStream = new Swift_CharacterStream_CharacterStream(
$charStream = new Swift_CharacterStream_NgCharacterStream(
$this->factory, $encoding);
$encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream);
@@ -18,10 +18,10 @@ class Swift_Mime_EmbeddedFileAcceptanceTest extends \PHPUnit\Framework\TestCase
$this->contentEncoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder();
$headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(
new Swift_CharacterStream_CharacterStream($factory, 'utf-8')
new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
);
$paramEncoder = new Swift_Encoder_Rfc2231Encoder(
new Swift_CharacterStream_CharacterStream($factory, 'utf-8')
new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
);
$this->emailValidator = new EmailValidator();
$this->idGenerator = new Swift_Mime_IdGenerator('example.com');
@@ -16,7 +16,7 @@ class Swift_Mime_MimePartAcceptanceTest extends \PHPUnit\Framework\TestCase
);
$factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
$this->contentEncoder = new Swift_Mime_ContentEncoder_QpContentEncoder(
new Swift_CharacterStream_CharacterStream($factory, 'utf-8'),
new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'),
new Swift_StreamFilters_ByteArrayReplacementFilter(
[[0x0D, 0x0A], [0x0D], [0x0A]],
[[0x0A], [0x0A], [0x0D, 0x0A]]
@@ -24,10 +24,10 @@ class Swift_Mime_MimePartAcceptanceTest extends \PHPUnit\Framework\TestCase
);
$headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(
new Swift_CharacterStream_CharacterStream($factory, 'utf-8')
new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
);
$paramEncoder = new Swift_Encoder_Rfc2231Encoder(
new Swift_CharacterStream_CharacterStream($factory, 'utf-8')
new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
);
$this->emailValidator = new EmailValidator();
$this->idGenerator = new Swift_Mime_IdGenerator('example.com');
@@ -10,10 +10,10 @@ class Swift_Bug206Test extends \PHPUnit\Framework\TestCase
{
$factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
$headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(
new Swift_CharacterStream_CharacterStream($factory, 'utf-8')
new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
);
$paramEncoder = new Swift_Encoder_Rfc2231Encoder(
new Swift_CharacterStream_CharacterStream($factory, 'utf-8')
new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
);
$emailValidator = new EmailValidator();
$this->factory = new Swift_Mime_SimpleHeaderFactory($headerEncoder, $paramEncoder, $emailValidator);
@@ -13,7 +13,7 @@ class Swift_Bug650Test extends \PHPUnit\Framework\TestCase
public function testMailboxHeaderEncoding($name, $expectedEncodedName)
{
$factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
$charStream = new Swift_CharacterStream_CharacterStream($factory, 'utf-8');
$charStream = new Swift_CharacterStream_NgCharacterStream($factory, 'utf-8');
$encoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder($charStream);
$header = new Swift_Mime_Headers_MailboxHeader('To', $encoder, new EmailValidator());
$header->setCharset('utf-8');
@@ -1,8 +1,5 @@
<?php
/**
* @group legacy
*/
class Swift_CharacterStream_ArrayCharacterStreamTest extends \SwiftMailerTestCase
{
public function testValidatorAlgorithmOnImportString()
@@ -393,7 +393,7 @@ class Swift_Encoder_QpEncoderTest extends \SwiftMailerTestCase
private function createEncoder()
{
$factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
$charStream = new Swift_CharacterStream_CharacterStream($factory, 'utf-8');
$charStream = new Swift_CharacterStream_NgCharacterStream($factory, 'utf-8');
return new Swift_Encoder_QpEncoder($charStream);
}
@@ -499,7 +499,7 @@ class Swift_Mime_ContentEncoder_QpContentEncoderTest extends \SwiftMailerTestCas
private function createEncoder()
{
$factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
$charStream = new Swift_CharacterStream_CharacterStream($factory, 'utf-8');
$charStream = new Swift_CharacterStream_NgCharacterStream($factory, 'utf-8');
return new Swift_Mime_ContentEncoder_QpContentEncoder($charStream);
}
@@ -147,8 +147,8 @@ class Swift_Signers_DKIMSignerTest extends \SwiftMailerTestCase
$factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
$contentEncoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder();
$headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(new Swift_CharacterStream_CharacterStream($factory, 'utf-8'));
$paramEncoder = new Swift_Encoder_Rfc2231Encoder(new Swift_CharacterStream_CharacterStream($factory, 'utf-8'));
$headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'));
$paramEncoder = new Swift_Encoder_Rfc2231Encoder(new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'));
$emailValidator = new EmailValidator();
$headers = new Swift_Mime_SimpleHeaderSet(new Swift_Mime_SimpleHeaderFactory($headerEncoder, $paramEncoder, $emailValidator));
@@ -165,8 +165,8 @@ class Swift_Signers_DKIMSignerTest extends \SwiftMailerTestCase
$factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
$contentEncoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder();
$headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(new Swift_CharacterStream_CharacterStream($factory, 'utf-8'));
$paramEncoder = new Swift_Encoder_Rfc2231Encoder(new Swift_CharacterStream_CharacterStream($factory, 'utf-8'));
$headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'));
$paramEncoder = new Swift_Encoder_Rfc2231Encoder(new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'));
$emailValidator = new EmailValidator();
$headerFactory = new Swift_Mime_SimpleHeaderFactory($headerEncoder, $paramEncoder, $emailValidator);
$headers = $this->getMockery('Swift_Mime_SimpleHeaderSet');
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2015-2018 Fabien Potencier
Copyright (c) 2015-2019 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+2 -2
View File
@@ -2,8 +2,8 @@ Symfony Polyfill / Iconv
========================
This component provides a native PHP implementation of the
[php.net/iconv](http://php.net/iconv) functions
(short of [`ob_iconv_handler`](http://php.net/manual/en/function.ob-iconv-handler.php)).
[php.net/iconv](https://php.net/iconv) functions
(short of [`ob_iconv_handler`](https://php.net/ob-iconv-handler)).
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
@@ -866,6 +866,7 @@ static $data = array (
'㋼' => '(ヰ)',
'㋽' => '(ヱ)',
'㋾' => '(ヲ)',
'㋿' => '令和',
'㌀' => 'アパート',
'㌁' => 'アルファ',
'㌂' => 'アンペア',
@@ -3133,6 +3134,7 @@ static $data = array (
'🈸' => '申',
'🈹' => '割',
'🈺' => '営',
'🈻' => '配',
'🉀' => '〔本〕',
'🉁' => '〔三〕',
'🉂' => '〔二〕',
@@ -3878,6 +3880,104 @@ static $data = array (
'ỽ' => 'v',
'Ỿ' => 'Y',
'ỿ' => 'y',
'Ⱡ' => 'L',
'ⱡ' => 'l',
'Ɫ' => 'L',
'Ᵽ' => 'P',
'Ɽ' => 'R',
'ⱥ' => 'a',
'ⱦ' => 't',
'Ⱨ' => 'H',
'ⱨ' => 'h',
'Ⱪ' => 'K',
'ⱪ' => 'k',
'Ⱬ' => 'Z',
'ⱬ' => 'z',
'Ɱ' => 'M',
'ⱱ' => 'v',
'Ⱳ' => 'W',
'ⱳ' => 'w',
'ⱴ' => 'v',
'ⱸ' => 'e',
'ⱺ' => 'o',
'Ȿ' => 'S',
'Ɀ' => 'Z',
'ꜰ' => 'F',
'' => 'S',
'Ꜳ' => 'AA',
'ꜳ' => 'aa',
'Ꜵ' => 'AO',
'ꜵ' => 'ao',
'Ꜷ' => 'AU',
'ꜷ' => 'au',
'Ꜹ' => 'AV',
'ꜹ' => 'av',
'Ꜻ' => 'AV',
'ꜻ' => 'av',
'Ꜽ' => 'AY',
'ꜽ' => 'ay',
'Ꝁ' => 'K',
'ꝁ' => 'k',
'Ꝃ' => 'K',
'ꝃ' => 'k',
'Ꝅ' => 'K',
'ꝅ' => 'k',
'Ꝇ' => 'L',
'ꝇ' => 'l',
'Ꝉ' => 'L',
'ꝉ' => 'l',
'Ꝋ' => 'O',
'ꝋ' => 'o',
'Ꝍ' => 'O',
'ꝍ' => 'o',
'Ꝏ' => 'OO',
'ꝏ' => 'oo',
'Ꝑ' => 'P',
'ꝑ' => 'p',
'Ꝓ' => 'P',
'ꝓ' => 'p',
'Ꝕ' => 'P',
'ꝕ' => 'p',
'Ꝗ' => 'Q',
'ꝗ' => 'q',
'Ꝙ' => 'Q',
'ꝙ' => 'q',
'Ꝟ' => 'V',
'ꝟ' => 'v',
'Ꝡ' => 'VY',
'ꝡ' => 'vy',
'Ꝥ' => 'TH',
'ꝥ' => 'th',
'Ꝧ' => 'TH',
'ꝧ' => 'th',
'ꝱ' => 'd',
'ꝲ' => 'l',
'ꝳ' => 'm',
'ꝴ' => 'n',
'ꝵ' => 'r',
'ꝶ' => 'R',
'ꝷ' => 't',
'Ꝺ' => 'D',
'ꝺ' => 'd',
'Ꝼ' => 'F',
'ꝼ' => 'f',
'Ꞇ' => 'T',
'ꞇ' => 't',
'Ꞑ' => 'N',
'ꞑ' => 'n',
'Ꞓ' => 'C',
'ꞓ' => 'c',
'Ꞡ' => 'G',
'ꞡ' => 'g',
'Ꞣ' => 'K',
'ꞣ' => 'k',
'Ꞥ' => 'N',
'ꞥ' => 'n',
'Ꞧ' => 'R',
'ꞧ' => 'r',
'Ꞩ' => 'S',
'ꞩ' => 's',
'Ɦ' => 'H',
'©' => '(C)',
'®' => '(R)',
'₠' => 'CE',
@@ -3887,8 +3987,28 @@ static $data = array (
'₧' => 'Pts',
'₺' => 'TL',
'₹' => 'Rs',
'℗' => '(P)',
'℘' => 'P',
'℞' => 'Rx',
'' => '0',
' ' => ' ',
'' => ' ',
'' => ' ',
'' => ' ',
'' => ' ',
'' => ' ',
'' => ' ',
'' => ' ',
'' => ' ',
'' => ' ',
'' => ' ',
'ʹ' => '\'',
'ʺ' => '"',
'ʻ' => '\'',
'ʼ' => '\'',
'ʽ' => '\'',
'ˈ' => '\'',
'ˋ' => '`',
'' => '\'',
'' => '\'',
'' => ',',
@@ -3904,6 +4024,7 @@ static $data = array (
'»' => '>>',
'' => '<',
'' => '>',
'­' => '-',
'' => '-',
'' => '-',
'' => '-',
@@ -3912,6 +4033,12 @@ static $data = array (
'―' => '-',
'︱' => '-',
'︲' => '-',
'˂' => '<',
'˃' => '>',
'˄' => '^',
'ˆ' => '^',
'ː' => ':',
'˜' => '~',
'‖' => '||',
'' => '/',
'⁅' => '[',
@@ -3952,6 +4079,8 @@ static $data = array (
'﹈' => ']',
'×' => '*',
'÷' => '/',
'˖' => '+',
'˗' => '-',
'' => '-',
'' => '/',
'' => '\\',
@@ -11,12 +11,14 @@
use Symfony\Polyfill\Iconv as p;
if (!function_exists('iconv')) {
if (!defined('ICONV_IMPL')) {
define('ICONV_IMPL', 'Symfony');
define('ICONV_VERSION', '1.0');
define('ICONV_MIME_DECODE_STRICT', 1);
define('ICONV_MIME_DECODE_CONTINUE_ON_ERROR', 2);
}
if (!function_exists('iconv')) {
function iconv($from, $to, $s) { return p\Iconv::iconv($from, $to, $s); }
function iconv_get_encoding($type = 'all') { return p\Iconv::iconv_get_encoding($type); }
function iconv_set_encoding($type, $charset) { return p\Iconv::iconv_set_encoding($type, $charset); }
@@ -28,7 +28,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
"dev-master": "1.15-dev"
}
}
}
@@ -43,6 +43,9 @@ namespace Symfony\Polyfill\Intl\Idn;
*/
final class Idn
{
const INTL_IDNA_VARIANT_2003 = 0;
const INTL_IDNA_VARIANT_UTS46 = 1;
private static $encodeTable = array(
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
@@ -60,18 +63,18 @@ final class Idn
public static function idn_to_ascii($domain, $options, $variant, &$idna_info = array())
{
if (\PHP_VERSION_ID >= 70200 && INTL_IDNA_VARIANT_2003 === $variant) {
if (\PHP_VERSION_ID >= 70200 && self::INTL_IDNA_VARIANT_2003 === $variant) {
@trigger_error('idn_to_ascii(): INTL_IDNA_VARIANT_2003 is deprecated', E_USER_DEPRECATED);
}
if (INTL_IDNA_VARIANT_UTS46 === $variant) {
if (self::INTL_IDNA_VARIANT_UTS46 === $variant) {
$domain = mb_strtolower($domain, 'utf-8');
}
$parts = explode('.', $domain);
foreach ($parts as &$part) {
if ('' === $part) {
foreach ($parts as $i => &$part) {
if ('' === $part && \count($parts) > 1 + $i) {
return false;
}
if (false === $part = self::encodePart($part)) {
@@ -92,7 +95,7 @@ final class Idn
public static function idn_to_utf8($domain, $options, $variant, &$idna_info = array())
{
if (\PHP_VERSION_ID >= 70200 && INTL_IDNA_VARIANT_2003 === $variant) {
if (\PHP_VERSION_ID >= 70200 && self::INTL_IDNA_VARIANT_2003 === $variant) {
@trigger_error('idn_to_utf8(): INTL_IDNA_VARIANT_2003 is deprecated', E_USER_DEPRECATED);
}
@@ -1,4 +1,4 @@
Copyright (c) 2018 Fabien Potencier
Copyright (c) 2018-2019 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -1,7 +1,7 @@
Symfony Polyfill / Intl: Idn
============================
This component provides `idn_to_ascii` and `idn_to_utf8` functions to users who run php versions without the intl extension.
This component provides [`idn_to_ascii`](https://php.net/idn-to-ascii) and [`idn_to_utf8`](https://php.net/idn-to-utf8) functions to users who run php versions without the [Intl](https://php.net/intl) extension.
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
@@ -11,7 +11,7 @@
use Symfony\Polyfill\Intl\Idn as p;
if (!function_exists('idn_to_ascii')) {
if (!defined('IDNA_DEFAULT')) {
define('U_IDNA_PROHIBITED_ERROR', 66560);
define('U_IDNA_ERROR_START', 66560);
define('U_IDNA_UNASSIGNED_ERROR', 66561);
@@ -48,7 +48,9 @@ if (!function_exists('idn_to_ascii')) {
define('IDNA_ERROR_INVALID_ACE_LABEL', 1024);
define('IDNA_ERROR_BIDI', 2048);
define('IDNA_ERROR_CONTEXTJ', 4096);
}
if (!function_exists('idn_to_ascii')) {
if (PHP_VERSION_ID < 70400) {
function idn_to_ascii($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_2003, &$idna_info = array()) { return p\Idn::idn_to_ascii($domain, $options, $variant, $idna_info); }
function idn_to_utf8($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_2003, &$idna_info = array()) { return p\Idn::idn_to_utf8($domain, $options, $variant, $idna_info); }
@@ -18,7 +18,7 @@
"require": {
"php": ">=5.3.3",
"symfony/polyfill-mbstring": "^1.3",
"symfony/polyfill-php72": "^1.9"
"symfony/polyfill-php72": "^1.10"
},
"autoload": {
"psr-4": { "Symfony\\Polyfill\\Intl\\Idn\\": "" },
@@ -30,7 +30,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
"dev-master": "1.15-dev"
}
}
}
@@ -1,4 +1,4 @@
Copyright (c) 2015-2018 Fabien Potencier
Copyright (c) 2015-2019 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -35,6 +35,7 @@ namespace Symfony\Polyfill\Mbstring;
* - mb_strlen - Get string length
* - mb_strpos - Find position of first occurrence of string in a string
* - mb_strrpos - Find position of last occurrence of a string in a string
* - mb_str_split - Convert a string to an array
* - mb_strtolower - Make a string lowercase
* - mb_strtoupper - Make a string uppercase
* - mb_substitute_character - Set/Get substitution character
@@ -511,7 +512,9 @@ final class Mbstring
$offset = 0;
} elseif ($offset = (int) $offset) {
if ($offset < 0) {
$haystack = self::mb_substr($haystack, 0, $offset, $encoding);
if (0 > $offset += self::mb_strlen($needle)) {
$haystack = self::mb_substr($haystack, 0, $offset, $encoding);
}
$offset = 0;
} else {
$haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
@@ -523,6 +526,45 @@ final class Mbstring
return false !== $pos ? $offset + $pos : false;
}
public static function mb_str_split($string, $split_length = 1, $encoding = null)
{
if (null !== $string && !\is_scalar($string) && !(\is_object($string) && \method_exists($string, '__toString'))) {
trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', E_USER_WARNING);
return null;
}
if (1 > $split_length = (int) $split_length) {
trigger_error('The length of each segment must be greater than zero', E_USER_WARNING);
return false;
}
if (null === $encoding) {
$encoding = mb_internal_encoding();
}
if ('UTF-8' === $encoding = self::getEncoding($encoding)) {
$rx = '/(';
while (65535 < $split_length) {
$rx .= '.{65535}';
$split_length -= 65535;
}
$rx .= '.{'.$split_length.'})/us';
return preg_split($rx, $string, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
}
$result = array();
$length = mb_strlen($string, $encoding);
for ($i = 0; $i < $length; $i += $split_length) {
$result[] = mb_substr($string, $i, $split_length, $encoding);
}
return $result;
}
public static function mb_strtolower($s, $encoding = null)
{
return self::mb_convert_case($s, MB_CASE_LOWER, $encoding);
@@ -546,7 +588,7 @@ final class Mbstring
{
$encoding = self::getEncoding($encoding);
if ('CP850' === $encoding || 'ASCII' === $encoding) {
return substr($s, $start, null === $length ? 2147483647 : $length);
return (string) substr($s, $start, null === $length ? 2147483647 : $length);
}
if ($start < 0) {
@@ -786,11 +828,16 @@ final class Mbstring
return self::$internalEncoding;
}
if ('UTF-8' === $encoding) {
return 'UTF-8';
}
$encoding = strtoupper($encoding);
if ('8BIT' === $encoding || 'BINARY' === $encoding) {
return 'CP850';
}
if ('UTF8' === $encoding) {
return 'UTF-8';
}
@@ -2,7 +2,7 @@ Symfony Polyfill / Mbstring
===========================
This component provides a partial, native PHP implementation for the
[Mbstring](http://php.net/mbstring) extension.
[Mbstring](https://php.net/mbstring) extension.
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
@@ -11,11 +11,13 @@
use Symfony\Polyfill\Mbstring as p;
if (!function_exists('mb_strlen')) {
if (!defined('MB_CASE_UPPER')) {
define('MB_CASE_UPPER', 0);
define('MB_CASE_LOWER', 1);
define('MB_CASE_TITLE', 2);
}
if (!function_exists('mb_strlen')) {
function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); }
function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); }
function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); }
@@ -56,3 +58,7 @@ if (!function_exists('mb_chr')) {
function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); }
function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
}
if (!function_exists('mb_str_split')) {
function mb_str_split($string, $split_length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $split_length, $encoding); }
}
@@ -28,7 +28,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
"dev-master": "1.15-dev"
}
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2015-2018 Fabien Potencier
Copyright (c) 2015-2019 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+1 -1
View File
@@ -16,7 +16,7 @@ Moved to core since 7.2 (was in the optional XML extension earlier):
- [`utf8_decode`](https://php.net/utf8_decode)
Also, it provides a constant added to PHP 7.2:
- [`PHP_OS_FAMILY`](http://php.net/manual/en/reserved.constants.php#constant.php-os-family)
- [`PHP_OS_FAMILY`](https://php.net/reserved.constants#constant.php-os-family)
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
@@ -25,7 +25,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
"dev-master": "1.15-dev"
}
}
}