diff --git a/README.md b/README.md
index 0b259c518..8aac9b9fe 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,5 @@
Marello
========================
-[![GitHub release](https://img.shields.io/github/release/marellocommerce/marello.svg)](https://github.com/marellocommerce/marello/releases)
What is Marello?
-----------
@@ -25,7 +24,7 @@ Use as dependency in composer
Run unit tests
--------------
-Please make sure you have at least phpunit 6.5 or above.
+Please make sure you have at least phpunit 7.5 or above.
To run unit tests of any bundles:
```bash
diff --git a/composer.json b/composer.json
index dd3e7bd8d..d57ff137c 100644
--- a/composer.json
+++ b/composer.json
@@ -5,7 +5,7 @@
"license": "OSL-3.0",
"authors": [
{
- "name": "Madia B.V.",
+ "name": "Marello B.V.",
"homepage": "https://www.marello.com"
}
],
@@ -20,16 +20,16 @@
}
},
"require": {
- "php": ">=7.1.26",
- "oro/platform": "~3.1.1",
- "oro/platform-serialised-fields": "~3.1.1",
- "oro/calendar-bundle": "~3.1.1"
+ "oro/platform": "4.1.*",
+ "oro/platform-serialised-fields": "4.1.*",
+ "oro/calendar-bundle": "4.1.*",
+ "mpdf/mpdf": "^7.1"
},
"minimum-stability": "dev",
"prefer-stable": true,
"extra": {
"branch-alias": {
- "dev-master": "2.1-dev"
+ "dev-master": "3.0-dev"
}
},
"autoload": {
diff --git a/phpcs.xml b/phpcs.xml
new file mode 100644
index 000000000..1ca997513
--- /dev/null
+++ b/phpcs.xml
@@ -0,0 +1,10 @@
+
+
Page 1
', + 'expected' => base64_decode(file_get_contents(__DIR__.'/data/single.txt')), + 'filename' => '/tmp/pdf_single.pdf', + ], + 'multiple pages' => [ + 'input' => 'Page 1
Page 2
', + 'expected' => base64_decode(file_get_contents(__DIR__.'/data/multiple.txt')), + 'filename' => '/tmp/pdf_multiple.pdf', + ], + ]; + } +} diff --git a/src/Marello/Bundle/PdfBundle/Tests/Unit/Renderer/data/multiple.txt b/src/Marello/Bundle/PdfBundle/Tests/Unit/Renderer/data/multiple.txt new file mode 100644 index 000000000..9d62e8b44 --- /dev/null +++ b/src/Marello/Bundle/PdfBundle/Tests/Unit/Renderer/data/multiple.txt @@ -0,0 +1 @@ +JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL01lZGlhQm94IFswIDAgNTk1LjI4MCA4NDEuODkwXQovVHJpbUJveCBbMC4wMDAgMC4wMDAgNTk1LjI4MCA4NDEuODkwXQovUmVzb3VyY2VzIDIgMCBSCi9Hcm91cCA8PCAvVHlwZSAvR3JvdXAgL1MgL1RyYW5zcGFyZW5jeSAvQ1MgL0RldmljZVJHQiA+PiAKL0NvbnRlbnRzIDQgMCBSPj4KZW5kb2JqCjQgMCBvYmoKPDwvRmlsdGVyIC9GbGF0ZURlY29kZSAvTGVuZ3RoIDE0MT4+CnN0cmVhbQp4nI2OsQoCQQxEU+crptQml4S9W2tBD6wUtxML4XTBTi38ffc8PNRCrBKYmTcDx4pV6ibizvOEamkwE1VFOmGRePhz8fS35ardGvJtzBTflXd7KLpRe3Ic7m+cCwZCBvoIiie41K6IMYg2M6QOmNCaDpTpSCCbIp1LFJtP8NfAl/ajIJi4+z8FDwKxOJwKZW5kc3RyZWFtCmVuZG9iago1IDAgb2JqCjw8L1R5cGUgL1BhZ2UKL1BhcmVudCAxIDAgUgovTWVkaWFCb3ggWzAgMCA1OTUuMjgwIDg0MS44OTBdCi9UcmltQm94IFswLjAwMCAwLjAwMCA1OTUuMjgwIDg0MS44OTBdCi9SZXNvdXJjZXMgMiAwIFIKL0dyb3VwIDw8IC9UeXBlIC9Hcm91cCAvUyAvVHJhbnNwYXJlbmN5IC9DUyAvRGV2aWNlUkdCID4+IAovQ29udGVudHMgNiAwIFI+PgplbmRvYmoKNiAwIG9iago8PC9GaWx0ZXIgL0ZsYXRlRGVjb2RlIC9MZW5ndGggMTQzPj4Kc3RyZWFtCnicjY6xCgIxEES33q+YUpu9TXATrxX0wEoxnVgIpwE7tfD3zXkY0EKsdmFm3gw81qxiIeLBi4Rm5eCcqCrSGcvE45+LZ7gdN93OId9rpvhuvD9A0VftxfFwQaxyrhgJGRgiKJ6ZF/OKGFsJc0PqgQlt6EiZTgTyU6RLiWL7Cf4a+NZ+FJhKa38VPAEQDji9CmVuZHN0cmVhbQplbmRvYmoKMSAwIG9iago8PC9UeXBlIC9QYWdlcwovS2lkcyBbMyAwIFIgNSAwIFIgXQovQ291bnQgMgovTWVkaWFCb3ggWzAgMCA1OTUuMjgwIDg0MS44OTBdCj4+CmVuZG9iago3IDAgb2JqCjw8L1R5cGUgL0V4dEdTdGF0ZQovQk0gL05vcm1hbAovY2EgMQovQ0EgMQo+PgplbmRvYmoKOCAwIG9iago8PC9UeXBlIC9Gb250Ci9TdWJ0eXBlIC9UeXBlMAovQmFzZUZvbnQgL01QREZBQStEZWphVnVTZXJpZkNvbmRlbnNlZAovRW5jb2RpbmcgL0lkZW50aXR5LUgKL0Rlc2NlbmRhbnRGb250cyBbOSAwIFJdCi9Ub1VuaWNvZGUgMTAgMCBSCj4+CmVuZG9iago5IDAgb2JqCjw8L1R5cGUgL0ZvbnQKL1N1YnR5cGUgL0NJREZvbnRUeXBlMgovQmFzZUZvbnQgL01QREZBQStEZWphVnVTZXJpZkNvbmRlbnNlZAovQ0lEU3lzdGVtSW5mbyAxMSAwIFIKL0ZvbnREZXNjcmlwdG9yIDEyIDAgUgovRFcgNTQwCi9XIFsgMzIgWyAyODYgMzYxIDQxNCA3NTQgNTcyIDg1NSA4MDEgMjQ3IDM1MSAzNTEgNDUwIDc1NCAyODYgMzA0IDI4NiAzMDMgXQogNDggNTcgNTcyIDU4IDU5IDMwMyA2MCA2MiA3NTQgNjMgWyA0ODIgOTAwIDY1MCA2NjEgNjg4IDcyMSA2NTcgNjI0IDcxOSA3ODUgMzU1IDM2MCA2NzIgNTk4IDkyMSA3ODcgNzM4IDYwNSA3MzggNjc3IDYxNiA2MDAgNzU4IDY1MCA5MjUgNjQxIDU5NCA2MjUgMzUxIDMwMyAzNTEgNzU0IDQ1MCA0NTAgNTM2IDU3NiA1MDQgNTc2IDUzMiAzMzMgNTc2IDU4MCAyODggMjc5IDU0NSAyODggODUzIDU4MCA1NDIgNTc2IDU3NiA0MzAgNDYxIDM2MSA1ODAgNTA4IDc3MCA1MDcgNTA4IDQ3NCA1NzIgMzAzIDU3MiA3NTQgXQogXQovQ0lEVG9HSURNYXAgMTMgMCBSCj4+CmVuZG9iagoxMCAwIG9iago8PC9MZW5ndGggMzQ2Pj4Kc3RyZWFtCi9DSURJbml0IC9Qcm9jU2V0IGZpbmRyZXNvdXJjZSBiZWdpbgoxMiBkaWN0IGJlZ2luCmJlZ2luY21hcAovQ0lEU3lzdGVtSW5mbwo8PC9SZWdpc3RyeSAoQWRvYmUpCi9PcmRlcmluZyAoVUNTKQovU3VwcGxlbWVudCAwCj4+IGRlZgovQ01hcE5hbWUgL0Fkb2JlLUlkZW50aXR5LVVDUyBkZWYKL0NNYXBUeXBlIDIgZGVmCjEgYmVnaW5jb2Rlc3BhY2VyYW5nZQo8MDAwMD4gPEZGRkY+CmVuZGNvZGVzcGFjZXJhbmdlCjEgYmVnaW5iZnJhbmdlCjwwMDAwPiA8RkZGRj4gPDAwMDA+CmVuZGJmcmFuZ2UKZW5kY21hcApDTWFwTmFtZSBjdXJyZW50ZGljdCAvQ01hcCBkZWZpbmVyZXNvdXJjZSBwb3AKZW5kCmVuZAoKZW5kc3RyZWFtCmVuZG9iagoxMSAwIG9iago8PC9SZWdpc3RyeSAoQWRvYmUpCi9PcmRlcmluZyAoVUNTKQovU3VwcGxlbWVudCAwCj4+CmVuZG9iagoxMiAwIG9iago8PC9UeXBlIC9Gb250RGVzY3JpcHRvcgovRm9udE5hbWUgL01QREZBQStEZWphVnVTZXJpZkNvbmRlbnNlZAogL0NhcEhlaWdodCA3MjkKIC9YSGVpZ2h0IDUxOQogL0ZvbnRCQm94IFstNjkzIC0zNDcgMTUxMiAxMTA5XQogL0ZsYWdzIDQKIC9Bc2NlbnQgOTI4CiAvRGVzY2VudCAtMjM2CiAvTGVhZGluZyAwCiAvSXRhbGljQW5nbGUgMAogL1N0ZW1WIDg3CiAvTWlzc2luZ1dpZHRoIDU0MAogL1N0eWxlIDw8IC9QYW5vc2UgPCAwIDAgMiA2IDYgNiA1IDYgNSAyIDIgND4gPj4KL0ZvbnRGaWxlMiAxNCAwIFIKPj4KZW5kb2JqCjEzIDAgb2JqCjw8L0xlbmd0aCAzMDQKL0ZpbHRlciAvRmxhdGVEZWNvZGUKPj4Kc3RyZWFtCnic7c/nVggAAIDR75zsUWZkJXtkVCqEbC2UyIjo/V+ih+ifc+8b3Nqlgfa0t33t70AHO9ThjnS0wYY61vFOdLJTnW64M51tpHOd70IXu9RolxvrSle71vVudLNb3e5OdxvvXvd70MMmmmyqR00302yPe9LT5nrW814038te9bo3ve1d7/vQQosttdxKH/vU51Zb60vrfe1bG33vRz/71Wa/+9NWf/vX9m7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vbnQKL1N1YnR5cGUgL0NJREZvbnRUeXBlMgovQmFzZUZvbnQgL01QREZBQStEZWphVnVTZXJpZkNvbmRlbnNlZC1Cb2xkCi9DSURTeXN0ZW1JbmZvIDE4IDAgUgovRm9udERlc2NyaXB0b3IgMTkgMCBSCi9EVyA1NDAKL1cgWyAzMiBbIDMxMyAzOTUgNDY5IDc1NCA2MjYgODU1IDgxMyAyNzUgNDI2IDQyNiA0NzAgNzU0IDMxMyAzNzQgMzEzIDMyOSBdCiA0OCA1NyA2MjYgNTggNTkgMzMyIDYwIDYyIDc1NCA2MyBbIDUyNyA5MDAgNjk4IDc2MCA3MTYgNzgwIDY4NiA2MzkgNzY5IDg1MCA0MjEgNDI2IDc4MiA2MzMgOTk2IDgyMiA3ODQgNjc3IDc4NCA3NDggNjUwIDY2OSA3ODUgNjk4IDEwMTEgNjk4IDY0MiA2NTcgNDI2IDMyOSA0MjYgNzU0IDQ1MCA0NTAgNTgzIDYyOSA1NDggNjI5IDU3MiAzODcgNjI5IDY1NCAzNDIgMzI1IDYyNCAzNDIgOTUyIDY1NCA2MDAgNjI5IDYyOSA0NzQgNTA2IDQxNiA2NTQgNTIzIDc3NCA1MzYgNTIzIDUxMSA1NzkgMzI3IDU3OSA3NTQgXQogXQovQ0lEVG9HSURNYXAgMjAgMCBSCj4+CmVuZG9iagoxNyAwIG9iago8PC9MZW5ndGggMzQ2Pj4Kc3RyZWFtCi9DSURJbml0IC9Qcm9jU2V0IGZpbmRyZXNvdXJjZSBiZWdpbgoxMiBkaWN0IGJlZ2luCmJlZ2luY21hcAovQ0lEU3lzdGVtSW5mbwo8PC9SZWdpc3RyeSAoQWRvYmUpCi9PcmRlcmluZyAoVUNTKQovU3VwcGxlbWVudCAwCj4+IGRlZgovQ01hcE5hbWUgL0Fkb2JlLUlkZW50aXR5LVVDUyBkZWYKL0NNYXBUeXBlIDIgZGVmCjEgYmVnaW5jb2Rlc3BhY2VyYW5nZQo8MDAwMD4gPEZGRkY+CmVuZGNvZGVzcGFjZXJhbmdlCjEgYmVnaW5iZnJhbmdlCjwwMDAwPiA8RkZGRj4gPDAwMDA+CmVuZGJmcmFuZ2UKZW5kY21hcApDTWFwTmFtZSBjdXJyZW50ZGljdCAvQ01hcCBkZWZpbmVyZXNvdXJjZSBwb3AKZW5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hZ2VMYXlvdXQgL09uZUNvbHVtbgo+PgplbmRvYmoKeHJlZgowIDI0CjAwMDAwMDAwMDAgNjU1MzUgZiAKMDAwMDAwMDg1NSAwMDAwMCBuIAowMDAwMDI3NTM3IDAwMDAwIG4gCjAwMDAwMDAwMTUgMDAwMDAgbiAKMDAwMDAwMDIyMyAwMDAwMCBuIAowMDAwMDAwNDM0IDAwMDAwIG4gCjAwMDAwMDA2NDIgMDAwMDAgbiAKMDAwMDAwMDk1MCAwMDAwMCBuIAowMDAwMDAxMDExIDAwMDAwIG4gCjAwMDAwMDExNjMgMDAwMDAgbiAKMDAwMDAwMTcwMyAwMDAwMCBuIAowMDAwMDAyMDk5IDAwMDAwIG4gCjAwMDAwMDIxNjggMDAwMDAgbiAKMDAwMDAwMjQ3NiAwMDAwMCBuIAowMDAwMDAyODUyIDAwMDAwIG4gCjAwMDAwMTQyMjEgMDAwMDAgbiAKMDAwMDAxNDM4MCAwMDAwMCBuIAowMDAwMDE0OTI3IDAwMDAwIG4gCjAwMDAwMTUzMjMgMDAwMDAgbiAKMDAwMDAxNTM5MiAwMDAwMCBuIAowMDAwMDE1NzExIDAwMDAwIG4gCjAwMDAwMTYwODcgMDAwMDAgbiAKMDAwMDAyNzY2NCAwMDAwMCBuIAowMDAwMDI3ODIwIDAwMDAwIG4gCnRyYWlsZXIKPDwKL1NpemUgMjQKL1Jvb3QgMjMgMCBSCi9JbmZvIDIyIDAgUgovSUQgWzw5NWYzMzNhYmJmYWQ5Y2I4NGJmZjQ4MjI3ZGQwMzQ2MD4gPDk1ZjMzM2FiYmZhZDljYjg0YmZmNDgyMjdkZDAzNDYwPl0KPj4Kc3RhcnR4cmVmCjI3OTMwCiUlRU9G \ No newline at end of file diff --git a/src/Marello/Bundle/PdfBundle/Tests/Unit/Renderer/data/single.txt b/src/Marello/Bundle/PdfBundle/Tests/Unit/Renderer/data/single.txt new file mode 100644 index 000000000..88b6839d4 --- /dev/null +++ b/src/Marello/Bundle/PdfBundle/Tests/Unit/Renderer/data/single.txt @@ -0,0 +1 @@ +JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL01lZGlhQm94IFswIDAgNTk1LjI4MCA4NDEuODkwXQovVHJpbUJveCBbMC4wMDAgMC4wMDAgNTk1LjI4MCA4NDEuODkwXQovUmVzb3VyY2VzIDIgMCBSCi9Hcm91cCA8PCAvVHlwZSAvR3JvdXAgL1MgL1RyYW5zcGFyZW5jeSAvQ1MgL0RldmljZVJHQiA+PiAKL0NvbnRlbnRzIDQgMCBSPj4KZW5kb2JqCjQgMCBvYmoKPDwvRmlsdGVyIC9GbGF0ZURlY29kZSAvTGVuZ3RoIDE0MT4+CnN0cmVhbQp4nI2OsQoCQQxEU+crptQml4S9W2tBD6wUtxML4XTBTi38ffc8PNRCrBKYmTcDx4pV6ibizvOEamkwE1VFOmGRePhz8fS35ardGvJtzBTflXd7KLpRe3Ic7m+cCwZCBvoIiie41K6IMYg2M6QOmNCaDpTpSCCbIp1LFJtP8NfAl/ajIJi4+z8FDwKxOJwKZW5kc3RyZWFtCmVuZG9iagoxIDAgb2JqCjw8L1R5cGUgL1BhZ2VzCi9LaWRzIFszIDAgUiBdCi9Db3VudCAxCi9NZWRpYUJveCBbMCAwIDU5NS4yODAgODQxLjg5MF0KPj4KZW5kb2JqCjUgMCBvYmoKPDwvVHlwZSAvRXh0R1N0YXRlCi9CTSAvTm9ybWFsCi9jYSAxCi9DQSAxCj4+CmVuZG9iago2IDAgb2JqCjw8L1R5cGUgL0ZvbnQKL1N1YnR5cGUgL1R5cGUwCi9CYXNlRm9udCAvTVBERkFBK0RlamFWdVNlcmlmQ29uZGVuc2VkCi9FbmNvZGluZyAvSWRlbnRpdHktSAovRGVzY2VuZGFudEZvbnRzIFs3IDAgUl0KL1RvVW5pY29kZSA4IDAgUgo+PgplbmRvYmoKNyAwIG9iago8PC9UeXBlIC9Gb250Ci9TdWJ0eXBlIC9DSURGb250VHlwZTIKL0Jhc2VGb250IC9NUERGQUErRGVqYVZ1U2VyaWZDb25kZW5zZWQKL0NJRFN5c3RlbUluZm8gOSAwIFIKL0ZvbnREZXNjcmlwdG9yIDEwIDAgUgovRFcgNTQwCi9XIFsgMzIgWyAyODYgMzYxIDQxNCA3NTQgNTcyIDg1NSA4MDEgMjQ3IDM1MSAzNTEgNDUwIDc1NCAyODYgMzA0IDI4NiAzMDMgXQogNDggNTcgNTcyIDU4IDU5IDMwMyA2MCA2MiA3NTQgNjMgWyA0ODIgOTAwIDY1MCA2NjEgNjg4IDcyMSA2NTcgNjI0IDcxOSA3ODUgMzU1IDM2MCA2NzIgNTk4IDkyMSA3ODcgNzM4IDYwNSA3MzggNjc3IDYxNiA2MDAgNzU4IDY1MCA5MjUgNjQxIDU5NCA2MjUgMzUxIDMwMyAzNTEgNzU0IDQ1MCA0NTAgNTM2IDU3NiA1MDQgNTc2IDUzMiAzMzMgNTc2IDU4MCAyODggMjc5IDU0NSAyODggODUzIDU4MCA1NDIgNTc2IDU3NiA0MzAgNDYxIDM2MSA1ODAgNTA4IDc3MCA1MDcgNTA4IDQ3NCA1NzIgMzAzIDU3MiA3NTQgXQogXQovQ0lEVG9HSURNYXAgMTEgMCBSCj4+CmVuZG9iago4IDAgb2JqCjw8L0xlbmd0aCAzNDY+PgpzdHJlYW0KL0NJREluaXQgL1Byb2NTZXQgZmluZHJlc291cmNlIGJlZ2luCjEyIGRpY3QgYmVnaW4KYmVnaW5jbWFwCi9DSURTeXN0ZW1JbmZvCjw8L1JlZ2lzdHJ5IChBZG9iZSkKL09yZGVyaW5nIChVQ1MpCi9TdXBwbGVtZW50IDAKPj4gZGVmCi9DTWFwTmFtZSAvQWRvYmUtSWRlbnRpdHktVUNTIGRlZgovQ01hcFR5cGUgMiBkZWYKMSBiZWdpbmNvZGVzcGFjZXJhbmdlCjwwMDAwPiA8RkZGRj4KZW5kY29kZXNwYWNlcmFuZ2UKMSBiZWdpbmJmcmFuZ2UKPDAwMDA+IDxGRkZGPiA8MDAwMD4KZW5kYmZyYW5nZQplbmRjbWFwCkNNYXBOYW1lIGN1cnJlbnRkaWN0IC9DTWFwIGRlZmluZXJlc291cmNlIHBvcAplbmQKZW5kCgplbmRzdHJlYW0KZW5kb2JqCjkgMCBvYmoKPDwvUmVnaXN0cnkgKEFkb2JlKQovT3JkZXJpbmcgKFVDUykKL1N1cHBsZW1lbnQgMAo+PgplbmRvYmoKMTAgMCBvYmoKPDwvVHlwZSAvRm9udERlc2NyaXB0b3IKL0ZvbnROYW1lIC9NUERGQUErRGVqYVZ1U2VyaWZ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wIDYyOSA2MjkgNDc0IDUwNiA0MTYgNjU0IDUyMyA3NzQgNTM2IDUyMyA1MTEgNTc5IDMyNyA1NzkgNzU0IF0KIF0KL0NJRFRvR0lETWFwIDE4IDAgUgo+PgplbmRvYmoKMTUgMCBvYmoKPDwvTGVuZ3RoIDM0Nj4+CnN0cmVhbQovQ0lESW5pdCAvUHJvY1NldCBmaW5kcmVzb3VyY2UgYmVnaW4KMTIgZGljdCBiZWdpbgpiZWdpbmNtYXAKL0NJRFN5c3RlbUluZm8KPDwvUmVnaXN0cnkgKEFkb2JlKQovT3JkZXJpbmcgKFVDUykKL1N1cHBsZW1lbnQgMAo+PiBkZWYKL0NNYXBOYW1lIC9BZG9iZS1JZGVudGl0eS1VQ1MgZGVmCi9DTWFwVHlwZSAyIGRlZgoxIGJlZ2luY29kZXNwYWNlcmFuZ2UKPDAwMDA+IDxGRkZGPgplbmRjb2Rlc3BhY2VyYW5nZQoxIGJlZ2luYmZyYW5nZQo8MDAwMD4gPEZGRkY+IDwwMDAwPgplbmRiZnJhbmdlCmVuZGNtYXAKQ01hcE5hbWUgY3VycmVudGRpY3QgL0NNYXAgZGVmaW5lcmVzb3VyY2UgcG9wCmVuZAplbmQKCmVuZHN0cmVhbQplbmRvYmoKMTYgMCBvYmoKPDwvUmVnaXN0cnkgKEFkb2JlKQovT3JkZXJpbmcgKFVDUykKL1N1cHBsZW1lbnQgMAo+PgplbmRvYmoKMTcgMCBvYmoKPDwvVHlwZSAvRm9udERlc2NyaXB0b3IKL0ZvbnROYW1lIC9NUERGQUErRGVqYVZ1U2VyaWZDb25kZW5zZWQtQm9sZAogL0NhcEhlaWdodCA3MjkKIC9YSGVpZ2h0IDUxOQogL0ZvbnRCQm94IFstNzUyIC0zODkgMTYxNyAxMTQ1XQogL0ZsYWdzIDI2MjE0OAogL0FzY2VudCA5MzkKIC9EZXNjZW50IC0yMzYKIC9MZWFkaW5nIDAKIC9JdGFsaWNBbmdsZSAwCiAvU3RlbVYgMTY1CiAvTWlzc2luZ1dpZHRoIDU0MAogL1N0eWxlIDw8IC9QYW5vc2UgPCAwIDAgMiA2IDggNiA1IDYgNSAyIDIgND4gPj4KL0ZvbnRGaWxlMiAxOSAwIFIKPj4KZW5kb2JqCjE4IDAgb2JqCjw8L0xlbmd0aCA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4vz+Irw/xTRF9ehFvGOp9lHiFE0+PYMnzKPEIJhqA1fQmkjeRUkSRBEliGBHbRIJ7SSSIkBRRgJZA4Z7gNhH5E3wE65etxsP+//xD/68Z6PoLR/8LJFTidAplbmRzdHJlYW0KZW5kb2JqCjIgMCBvYmoKPDwvUHJvY1NldCBbL1BERiAvVGV4dCAvSW1hZ2VCIC9JbWFnZUMgL0ltYWdlSV0KL0ZvbnQgPDwKL0YxIDYgMCBSCi9GMiAxMyAwIFIKPj4KL0V4dEdTdGF0ZSA8PAovR1MxIDUgMCBSCj4+Cj4+CmVuZG9iagoyMCAwIG9iago8PAovUHJvZHVjZXIgKP7/AG0AUABEAEYAIAA3AC4AMQAuADkpCi9UaXRsZSAo/v8AUABEAEYAIAB0AGUAcwB0KQovQ3JlYXRpb25EYXRlICgyMDE5MDgyODE0MTcxMyswMCcwMCcpCi9Nb2REYXRlICgyMDE5MDgyODE0MTcxMyswMCcwMCcpCj4+CmVuZG9iagoyMSAwIG9iago8PAovVHlwZSAvQ2F0YWxvZwovUGFnZXMgMSAwIFIKL09wZW5BY3Rpb24gWzMgMCBSIC9YWVogbnVsbCBudWxsIDFdCi9QYWdlTGF5b3V0IC9PbmVDb2x1bW4KPj4KZW5kb2JqCnhyZWYKMCAyMgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDA0MzQgMDAwMDAgbiAKMDAwMDAyNzEwNiAwMDAwMCBuIAowMDAwMDAwMDE1IDAwMDAwIG4gCjAwMDAwMDAyMjMgMDAwMDAgbiAKMDAwMDAwMDUyMyAwMDAwMCBuIAowMDAwMDAwNTg0IDAwMDAwIG4gCjAwMDAwMDA3MzUgMDAwMDAgbiAKMDAwMDAwMTI3NCAwMDAwMCBuIAowMDAwMDAxNjY5IDAwMDAwIG4gCjAwMDAwMDE3MzcgMDAwMDAgbiAKMDAwMDAwMjA0NSAwMDAwMCBuIAowMDAwMDAyNDIxIDAwMDAwIG4gCjAwMDAwMTM3OTAgMDAwMDAgbiAKMDAwMDAxMzk0OSAwMDAwMCBuIAowMDAwMDE0NDk2IDAwMDAwIG4gCjAwMDAwMTQ4OTIgMDAwMDAgbiAKMDAwMDAxNDk2MSAwMDAwMCBuIAowMDAwMDE1MjgwIDAwMDAwIG4gCjAwMDAwMTU2NTYgMDAwMDAgbiAKMDAwMDAyNzIzMyAwMDAwMCBuIAowMDAwMDI3Mzg5IDAwMDAwIG4gCnRyYWlsZXIKPDwKL1NpemUgMjIKL1Jvb3QgMjEgMCBSCi9JbmZvIDIwIDAgUgovSUQgWzwxMzY5NGYwNjYzMTgzNjkwMmZjNDM1ZTVlOThkODk4Zj4gPDEzNjk0ZjA2NjMxODM2OTAyZmM0MzVlNWU5OGQ4OThmPl0KPj4Kc3RhcnR4cmVmCjI3NDk5CiUlRU9G \ No newline at end of file diff --git a/src/Marello/Bundle/PdfBundle/Tests/Unit/Twig/Extension/DocumentTableExtensionTest.php b/src/Marello/Bundle/PdfBundle/Tests/Unit/Twig/Extension/DocumentTableExtensionTest.php new file mode 100644 index 000000000..66b558029 --- /dev/null +++ b/src/Marello/Bundle/PdfBundle/Tests/Unit/Twig/Extension/DocumentTableExtensionTest.php @@ -0,0 +1,63 @@ +createMock(DocumentTableProvider::class); + + $this->extension = new DocumentTableExtension($tableProvider); + } + + public function testGetFilters() + { + $this->assertCount(0, $this->extension->getFilters()); + } + + public function testGetNodeVisitors() + { + $this->assertCount(0, $this->extension->getNodeVisitors()); + } + + public function testGetOperators() + { + $this->assertCount(0, $this->extension->getOperators()); + } + + public function testGetTests() + { + $this->assertCount(0, $this->extension->getTests()); + } + + public function testGetTokenParsers() + { + $this->assertCount(0, $this->extension->getTokenParsers()); + } + + public function testGetFunctions() + { + $functions = $this->extension->getFunctions(); + + $this->assertCount(1, $functions); + + /** @var TwigFunction $twigFunction */ + $twigFunction = reset($functions); + $this->assertEquals('get_document_tables', $twigFunction->getName()); + $this->assertTrue(is_callable($twigFunction->getCallable())); + } + + public function testGetName() + { + $this->assertEquals(DocumentTableExtension::NAME, $this->extension->getName()); + } +} diff --git a/src/Marello/Bundle/PdfBundle/Tests/Unit/Workflow/Action/SendEmailTemplateAttachmentActionTest.php b/src/Marello/Bundle/PdfBundle/Tests/Unit/Workflow/Action/SendEmailTemplateAttachmentActionTest.php new file mode 100644 index 000000000..36f1c35ba --- /dev/null +++ b/src/Marello/Bundle/PdfBundle/Tests/Unit/Workflow/Action/SendEmailTemplateAttachmentActionTest.php @@ -0,0 +1,137 @@ +createMock(Processor::class); + /** @var EntityNameResolver|\PHPUnit_Framework_MockObject_MockObject $entityNameResolver */ + $entityNameResolver = $this->createMock(EntityNameResolver::class); + /** @var EmailRenderer|\PHPUnit_Framework_MockObject_MockObject $renderer */ + $renderer = $this->createMock(EmailRenderer::class); + /** @var ManagerRegistry|\PHPUnit_Framework_MockObject_MockObject $managerRegistry */ + $managerRegistry = $this->createMock(ManagerRegistry::class); + /** @var ValidatorInterface|\PHPUnit_Framework_MockObject_MockObject $validator */ + $validator = $this->createMock(ValidatorInterface::class); + /** @var EmailOriginHelper|\PHPUnit_Framework_MockObject_MockObject $emailOriginHelper */ + $emailOriginHelper = $this->getMockBuilder(EmailOriginHelper::class)->disableOriginalConstructor()->getMock(); + + $this->action = new SendEmailTemplateAttachmentAction( + new ContextAccessor(), + $emailProcessor, + new EmailAddressHelper(), + $entityNameResolver, + $managerRegistry, + $validator, + $emailOriginHelper, + $renderer, + ); + } + + /** + * @dataProvider initializeProvider + */ + public function testInitialize($options, $exception = null, $exceptionMessage = null) + { + if ($exception !== null) { + $this->expectException($exception); + if ($exceptionMessage !== null) { + $this->expectExceptionMessage($exceptionMessage); + } + } + + $this->action->initialize($options); + } + + public function initializeProvider() + { + $baseOptions = [ + 'from' => 'test@example.com', + 'to' => 'test@example.com', + 'template' => 'template-name', + 'subject' => 'subject', + 'entity' => new \stdClass(), + ]; + + return [ + 'valid bcc simple' => [ + 'options' => array_merge($baseOptions, [ + SendEmailTemplateAttachmentAction::OPTION_BCC => 'test@example.com', + ]), + ], + 'valid bcc array' => [ + 'options' => array_merge($baseOptions, [ + SendEmailTemplateAttachmentAction::OPTION_BCC => [ + 'email' => 'test@example.com', + 'name' => 'test bcc' + ], + ]), + ], + 'invalid bcc' => [ + 'options' => array_merge($baseOptions, [ + SendEmailTemplateAttachmentAction::OPTION_BCC => ['name' => 'test bcc'], + ]), + 'exception' => InvalidArgumentException::class, + 'exceptionMessage' => 'Email parameter is required', + ], + 'empty_bcc' => [ + 'options' => array_merge($baseOptions, [ + SendEmailTemplateAttachmentAction::OPTION_BCC => null, + ]), + ], + 'attachments not array' => [ + 'options' => array_merge($baseOptions, [ + SendEmailTemplateAttachmentAction::OPTION_ATTACHMENTS => 'attachments', + ]), + 'exception' => InvalidArgumentException::class, + 'exceptionMessage' => 'Attachments should be array', + ], + 'attachment options not array' => [ + 'options' => array_merge($baseOptions, [ + SendEmailTemplateAttachmentAction::OPTION_ATTACHMENTS => ['attachments'], + ]), + 'exception' => InvalidArgumentException::class, + 'exceptionMessage' => 'Attachment options invalid', + ], + 'body or file not set' => [ + 'options' => array_merge($baseOptions, [ + SendEmailTemplateAttachmentAction::OPTION_ATTACHMENTS => [ + [] + ], + ]), + 'exception' => InvalidArgumentException::class, + 'exceptionMessage' => 'Attachment option "body" or "file" should be set', + ], + 'body and file set' => [ + 'options' => array_merge($baseOptions, [ + SendEmailTemplateAttachmentAction::OPTION_ATTACHMENTS => [ + [ + SendEmailTemplateAttachmentAction::OPTION_ATTACHMENT_BODY => 'body', + SendEmailTemplateAttachmentAction::OPTION_ATTACHMENT_FILE => 'file', + ] + ], + ]), + 'exception' => InvalidArgumentException::class, + 'exceptionMessage' => 'Only one of options "body" and "file" should be set', + ], + ]; + } +} diff --git a/src/Marello/Bundle/PdfBundle/Tests/Unit/Workflow/Condition/IsSendEmailTransitionTest.php b/src/Marello/Bundle/PdfBundle/Tests/Unit/Workflow/Condition/IsSendEmailTransitionTest.php new file mode 100644 index 000000000..2bbbd2c1a --- /dev/null +++ b/src/Marello/Bundle/PdfBundle/Tests/Unit/Workflow/Condition/IsSendEmailTransitionTest.php @@ -0,0 +1,94 @@ +configManager = $this->createMock(ConfigManager::class); + + $this->isSendTransition = new IsSendEmailTransition($this->configManager); + $this->isSendTransition->setContextAccessor(new ContextAccessor()); + } + + /** + * @dataProvider isConditionAllowedProvider + */ + public function testIsConditionAllowed($configTransition, $context, $options, $salesChannel, $allowed) + { + $this->configManager->expects($this->once()) + ->method('get') + ->with('marello_pdf.email_workflow_transition', false, false, $salesChannel) + ->willReturn($configTransition) + ; + + $this->isSendTransition->initialize($options); + + $this->assertEquals($allowed, $this->isSendTransition->isConditionAllowed($context)); + } + + public function isConditionAllowedProvider() + { + $salesChannel = $this->getEntity(SalesChannel::class, [ + 'id' => 1, + 'name' => 'test channel', + 'code' => 'test', + ]); + + $options = [ + IsSendEmailTransition::OPTION_CURRENT_TRANSITION => 'provided', + IsSendEmailTransition::OPTION_CONFIG_SCOPE => new PropertyPath('scope'), + ]; + + $context = [ + 'scope' => $salesChannel, + ]; + + return [ + 'not_set' => [ + 'configTransition' => null, + 'context' => $context, + 'options' => $options, + 'salesChannel' => $salesChannel, + 'allowed' => false, + ], + 'allowed' => [ + 'configTransition' => 'provided', + 'context' => $context, + 'options' => $options, + 'salesChannel' => $salesChannel, + 'allowed' => true, + ], + 'not_allowed' => [ + 'configTransition' => 'config', + 'context' => $context, + 'options' => $options, + 'salesChannel' => $salesChannel, + 'allowed' => false, + ], + ]; + } + + public function testGetName() + { + $this->assertEquals(IsSendEmailTransition::NAME, $this->isSendTransition->getName()); + } +} diff --git a/src/Marello/Bundle/PdfBundle/Twig/Extension/DocumentTableExtension.php b/src/Marello/Bundle/PdfBundle/Twig/Extension/DocumentTableExtension.php new file mode 100644 index 000000000..433344d6d --- /dev/null +++ b/src/Marello/Bundle/PdfBundle/Twig/Extension/DocumentTableExtension.php @@ -0,0 +1,31 @@ +tableProvider = $tableProvider; + } + + public function getFunctions() + { + return [ + new TwigFunction('get_document_tables', [$this->tableProvider, 'getTables']), + ]; + } + + public function getName() + { + return self::NAME; + } +} diff --git a/src/Marello/Bundle/PdfBundle/Workflow/Action/SendEmailTemplateAttachmentAction.php b/src/Marello/Bundle/PdfBundle/Workflow/Action/SendEmailTemplateAttachmentAction.php new file mode 100644 index 000000000..00dcf56f6 --- /dev/null +++ b/src/Marello/Bundle/PdfBundle/Workflow/Action/SendEmailTemplateAttachmentAction.php @@ -0,0 +1,375 @@ +registry = $registry; + $this->validator = $validator; + $this->renderer = $renderer; + $this->emailOriginHelper = $emailOriginHelper; + } + + /** + * @param array $options + * @return SendEmailTemplate + */ + public function initialize(array $options): self + { + if (isset($options[self::OPTION_BCC])) { + $this->assertEmailAddressOption($options[self::OPTION_BCC]); + } + if (empty($options['from'])) { + throw new InvalidParameterException('From parameter is required'); + } + + $this->assertEmailAddressOption($options['from']); + + if (empty($options['to'])) { + throw new InvalidParameterException('Need to specify "to" parameters'); + } + + $options = $this->normalizeToOption($options); + + if (empty($options['template'])) { + throw new InvalidParameterException('Template parameter is required'); + } + + if (empty($options['entity'])) { + throw new InvalidParameterException('Entity parameter is required'); + } + + if (isset($options[self::OPTION_ATTACHMENTS])) { + $attachments = $options[self::OPTION_ATTACHMENTS]; + + if (!is_array($attachments)) { + throw new InvalidArgumentException('Attachments should be array'); + } + foreach ($attachments as $attachment) { + if (!is_array($attachment)) { + throw new InvalidArgumentException('Attachment options invalid'); + } + + if (!isset($attachment[self::OPTION_ATTACHMENT_BODY]) + && !isset($attachment[self::OPTION_ATTACHMENT_FILE]) + ) { + throw new InvalidArgumentException(sprintf( + 'Attachment option "%s" or "%s" should be set', + self::OPTION_ATTACHMENT_BODY, + self::OPTION_ATTACHMENT_FILE + )); + } + if (isset($attachment[self::OPTION_ATTACHMENT_BODY]) + && isset($attachment[self::OPTION_ATTACHMENT_FILE]) + ) { + throw new InvalidArgumentException(sprintf( + 'Only one of options "%s" and "%s" should be set', + self::OPTION_ATTACHMENT_BODY, + self::OPTION_ATTACHMENT_FILE + )); + } + } + } + + $this->options = $options; + $this->emailConstraint = new EmailConstraints(['message' => 'Invalid email address']); + + return $this; + } + + /** + * @param mixed $context + * @throws EntityNotFoundException + * @throws \Twig\Error\Error + * @throws \Twig_Error + */ + public function executeAction($context): void + { + $emailModel = new Email(); + + $from = $this->getEmailAddress($context, $this->options['from']); + $this->validateAddress($from); + $emailModel->setFrom($from); + $to = []; + + foreach ($this->options['to'] as $email) { + if ($email) { + $address = $this->getEmailAddress($context, $email); + $this->validateAddress($address); + $to[] = $address; + } + } + $emailModel->setTo($to); + $entity = $this->contextAccessor->getValue($context, $this->options['entity']); + $template = $this->contextAccessor->getValue($context, $this->options['template']); + + $emailTemplate = $this + ->registry + ->getManagerForClass(\get_class($entity)) + ->getRepository(EmailTemplate::class) + ->findByName($template) + ; + if (!$emailTemplate) { + $errorMessage = sprintf('Template "%s" not found.', $template); + $this->logger->error('Workflow send email action.' . $errorMessage); + throw new EntityNotFoundException($errorMessage); + } + $templateData = $this->renderer->compileMessage($emailTemplate, ['entity' => $entity]); + + list ($subjectRendered, $templateRendered) = $templateData; + + $emailModel->setSubject($subjectRendered); + $emailModel->setBody($templateRendered); + $emailModel->setType($emailTemplate->getType()); + $emailModel->setBcc($this->getBcc($context)); + + $this->addAttachments($emailModel, $context); + + $emailUser = null; + try { + $emailOrigin = $this->emailOriginHelper->getEmailOrigin( + $emailModel->getFrom(), + $emailModel->getOrganization() + ); + + $emailUser = $this->emailProcessor->process($emailModel, $emailOrigin); + } catch (\Swift_SwiftException $exception) { + $this->logger->error('Workflow send email template action.', ['exception' => $exception]); + } + + if (array_key_exists('attribute', $this->options) && $emailUser instanceof EmailUser) { + $this->contextAccessor->setValue($context, $this->options['attribute'], $emailUser->getEmail()); + } + } + + /** + * @param $context + * @return array|string + */ + protected function getBcc($context) + { + if (isset($this->options[self::OPTION_BCC])) { + $bcc = $this->getEmailAddress($context, $this->options[self::OPTION_BCC]); + $this->validateAddress($bcc); + + $bcc = [$bcc]; + } else { + $bcc = []; + } + + return array_filter($bcc); + } + + /** + * @param Email $emailModel + * @param $context + */ + protected function addAttachments(Email $emailModel, $context) + { + if (isset($this->options[self::OPTION_ATTACHMENTS])) { + $attachments = $this->options[self::OPTION_ATTACHMENTS]; + foreach ($attachments as $attachment) { + $emailModel->addAttachment($this->buildAttachment($attachment, $context)); + } + } + } + + /** + * @param $attachment + * @param $context + * @return EmailAttachment + */ + protected function buildAttachment($attachment, $context) + { + if (isset($attachment[self::OPTION_ATTACHMENT_FILE])) { + $emailAttachment = $this->buildFileAttachment($attachment, $context); + } else { + $emailAttachment = $this->buildStringAttachment($attachment, $context); + } + + return $emailAttachment; + } + + /** + * @param $attachment + * @param $context + * @return EmailAttachment + */ + protected function buildFileAttachment($attachment, $context) + { + $path = $this->contextAccessor->getValue($context, $attachment[self::OPTION_ATTACHMENT_FILE]); + $content = base64_encode(file_get_contents($path)); + if (isset($attachment[self::OPTION_ATTACHMENT_MIMETYPE])) { + $mimetype = $this->contextAccessor->getValue($context, $attachment[self::OPTION_ATTACHMENT_MIMETYPE]); + } else { + $extension = pathinfo($path, PATHINFO_EXTENSION); + $mimetype = $this->getMimeTypeGuesser()->guess($extension); + } + if (isset($attachment[self::OPTION_ATTACHMENT_FILENAME])) { + $filename = $this->contextAccessor->getValue($context, $attachment[self::OPTION_ATTACHMENT_FILENAME]); + } else { + $filename = pathinfo($path, PATHINFO_BASENAME); + } + + return $this->buildAttachmentFromString($content, $filename, $mimetype); + } + + /** + * @param $attachment + * @param $context + * @return EmailAttachment + */ + protected function buildStringAttachment($attachment, $context) + { + $content = $this->contextAccessor->getValue($context, $attachment[self::OPTION_ATTACHMENT_BODY]); + $filename = $this->contextAccessor->getValue($context, $attachment[self::OPTION_ATTACHMENT_FILENAME]); + $mimetype = $this->contextAccessor->getValue($context, $attachment[self::OPTION_ATTACHMENT_MIMETYPE]); + + return $this->buildAttachmentFromString($content, $filename, $mimetype); + } + + /** + * @param $content + * @param $filename + * @param $mimetype + * @return EmailAttachment + */ + protected function buildAttachmentFromString($content, $filename, $mimetype) + { + $attachmentEntity = new AttachmentEntity(); + + $attachmentContent = new EmailAttachmentContent(); + $attachmentContent->setContent($content); + $attachmentContent->setContentTransferEncoding('base64'); + $attachmentContent->setEmailAttachment($attachmentEntity); + + $attachmentEntity->setContent($attachmentContent); + $attachmentEntity->setContentType($mimetype); + $attachmentEntity->setFileName($filename); + + $emailAttachment = new EmailAttachment(); + $emailAttachment->setType(EmailAttachment::TYPE_EMAIL_ATTACHMENT); + $emailAttachment->setEmailAttachment($attachmentEntity); + + return $emailAttachment; + } + + /** + * @return MimeTypeGuesser + */ + protected function getMimeTypeGuesser() + { + if ($this->mimeTypeGuesser === null) { + $this->mimeTypeGuesser = MimeTypeGuesser::getInstance(); + } + + return $this->mimeTypeGuesser; + } + + /** + * @param string $email + * @throws ValidatorException + */ + protected function validateAddress($email): void + { + $errorList = $this->validator->validate($email, $this->emailConstraint); + + if ($errorList && $errorList->count() > 0) { + throw new ValidatorException($errorList->get(0)->getMessage()); + } + } + + /** + * @param array $options + * @return array + */ + protected function normalizeToOption(array $options): array + { + if (empty($options['to'])) { + $options['to'] = []; + } + if (!is_array($options['to']) + || array_key_exists('name', $options['to']) + || array_key_exists('email', $options['to']) + ) { + $options['to'] = [$options['to']]; + } + + foreach ($options['to'] as $to) { + $this->assertEmailAddressOption($to); + } + + return $options; + } +} diff --git a/src/Marello/Bundle/PdfBundle/Workflow/Condition/IsSendEmailTransition.php b/src/Marello/Bundle/PdfBundle/Workflow/Condition/IsSendEmailTransition.php new file mode 100644 index 000000000..6bbcef491 --- /dev/null +++ b/src/Marello/Bundle/PdfBundle/Workflow/Condition/IsSendEmailTransition.php @@ -0,0 +1,70 @@ +configManager = $configManager; + } + + public function initialize(array $options) + { + $this->currentTransition = $options[self::OPTION_CURRENT_TRANSITION]; + $this->configScope = $options[self::OPTION_CONFIG_SCOPE]; + + return $this; + } + + public function isConditionAllowed($context) + { + $currentTransition = $this->contextAccessor->getValue($context, $this->currentTransition); + $configScope = $this->contextAccessor->getValue($context, $this->configScope); + + $configKey = sprintf('%s.%s', Configuration::CONFIG_NAME, Configuration::CONFIG_KEY_EMAIL_WORKFLOW_TRANSITION); + + $configuredTransitions = $this->configManager->get($configKey, false, false, $configScope); + if ($configuredTransitions === null) { + $configuredTransitions = []; + } + if (is_scalar($configuredTransitions)) { + $configuredTransitions = [$configuredTransitions]; + } + + return in_array($currentTransition, $configuredTransitions); + } + + public function getName() + { + return self::NAME; + } + + public function toArray() + { + return $this->convertToArray([$this->currentTransition]); + } + + public function compile($factoryAccessor) + { + return $this->convertToPhpCode([$this->currentTransition], $factoryAccessor); + } +} diff --git a/src/Marello/Bundle/PricingBundle/Controller/PricingController.php b/src/Marello/Bundle/PricingBundle/Controller/PricingController.php index 062061631..9a7db55d3 100644 --- a/src/Marello/Bundle/PricingBundle/Controller/PricingController.php +++ b/src/Marello/Bundle/PricingBundle/Controller/PricingController.php @@ -2,17 +2,20 @@ namespace Marello\Bundle\PricingBundle\Controller; -use Sensio\Bundle\FrameworkExtraBundle\Configuration as Config; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Oro\Bundle\SecurityBundle\Annotation\AclAncestor; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; -use Oro\Bundle\SecurityBundle\Annotation\AclAncestor; +use Symfony\Component\Routing\Annotation\Route; -class PricingController extends Controller +class PricingController extends AbstractController { /** - * @Config\Route("/get-currency-by-channel", name="marello_pricing_currency_by_channel") - * @Config\Method({"GET"}) + * @Route( + * path="/get-currency-by-channel", + * methods={"GET"}, + * name="marello_pricing_currency_by_channel" + * ) * @AclAncestor("marello_sales_saleschannel_view") * * {@inheritdoc} diff --git a/src/Marello/Bundle/PricingBundle/EventListener/Datagrid/ChannelPricesDatagridListener.php b/src/Marello/Bundle/PricingBundle/EventListener/Datagrid/ChannelPricesDatagridListener.php new file mode 100644 index 000000000..d3445f71b --- /dev/null +++ b/src/Marello/Bundle/PricingBundle/EventListener/Datagrid/ChannelPricesDatagridListener.php @@ -0,0 +1,190 @@ +relatedEntityClass = $relatedEntityClass; + + $this->expressionBuilder = new Expr(); + } + + /** + * @param BuildBefore $event + */ + public function onBuildBefore(BuildBefore $event) + { + $config = $event->getConfig(); + + $this->addSelect($config); + $this->addJoin($config); + $this->addColumn($config); + $this->addSorter($config); + $this->addFilter($config); + } + + /** + * @param DatagridConfiguration $configuration + * @return string + * @throws \InvalidArgumentException when a root entity not found in the grid + */ + protected function getAlias(DatagridConfiguration $configuration) + { + $rootAlias = $configuration->getOrmQuery()->getRootAlias(); + if (!$rootAlias) { + throw new \InvalidArgumentException( + sprintf( + 'A root entity is missing for grid "%s"', + $configuration->getName() + ) + ); + } + + return $rootAlias; + } + + /** + * @return string + */ + protected function getDataName() + { + return self::DATA_NAME; + } + + /** + * @return string + */ + protected function getJoinAlias() + { + return self::JOIN_ALIAS; + } + + /** + * @param DatagridConfiguration $config + */ + protected function addSelect(DatagridConfiguration $config) + { + $ormQuery = $config->getOrmQuery(); + $ormQuery + ->addSelect( + sprintf( + 'GROUP_CONCAT( + DISTINCT CONCAT_WS(\'|\', %1$s.name, %2$s.value, %2$s.currency) SEPARATOR \';\' + ) as defaultChannelPrices', + self::CHANNEL_JOIN_ALIAS, + self::DEFAULT_JOIN_ALIAS + ) + ) + ->addSelect( + sprintf( + 'GROUP_CONCAT( + DISTINCT CONCAT_WS(\'|\', %1$s.name, %2$s.value, %2$s.currency) SEPARATOR \';\' + ) as specialChannelPrices', + self::CHANNEL_JOIN_ALIAS, + self::SPECIAL_JOIN_ALIAS + ) + ) + ->addSelect(sprintf('sum(%s.value) as defaultChannelPricesSum', self::DEFAULT_JOIN_ALIAS)) + ->addSelect(sprintf('sum(%s.value) as specialChannelPricesSum', self::SPECIAL_JOIN_ALIAS)); + } + + /** + * @param DatagridConfiguration $config + */ + protected function addJoin(DatagridConfiguration $config) + { + $ormQuery = $config->getOrmQuery(); + $ormQuery + ->addLeftJoin(sprintf('%s.%s', $this->getAlias($config), self::DATA_NAME), $this->getJoinAlias()) + ->addLeftJoin(sprintf('%s.%s', $this->getJoinAlias(), self::CHANNEL_DATA_NAME), self::CHANNEL_JOIN_ALIAS) + ->addLeftJoin(sprintf('%s.%s', $this->getJoinAlias(), self::DEFAULT_DATA_NAME), self::DEFAULT_JOIN_ALIAS) + ->addLeftJoin(sprintf('%s.%s', $this->getJoinAlias(), self::SPECIAL_DATA_NAME), self::SPECIAL_JOIN_ALIAS); + } + + /** + * @param DatagridConfiguration $config + */ + protected function addColumn(DatagridConfiguration $config) + { + $config->offsetSetByPath(sprintf('[columns][%s]', 'defaultChannelPrices'), [ + 'label' => 'marello.pricing.assembledchannelpricelist.default_price.plural_label', + 'type' => 'twig', + 'frontend_type' => 'html', + 'template' => 'MarelloPricingBundle:Datagrid/Property:defaultChannelPrices.html.twig', + 'renderable' => false, + 'align' => 'right' + ]); + $config->offsetSetByPath(sprintf('[columns][%s]', 'specialChannelPrices'), [ + 'label' => 'marello.pricing.assembledchannelpricelist.special_price.plural_label', + 'type' => 'twig', + 'frontend_type' => 'html', + 'template' => 'MarelloPricingBundle:Datagrid/Property:specialChannelPrices.html.twig', + 'renderable' => false, + 'align' => 'right' + ]); + } + + /** + * @param DatagridConfiguration $config + */ + protected function addSorter(DatagridConfiguration $config) + { + $config + ->offsetSetByPath( + sprintf('[sorters][columns][%s]', 'defaultChannelPrices'), + ['data_name' => 'defaultChannelPricesSum'] + ) + ->offsetSetByPath( + sprintf('[sorters][columns][%s]', 'specialChannelPrices'), + ['data_name' => 'specialChannelPricesSum'] + ); + } + + /** + * @param DatagridConfiguration $config + */ + protected function addFilter(DatagridConfiguration $config) + { + $config->offsetSetByPath( + sprintf('[filters][columns][%s]', 'defaultChannelPrices'), + [ + 'type' => 'number', + 'data_name' => self::DEFAULT_JOIN_ALIAS . '.value', + 'enabled' => false, + ] + ); + $config->offsetSetByPath( + sprintf('[filters][columns][%s]', 'specialChannelPrices'), + [ + 'type' => 'number', + 'data_name' => self::SPECIAL_JOIN_ALIAS . '.value', + 'enabled' => false, + ] + ); + } +} diff --git a/src/Marello/Bundle/PricingBundle/EventListener/Datagrid/PricesDatagridListener.php b/src/Marello/Bundle/PricingBundle/EventListener/Datagrid/PricesDatagridListener.php new file mode 100644 index 000000000..0a0fa4b17 --- /dev/null +++ b/src/Marello/Bundle/PricingBundle/EventListener/Datagrid/PricesDatagridListener.php @@ -0,0 +1,208 @@ +relatedEntityClass = $relatedEntityClass; + + $this->expressionBuilder = new Expr(); + } + + /** + * @param BuildBefore $event + */ + public function onBuildBefore(BuildBefore $event) + { + $config = $event->getConfig(); + + $this->addSelect($config); + $this->addJoin($config); + $this->addColumn($config); + $this->addSorter($config); + $this->addFilter($config); + } + + /** + * @param DatagridConfiguration $configuration + * @return string + * @throws \InvalidArgumentException when a root entity not found in the grid + */ + protected function getAlias(DatagridConfiguration $configuration) + { + $rootAlias = $configuration->getOrmQuery()->getRootAlias(); + if (!$rootAlias) { + throw new \InvalidArgumentException( + sprintf( + 'A root entity is missing for grid "%s"', + $configuration->getName() + ) + ); + } + + return $rootAlias; + } + + /** + * @return string + */ + protected function getDataName() + { + return self::DATA_NAME; + } + + /** + * @return string + */ + protected function getJoinAlias() + { + return self::JOIN_ALIAS; + } + + /** + * @param DatagridConfiguration $config + */ + protected function addSelect(DatagridConfiguration $config) + { + $ormQuery = $config->getOrmQuery(); + $ormQuery + ->addSelect( + sprintf( + 'GROUP_CONCAT( + DISTINCT CONCAT_WS(\'|\', %1$s.value, %1$s.currency) SEPARATOR \';\' + ) as defaultPrices', + self::DEFAULT_JOIN_ALIAS + ) + ) + ->addSelect( + sprintf( + 'GROUP_CONCAT( + DISTINCT CONCAT_WS(\'|\', %1$s.value, %1$s.currency) SEPARATOR \';\' + ) as specialPrices', + self::SPECIAL_JOIN_ALIAS + ) + ) + ->addSelect( + sprintf( + 'GROUP_CONCAT( + DISTINCT CONCAT_WS(\'|\', %1$s.value, %1$s.currency) SEPARATOR \';\' + ) as msrpPrices', + self::MSRP_JOIN_ALIAS + ) + ) + ->addSelect(sprintf('SUM(%s.value) as defaultPricesSum', self::DEFAULT_JOIN_ALIAS)) + ->addSelect(sprintf('SUM(%s.value) as specialPricesSum', self::SPECIAL_JOIN_ALIAS)) + ->addSelect(sprintf('SUM(%s.value) as msrpPricesSum', self::MSRP_JOIN_ALIAS)); + } + + /** + * @param DatagridConfiguration $config + */ + protected function addJoin(DatagridConfiguration $config) + { + $ormQuery = $config->getOrmQuery(); + $ormQuery + ->addLeftJoin(sprintf('%s.%s', $this->getAlias($config), self::DATA_NAME), $this->getJoinAlias()) + ->addLeftJoin(sprintf('%s.%s', $this->getJoinAlias(), self::DEFAULT_DATA_NAME), self::DEFAULT_JOIN_ALIAS) + ->addLeftJoin(sprintf('%s.%s', $this->getJoinAlias(), self::SPECIAL_DATA_NAME), self::SPECIAL_JOIN_ALIAS) + ->addLeftJoin(sprintf('%s.%s', $this->getJoinAlias(), self::MSRP_DATA_NAME), self::MSRP_JOIN_ALIAS); + } + + /** + * @param DatagridConfiguration $config + */ + protected function addColumn(DatagridConfiguration $config) + { + $config->offsetSetByPath(sprintf('[columns][%s]', 'defaultPrices'), [ + 'label' => 'marello.pricing.assembledpricelist.default_price.plural_label', + 'type' => 'twig', + 'frontend_type' => 'html', + 'template' => 'MarelloPricingBundle:Datagrid/Property:defaultPrices.html.twig', + 'renderable' => false, + 'align' => 'right' + ]); + $config->offsetSetByPath(sprintf('[columns][%s]', 'specialPrices'), [ + 'label' => 'marello.pricing.assembledpricelist.special_price.plural_label', + 'type' => 'twig', + 'frontend_type' => 'html', + 'template' => 'MarelloPricingBundle:Datagrid/Property:specialPrices.html.twig', + 'renderable' => false, + 'align' => 'right' + ]); + $config->offsetSetByPath(sprintf('[columns][%s]', 'msrpPrices'), [ + 'label' => 'marello.pricing.assembledpricelist.msrp_price.plural_label', + 'type' => 'twig', + 'frontend_type' => 'html', + 'template' => 'MarelloPricingBundle:Datagrid/Property:msrpPrices.html.twig', + 'renderable' => false, + 'align' => 'right' + ]); + } + + /** + * @param DatagridConfiguration $config + */ + protected function addSorter(DatagridConfiguration $config) + { + $config + ->offsetSetByPath(sprintf('[sorters][columns][%s]', 'defaultPrices'), ['data_name' => 'defaultPricesSum']) + ->offsetSetByPath(sprintf('[sorters][columns][%s]', 'specialPrices'), ['data_name' => 'specialPricesSum']) + ->offsetSetByPath(sprintf('[sorters][columns][%s]', 'msrpPrices'), ['data_name' => 'msrpPricesSum']); + } + + /** + * @param DatagridConfiguration $config + */ + protected function addFilter(DatagridConfiguration $config) + { + $config->offsetSetByPath( + sprintf('[filters][columns][%s]', 'defaultPrices'), + [ + 'type' => 'number', + 'data_name' => self::DEFAULT_JOIN_ALIAS . '.value', + 'enabled' => false, + ] + ); + $config->offsetSetByPath( + sprintf('[filters][columns][%s]', 'specialPrices'), + [ + 'type' => 'number', + 'data_name' => self::SPECIAL_JOIN_ALIAS . '.value', + 'enabled' => false, + ] + ); + $config->offsetSetByPath( + sprintf('[filters][columns][%s]', 'msrpPrices'), + [ + 'type' => 'number', + 'data_name' => self::MSRP_JOIN_ALIAS . '.value', + 'enabled' => false, + ] + ); + } +} diff --git a/src/Marello/Bundle/PricingBundle/Form/EventListener/PricingSubscriber.php b/src/Marello/Bundle/PricingBundle/Form/EventListener/PricingSubscriber.php index dded8a447..33ee0d1d3 100644 --- a/src/Marello/Bundle/PricingBundle/Form/EventListener/PricingSubscriber.php +++ b/src/Marello/Bundle/PricingBundle/Form/EventListener/PricingSubscriber.php @@ -11,7 +11,7 @@ use Marello\Bundle\PricingBundle\Entity\ProductPrice; use Marello\Bundle\PricingBundle\Provider\CurrencyProvider; use Marello\Bundle\PricingBundle\Model\PricingAwareInterface; -use Marello\Bundle\SalesBundle\Model\SalesChannelAwareInterface; +use Marello\Bundle\SalesBundle\Model\SalesChannelsAwareInterface; use Marello\Bundle\PricingBundle\Entity\AssembledPriceList; use Marello\Bundle\PricingBundle\Entity\PriceType; use Marello\Bundle\PricingBundle\Form\Type\AssembledPriceListCollectionType; @@ -67,7 +67,7 @@ public function preSetData(FormEvent $event) $entity = $event->getData(); $form = $event->getForm(); - if ($entity instanceof PricingAwareInterface && $entity instanceof SalesChannelAwareInterface) { + if ($entity instanceof PricingAwareInterface && $entity instanceof SalesChannelsAwareInterface) { $currencies = $this->provider->getCurrencies($entity->getChannels()); if ($entity->hasPrices()) { $existingCurrencies = []; diff --git a/src/Marello/Bundle/PricingBundle/Form/Type/AssembledChannelPriceListType.php b/src/Marello/Bundle/PricingBundle/Form/Type/AssembledChannelPriceListType.php index 35437b5be..2f282883c 100644 --- a/src/Marello/Bundle/PricingBundle/Form/Type/AssembledChannelPriceListType.php +++ b/src/Marello/Bundle/PricingBundle/Form/Type/AssembledChannelPriceListType.php @@ -8,6 +8,7 @@ use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Validator\Constraints\NotNull; class AssembledChannelPriceListType extends AbstractType { @@ -27,6 +28,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) ]) ->add('defaultPrice', ProductChannelPriceType::class, [ 'required' => true, + 'allowed_empty_value' => false ]) ->add('specialPrice', ProductChannelPriceType::class, [ 'required' => false, diff --git a/src/Marello/Bundle/PricingBundle/Form/Type/ProductChannelPriceType.php b/src/Marello/Bundle/PricingBundle/Form/Type/ProductChannelPriceType.php index b2bc176f4..045c5292a 100644 --- a/src/Marello/Bundle/PricingBundle/Form/Type/ProductChannelPriceType.php +++ b/src/Marello/Bundle/PricingBundle/Form/Type/ProductChannelPriceType.php @@ -9,6 +9,7 @@ use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Validator\Constraints\NotNull; class ProductChannelPriceType extends AbstractType { @@ -28,6 +29,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) ]) ->add('value', OroMoneyType::class, [ 'required' => false, + 'constraints' => $options['allowed_empty_value'] === false ? new NotNull() : null, 'label' => 'marello.pricing.productprice.value.label', ]); } @@ -41,7 +43,8 @@ public function configureOptions(OptionsResolver $resolver) 'data_class' => ProductChannelPrice::class, 'intention' => 'productchannelprice', 'single_form' => true, - 'excluded_channels' => [] + 'excluded_channels' => [], + 'allowed_empty_value' => true ]); } diff --git a/src/Marello/Bundle/PricingBundle/Formatter/LabelVATAwareFormatter.php b/src/Marello/Bundle/PricingBundle/Formatter/LabelVATAwareFormatter.php index 49113744a..854d5612b 100644 --- a/src/Marello/Bundle/PricingBundle/Formatter/LabelVATAwareFormatter.php +++ b/src/Marello/Bundle/PricingBundle/Formatter/LabelVATAwareFormatter.php @@ -4,7 +4,7 @@ use Marello\Bundle\PricingBundle\DependencyInjection\Configuration; use Oro\Bundle\ConfigBundle\Config\ConfigManager; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class LabelVATAwareFormatter { diff --git a/src/Marello/Bundle/PricingBundle/Model/PricingAwareInterface.php b/src/Marello/Bundle/PricingBundle/Model/PricingAwareInterface.php index d53d3ad7c..a29862f1b 100644 --- a/src/Marello/Bundle/PricingBundle/Model/PricingAwareInterface.php +++ b/src/Marello/Bundle/PricingBundle/Model/PricingAwareInterface.php @@ -5,7 +5,6 @@ use Doctrine\Common\Collections\ArrayCollection; use Marello\Bundle\PricingBundle\Entity\AssembledChannelPriceList; use Marello\Bundle\PricingBundle\Entity\AssembledPriceList; -use Marello\Bundle\PricingBundle\Entity\ProductChannelPrice; interface PricingAwareInterface { diff --git a/src/Marello/Bundle/PricingBundle/Resources/config/jsmodules.yml b/src/Marello/Bundle/PricingBundle/Resources/config/jsmodules.yml new file mode 100644 index 000000000..8874ecdc2 --- /dev/null +++ b/src/Marello/Bundle/PricingBundle/Resources/config/jsmodules.yml @@ -0,0 +1,4 @@ +dynamic-imports: + marellopricing: + - marellopricing/js/app/views/channel-pricing-item-view + - marellopricing/js/app/views/channel-pricing-items-view \ No newline at end of file diff --git a/src/Marello/Bundle/PricingBundle/Resources/config/oro/twig.yml b/src/Marello/Bundle/PricingBundle/Resources/config/oro/twig.yml new file mode 100644 index 000000000..7532b70f4 --- /dev/null +++ b/src/Marello/Bundle/PricingBundle/Resources/config/oro/twig.yml @@ -0,0 +1,2 @@ +bundles: + - MarelloPricingBundle:Form:fields.html.twig diff --git a/src/Marello/Bundle/PricingBundle/Resources/config/services.yml b/src/Marello/Bundle/PricingBundle/Resources/config/services.yml index cefb7c7fb..3fd6760df 100644 --- a/src/Marello/Bundle/PricingBundle/Resources/config/services.yml +++ b/src/Marello/Bundle/PricingBundle/Resources/config/services.yml @@ -1,6 +1,7 @@ services: marello_productprice.pricing.provider.currency_provider: class: Marello\Bundle\PricingBundle\Provider\CurrencyProvider + public: true arguments: - '@doctrine' - '@oro_locale.settings' @@ -64,3 +65,17 @@ services: - '@marello_productprice.pricing.formatter.vat_aware_label' tags: - { name: kernel.event_listener, event: oro_datagrid.datagrid.build.before.marello-productchannelprice-grid, method: onBuildBefore } + + marello_productprice.pricing.listener.datagrid.products_grid.prices: + class: 'Marello\Bundle\PricingBundle\EventListener\Datagrid\PricesDatagridListener' + arguments: + - 'Marello\Bundle\ProductBundle\Entity\Product' + tags: + - { name: kernel.event_listener, event: oro_datagrid.datagrid.build.before.marello-products-grid, method: onBuildBefore } + + marello_productprice.pricing.listener.datagrid.products_grid.channel_prices: + class: 'Marello\Bundle\PricingBundle\EventListener\Datagrid\ChannelPricesDatagridListener' + arguments: + - 'Marello\Bundle\ProductBundle\Entity\Product' + tags: + - { name: kernel.event_listener, event: oro_datagrid.datagrid.build.before.marello-products-grid, method: onBuildBefore } \ No newline at end of file diff --git a/src/Marello/Bundle/PricingBundle/Resources/public/js/app/views/channel-pricing-item-view.js b/src/Marello/Bundle/PricingBundle/Resources/public/js/app/views/channel-pricing-item-view.js index 54fefe60b..d42ff5c6d 100644 --- a/src/Marello/Bundle/PricingBundle/Resources/public/js/app/views/channel-pricing-item-view.js +++ b/src/Marello/Bundle/PricingBundle/Resources/public/js/app/views/channel-pricing-item-view.js @@ -1,7 +1,7 @@ define(function(require) { 'use strict'; - var ChannelPricingItemView, + const $ = require('jquery'), _ = require('underscore'), mediator = require('oroui/js/mediator'), @@ -12,7 +12,7 @@ define(function(require) { * @extends marellolayout.app.views.AbstractItemView * @class marellopricing.app.views.ChannelPricingItemView */ - ChannelPricingItemView = AbstractItemView.extend({ + const ChannelPricingItemView = AbstractItemView.extend({ /** * @property {Object} */ diff --git a/src/Marello/Bundle/PricingBundle/Resources/public/js/app/views/channel-pricing-items-view.js b/src/Marello/Bundle/PricingBundle/Resources/public/js/app/views/channel-pricing-items-view.js index 9b8179372..f6b027f17 100644 --- a/src/Marello/Bundle/PricingBundle/Resources/public/js/app/views/channel-pricing-items-view.js +++ b/src/Marello/Bundle/PricingBundle/Resources/public/js/app/views/channel-pricing-items-view.js @@ -1,7 +1,7 @@ define(function(require) { 'use strict'; - var PricingItemsView, + const $ = require('jquery'), __ = require('orotranslation/js/translator'), routing = require('routing'), @@ -14,7 +14,7 @@ define(function(require) { * @extends marellolayout.app.views.AbstractItemsView * @class marellopricing.app.views.PricingItemsView */ - PricingItemsView = AbstractItemsView.extend({ + const PricingItemsView = AbstractItemsView.extend({ /** * @property {Object} */ diff --git a/src/Marello/Bundle/PricingBundle/Resources/translations/messages.en.yml b/src/Marello/Bundle/PricingBundle/Resources/translations/messages.en.yml index bc71b2666..7d22bea85 100644 --- a/src/Marello/Bundle/PricingBundle/Resources/translations/messages.en.yml +++ b/src/Marello/Bundle/PricingBundle/Resources/translations/messages.en.yml @@ -45,7 +45,6 @@ marello: No configured channels found for the current product. Please make sure Sales Channels exist and linked. no_prices_configured: No prices configured for current product - type.label: Price Type pricetype: entity_label: Price Type diff --git a/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/defaultChannelPrices.html.twig b/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/defaultChannelPrices.html.twig new file mode 100644 index 000000000..63a2d5436 --- /dev/null +++ b/src/Marello/Bundle/PricingBundle/Resources/views/Datagrid/Property/defaultChannelPrices.html.twig @@ -0,0 +1,7 @@ +{% set prices = record.getValue('defaultChannelPrices')|split(';') %} +{% for index, valueSet in prices %} + {% set values = valueSet|split('|') %} + {% if values|length == 3 %} + {{ values[0] }}: {{ values[1]|oro_format_currency({'currency': values[2]}) }}{{ 'marello.sales.saleschannel.entity_label'|trans }} | -{{ 'marello.pricing.productchannelprice.currency.label'|trans }} | -{{ marello_pricing_vat_aware_label('marello.pricing.productchannelprice.value.label') }} | - {% if form.vars.allow_delete %} -- {% endif %} - |
---|
{{ 'marello.pricing.productprice.currency.label'|trans }} | -{{ marello_pricing_vat_aware_label('marello.pricing.productprice.value.label') }} | -
---|