Create email class
This commit is contained in:
parent
e866f9ae49
commit
cb47a12005
42 changed files with 7360 additions and 18 deletions
|
@ -8,6 +8,12 @@
|
||||||
"grandel/include-directory": "^0.2.2",
|
"grandel/include-directory": "^0.2.2",
|
||||||
"knplabs/github-api": "^3.0",
|
"knplabs/github-api": "^3.0",
|
||||||
"guzzlehttp/guzzle": "^7.0.1",
|
"guzzlehttp/guzzle": "^7.0.1",
|
||||||
"http-interop/http-factory-guzzle": "^1.0"
|
"http-interop/http-factory-guzzle": "^1.0",
|
||||||
|
"qferr/mjml-php": "^1.1"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"allow-plugins": {
|
||||||
|
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
107
composer.lock
generated
107
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "c370a196fb020d63e645d8ea571d04ac",
|
"content-hash": "25846fd23f7252ccce4ba4832e5697ad",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "clue/stream-filter",
|
"name": "clue/stream-filter",
|
||||||
|
@ -1722,6 +1722,47 @@
|
||||||
},
|
},
|
||||||
"time": "2016-08-06T14:39:51+00:00"
|
"time": "2016-08-06T14:39:51+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "qferr/mjml-php",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/qferr/mjml-php.git",
|
||||||
|
"reference": "c6ea36c190e304e399a957f7e03b5a378faf41b9"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/qferr/mjml-php/zipball/c6ea36c190e304e399a957f7e03b5a378faf41b9",
|
||||||
|
"reference": "c6ea36c190e304e399a957f7e03b5a378faf41b9",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"guzzlehttp/guzzle": "~6.0|~7.0",
|
||||||
|
"php": ">=7.2",
|
||||||
|
"symfony/process": "~4.0|~5.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "~7.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Qferrer\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Quentin",
|
||||||
|
"email": "qferrer@outook.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/qferr/mjml-php/issues",
|
||||||
|
"source": "https://github.com/qferr/mjml-php/tree/1.1.0"
|
||||||
|
},
|
||||||
|
"time": "2021-03-19T19:03:44+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "ralouphie/getallheaders",
|
"name": "ralouphie/getallheaders",
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
|
@ -1982,6 +2023,68 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2021-09-13T13:58:33+00:00"
|
"time": "2021-09-13T13:58:33+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/process",
|
||||||
|
"version": "v5.4.5",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/process.git",
|
||||||
|
"reference": "95440409896f90a5f85db07a32b517ecec17fa4c"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/process/zipball/95440409896f90a5f85db07a32b517ecec17fa4c",
|
||||||
|
"reference": "95440409896f90a5f85db07a32b517ecec17fa4c",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.2.5",
|
||||||
|
"symfony/polyfill-php80": "^1.16"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\Process\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Executes commands in sub-processes",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/process/tree/v5.4.5"
|
||||||
|
},
|
||||||
|
"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": "2022-01-30T18:16:22+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
|
@ -2124,5 +2227,5 @@
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": [],
|
"platform": [],
|
||||||
"platform-dev": [],
|
"platform-dev": [],
|
||||||
"plugin-api-version": "2.0.0"
|
"plugin-api-version": "2.2.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,6 +215,9 @@ p .ui.horizontal.label {
|
||||||
/**
|
/**
|
||||||
* Menu
|
* Menu
|
||||||
*/
|
*/
|
||||||
|
.pusher {
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
.pusher .menu.toggle {
|
.pusher .menu.toggle {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
36
src/classes/email.php
Normal file
36
src/classes/email.php
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an email
|
||||||
|
*
|
||||||
|
* Requires MJML input.
|
||||||
|
*
|
||||||
|
* @see https://mjml.io
|
||||||
|
*
|
||||||
|
* @author Jay Trees <github.jay@grandel.anonaddy.me>
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace wishthis;
|
||||||
|
|
||||||
|
class Email
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private string $to,
|
||||||
|
private string $subject,
|
||||||
|
private string $mjml
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function send()
|
||||||
|
{
|
||||||
|
$to = $this->to;
|
||||||
|
$subject = $this->subject;
|
||||||
|
$message = $this->mjml;
|
||||||
|
$headers = array(
|
||||||
|
'From' => 'no-reply@' . $_SERVER['HTTP_HOST'],
|
||||||
|
'Content-type' => 'text/html; charset=utf-8',
|
||||||
|
);
|
||||||
|
|
||||||
|
$success = mail($to, $subject, $message, $headers);
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,7 +10,10 @@ use wishthis\Page;
|
||||||
|
|
||||||
$page = new Page(__FILE__, 'Login');
|
$page = new Page(__FILE__, 'Login');
|
||||||
|
|
||||||
if (isset($_POST['email'], $_POST['password'])) {
|
/**
|
||||||
|
* Login
|
||||||
|
*/
|
||||||
|
if (isset($_POST['login'], $_POST['email'], $_POST['password'])) {
|
||||||
$email = $_POST['email'];
|
$email = $_POST['email'];
|
||||||
$password = sha1($_POST['password']);
|
$password = sha1($_POST['password']);
|
||||||
|
|
||||||
|
@ -36,6 +39,21 @@ if (isset($_SESSION['user'])) {
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset
|
||||||
|
*/
|
||||||
|
if (isset($_POST['reset'], $_POST['email'])) {
|
||||||
|
$user = $database
|
||||||
|
->query('SELECT *
|
||||||
|
FROM `users`
|
||||||
|
WHERE `email` = ' . $_POST['email'] . ';')
|
||||||
|
->fetch();
|
||||||
|
|
||||||
|
if ($user) {
|
||||||
|
$emailReset = new email($_POST['email']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$page->header();
|
$page->header();
|
||||||
$page->bodyStart();
|
$page->bodyStart();
|
||||||
$page->navigation();
|
$page->navigation();
|
||||||
|
@ -51,19 +69,67 @@ $page->navigation();
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="ui segment">
|
<div class="ui segment">
|
||||||
<form class="ui form" method="post">
|
<div class="ui divided relaxed stackable two column grid">
|
||||||
<div class="field">
|
|
||||||
<label>Email</label>
|
<div class="row">
|
||||||
<input type="email" name="email" placeholder="john.doe@domain.tld" />
|
<div class="column">
|
||||||
</div>
|
<h2 class="ui header">Credentials</h2>
|
||||||
<div class="field">
|
|
||||||
<label>Password</label>
|
<form class="ui form login" method="post">
|
||||||
<input type="password" name="password" />
|
<div class="field">
|
||||||
|
<label>Email</label>
|
||||||
|
|
||||||
|
<div class="ui left icon input">
|
||||||
|
<input type="email" name="email" placeholder="john.doe@domain.tld" />
|
||||||
|
<i class="envelope icon"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<label>Password</label>
|
||||||
|
|
||||||
|
<div class="ui left icon input">
|
||||||
|
<input type="password" name="password" />
|
||||||
|
<i class="key icon"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input class="ui primary button" type="submit" name="login" value="Login" />
|
||||||
|
<a class="ui tertiary button" href="/?page=register">Register</a>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="column">
|
||||||
|
<h2 class="ui header">Forgot password?</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Consider using a password manager.
|
||||||
|
It will save all your passwords and allow you to access them with one master password.
|
||||||
|
Never forget a password ever again.
|
||||||
|
</p>
|
||||||
|
<p><a href="https://bitwarden.com/" target="_blank">Bitwarden</a> is the most trusted open source password manager.</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<form class="ui form reset" method="post">
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui action input">
|
||||||
|
<div class="ui left icon action input">
|
||||||
|
<input type="email" name="email" placeholder="john.doe@domain.tld" />
|
||||||
|
<i class="envelope icon"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input class="ui primary button" type="submit" name="reset" value="Send email" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Please note that you have to enter the email address, you have registered with.</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input class="ui primary button" type="submit" value="Login" />
|
</div>
|
||||||
<a href="/?page=register">Register</a>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
|
@ -101,11 +101,20 @@ $page->navigation();
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Email</label>
|
<label>Email</label>
|
||||||
<input type="email" name="email" placeholder="john.doe@domain.tld" />
|
|
||||||
|
<div class="ui left icon input">
|
||||||
|
<input type="email" name="email" placeholder="john.doe@domain.tld" />
|
||||||
|
<i class="envelope icon"></i>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Password</label>
|
<label>Password</label>
|
||||||
<input type="password" name="password" />
|
|
||||||
|
<div class="ui left icon input">
|
||||||
|
<input type="password" name="password" />
|
||||||
|
<i class="key icon"></i>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -118,7 +127,11 @@ $page->navigation();
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Planet</label>
|
<label>Planet</label>
|
||||||
<input type="text" name="planet" />
|
|
||||||
|
<div class="ui left icon input">
|
||||||
|
<input type="text" name="planet" />
|
||||||
|
<i class="globe icon"></i>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>Robots are obivously from another solar system so this will keep them at bay.</p>
|
<p>Robots are obivously from another solar system so this will keep them at bay.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
3
vendor/qferr/mjml-php/.gitignore
vendored
Normal file
3
vendor/qferr/mjml-php/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
.idea/
|
||||||
|
vendor/
|
||||||
|
node_modules/
|
79
vendor/qferr/mjml-php/README.md
vendored
Normal file
79
vendor/qferr/mjml-php/README.md
vendored
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
MJML in PHP
|
||||||
|
===========
|
||||||
|
|
||||||
|
A simple PHP library to render MJML to HTML.
|
||||||
|
|
||||||
|
There are two ways for integrating MJML in PHP:
|
||||||
|
* using the MJML API
|
||||||
|
* using the MJML library
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
```shell script
|
||||||
|
composer require qferr/mjml-php
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using MJML library
|
||||||
|
|
||||||
|
Install the MJML library:
|
||||||
|
|
||||||
|
```shell script
|
||||||
|
npm install mjml --save
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want a specific version, use the following syntax: `npm install mjml@4.7.1 --save`
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
require_once 'vendor/autoload.php';
|
||||||
|
|
||||||
|
$renderer = new \Qferrer\Mjml\Renderer\BinaryRenderer(__DIR__ . '/node_modules/.bin/mjml');
|
||||||
|
|
||||||
|
$html = $renderer->render('
|
||||||
|
<mjml>
|
||||||
|
<mj-body>
|
||||||
|
<mj-section>
|
||||||
|
<mj-column>
|
||||||
|
<mj-text>Hello world</mj-text>
|
||||||
|
</mj-column>
|
||||||
|
</mj-section>
|
||||||
|
</mj-body>
|
||||||
|
</mjml>
|
||||||
|
');
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using MJML API
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
require_once 'vendor/autoload.php';
|
||||||
|
|
||||||
|
$apiId = 'abcdef-1234-5678-ghijkl';
|
||||||
|
$secretKey = 'ghijkl-5678-1234-abcdef';
|
||||||
|
|
||||||
|
$renderer = new \Qferrer\Mjml\Renderer\ApiRenderer($apiId, $secretKey);
|
||||||
|
|
||||||
|
$html = $renderer->render('
|
||||||
|
<mjml>
|
||||||
|
<mj-body>
|
||||||
|
<mj-section>
|
||||||
|
<mj-column>
|
||||||
|
<mj-text>Hello world</mj-text>
|
||||||
|
</mj-column>
|
||||||
|
</mj-section>
|
||||||
|
</mj-body>
|
||||||
|
</mjml>
|
||||||
|
');
|
||||||
|
```
|
||||||
|
|
||||||
|
To find out which version of the library is used by the API, check the `mjml_version` key in the payload returned by the API:
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"html": "\n <!doctype html>\n <html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\">\n <head>\n <title>\n \n </title>\n <!--[if !mso]><!-- -->\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n <!--<![endif]-->\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <style type=\"text/css\">\n #outlook a { padding:0; }\n body { margin:0;padding:0;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%; }\n table, td { border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt; }\n img { border:0;height:auto;line-height:100%; outline:none;text-decoration:none;-ms-interpolation-mode:bicubic; }\n p { display:block;margin:13px 0; }\n </style>\n <!--[if mso]>\n <xml>\n <o:OfficeDocumentSettings>\n <o:AllowPNG/>\n <o:PixelsPerInch>96</o:PixelsPerInch>\n </o:OfficeDocumentSettings>\n </xml>\n <![endif]-->\n <!--[if lte mso 11]>\n <style type=\"text/css\">\n .mj-outlook-group-fix { width:100% !important; }\n </style>\n <![endif]-->\n \n <!--[if !mso]><!-->\n <link href=\"https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700\" rel=\"stylesheet\" type=\"text/css\">\n <style type=\"text/css\">\n @import url(https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700);\n </style>\n <!--<![endif]-->\n\n \n \n <style type=\"text/css\">\n @media only screen and (min-width:480px) {\n .mj-column-per-100 { width:100% !important; max-width: 100%; }\n }\n </style>\n \n \n <style type=\"text/css\">\n \n \n </style>\n \n \n </head>\n <body>\n \n \n <div\n style=\"\"\n >\n \n \n <!--[if mso | IE]>\n <table\n align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"\" style=\"width:600px;\" width=\"600\"\n >\n <tr>\n <td style=\"line-height:0px;font-size:0px;mso-line-height-rule:exactly;\">\n <![endif]-->\n \n \n <div style=\"margin:0px auto;max-width:600px;\">\n \n <table\n align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"width:100%;\"\n >\n <tbody>\n <tr>\n <td\n style=\"direction:ltr;font-size:0px;padding:20px 0;text-align:center;\"\n >\n <!--[if mso | IE]>\n <table role=\"presentation\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n \n <tr>\n \n <td\n class=\"\" style=\"vertical-align:top;width:600px;\"\n >\n <![endif]-->\n \n <div\n class=\"mj-column-per-100 mj-outlook-group-fix\" style=\"font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;\"\n >\n \n <table\n border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"vertical-align:top;\" width=\"100%\"\n >\n \n <tr>\n <td\n align=\"left\" style=\"font-size:0px;padding:10px 25px;word-break:break-word;\"\n >\n \n <div\n style=\"font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:13px;line-height:1;text-align:left;color:#000000;\"\n >Hello World</div>\n \n </td>\n </tr>\n \n </table>\n \n </div>\n \n <!--[if mso | IE]>\n </td>\n \n </tr>\n \n </table>\n <![endif]-->\n </td>\n </tr>\n </tbody>\n </table>\n \n </div>\n \n \n <!--[if mso | IE]>\n </td>\n </tr>\n </table>\n <![endif]-->\n \n \n </div>\n \n </body>\n </html>\n ",
|
||||||
|
"errors": [],
|
||||||
|
"mjml": "<mjml><mj-body><mj-container><mj-section><mj-column><mj-text>Hello World</mj-text></mj-column></mj-section></mj-container></mj-body></mjml>",
|
||||||
|
"mjml_version": "4.6.1"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
More details in the API documentation: https://mjml.io/api/documentation/
|
28
vendor/qferr/mjml-php/composer.json
vendored
Normal file
28
vendor/qferr/mjml-php/composer.json
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"name": "qferr/mjml-php",
|
||||||
|
"type": "library",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Quentin",
|
||||||
|
"email": "qferrer@outook.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.2",
|
||||||
|
"symfony/process": "~4.0|~5.0",
|
||||||
|
"guzzlehttp/guzzle": "~6.0|~7.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "~7.0"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Qferrer\\" : "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"Qferrer\\Tests\\" : "tests/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2101
vendor/qferr/mjml-php/composer.lock
generated
vendored
Normal file
2101
vendor/qferr/mjml-php/composer.lock
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
1353
vendor/qferr/mjml-php/package-lock.json
generated
vendored
Normal file
1353
vendor/qferr/mjml-php/package-lock.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
12
vendor/qferr/mjml-php/package.json
vendored
Normal file
12
vendor/qferr/mjml-php/package.json
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"name": "mjml-php",
|
||||||
|
"description": "MJML in PHP",
|
||||||
|
"author": "Quentin Ferrer",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/qferr/mjml-php/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/qferr/mjml-php#readme",
|
||||||
|
"devDependencies": {
|
||||||
|
"mjml": "^4.9.0"
|
||||||
|
}
|
||||||
|
}
|
71
vendor/qferr/mjml-php/src/Mjml/Renderer/ApiRenderer.php
vendored
Normal file
71
vendor/qferr/mjml-php/src/Mjml/Renderer/ApiRenderer.php
vendored
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Qferrer\Mjml\Renderer;
|
||||||
|
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ApiRenderer
|
||||||
|
*/
|
||||||
|
class ApiRenderer implements RendererInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The client
|
||||||
|
*
|
||||||
|
* @var Client
|
||||||
|
*/
|
||||||
|
private $client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The application ID
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $appId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The secret key
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $secretKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The MJML base uri.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const BASE_URI = "https://api.mjml.io/v1/";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ApiRenderer constructor.
|
||||||
|
*
|
||||||
|
* @param string $appId
|
||||||
|
* @param string $secretKey
|
||||||
|
*/
|
||||||
|
public function __construct(string $appId, string $secretKey)
|
||||||
|
{
|
||||||
|
$this->appId = $appId;
|
||||||
|
$this->secretKey = $secretKey;
|
||||||
|
$this->client = new Client(['base_uri' => self::BASE_URI]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function render(string $content): string
|
||||||
|
{
|
||||||
|
$response = $this->client->post('render', [
|
||||||
|
'auth' => [$this->appId, $this->secretKey],
|
||||||
|
'body' => json_encode([
|
||||||
|
'mjml' => $content
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (false === $data = json_decode($response->getBody()->getContents(), true)) {
|
||||||
|
throw new \RuntimeException('Unable to decode response');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data['html'];
|
||||||
|
}
|
||||||
|
}
|
54
vendor/qferr/mjml-php/src/Mjml/Renderer/BinaryRenderer.php
vendored
Normal file
54
vendor/qferr/mjml-php/src/Mjml/Renderer/BinaryRenderer.php
vendored
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Qferrer\Mjml\Renderer;
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Exception\ProcessFailedException;
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BinaryRenderer
|
||||||
|
*/
|
||||||
|
class BinaryRenderer implements RendererInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The MJML CLI path.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $bin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BinaryRenderer constructor.
|
||||||
|
*
|
||||||
|
* @param string $bin
|
||||||
|
*/
|
||||||
|
public function __construct(string $bin)
|
||||||
|
{
|
||||||
|
$this->bin = $bin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function render(string $content): string
|
||||||
|
{
|
||||||
|
$arguments = [
|
||||||
|
$this->bin,
|
||||||
|
'-i',
|
||||||
|
'-s',
|
||||||
|
'--config.validationLevel',
|
||||||
|
'--config.minify'
|
||||||
|
];
|
||||||
|
|
||||||
|
$process = new Process($arguments);
|
||||||
|
$process->setInput($content);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$process->mustRun();
|
||||||
|
} catch (ProcessFailedException $e) {
|
||||||
|
throw new \RuntimeException('Unable to compile MJML. Stack error: '.$e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $process->getOutput();
|
||||||
|
}
|
||||||
|
}
|
18
vendor/qferr/mjml-php/src/Mjml/Renderer/RendererInterface.php
vendored
Normal file
18
vendor/qferr/mjml-php/src/Mjml/Renderer/RendererInterface.php
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Qferrer\Mjml\Renderer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface RendererInterface
|
||||||
|
*/
|
||||||
|
interface RendererInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Renderer MJML to HTML content
|
||||||
|
*
|
||||||
|
* @param string $content The MJML content
|
||||||
|
*
|
||||||
|
* @return string The generated HTML
|
||||||
|
*/
|
||||||
|
public function render(string $content): string;
|
||||||
|
}
|
30
vendor/qferr/mjml-php/tests/Mjml/Renderer/ApiRendererTests.php
vendored
Normal file
30
vendor/qferr/mjml-php/tests/Mjml/Renderer/ApiRendererTests.php
vendored
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Qferrer\Tests\Mjml\Renderer;
|
||||||
|
|
||||||
|
use GuzzleHttp\Exception\ClientException;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Qferrer\Mjml\Renderer\ApiRenderer;
|
||||||
|
use Qferrer\Tests\ResourcesTrait;
|
||||||
|
|
||||||
|
class ApiRendererTests extends TestCase
|
||||||
|
{
|
||||||
|
use ResourcesTrait;
|
||||||
|
|
||||||
|
public function testRender()
|
||||||
|
{
|
||||||
|
$renderer = new ApiRenderer($_ENV['MJML_API_ID'], $_ENV['MJML_API_SECRET_KEY']);
|
||||||
|
|
||||||
|
$html = $renderer->render($this->loadResource('hello_world.mjml'));
|
||||||
|
|
||||||
|
$this->assertEquals($this->loadResource('hello_world.html'), $html);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRenderWithInvalidCredentialsThrowException()
|
||||||
|
{
|
||||||
|
$this->expectException(ClientException::class);
|
||||||
|
|
||||||
|
$renderer = new ApiRenderer('test', 'test');
|
||||||
|
$renderer->render($this->loadResource('hello_world.html'));
|
||||||
|
}
|
||||||
|
}
|
29
vendor/qferr/mjml-php/tests/Mjml/Renderer/BinaryRendererTest.php
vendored
Normal file
29
vendor/qferr/mjml-php/tests/Mjml/Renderer/BinaryRendererTest.php
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Qferrer\Tests\Mjml\Renderer;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Qferrer\Mjml\Renderer\BinaryRenderer;
|
||||||
|
use Qferrer\Tests\ResourcesTrait;
|
||||||
|
|
||||||
|
class BinaryRendererTest extends TestCase
|
||||||
|
{
|
||||||
|
use ResourcesTrait;
|
||||||
|
|
||||||
|
public function testRender()
|
||||||
|
{
|
||||||
|
$renderer = new BinaryRenderer(__DIR__ . '/../../../node_modules/.bin/mjml');
|
||||||
|
|
||||||
|
$html = $renderer->render($this->loadResource('hello_world.mjml'));
|
||||||
|
|
||||||
|
$this->assertEquals($this->loadResource('hello_world.min.html'), $html);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRenderWithInvalidBinaryThrowException()
|
||||||
|
{
|
||||||
|
$this->expectException(\RuntimeException::class);
|
||||||
|
|
||||||
|
$renderer = new BinaryRenderer('unknown');
|
||||||
|
$renderer->render($this->loadResource('hello_world.mjml'));
|
||||||
|
}
|
||||||
|
}
|
144
vendor/qferr/mjml-php/tests/Resources/hello_world.html
vendored
Normal file
144
vendor/qferr/mjml-php/tests/Resources/hello_world.html
vendored
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||||
|
<head>
|
||||||
|
<title>
|
||||||
|
|
||||||
|
</title>
|
||||||
|
<!--[if !mso]><!-- -->
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<!--<![endif]-->
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<style type="text/css">
|
||||||
|
#outlook a { padding:0; }
|
||||||
|
body { margin:0;padding:0;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%; }
|
||||||
|
table, td { border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt; }
|
||||||
|
img { border:0;height:auto;line-height:100%; outline:none;text-decoration:none;-ms-interpolation-mode:bicubic; }
|
||||||
|
p { display:block;margin:13px 0; }
|
||||||
|
</style>
|
||||||
|
<!--[if mso]>
|
||||||
|
<xml>
|
||||||
|
<o:OfficeDocumentSettings>
|
||||||
|
<o:AllowPNG/>
|
||||||
|
<o:PixelsPerInch>96</o:PixelsPerInch>
|
||||||
|
</o:OfficeDocumentSettings>
|
||||||
|
</xml>
|
||||||
|
<![endif]-->
|
||||||
|
<!--[if lte mso 11]>
|
||||||
|
<style type="text/css">
|
||||||
|
.mj-outlook-group-fix { width:100% !important; }
|
||||||
|
</style>
|
||||||
|
<![endif]-->
|
||||||
|
|
||||||
|
<!--[if !mso]><!-->
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700" rel="stylesheet" type="text/css">
|
||||||
|
<style type="text/css">
|
||||||
|
@import url(https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700);
|
||||||
|
</style>
|
||||||
|
<!--<![endif]-->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
@media only screen and (min-width:480px) {
|
||||||
|
.mj-column-per-100 { width:100% !important; max-width: 100%; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
|
||||||
|
<div
|
||||||
|
style=""
|
||||||
|
>
|
||||||
|
|
||||||
|
|
||||||
|
<!--[if mso | IE]>
|
||||||
|
<table
|
||||||
|
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
|
||||||
|
<![endif]-->
|
||||||
|
|
||||||
|
|
||||||
|
<div style="margin:0px auto;max-width:600px;">
|
||||||
|
|
||||||
|
<table
|
||||||
|
align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"
|
||||||
|
>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td
|
||||||
|
style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;"
|
||||||
|
>
|
||||||
|
<!--[if mso | IE]>
|
||||||
|
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td
|
||||||
|
class="" style="vertical-align:top;width:600px;"
|
||||||
|
>
|
||||||
|
<![endif]-->
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"
|
||||||
|
>
|
||||||
|
|
||||||
|
<table
|
||||||
|
border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"
|
||||||
|
>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td
|
||||||
|
align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;"
|
||||||
|
>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:13px;line-height:1;text-align:left;color:#000000;"
|
||||||
|
>Hello world</div>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--[if mso | IE]>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
<![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!--[if mso | IE]>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<![endif]-->
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
51
vendor/qferr/mjml-php/tests/Resources/hello_world.min.html
vendored
Normal file
51
vendor/qferr/mjml-php/tests/Resources/hello_world.min.html
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
<!-- FILE: undefined -->
|
||||||
|
<!doctype html><html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"><head><title></title><!--[if !mso]><!--><meta http-equiv="X-UA-Compatible" content="IE=edge"><!--<![endif]--><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><style type="text/css">#outlook a {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
-ms-text-size-adjust: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table,
|
||||||
|
td {
|
||||||
|
border-collapse: collapse;
|
||||||
|
mso-table-lspace: 0pt;
|
||||||
|
mso-table-rspace: 0pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
border: 0;
|
||||||
|
height: auto;
|
||||||
|
line-height: 100%;
|
||||||
|
outline: none;
|
||||||
|
text-decoration: none;
|
||||||
|
-ms-interpolation-mode: bicubic;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
display: block;
|
||||||
|
margin: 13px 0;
|
||||||
|
}</style><!--[if mso]>
|
||||||
|
<xml>
|
||||||
|
<o:OfficeDocumentSettings>
|
||||||
|
<o:AllowPNG/>
|
||||||
|
<o:PixelsPerInch>96</o:PixelsPerInch>
|
||||||
|
</o:OfficeDocumentSettings>
|
||||||
|
</xml>
|
||||||
|
<![endif]--><!--[if lte mso 11]>
|
||||||
|
<style type="text/css">
|
||||||
|
.mj-outlook-group-fix { width:100% !important; }
|
||||||
|
</style>
|
||||||
|
<![endif]--><!--[if !mso]><!--><link href="https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700" rel="stylesheet" type="text/css"><style type="text/css">@import url(https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700);</style><!--<![endif]--><style type="text/css">@media only screen and (min-width:480px) {
|
||||||
|
.mj-column-per-100 {
|
||||||
|
width: 100% !important;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}</style><style media="screen and (min-width:480px)">.moz-text-html .mj-column-per-100 {
|
||||||
|
width: 100% !important;
|
||||||
|
max-width: 100%;
|
||||||
|
}</style><style type="text/css"></style></head><body style="word-spacing:normal;"><div><!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="margin:0px auto;max-width:600px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]--><div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tbody><tr><td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;"><div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:13px;line-height:1;text-align:left;color:#000000;">Hello world</div></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></div></body></html>
|
9
vendor/qferr/mjml-php/tests/Resources/hello_world.mjml
vendored
Normal file
9
vendor/qferr/mjml-php/tests/Resources/hello_world.mjml
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<mjml>
|
||||||
|
<mj-body>
|
||||||
|
<mj-section>
|
||||||
|
<mj-column>
|
||||||
|
<mj-text>Hello world</mj-text>
|
||||||
|
</mj-column>
|
||||||
|
</mj-section>
|
||||||
|
</mj-body>
|
||||||
|
</mjml>
|
11
vendor/qferr/mjml-php/tests/ResourcesTrait.php
vendored
Normal file
11
vendor/qferr/mjml-php/tests/ResourcesTrait.php
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Qferrer\Tests;
|
||||||
|
|
||||||
|
trait ResourcesTrait
|
||||||
|
{
|
||||||
|
private function loadResource($filename)
|
||||||
|
{
|
||||||
|
return file_get_contents(__DIR__ . '/Resources/' . $filename);
|
||||||
|
}
|
||||||
|
}
|
116
vendor/symfony/process/CHANGELOG.md
vendored
Normal file
116
vendor/symfony/process/CHANGELOG.md
vendored
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
CHANGELOG
|
||||||
|
=========
|
||||||
|
|
||||||
|
5.2.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* added `Process::setOptions()` to set `Process` specific options
|
||||||
|
* added option `create_new_console` to allow a subprocess to continue
|
||||||
|
to run after the main script exited, both on Linux and on Windows
|
||||||
|
|
||||||
|
5.1.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* added `Process::getStartTime()` to retrieve the start time of the process as float
|
||||||
|
|
||||||
|
5.0.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* removed `Process::inheritEnvironmentVariables()`
|
||||||
|
* removed `PhpProcess::setPhpBinary()`
|
||||||
|
* `Process` must be instantiated with a command array, use `Process::fromShellCommandline()` when the command should be parsed by the shell
|
||||||
|
* removed `Process::setCommandLine()`
|
||||||
|
|
||||||
|
4.4.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* deprecated `Process::inheritEnvironmentVariables()`: env variables are always inherited.
|
||||||
|
* added `Process::getLastOutputTime()` method
|
||||||
|
|
||||||
|
4.2.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* added the `Process::fromShellCommandline()` to run commands in a shell wrapper
|
||||||
|
* deprecated passing a command as string when creating a `Process` instance
|
||||||
|
* deprecated the `Process::setCommandline()` and the `PhpProcess::setPhpBinary()` methods
|
||||||
|
* added the `Process::waitUntil()` method to wait for the process only for a
|
||||||
|
specific output, then continue the normal execution of your application
|
||||||
|
|
||||||
|
4.1.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* added the `Process::isTtySupported()` method that allows to check for TTY support
|
||||||
|
* made `PhpExecutableFinder` look for the `PHP_BINARY` env var when searching the php binary
|
||||||
|
* added the `ProcessSignaledException` class to properly catch signaled process errors
|
||||||
|
|
||||||
|
4.0.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* environment variables will always be inherited
|
||||||
|
* added a second `array $env = []` argument to the `start()`, `run()`,
|
||||||
|
`mustRun()`, and `restart()` methods of the `Process` class
|
||||||
|
* added a second `array $env = []` argument to the `start()` method of the
|
||||||
|
`PhpProcess` class
|
||||||
|
* the `ProcessUtils::escapeArgument()` method has been removed
|
||||||
|
* the `areEnvironmentVariablesInherited()`, `getOptions()`, and `setOptions()`
|
||||||
|
methods of the `Process` class have been removed
|
||||||
|
* support for passing `proc_open()` options has been removed
|
||||||
|
* removed the `ProcessBuilder` class, use the `Process` class instead
|
||||||
|
* removed the `getEnhanceWindowsCompatibility()` and `setEnhanceWindowsCompatibility()` methods of the `Process` class
|
||||||
|
* passing a not existing working directory to the constructor of the `Symfony\Component\Process\Process` class is not
|
||||||
|
supported anymore
|
||||||
|
|
||||||
|
3.4.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* deprecated the ProcessBuilder class
|
||||||
|
* deprecated calling `Process::start()` without setting a valid working directory beforehand (via `setWorkingDirectory()` or constructor)
|
||||||
|
|
||||||
|
3.3.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* added command line arrays in the `Process` class
|
||||||
|
* added `$env` argument to `Process::start()`, `run()`, `mustRun()` and `restart()` methods
|
||||||
|
* deprecated the `ProcessUtils::escapeArgument()` method
|
||||||
|
* deprecated not inheriting environment variables
|
||||||
|
* deprecated configuring `proc_open()` options
|
||||||
|
* deprecated configuring enhanced Windows compatibility
|
||||||
|
* deprecated configuring enhanced sigchild compatibility
|
||||||
|
|
||||||
|
2.5.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* added support for PTY mode
|
||||||
|
* added the convenience method "mustRun"
|
||||||
|
* deprecation: Process::setStdin() is deprecated in favor of Process::setInput()
|
||||||
|
* deprecation: Process::getStdin() is deprecated in favor of Process::getInput()
|
||||||
|
* deprecation: Process::setInput() and ProcessBuilder::setInput() do not accept non-scalar types
|
||||||
|
|
||||||
|
2.4.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* added the ability to define an idle timeout
|
||||||
|
|
||||||
|
2.3.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* added ProcessUtils::escapeArgument() to fix the bug in escapeshellarg() function on Windows
|
||||||
|
* added Process::signal()
|
||||||
|
* added Process::getPid()
|
||||||
|
* added support for a TTY mode
|
||||||
|
|
||||||
|
2.2.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* added ProcessBuilder::setArguments() to reset the arguments on a builder
|
||||||
|
* added a way to retrieve the standard and error output incrementally
|
||||||
|
* added Process:restart()
|
||||||
|
|
||||||
|
2.1.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* added support for non-blocking processes (start(), wait(), isRunning(), stop())
|
||||||
|
* enhanced Windows compatibility
|
||||||
|
* added Process::getExitCodeText() that returns a string representation for
|
||||||
|
the exit code returned by the process
|
||||||
|
* added ProcessBuilder
|
21
vendor/symfony/process/Exception/ExceptionInterface.php
vendored
Normal file
21
vendor/symfony/process/Exception/ExceptionInterface.php
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Process\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marker Interface for the Process Component.
|
||||||
|
*
|
||||||
|
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||||
|
*/
|
||||||
|
interface ExceptionInterface extends \Throwable
|
||||||
|
{
|
||||||
|
}
|
21
vendor/symfony/process/Exception/InvalidArgumentException.php
vendored
Normal file
21
vendor/symfony/process/Exception/InvalidArgumentException.php
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Process\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InvalidArgumentException for the Process Component.
|
||||||
|
*
|
||||||
|
* @author Romain Neutron <imprec@gmail.com>
|
||||||
|
*/
|
||||||
|
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
|
||||||
|
{
|
||||||
|
}
|
21
vendor/symfony/process/Exception/LogicException.php
vendored
Normal file
21
vendor/symfony/process/Exception/LogicException.php
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Process\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LogicException for the Process Component.
|
||||||
|
*
|
||||||
|
* @author Romain Neutron <imprec@gmail.com>
|
||||||
|
*/
|
||||||
|
class LogicException extends \LogicException implements ExceptionInterface
|
||||||
|
{
|
||||||
|
}
|
54
vendor/symfony/process/Exception/ProcessFailedException.php
vendored
Normal file
54
vendor/symfony/process/Exception/ProcessFailedException.php
vendored
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Process\Exception;
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception for failed processes.
|
||||||
|
*
|
||||||
|
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||||
|
*/
|
||||||
|
class ProcessFailedException extends RuntimeException
|
||||||
|
{
|
||||||
|
private $process;
|
||||||
|
|
||||||
|
public function __construct(Process $process)
|
||||||
|
{
|
||||||
|
if ($process->isSuccessful()) {
|
||||||
|
throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$error = sprintf('The command "%s" failed.'."\n\nExit Code: %s(%s)\n\nWorking directory: %s",
|
||||||
|
$process->getCommandLine(),
|
||||||
|
$process->getExitCode(),
|
||||||
|
$process->getExitCodeText(),
|
||||||
|
$process->getWorkingDirectory()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!$process->isOutputDisabled()) {
|
||||||
|
$error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
|
||||||
|
$process->getOutput(),
|
||||||
|
$process->getErrorOutput()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::__construct($error);
|
||||||
|
|
||||||
|
$this->process = $process;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getProcess()
|
||||||
|
{
|
||||||
|
return $this->process;
|
||||||
|
}
|
||||||
|
}
|
41
vendor/symfony/process/Exception/ProcessSignaledException.php
vendored
Normal file
41
vendor/symfony/process/Exception/ProcessSignaledException.php
vendored
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Process\Exception;
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception that is thrown when a process has been signaled.
|
||||||
|
*
|
||||||
|
* @author Sullivan Senechal <soullivaneuh@gmail.com>
|
||||||
|
*/
|
||||||
|
final class ProcessSignaledException extends RuntimeException
|
||||||
|
{
|
||||||
|
private $process;
|
||||||
|
|
||||||
|
public function __construct(Process $process)
|
||||||
|
{
|
||||||
|
$this->process = $process;
|
||||||
|
|
||||||
|
parent::__construct(sprintf('The process has been signaled with signal "%s".', $process->getTermSignal()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getProcess(): Process
|
||||||
|
{
|
||||||
|
return $this->process;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSignal(): int
|
||||||
|
{
|
||||||
|
return $this->getProcess()->getTermSignal();
|
||||||
|
}
|
||||||
|
}
|
69
vendor/symfony/process/Exception/ProcessTimedOutException.php
vendored
Normal file
69
vendor/symfony/process/Exception/ProcessTimedOutException.php
vendored
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Process\Exception;
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception that is thrown when a process times out.
|
||||||
|
*
|
||||||
|
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||||
|
*/
|
||||||
|
class ProcessTimedOutException extends RuntimeException
|
||||||
|
{
|
||||||
|
public const TYPE_GENERAL = 1;
|
||||||
|
public const TYPE_IDLE = 2;
|
||||||
|
|
||||||
|
private $process;
|
||||||
|
private $timeoutType;
|
||||||
|
|
||||||
|
public function __construct(Process $process, int $timeoutType)
|
||||||
|
{
|
||||||
|
$this->process = $process;
|
||||||
|
$this->timeoutType = $timeoutType;
|
||||||
|
|
||||||
|
parent::__construct(sprintf(
|
||||||
|
'The process "%s" exceeded the timeout of %s seconds.',
|
||||||
|
$process->getCommandLine(),
|
||||||
|
$this->getExceededTimeout()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getProcess()
|
||||||
|
{
|
||||||
|
return $this->process;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isGeneralTimeout()
|
||||||
|
{
|
||||||
|
return self::TYPE_GENERAL === $this->timeoutType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isIdleTimeout()
|
||||||
|
{
|
||||||
|
return self::TYPE_IDLE === $this->timeoutType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getExceededTimeout()
|
||||||
|
{
|
||||||
|
switch ($this->timeoutType) {
|
||||||
|
case self::TYPE_GENERAL:
|
||||||
|
return $this->process->getTimeout();
|
||||||
|
|
||||||
|
case self::TYPE_IDLE:
|
||||||
|
return $this->process->getIdleTimeout();
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
vendor/symfony/process/Exception/RuntimeException.php
vendored
Normal file
21
vendor/symfony/process/Exception/RuntimeException.php
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Process\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RuntimeException for the Process Component.
|
||||||
|
*
|
||||||
|
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||||
|
*/
|
||||||
|
class RuntimeException extends \RuntimeException implements ExceptionInterface
|
||||||
|
{
|
||||||
|
}
|
86
vendor/symfony/process/ExecutableFinder.php
vendored
Normal file
86
vendor/symfony/process/ExecutableFinder.php
vendored
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Process;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic executable finder.
|
||||||
|
*
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||||
|
*/
|
||||||
|
class ExecutableFinder
|
||||||
|
{
|
||||||
|
private $suffixes = ['.exe', '.bat', '.cmd', '.com'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces default suffixes of executable.
|
||||||
|
*/
|
||||||
|
public function setSuffixes(array $suffixes)
|
||||||
|
{
|
||||||
|
$this->suffixes = $suffixes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds new possible suffix to check for executable.
|
||||||
|
*/
|
||||||
|
public function addSuffix(string $suffix)
|
||||||
|
{
|
||||||
|
$this->suffixes[] = $suffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds an executable by name.
|
||||||
|
*
|
||||||
|
* @param string $name The executable name (without the extension)
|
||||||
|
* @param string|null $default The default to return if no executable is found
|
||||||
|
* @param array $extraDirs Additional dirs to check into
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function find(string $name, string $default = null, array $extraDirs = [])
|
||||||
|
{
|
||||||
|
if (ini_get('open_basedir')) {
|
||||||
|
$searchPath = array_merge(explode(\PATH_SEPARATOR, ini_get('open_basedir')), $extraDirs);
|
||||||
|
$dirs = [];
|
||||||
|
foreach ($searchPath as $path) {
|
||||||
|
// Silencing against https://bugs.php.net/69240
|
||||||
|
if (@is_dir($path)) {
|
||||||
|
$dirs[] = $path;
|
||||||
|
} else {
|
||||||
|
if (basename($path) == $name && @is_executable($path)) {
|
||||||
|
return $path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$dirs = array_merge(
|
||||||
|
explode(\PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
|
||||||
|
$extraDirs
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$suffixes = [''];
|
||||||
|
if ('\\' === \DIRECTORY_SEPARATOR) {
|
||||||
|
$pathExt = getenv('PATHEXT');
|
||||||
|
$suffixes = array_merge($pathExt ? explode(\PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes);
|
||||||
|
}
|
||||||
|
foreach ($suffixes as $suffix) {
|
||||||
|
foreach ($dirs as $dir) {
|
||||||
|
if (@is_file($file = $dir.\DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === \DIRECTORY_SEPARATOR || @is_executable($file))) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
}
|
96
vendor/symfony/process/InputStream.php
vendored
Normal file
96
vendor/symfony/process/InputStream.php
vendored
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Process;
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Exception\RuntimeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a way to continuously write to the input of a Process until the InputStream is closed.
|
||||||
|
*
|
||||||
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
|
*
|
||||||
|
* @implements \IteratorAggregate<int, string>
|
||||||
|
*/
|
||||||
|
class InputStream implements \IteratorAggregate
|
||||||
|
{
|
||||||
|
/** @var callable|null */
|
||||||
|
private $onEmpty = null;
|
||||||
|
private $input = [];
|
||||||
|
private $open = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a callback that is called when the write buffer becomes empty.
|
||||||
|
*/
|
||||||
|
public function onEmpty(callable $onEmpty = null)
|
||||||
|
{
|
||||||
|
$this->onEmpty = $onEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends an input to the write buffer.
|
||||||
|
*
|
||||||
|
* @param resource|string|int|float|bool|\Traversable|null $input The input to append as scalar,
|
||||||
|
* stream resource or \Traversable
|
||||||
|
*/
|
||||||
|
public function write($input)
|
||||||
|
{
|
||||||
|
if (null === $input) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($this->isClosed()) {
|
||||||
|
throw new RuntimeException(sprintf('"%s" is closed.', static::class));
|
||||||
|
}
|
||||||
|
$this->input[] = ProcessUtils::validateInput(__METHOD__, $input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the write buffer.
|
||||||
|
*/
|
||||||
|
public function close()
|
||||||
|
{
|
||||||
|
$this->open = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells whether the write buffer is closed or not.
|
||||||
|
*/
|
||||||
|
public function isClosed()
|
||||||
|
{
|
||||||
|
return !$this->open;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Traversable<int, string>
|
||||||
|
*/
|
||||||
|
#[\ReturnTypeWillChange]
|
||||||
|
public function getIterator()
|
||||||
|
{
|
||||||
|
$this->open = true;
|
||||||
|
|
||||||
|
while ($this->open || $this->input) {
|
||||||
|
if (!$this->input) {
|
||||||
|
yield '';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$current = array_shift($this->input);
|
||||||
|
|
||||||
|
if ($current instanceof \Iterator) {
|
||||||
|
yield from $current;
|
||||||
|
} else {
|
||||||
|
yield $current;
|
||||||
|
}
|
||||||
|
if (!$this->input && $this->open && null !== $onEmpty = $this->onEmpty) {
|
||||||
|
$this->write($onEmpty($this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
vendor/symfony/process/LICENSE
vendored
Normal file
19
vendor/symfony/process/LICENSE
vendored
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright (c) 2004-2022 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
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
99
vendor/symfony/process/PhpExecutableFinder.php
vendored
Normal file
99
vendor/symfony/process/PhpExecutableFinder.php
vendored
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Process;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An executable finder specifically designed for the PHP executable.
|
||||||
|
*
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||||
|
*/
|
||||||
|
class PhpExecutableFinder
|
||||||
|
{
|
||||||
|
private $executableFinder;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->executableFinder = new ExecutableFinder();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds The PHP executable.
|
||||||
|
*
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
|
public function find(bool $includeArgs = true)
|
||||||
|
{
|
||||||
|
if ($php = getenv('PHP_BINARY')) {
|
||||||
|
if (!is_executable($php)) {
|
||||||
|
$command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v';
|
||||||
|
if ($php = strtok(exec($command.' '.escapeshellarg($php)), \PHP_EOL)) {
|
||||||
|
if (!is_executable($php)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $php;
|
||||||
|
}
|
||||||
|
|
||||||
|
$args = $this->findArguments();
|
||||||
|
$args = $includeArgs && $args ? ' '.implode(' ', $args) : '';
|
||||||
|
|
||||||
|
// PHP_BINARY return the current sapi executable
|
||||||
|
if (\PHP_BINARY && \in_array(\PHP_SAPI, ['cgi-fcgi', 'cli', 'cli-server', 'phpdbg'], true)) {
|
||||||
|
return \PHP_BINARY.$args;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($php = getenv('PHP_PATH')) {
|
||||||
|
if (!@is_executable($php)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $php;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($php = getenv('PHP_PEAR_PHP_BIN')) {
|
||||||
|
if (@is_executable($php)) {
|
||||||
|
return $php;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (@is_executable($php = \PHP_BINDIR.('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) {
|
||||||
|
return $php;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dirs = [\PHP_BINDIR];
|
||||||
|
if ('\\' === \DIRECTORY_SEPARATOR) {
|
||||||
|
$dirs[] = 'C:\xampp\php\\';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->executableFinder->find('php', false, $dirs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the PHP executable arguments.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function findArguments()
|
||||||
|
{
|
||||||
|
$arguments = [];
|
||||||
|
if ('phpdbg' === \PHP_SAPI) {
|
||||||
|
$arguments[] = '-qrr';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $arguments;
|
||||||
|
}
|
||||||
|
}
|
72
vendor/symfony/process/PhpProcess.php
vendored
Normal file
72
vendor/symfony/process/PhpProcess.php
vendored
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Process;
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Exception\LogicException;
|
||||||
|
use Symfony\Component\Process\Exception\RuntimeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PhpProcess runs a PHP script in an independent process.
|
||||||
|
*
|
||||||
|
* $p = new PhpProcess('<?php echo "foo"; ?>');
|
||||||
|
* $p->run();
|
||||||
|
* print $p->getOutput()."\n";
|
||||||
|
*
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*/
|
||||||
|
class PhpProcess extends Process
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param string $script The PHP script to run (as a string)
|
||||||
|
* @param string|null $cwd The working directory or null to use the working dir of the current PHP process
|
||||||
|
* @param array|null $env The environment variables or null to use the same environment as the current PHP process
|
||||||
|
* @param int $timeout The timeout in seconds
|
||||||
|
* @param array|null $php Path to the PHP binary to use with any additional arguments
|
||||||
|
*/
|
||||||
|
public function __construct(string $script, string $cwd = null, array $env = null, int $timeout = 60, array $php = null)
|
||||||
|
{
|
||||||
|
if (null === $php) {
|
||||||
|
$executableFinder = new PhpExecutableFinder();
|
||||||
|
$php = $executableFinder->find(false);
|
||||||
|
$php = false === $php ? null : array_merge([$php], $executableFinder->findArguments());
|
||||||
|
}
|
||||||
|
if ('phpdbg' === \PHP_SAPI) {
|
||||||
|
$file = tempnam(sys_get_temp_dir(), 'dbg');
|
||||||
|
file_put_contents($file, $script);
|
||||||
|
register_shutdown_function('unlink', $file);
|
||||||
|
$php[] = $file;
|
||||||
|
$script = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::__construct($php, $cwd, $env, $script, $timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public static function fromShellCommandline(string $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60)
|
||||||
|
{
|
||||||
|
throw new LogicException(sprintf('The "%s()" method cannot be called when using "%s".', __METHOD__, self::class));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function start(callable $callback = null, array $env = [])
|
||||||
|
{
|
||||||
|
if (null === $this->getCommandLine()) {
|
||||||
|
throw new RuntimeException('Unable to find the PHP executable.');
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::start($callback, $env);
|
||||||
|
}
|
||||||
|
}
|
180
vendor/symfony/process/Pipes/AbstractPipes.php
vendored
Normal file
180
vendor/symfony/process/Pipes/AbstractPipes.php
vendored
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Process\Pipes;
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Exception\InvalidArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Romain Neutron <imprec@gmail.com>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
abstract class AbstractPipes implements PipesInterface
|
||||||
|
{
|
||||||
|
public $pipes = [];
|
||||||
|
|
||||||
|
private $inputBuffer = '';
|
||||||
|
private $input;
|
||||||
|
private $blocked = true;
|
||||||
|
private $lastError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param resource|string|int|float|bool|\Iterator|null $input
|
||||||
|
*/
|
||||||
|
public function __construct($input)
|
||||||
|
{
|
||||||
|
if (\is_resource($input) || $input instanceof \Iterator) {
|
||||||
|
$this->input = $input;
|
||||||
|
} elseif (\is_string($input)) {
|
||||||
|
$this->inputBuffer = $input;
|
||||||
|
} else {
|
||||||
|
$this->inputBuffer = (string) $input;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function close()
|
||||||
|
{
|
||||||
|
foreach ($this->pipes as $pipe) {
|
||||||
|
if (\is_resource($pipe)) {
|
||||||
|
fclose($pipe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->pipes = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if a system call has been interrupted.
|
||||||
|
*/
|
||||||
|
protected function hasSystemCallBeenInterrupted(): bool
|
||||||
|
{
|
||||||
|
$lastError = $this->lastError;
|
||||||
|
$this->lastError = null;
|
||||||
|
|
||||||
|
// stream_select returns false when the `select` system call is interrupted by an incoming signal
|
||||||
|
return null !== $lastError && false !== stripos($lastError, 'interrupted system call');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unblocks streams.
|
||||||
|
*/
|
||||||
|
protected function unblock()
|
||||||
|
{
|
||||||
|
if (!$this->blocked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->pipes as $pipe) {
|
||||||
|
stream_set_blocking($pipe, 0);
|
||||||
|
}
|
||||||
|
if (\is_resource($this->input)) {
|
||||||
|
stream_set_blocking($this->input, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->blocked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes input to stdin.
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException When an input iterator yields a non supported value
|
||||||
|
*/
|
||||||
|
protected function write(): ?array
|
||||||
|
{
|
||||||
|
if (!isset($this->pipes[0])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$input = $this->input;
|
||||||
|
|
||||||
|
if ($input instanceof \Iterator) {
|
||||||
|
if (!$input->valid()) {
|
||||||
|
$input = null;
|
||||||
|
} elseif (\is_resource($input = $input->current())) {
|
||||||
|
stream_set_blocking($input, 0);
|
||||||
|
} elseif (!isset($this->inputBuffer[0])) {
|
||||||
|
if (!\is_string($input)) {
|
||||||
|
if (!is_scalar($input)) {
|
||||||
|
throw new InvalidArgumentException(sprintf('"%s" yielded a value of type "%s", but only scalars and stream resources are supported.', get_debug_type($this->input), get_debug_type($input)));
|
||||||
|
}
|
||||||
|
$input = (string) $input;
|
||||||
|
}
|
||||||
|
$this->inputBuffer = $input;
|
||||||
|
$this->input->next();
|
||||||
|
$input = null;
|
||||||
|
} else {
|
||||||
|
$input = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$r = $e = [];
|
||||||
|
$w = [$this->pipes[0]];
|
||||||
|
|
||||||
|
// let's have a look if something changed in streams
|
||||||
|
if (false === @stream_select($r, $w, $e, 0, 0)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($w as $stdin) {
|
||||||
|
if (isset($this->inputBuffer[0])) {
|
||||||
|
$written = fwrite($stdin, $this->inputBuffer);
|
||||||
|
$this->inputBuffer = substr($this->inputBuffer, $written);
|
||||||
|
if (isset($this->inputBuffer[0])) {
|
||||||
|
return [$this->pipes[0]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($input) {
|
||||||
|
while (true) {
|
||||||
|
$data = fread($input, self::CHUNK_SIZE);
|
||||||
|
if (!isset($data[0])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$written = fwrite($stdin, $data);
|
||||||
|
$data = substr($data, $written);
|
||||||
|
if (isset($data[0])) {
|
||||||
|
$this->inputBuffer = $data;
|
||||||
|
|
||||||
|
return [$this->pipes[0]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (feof($input)) {
|
||||||
|
if ($this->input instanceof \Iterator) {
|
||||||
|
$this->input->next();
|
||||||
|
} else {
|
||||||
|
$this->input = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no input to read on resource, buffer is empty
|
||||||
|
if (!isset($this->inputBuffer[0]) && !($this->input instanceof \Iterator ? $this->input->valid() : $this->input)) {
|
||||||
|
$this->input = null;
|
||||||
|
fclose($this->pipes[0]);
|
||||||
|
unset($this->pipes[0]);
|
||||||
|
} elseif (!$w) {
|
||||||
|
return [$this->pipes[0]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
public function handleError(int $type, string $msg)
|
||||||
|
{
|
||||||
|
$this->lastError = $msg;
|
||||||
|
}
|
||||||
|
}
|
61
vendor/symfony/process/Pipes/PipesInterface.php
vendored
Normal file
61
vendor/symfony/process/Pipes/PipesInterface.php
vendored
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Process\Pipes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PipesInterface manages descriptors and pipes for the use of proc_open.
|
||||||
|
*
|
||||||
|
* @author Romain Neutron <imprec@gmail.com>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
interface PipesInterface
|
||||||
|
{
|
||||||
|
public const CHUNK_SIZE = 16384;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of descriptors for the use of proc_open.
|
||||||
|
*/
|
||||||
|
public function getDescriptors(): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of filenames indexed by their related stream in case these pipes use temporary files.
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getFiles(): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads data in file handles and pipes.
|
||||||
|
*
|
||||||
|
* @param bool $blocking Whether to use blocking calls or not
|
||||||
|
* @param bool $close Whether to close pipes if they've reached EOF
|
||||||
|
*
|
||||||
|
* @return string[] An array of read data indexed by their fd
|
||||||
|
*/
|
||||||
|
public function readAndWrite(bool $blocking, bool $close = false): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if the current state has open file handles or pipes.
|
||||||
|
*/
|
||||||
|
public function areOpen(): bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if pipes are able to read output.
|
||||||
|
*/
|
||||||
|
public function haveReadSupport(): bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes file handles and pipes.
|
||||||
|
*/
|
||||||
|
public function close();
|
||||||
|
}
|
163
vendor/symfony/process/Pipes/UnixPipes.php
vendored
Normal file
163
vendor/symfony/process/Pipes/UnixPipes.php
vendored
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Process\Pipes;
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UnixPipes implementation uses unix pipes as handles.
|
||||||
|
*
|
||||||
|
* @author Romain Neutron <imprec@gmail.com>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class UnixPipes extends AbstractPipes
|
||||||
|
{
|
||||||
|
private $ttyMode;
|
||||||
|
private $ptyMode;
|
||||||
|
private $haveReadSupport;
|
||||||
|
|
||||||
|
public function __construct(?bool $ttyMode, bool $ptyMode, $input, bool $haveReadSupport)
|
||||||
|
{
|
||||||
|
$this->ttyMode = $ttyMode;
|
||||||
|
$this->ptyMode = $ptyMode;
|
||||||
|
$this->haveReadSupport = $haveReadSupport;
|
||||||
|
|
||||||
|
parent::__construct($input);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __sleep(): array
|
||||||
|
{
|
||||||
|
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __wakeup()
|
||||||
|
{
|
||||||
|
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
$this->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getDescriptors(): array
|
||||||
|
{
|
||||||
|
if (!$this->haveReadSupport) {
|
||||||
|
$nullstream = fopen('/dev/null', 'c');
|
||||||
|
|
||||||
|
return [
|
||||||
|
['pipe', 'r'],
|
||||||
|
$nullstream,
|
||||||
|
$nullstream,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->ttyMode) {
|
||||||
|
return [
|
||||||
|
['file', '/dev/tty', 'r'],
|
||||||
|
['file', '/dev/tty', 'w'],
|
||||||
|
['file', '/dev/tty', 'w'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->ptyMode && Process::isPtySupported()) {
|
||||||
|
return [
|
||||||
|
['pty'],
|
||||||
|
['pty'],
|
||||||
|
['pty'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
['pipe', 'r'],
|
||||||
|
['pipe', 'w'], // stdout
|
||||||
|
['pipe', 'w'], // stderr
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getFiles(): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function readAndWrite(bool $blocking, bool $close = false): array
|
||||||
|
{
|
||||||
|
$this->unblock();
|
||||||
|
$w = $this->write();
|
||||||
|
|
||||||
|
$read = $e = [];
|
||||||
|
$r = $this->pipes;
|
||||||
|
unset($r[0]);
|
||||||
|
|
||||||
|
// let's have a look if something changed in streams
|
||||||
|
set_error_handler([$this, 'handleError']);
|
||||||
|
if (($r || $w) && false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
|
||||||
|
restore_error_handler();
|
||||||
|
// if a system call has been interrupted, forget about it, let's try again
|
||||||
|
// otherwise, an error occurred, let's reset pipes
|
||||||
|
if (!$this->hasSystemCallBeenInterrupted()) {
|
||||||
|
$this->pipes = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $read;
|
||||||
|
}
|
||||||
|
restore_error_handler();
|
||||||
|
|
||||||
|
foreach ($r as $pipe) {
|
||||||
|
// prior PHP 5.4 the array passed to stream_select is modified and
|
||||||
|
// lose key association, we have to find back the key
|
||||||
|
$read[$type = array_search($pipe, $this->pipes, true)] = '';
|
||||||
|
|
||||||
|
do {
|
||||||
|
$data = @fread($pipe, self::CHUNK_SIZE);
|
||||||
|
$read[$type] .= $data;
|
||||||
|
} while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1])));
|
||||||
|
|
||||||
|
if (!isset($read[$type][0])) {
|
||||||
|
unset($read[$type]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($close && feof($pipe)) {
|
||||||
|
fclose($pipe);
|
||||||
|
unset($this->pipes[$type]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $read;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function haveReadSupport(): bool
|
||||||
|
{
|
||||||
|
return $this->haveReadSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function areOpen(): bool
|
||||||
|
{
|
||||||
|
return (bool) $this->pipes;
|
||||||
|
}
|
||||||
|
}
|
204
vendor/symfony/process/Pipes/WindowsPipes.php
vendored
Normal file
204
vendor/symfony/process/Pipes/WindowsPipes.php
vendored
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Process\Pipes;
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Exception\RuntimeException;
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WindowsPipes implementation uses temporary files as handles.
|
||||||
|
*
|
||||||
|
* @see https://bugs.php.net/51800
|
||||||
|
* @see https://bugs.php.net/65650
|
||||||
|
*
|
||||||
|
* @author Romain Neutron <imprec@gmail.com>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class WindowsPipes extends AbstractPipes
|
||||||
|
{
|
||||||
|
private $files = [];
|
||||||
|
private $fileHandles = [];
|
||||||
|
private $lockHandles = [];
|
||||||
|
private $readBytes = [
|
||||||
|
Process::STDOUT => 0,
|
||||||
|
Process::STDERR => 0,
|
||||||
|
];
|
||||||
|
private $haveReadSupport;
|
||||||
|
|
||||||
|
public function __construct($input, bool $haveReadSupport)
|
||||||
|
{
|
||||||
|
$this->haveReadSupport = $haveReadSupport;
|
||||||
|
|
||||||
|
if ($this->haveReadSupport) {
|
||||||
|
// Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big.
|
||||||
|
// Workaround for this problem is to use temporary files instead of pipes on Windows platform.
|
||||||
|
//
|
||||||
|
// @see https://bugs.php.net/51800
|
||||||
|
$pipes = [
|
||||||
|
Process::STDOUT => Process::OUT,
|
||||||
|
Process::STDERR => Process::ERR,
|
||||||
|
];
|
||||||
|
$tmpDir = sys_get_temp_dir();
|
||||||
|
$lastError = 'unknown reason';
|
||||||
|
set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; });
|
||||||
|
for ($i = 0;; ++$i) {
|
||||||
|
foreach ($pipes as $pipe => $name) {
|
||||||
|
$file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
|
||||||
|
|
||||||
|
if (!$h = fopen($file.'.lock', 'w')) {
|
||||||
|
if (file_exists($file.'.lock')) {
|
||||||
|
continue 2;
|
||||||
|
}
|
||||||
|
restore_error_handler();
|
||||||
|
throw new RuntimeException('A temporary file could not be opened to write the process output: '.$lastError);
|
||||||
|
}
|
||||||
|
if (!flock($h, \LOCK_EX | \LOCK_NB)) {
|
||||||
|
continue 2;
|
||||||
|
}
|
||||||
|
if (isset($this->lockHandles[$pipe])) {
|
||||||
|
flock($this->lockHandles[$pipe], \LOCK_UN);
|
||||||
|
fclose($this->lockHandles[$pipe]);
|
||||||
|
}
|
||||||
|
$this->lockHandles[$pipe] = $h;
|
||||||
|
|
||||||
|
if (!($h = fopen($file, 'w')) || !fclose($h) || !$h = fopen($file, 'r')) {
|
||||||
|
flock($this->lockHandles[$pipe], \LOCK_UN);
|
||||||
|
fclose($this->lockHandles[$pipe]);
|
||||||
|
unset($this->lockHandles[$pipe]);
|
||||||
|
continue 2;
|
||||||
|
}
|
||||||
|
$this->fileHandles[$pipe] = $h;
|
||||||
|
$this->files[$pipe] = $file;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
restore_error_handler();
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::__construct($input);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __sleep(): array
|
||||||
|
{
|
||||||
|
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __wakeup()
|
||||||
|
{
|
||||||
|
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
$this->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getDescriptors(): array
|
||||||
|
{
|
||||||
|
if (!$this->haveReadSupport) {
|
||||||
|
$nullstream = fopen('NUL', 'c');
|
||||||
|
|
||||||
|
return [
|
||||||
|
['pipe', 'r'],
|
||||||
|
$nullstream,
|
||||||
|
$nullstream,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're not using pipe on Windows platform as it hangs (https://bugs.php.net/51800)
|
||||||
|
// We're not using file handles as it can produce corrupted output https://bugs.php.net/65650
|
||||||
|
// So we redirect output within the commandline and pass the nul device to the process
|
||||||
|
return [
|
||||||
|
['pipe', 'r'],
|
||||||
|
['file', 'NUL', 'w'],
|
||||||
|
['file', 'NUL', 'w'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getFiles(): array
|
||||||
|
{
|
||||||
|
return $this->files;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function readAndWrite(bool $blocking, bool $close = false): array
|
||||||
|
{
|
||||||
|
$this->unblock();
|
||||||
|
$w = $this->write();
|
||||||
|
$read = $r = $e = [];
|
||||||
|
|
||||||
|
if ($blocking) {
|
||||||
|
if ($w) {
|
||||||
|
@stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6);
|
||||||
|
} elseif ($this->fileHandles) {
|
||||||
|
usleep(Process::TIMEOUT_PRECISION * 1E6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($this->fileHandles as $type => $fileHandle) {
|
||||||
|
$data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);
|
||||||
|
|
||||||
|
if (isset($data[0])) {
|
||||||
|
$this->readBytes[$type] += \strlen($data);
|
||||||
|
$read[$type] = $data;
|
||||||
|
}
|
||||||
|
if ($close) {
|
||||||
|
ftruncate($fileHandle, 0);
|
||||||
|
fclose($fileHandle);
|
||||||
|
flock($this->lockHandles[$type], \LOCK_UN);
|
||||||
|
fclose($this->lockHandles[$type]);
|
||||||
|
unset($this->fileHandles[$type], $this->lockHandles[$type]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $read;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function haveReadSupport(): bool
|
||||||
|
{
|
||||||
|
return $this->haveReadSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function areOpen(): bool
|
||||||
|
{
|
||||||
|
return $this->pipes && $this->fileHandles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function close()
|
||||||
|
{
|
||||||
|
parent::close();
|
||||||
|
foreach ($this->fileHandles as $type => $handle) {
|
||||||
|
ftruncate($handle, 0);
|
||||||
|
fclose($handle);
|
||||||
|
flock($this->lockHandles[$type], \LOCK_UN);
|
||||||
|
fclose($this->lockHandles[$type]);
|
||||||
|
}
|
||||||
|
$this->fileHandles = $this->lockHandles = [];
|
||||||
|
}
|
||||||
|
}
|
1652
vendor/symfony/process/Process.php
vendored
Normal file
1652
vendor/symfony/process/Process.php
vendored
Normal file
File diff suppressed because it is too large
Load diff
69
vendor/symfony/process/ProcessUtils.php
vendored
Normal file
69
vendor/symfony/process/ProcessUtils.php
vendored
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Process;
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Exception\InvalidArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ProcessUtils is a bunch of utility methods.
|
||||||
|
*
|
||||||
|
* This class contains static methods only and is not meant to be instantiated.
|
||||||
|
*
|
||||||
|
* @author Martin Hasoň <martin.hason@gmail.com>
|
||||||
|
*/
|
||||||
|
class ProcessUtils
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* This class should not be instantiated.
|
||||||
|
*/
|
||||||
|
private function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates and normalizes a Process input.
|
||||||
|
*
|
||||||
|
* @param string $caller The name of method call that validates the input
|
||||||
|
* @param mixed $input The input to validate
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException In case the input is not valid
|
||||||
|
*/
|
||||||
|
public static function validateInput(string $caller, $input)
|
||||||
|
{
|
||||||
|
if (null !== $input) {
|
||||||
|
if (\is_resource($input)) {
|
||||||
|
return $input;
|
||||||
|
}
|
||||||
|
if (\is_string($input)) {
|
||||||
|
return $input;
|
||||||
|
}
|
||||||
|
if (is_scalar($input)) {
|
||||||
|
return (string) $input;
|
||||||
|
}
|
||||||
|
if ($input instanceof Process) {
|
||||||
|
return $input->getIterator($input::ITER_SKIP_ERR);
|
||||||
|
}
|
||||||
|
if ($input instanceof \Iterator) {
|
||||||
|
return $input;
|
||||||
|
}
|
||||||
|
if ($input instanceof \Traversable) {
|
||||||
|
return new \IteratorIterator($input);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidArgumentException(sprintf('"%s" only accepts strings, Traversable objects or stream resources.', $caller));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $input;
|
||||||
|
}
|
||||||
|
}
|
28
vendor/symfony/process/README.md
vendored
Normal file
28
vendor/symfony/process/README.md
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
Process Component
|
||||||
|
=================
|
||||||
|
|
||||||
|
The Process component executes commands in sub-processes.
|
||||||
|
|
||||||
|
Sponsor
|
||||||
|
-------
|
||||||
|
|
||||||
|
The Process component for Symfony 5.4/6.0 is [backed][1] by [SensioLabs][2].
|
||||||
|
|
||||||
|
As the creator of Symfony, SensioLabs supports companies using Symfony, with an
|
||||||
|
offering encompassing consultancy, expertise, services, training, and technical
|
||||||
|
assistance to ensure the success of web application development projects.
|
||||||
|
|
||||||
|
Help Symfony by [sponsoring][3] its development!
|
||||||
|
|
||||||
|
Resources
|
||||||
|
---------
|
||||||
|
|
||||||
|
* [Documentation](https://symfony.com/doc/current/components/process.html)
|
||||||
|
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||||
|
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||||
|
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||||
|
in the [main Symfony repository](https://github.com/symfony/symfony)
|
||||||
|
|
||||||
|
[1]: https://symfony.com/backers
|
||||||
|
[2]: https://sensiolabs.com
|
||||||
|
[3]: https://symfony.com/sponsor
|
29
vendor/symfony/process/composer.json
vendored
Normal file
29
vendor/symfony/process/composer.json
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"name": "symfony/process",
|
||||||
|
"type": "library",
|
||||||
|
"description": "Executes commands in sub-processes",
|
||||||
|
"keywords": [],
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.2.5",
|
||||||
|
"symfony/polyfill-php80": "^1.16"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": { "Symfony\\Component\\Process\\": "" },
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"minimum-stability": "dev"
|
||||||
|
}
|
Loading…
Reference in a new issue