Add Mailer service and start Track command.
parent
87e4a5a4fd
commit
aeae9ea490
|
@ -19,7 +19,8 @@
|
|||
"php-di/php-di": "^6.3",
|
||||
"symfony/yaml": "^5.2",
|
||||
"mpdf/mpdf": "^8.0",
|
||||
"swiftmailer/swiftmailer": "^6.2"
|
||||
"symfony/mailer": "^5.3",
|
||||
"symfony/google-mailer": "^5.3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "cbb7d7281f9622e5b410185c54558b28",
|
||||
"content-hash": "81050635de2f87c3f7f693ec8cb30645",
|
||||
"packages": [
|
||||
{
|
||||
"name": "doctrine/lexer",
|
||||
|
@ -764,6 +764,56 @@
|
|||
],
|
||||
"time": "2021-03-05T17:36:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/event-dispatcher",
|
||||
"version": "1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/event-dispatcher.git",
|
||||
"reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0",
|
||||
"reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\EventDispatcher\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Standard interfaces for event handling.",
|
||||
"keywords": [
|
||||
"events",
|
||||
"psr",
|
||||
"psr-14"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-fig/event-dispatcher/issues",
|
||||
"source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0"
|
||||
},
|
||||
"time": "2019-01-08T18:20:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-client",
|
||||
"version": "1.0.1",
|
||||
|
@ -1012,81 +1062,6 @@
|
|||
],
|
||||
"time": "2021-02-11T11:37:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "swiftmailer/swiftmailer",
|
||||
"version": "v6.2.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/swiftmailer/swiftmailer.git",
|
||||
"reference": "15f7faf8508e04471f666633addacf54c0ab5933"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/15f7faf8508e04471f666633addacf54c0ab5933",
|
||||
"reference": "15f7faf8508e04471f666633addacf54c0ab5933",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"egulias/email-validator": "^2.0|^3.1",
|
||||
"php": ">=7.0.0",
|
||||
"symfony/polyfill-iconv": "^1.0",
|
||||
"symfony/polyfill-intl-idn": "^1.10",
|
||||
"symfony/polyfill-mbstring": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.0",
|
||||
"symfony/phpunit-bridge": "^4.4|^5.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-intl": "Needed to support internationalized email addresses"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "6.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"lib/swift_required.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Chris Corbyn"
|
||||
},
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
}
|
||||
],
|
||||
"description": "Swiftmailer, free feature-rich PHP mailer",
|
||||
"homepage": "https://swiftmailer.symfony.com",
|
||||
"keywords": [
|
||||
"email",
|
||||
"mail",
|
||||
"mailer"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/swiftmailer/swiftmailer/issues",
|
||||
"source": "https://github.com/swiftmailer/swiftmailer/tree/v6.2.7"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/swiftmailer/swiftmailer",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-03-09T12:30:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v5.2.6",
|
||||
|
@ -1217,6 +1192,393 @@
|
|||
"homepage": "https://symfony.com",
|
||||
"time": "2020-09-07T11:33:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
"version": "v5.3.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||
"reference": "ce7b20d69c66a20939d8952b617506a44d102130"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ce7b20d69c66a20939d8952b617506a44d102130",
|
||||
"reference": "ce7b20d69c66a20939d8952b617506a44d102130",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"symfony/deprecation-contracts": "^2.1",
|
||||
"symfony/event-dispatcher-contracts": "^2",
|
||||
"symfony/polyfill-php80": "^1.16"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/dependency-injection": "<4.4"
|
||||
},
|
||||
"provide": {
|
||||
"psr/event-dispatcher-implementation": "1.0",
|
||||
"symfony/event-dispatcher-implementation": "2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"psr/log": "^1|^2|^3",
|
||||
"symfony/config": "^4.4|^5.0",
|
||||
"symfony/dependency-injection": "^4.4|^5.0",
|
||||
"symfony/error-handler": "^4.4|^5.0",
|
||||
"symfony/expression-language": "^4.4|^5.0",
|
||||
"symfony/http-foundation": "^4.4|^5.0",
|
||||
"symfony/service-contracts": "^1.1|^2",
|
||||
"symfony/stopwatch": "^4.4|^5.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/dependency-injection": "",
|
||||
"symfony/http-kernel": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\EventDispatcher\\": ""
|
||||
},
|
||||
"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": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/event-dispatcher/tree/v5.3.7"
|
||||
},
|
||||
"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": "2021-08-04T21:20:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher-contracts",
|
||||
"version": "v2.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
|
||||
"reference": "69fee1ad2332a7cbab3aca13591953da9cdb7a11"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/69fee1ad2332a7cbab3aca13591953da9cdb7a11",
|
||||
"reference": "69fee1ad2332a7cbab3aca13591953da9cdb7a11",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"psr/event-dispatcher": "^1"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/event-dispatcher-implementation": ""
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "2.4-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/contracts",
|
||||
"url": "https://github.com/symfony/contracts"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Contracts\\EventDispatcher\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Generic abstractions related to dispatching event",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"abstractions",
|
||||
"contracts",
|
||||
"decoupling",
|
||||
"interfaces",
|
||||
"interoperability",
|
||||
"standards"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.4.0"
|
||||
},
|
||||
"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": "2021-03-23T23:28:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/google-mailer",
|
||||
"version": "v5.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/google-mailer.git",
|
||||
"reference": "6b6aa67cc6a6c24adc88d98c23c642950effb739"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/google-mailer/zipball/6b6aa67cc6a6c24adc88d98c23c642950effb739",
|
||||
"reference": "6b6aa67cc6a6c24adc88d98c23c642950effb739",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"symfony/mailer": "^4.4|^5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/http-client": "^4.4|^5.0"
|
||||
},
|
||||
"type": "symfony-bridge",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Mailer\\Bridge\\Google\\": ""
|
||||
},
|
||||
"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": "Symfony Google Mailer Bridge",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/google-mailer/tree/v5.3.0"
|
||||
},
|
||||
"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": "2021-05-26T17:33:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/mailer",
|
||||
"version": "v5.3.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/mailer.git",
|
||||
"reference": "c1f83da2296741110be35dd779f2a9e412cec466"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/mailer/zipball/c1f83da2296741110be35dd779f2a9e412cec466",
|
||||
"reference": "c1f83da2296741110be35dd779f2a9e412cec466",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"egulias/email-validator": "^2.1.10|^3",
|
||||
"php": ">=7.2.5",
|
||||
"psr/log": "^1|^2|^3",
|
||||
"symfony/deprecation-contracts": "^2.1",
|
||||
"symfony/event-dispatcher": "^4.4|^5.0",
|
||||
"symfony/mime": "^5.2.6",
|
||||
"symfony/polyfill-php80": "^1.16",
|
||||
"symfony/service-contracts": "^1.1|^2"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/http-kernel": "<4.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/http-client-contracts": "^1.1|^2",
|
||||
"symfony/messenger": "^4.4|^5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Mailer\\": ""
|
||||
},
|
||||
"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": "Helps sending emails",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/mailer/tree/v5.3.4"
|
||||
},
|
||||
"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": "2021-07-23T15:55:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/mime",
|
||||
"version": "v5.3.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/mime.git",
|
||||
"reference": "ae887cb3b044658676129f5e97aeb7e9eb69c2d8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/mime/zipball/ae887cb3b044658676129f5e97aeb7e9eb69c2d8",
|
||||
"reference": "ae887cb3b044658676129f5e97aeb7e9eb69c2d8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"symfony/deprecation-contracts": "^2.1",
|
||||
"symfony/polyfill-intl-idn": "^1.10",
|
||||
"symfony/polyfill-mbstring": "^1.0",
|
||||
"symfony/polyfill-php80": "^1.16"
|
||||
},
|
||||
"conflict": {
|
||||
"egulias/email-validator": "~3.0.0",
|
||||
"phpdocumentor/reflection-docblock": "<3.2.2",
|
||||
"phpdocumentor/type-resolver": "<1.4.0",
|
||||
"symfony/mailer": "<4.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"egulias/email-validator": "^2.1.10|^3.1",
|
||||
"phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
|
||||
"symfony/dependency-injection": "^4.4|^5.0",
|
||||
"symfony/property-access": "^4.4|^5.1",
|
||||
"symfony/property-info": "^4.4|^5.1",
|
||||
"symfony/serializer": "^5.2"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Mime\\": ""
|
||||
},
|
||||
"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": "Allows manipulating MIME messages",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"mime",
|
||||
"mime-type"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/mime/tree/v5.3.7"
|
||||
},
|
||||
"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": "2021-08-20T11:40:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.22.1",
|
||||
|
@ -1279,86 +1641,6 @@
|
|||
],
|
||||
"time": "2021-01-07T16:49:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-iconv",
|
||||
"version": "v1.23.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-iconv.git",
|
||||
"reference": "63b5bb7db83e5673936d6e3b8b3e022ff6474933"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/63b5bb7db83e5673936d6e3b8b3e022ff6474933",
|
||||
"reference": "63b5bb7db83e5673936d6e3b8b3e022ff6474933",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-iconv": "For best performance"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Iconv\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for the Iconv extension",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"iconv",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-iconv/tree/v1.23.0"
|
||||
},
|
||||
"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": "2021-05-27T09:27:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-grapheme",
|
||||
"version": "v1.22.1",
|
||||
|
@ -4013,5 +4295,5 @@
|
|||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.0.0"
|
||||
"plugin-api-version": "2.1.0"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
Hello [[name]],
|
||||
|
||||
I'm sending you the invoice for [[month]] [[year]].
|
||||
|
||||
This email and invoice were generated and send by rprt-cli.
|
||||
|
||||
|
||||
Kind regards
|
||||
|
||||
[[me]]
|
|
@ -17,6 +17,10 @@ export:
|
|||
- 'Hours'
|
||||
- 'Rate'
|
||||
- 'Price'
|
||||
email:
|
||||
tokens:
|
||||
me: 'Lio Novelli'
|
||||
another_token: '1234567890'
|
||||
projects:
|
||||
'<short name of first project>':
|
||||
name: '<Project long name>'
|
||||
|
|
|
@ -10,6 +10,8 @@ use RprtCli\Utils\CsvReport\CsvReport;
|
|||
use RprtCli\Utils\CsvReport\CsvReportInterface;
|
||||
use GuzzleHttp\Client;
|
||||
use Mpdf\Mpdf;
|
||||
use RprtCli\Utils\Mailer\MailerInterface;
|
||||
use RprtCli\Utils\Mailer\MailerService;
|
||||
use RprtCli\Utils\PdfExport\PdfExportInterface;
|
||||
use RprtCli\Utils\PdfExport\PdfExportService;
|
||||
use RprtCli\Utils\TimeTrackingServices\YoutrackInterface;
|
||||
|
@ -52,10 +54,21 @@ return [
|
|||
get('config.service')
|
||||
),
|
||||
'csv.report' => get(CsvReportInterface::class),
|
||||
MailerInterface::class => get(MailerService::class),
|
||||
MailerService::class => create()->constructor(
|
||||
get('config.service'),
|
||||
get('pdf_export.service')
|
||||
),
|
||||
'mailer' => get(MailerInterface::class),
|
||||
RprtCommand::class => create()->constructor(
|
||||
get('csv.report'),
|
||||
get('config.service'),
|
||||
get('youtrack.service'),
|
||||
get('pdf_export.service')
|
||||
get('pdf_export.service'),
|
||||
get('mailer')
|
||||
),
|
||||
TrackCommand::class => create()->constructor(
|
||||
get('config.service'),
|
||||
get('youtrack.service')
|
||||
)
|
||||
];
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace RprtCli\Commands;
|
|||
|
||||
use RprtCli\Utils\Configuration\ConfigurationInterface;
|
||||
use RprtCli\Utils\CsvReport\CsvReportInterface;
|
||||
use RprtCli\Utils\Mailer\MailerInterface;
|
||||
use RprtCli\Utils\PdfExport\PdfExportInterface;
|
||||
use RprtCli\Utils\TimeTrackingServices\YoutrackInterface;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
|
@ -38,12 +39,14 @@ class RprtCommand extends Command
|
|||
ConfigurationInterface $configuration,
|
||||
YoutrackInterface $youtrack,
|
||||
PdfExportInterface $pdf_export,
|
||||
MailerInterface $mailer,
|
||||
?string $name = null
|
||||
) {
|
||||
$this->csv = $csv;
|
||||
$this->configuration = $configuration;
|
||||
$this->youtrack = $youtrack;
|
||||
$this->pdfExport = $pdf_export;
|
||||
$this->mailer = $mailer;
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
|
@ -112,18 +115,19 @@ class RprtCommand extends Command
|
|||
$table->render();
|
||||
|
||||
if ($pdf = $input->getOption('pdf')) {
|
||||
$nice_data = $this->csv->arangeDataForPdfExport($data);
|
||||
$nice_data = $this->csv->arangeDataForDefaultPdfExport($data);
|
||||
// @TODO method gatherTokens();
|
||||
if ($output = $input->getOption('output')) {
|
||||
$this->pdfExport->setOutput($output);
|
||||
}
|
||||
$output_path = $this->pdfExport->fromDataToPdf($nice_data);
|
||||
$output_path = $this->pdfExport->fromDefaultDataToPdf($nice_data);
|
||||
}
|
||||
|
||||
// return Command::SUCCESS;
|
||||
}
|
||||
if ($send = $input->getOption('send') && $output_path) {
|
||||
// Send email to configured address.
|
||||
$this->mailer->sendDefaultMail($output_path);
|
||||
}
|
||||
|
||||
// $this->dummyOutput($input, $output);
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace RprtCli\Commands;
|
||||
|
||||
use RprtCli\Utils\Configuration\ConfigurationInterface;
|
||||
use RprtCli\Utils\TimeTrackingServices\YoutrackInterface;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
|
||||
/**
|
||||
* Track time from comfortableness of your terminal.
|
||||
*
|
||||
* Later connect this command to the Emacs and have your time tracked directly
|
||||
* from orgmode.
|
||||
*/
|
||||
class TrackCommand extends Command {
|
||||
|
||||
protected $config;
|
||||
|
||||
protected $youtrack;
|
||||
|
||||
public function __construct(
|
||||
ConfigurationInterface $config,
|
||||
YoutrackInterface $youtrack,
|
||||
?string $name = null
|
||||
) {
|
||||
$this->config = $config;
|
||||
$this->youtrack = $youtrack;
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function configure(): void {
|
||||
$this->setName('youtrack');
|
||||
$this->setDescription('Track time into your youtrack service');
|
||||
$this->addUsage('rprt-cli youtrack --issue=[issue-name] --minutes=[minutes] --date=[days-ago] --description=[text] --work-type=[work-type]');
|
||||
// Options or arguments? Technically they are arguments but default value could be provided by config.
|
||||
// Options are more suitable.
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -75,7 +75,7 @@ class CsvReport implements CsvReportInterface
|
|||
return [];
|
||||
}
|
||||
|
||||
public function arangeDataForPdfExport(array $data): array {
|
||||
public function arangeDataForDefaultPdfExport(array $data): array {
|
||||
[$rows, $totalHours, $totalPrice] = [[], 0, 0];
|
||||
$projectsConfig = $this->configurationService->get('projects');
|
||||
$header = $this->configurationService->get('export.labels', null);
|
||||
|
|
|
@ -18,4 +18,13 @@ interface CsvReportInterface
|
|||
* Project key as key and number of hours as value.
|
||||
*/
|
||||
public function getReportData(string $filePath) : array;
|
||||
|
||||
/**
|
||||
* Data for default drunomics pdf export.
|
||||
*
|
||||
* @param array $data
|
||||
* Parsed data from csv report.
|
||||
*/
|
||||
public function arangeDataForDefaultPdfExport(array $data): array;
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace RprtCli\Utils\Mailer;
|
||||
|
||||
/**
|
||||
* Methods for symfony (swift)mailer service.
|
||||
*/
|
||||
interface MailerInterface {
|
||||
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// src/Utils/Mailer/MailerService.php
|
||||
|
||||
namespace RprtCli\Utils\Mailer;
|
||||
|
||||
use RprtCli\Utils\Configuration\ConfigurationInterface;
|
||||
use RprtCli\Utils\PdfExport\PdfExportInterface;
|
||||
use Symfony\Component\Mime\Email;
|
||||
use \Exception;
|
||||
use Symfony\Component\Mailer\Transport;
|
||||
use Symfony\Component\Mailer\Mailer;
|
||||
|
||||
/**
|
||||
* Send emails with invoices as attachments.
|
||||
*
|
||||
* https://symfony.com/doc/current/mailer.html
|
||||
*/
|
||||
class MailerService implements MailerInterface {
|
||||
|
||||
|
||||
protected $config;
|
||||
|
||||
protected $pdf;
|
||||
|
||||
// Data properties.
|
||||
protected $to;
|
||||
protected $subject;
|
||||
protected $text;
|
||||
protected $attachment;
|
||||
protected $templatePath;
|
||||
|
||||
protected $email;
|
||||
|
||||
public function __construct(ConfigurationInterface $config, PdfExportInterface $pdf) {
|
||||
$this->config = $config;
|
||||
$this->pdf = $pdf;
|
||||
}
|
||||
|
||||
public function setRecipents(array $to): void
|
||||
{
|
||||
$this->to = $to;
|
||||
}
|
||||
|
||||
public function setSubject(string $subject): void {
|
||||
$this->subject = $subject;
|
||||
}
|
||||
|
||||
public function setAttachment(string $path): void {
|
||||
// @TODO - add some error handling.
|
||||
$this->attachment = $path;
|
||||
}
|
||||
|
||||
public function getProperty(string $property) {
|
||||
// Only for simple value properies - string and numbers.
|
||||
// from, to, subject.
|
||||
if (!isset($this->{$property})) {
|
||||
$value = $this->config->get('email.' . $property, FALSE);
|
||||
if (!$value) {
|
||||
$value = readline("Property {$property} is not configured. Enter value: ");
|
||||
}
|
||||
$this->{$property} = $value;
|
||||
}
|
||||
return $this->{$property};
|
||||
}
|
||||
|
||||
public function sendMail(string $from, array $to, string $subject, string $text, array $attachment = []): void {
|
||||
$email = new Email();
|
||||
$email->from($from);
|
||||
$email->to($to[0]);
|
||||
// @TODO use twig for templates. Create new template service.
|
||||
// https://github.com/symfony/mailer
|
||||
$email->subject($subject);
|
||||
$email->text($text);
|
||||
if (!empty($attachment)) {
|
||||
if (!isset($attachment['path'])) {
|
||||
var_dump('Attachment path missing!');
|
||||
}
|
||||
else {
|
||||
$email->attachFromPath($attachment['path'], $attachment['name'] ?? null, $attachment['type'] ?? null);
|
||||
}
|
||||
}
|
||||
// Not sure whether it would be nicer to use class property instead of variable.
|
||||
$transport = $this->getTransport();
|
||||
$mailer = $this->getMailer($transport);
|
||||
$mailer->send($email);
|
||||
}
|
||||
|
||||
public function getTransport() {
|
||||
// @TODO remove username and password from config.
|
||||
$username = rawurlencode($this->getProperty('username'));
|
||||
$password = rawurlencode($this->getProperty('password'));
|
||||
// If your credentials contain special characters, you must URL-encode them.
|
||||
$mailer_dsn = "gmail+smtp://{$username}:{$password}@default";
|
||||
return Transport::fromDsn($mailer_dsn);
|
||||
}
|
||||
|
||||
public function getMailer($transport) {
|
||||
return new Mailer($transport);
|
||||
}
|
||||
|
||||
public function sendDefaultMail(string $output): void {
|
||||
$tokens = $this->pdf->gatherTokensForTemplate($this->getEmailTemplatePath(), FALSE, $this->getDefaultTokens(), 'email.tokens');
|
||||
$text = $this->pdf->replaceTokensInTemplate($this->getEmailTemplatePath(), $tokens);
|
||||
$this->sendMail(
|
||||
$this->getProperty('from'),
|
||||
$this->getProperty('to'),
|
||||
$this->getProperty('subject'),
|
||||
$text,
|
||||
['path' => $output, 'Invoice', 'application/pdf']
|
||||
);
|
||||
}
|
||||
|
||||
public function getDefaultTokens(): array {
|
||||
$tokens = [];
|
||||
$date = strtotime('-1 month');
|
||||
$tokens['month'] = date('F', $date);
|
||||
$tokens['year'] = date('Y', $date);
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
protected function getEmailTemplatePath(): ?string {
|
||||
if (!isset($this->templatePath)) {
|
||||
$template_path = $this->config->get('email.template_path', FALSE);
|
||||
if (!$template_path) {
|
||||
$template_path = readline('Enter template file path: ');
|
||||
}
|
||||
if (!file_exists($template_path)) {
|
||||
throw new Exception('Template file not found!');
|
||||
}
|
||||
$this->templatePath = $template_path;
|
||||
}
|
||||
return $this->templatePath;
|
||||
}
|
||||
|
||||
public function setEmailTemplatePath(string $path): void {
|
||||
if (file_exists($path)) {
|
||||
$this->templatePath = $path;
|
||||
return;
|
||||
}
|
||||
throw new Exception('Email template file not found!');
|
||||
}
|
||||
|
||||
}
|
|
@ -41,4 +41,42 @@ interface PdfExportInterface {
|
|||
*/
|
||||
public function pdfExport(string $html) : bool;
|
||||
|
||||
/**
|
||||
* Goes through the whole process of creating a pdf for the invoice.
|
||||
*
|
||||
* @param array $nice_data
|
||||
* Parsed csv report export data.
|
||||
*
|
||||
* @return string
|
||||
* Path of the pdf file.
|
||||
*/
|
||||
public function fromDefaultDataToPdf(array $nice_data, array $tokens = []): string;
|
||||
|
||||
/**
|
||||
* Sets output file override via command paramater.
|
||||
*
|
||||
* @param string $output
|
||||
* Path of the output pdf file ('/tmp/test.pdf').
|
||||
*/
|
||||
public function setOutput(string $output): void;
|
||||
|
||||
// @TODO support multiple templates by adding template id in config.
|
||||
// @TODO implement twig.
|
||||
/**
|
||||
* Get tokens to replace in the template.
|
||||
*
|
||||
* @param string $template_path
|
||||
* Path to the template file (long term plan is to support multiple templates).
|
||||
* @param bool $skip_missing
|
||||
* Just skip missing tokens.
|
||||
* @param array $runtime_tokens
|
||||
* Provide tokens at runtime of the application (not supported yet). @TODO
|
||||
* @param string $config
|
||||
* Config path to tokens.
|
||||
*
|
||||
* @return array
|
||||
* Token keys and values array.
|
||||
*/
|
||||
public function gatherTokensForTemplate(string $template_path, bool $skip_missing, array $runtime_tokens = [], string $config = 'export.token'): array;
|
||||
|
||||
}
|
||||
|
|
|
@ -22,8 +22,7 @@ class PdfExportService implements PdfExportInterface {
|
|||
$this->mpdf = $mpdf;
|
||||
}
|
||||
|
||||
public function getTemplatePath(): ?string
|
||||
{
|
||||
public function getTemplatePath(): ?string {
|
||||
if (!isset($this->templatePath)) {
|
||||
$template_path = $this->config->get('export.template_path', FALSE);
|
||||
if (!$template_path) {
|
||||
|
@ -42,7 +41,7 @@ class PdfExportService implements PdfExportInterface {
|
|||
$this->templatePath = $path;
|
||||
return;
|
||||
}
|
||||
throw new Exception('Template file not found!');
|
||||
throw new Exception('Invoice template file not found!');
|
||||
}
|
||||
|
||||
// @TODO move this method to CsvReport.
|
||||
|
@ -104,14 +103,16 @@ class PdfExportService implements PdfExportInterface {
|
|||
* Just skip missing tokens.
|
||||
* @param array $runtime_tokens
|
||||
* Provide tokens at runtime of the application (not supported yet). @TODO
|
||||
* @param string $config
|
||||
* Config path to tokens.
|
||||
*
|
||||
* @return array
|
||||
* Token keys and values array.
|
||||
*/
|
||||
public function gatherTokensForTemplate(string $template_path, bool $skip_missing = FALSE, array $runtime_tokens = []): array {
|
||||
public function gatherTokensForTemplate(string $template_path, bool $skip_missing = FALSE, array $runtime_tokens = [], string $config = 'export.tokens'): array {
|
||||
list($tokens, $missing) = [[], []];
|
||||
$token_keys = $this->getTokensInTemplate(file_get_contents($template_path));
|
||||
$config_tokens = $this->config->get('export.tokens');
|
||||
$config_tokens = $this->config->get($config);
|
||||
foreach ($token_keys as $token_key) {
|
||||
if (isset($runtime_tokens[$token_key])) {
|
||||
$tokens[$token_key] = $runtime_tokens[$token_key];
|
||||
|
@ -145,24 +146,28 @@ class PdfExportService implements PdfExportInterface {
|
|||
return $this->output;
|
||||
}
|
||||
$output = $this->config->get('export.output', NULL) ?? readline('Enter output file path: ');
|
||||
$output = str_replace('[[month]]', date('F'), $output);
|
||||
$output = str_replace('[[year]]', date('Y'), $output);
|
||||
$date = strtotime("-1 month");
|
||||
$output = str_replace('[[month]]', date('F', $date), $output);
|
||||
$output = str_replace('[[year]]', date('Y', $date), $output);
|
||||
$this->output = $output;
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function setOutput(string $path) {
|
||||
public function setOutput(string $path): void {
|
||||
$this->output = $path;
|
||||
}
|
||||
|
||||
public function fromDataToPdf(array $data, array $tokens = []): bool {
|
||||
public function fromDefaultDataToPdf(array $data, array $tokens = []): string {
|
||||
$template_path = $this->getTemplatePath();
|
||||
$tokens = $this->defaultTokens();
|
||||
$tokens['table'] = $this->parsedDataToHtmlTable($data);
|
||||
$tokens = $this->gatherTokensForTemplate($template_path, FALSE, $tokens);
|
||||
$html = $this->replaceTokensInTemplate($template_path, $tokens);
|
||||
$success = $this->pdfExport($html);
|
||||
return $success;
|
||||
if ($success) {
|
||||
return $this->getOutput();
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -64,7 +64,7 @@ class YoutrackService implements YoutrackInterface
|
|||
public function downloadReport(string $report_id): ?string
|
||||
{
|
||||
$path = "youtrack/api/reports/$report_id/export/csv";
|
||||
$query = ['$top' => -1];
|
||||
$query = ['\$top' => -1];
|
||||
$yt_token = $this->getYtToken();
|
||||
$headers = [
|
||||
'Accept' => 'text/plain, */*',
|
||||
|
|
Loading…
Reference in New Issue