Compare commits
223 Commits
Author | SHA1 | Date | |
---|---|---|---|
841c69af59 | |||
56b4688f93 | |||
e60bc7c387 | |||
6094a83f4b | |||
91ddb98f56 | |||
27d5972306 | |||
6088497433 | |||
0d894a6fef | |||
57f0b88299 | |||
5121dbe0c8 | |||
f874ffc19c | |||
e928a5c2bc | |||
d11badf3ce | |||
3006c982cb | |||
b29e31fdd6 | |||
bc42c8e280 | |||
409697ee64 | |||
cfb4265971 | |||
13d78aac05 | |||
6f176f4e6c | |||
9b584296a5 | |||
5ea87c5eed | |||
7522084ccb | |||
214aa60d0e | |||
7a049ce1b7 | |||
94d293deb7 | |||
bd2d38d757 | |||
abec524daa | |||
cac6beb4ac | |||
cac995e15b | |||
b26380fd10 | |||
6c6a4070be | |||
8b001d820b | |||
2ae3d8ebdf | |||
459ec21f9d | |||
9c7790d07e | |||
f9c5b99e46 | |||
95b0b39366 | |||
4b6fa0e760 | |||
67a3440ced | |||
0de372344a | |||
7a04eeb650 | |||
8dbfe82922 | |||
7322f2151c | |||
c43d2f240d | |||
bbcd267b6f | |||
bbc4acb2a4 | |||
c89cc5a919 | |||
33075940de | |||
51c09b8360 | |||
2fbf85f371 | |||
24cb614adb | |||
55f851208b | |||
990dac7727 | |||
233020ca20 | |||
0c419cde16 | |||
35f9530d8e | |||
992fe2a6e9 | |||
c2cb88f995 | |||
ba69d659ab | |||
397d988eb1 | |||
d85f2341ec | |||
2b3c288b5f | |||
8ec28a23a7 | |||
12c9623e2f | |||
8ba9fdccbc | |||
a2ef62302f | |||
24ecc879d3 | |||
a1104a7f90 | |||
aa959810e9 | |||
45b7a79277 | |||
41c8c0dae5 | |||
2aeab7aaff | |||
4fd0c4b484 | |||
d4623cf763 | |||
181c4fed08 | |||
7884dd8389 | |||
b577d33414 | |||
70de0a01bf | |||
3b7f77d9af | |||
21847ca875 | |||
6153316047 | |||
32f8f07602 | |||
70a04d9bf6 | |||
bb1cc997cc | |||
24f96d9d7d | |||
46c7332da2 | |||
2f42f643ab | |||
63c87f3746 | |||
d4d575cda4 | |||
2cf03ec0a3 | |||
72ad98a77f | |||
b5094f568c | |||
7d224274fc | |||
f3b9f7be92 | |||
6e74f82ace | |||
831eb6af44 | |||
1e8e5aecee | |||
c0f98c9ba6 | |||
746c19d6ed | |||
894a9e8c90 | |||
8fea917337 | |||
c60425afb2 | |||
0776e9ad73 | |||
91981cc324 | |||
1906fafacb | |||
c11d95b402 | |||
b4c8fe6f45 | |||
d0e770e0fc | |||
3d6d1a4282 | |||
dc3b47db00 | |||
900d6694e2 | |||
e8074a61a5 | |||
64501a914a | |||
de70e855ad | |||
03e3b5a94b | |||
3331bed31c | |||
8c5a33a0fe | |||
01eb6c7a98 | |||
f502e0b677 | |||
a6b64a1c5d | |||
5019131b21 | |||
da483fb88f | |||
788bed4622 | |||
3fbe5423d0 | |||
8357295be2 | |||
8072b162d4 | |||
3f2f0ec1a9 | |||
5a5a777b7d | |||
6cac7f3652 | |||
6a9313107c | |||
72c9d301b7 | |||
ad925de801 | |||
1da28b7299 | |||
e837ad7014 | |||
daec56191f | |||
7bd25660df | |||
3b9821fbe1 | |||
cabe2d61b7 | |||
a6d802e2fa | |||
1732c4f634 | |||
bb77134224 | |||
f1cb64b240 | |||
3689545589 | |||
9b67c56281 | |||
dc38b19667 | |||
a574733217 | |||
b90aaa629e | |||
8de186c0e6 | |||
e3719967f9 | |||
138a631ed7 | |||
07b7636a72 | |||
a63ce3cdac | |||
f5c7bb87af | |||
2c8d925971 | |||
0c5beb2511 | |||
9c0316a87d | |||
46c1b682fa | |||
7954346a3f | |||
d87ff67f50 | |||
6642bb3bfa | |||
2cb32e7a78 | |||
fcea9adbd9 | |||
bbdd0dbb6e | |||
1b2cf7bd16 | |||
b7cfa549d5 | |||
ffc1d0a61c | |||
d1b160def7 | |||
493fd01754 | |||
9ced4b1757 | |||
17010e5ba9 | |||
42ad7584d4 | |||
dbc0f9b238 | |||
e62e9a5892 | |||
bc25fa61b4 | |||
2590967183 | |||
86eafd3c17 | |||
90a6f160c2 | |||
c774aec6a2 | |||
8f2fd1d76e | |||
4df11163a1 | |||
82a736ffbb | |||
87052986e8 | |||
0c73c0fadc | |||
5c7e11076d | |||
d1df94c759 | |||
53cc39c6f5 | |||
4955c72ee1 | |||
16661af8c3 | |||
bc80f69e41 | |||
0192934e65 | |||
2793e74858 | |||
5996696cc9 | |||
7f6cf5bbf3 | |||
c0ef2254cd | |||
0dbe04c3f8 | |||
ef1805d9b5 | |||
514f539e83 | |||
50f072705e | |||
f8f7bc3d3d | |||
f1bf2bb097 | |||
bbe2f69a7f | |||
c844488b0b | |||
112fe0cd6e | |||
c9e6dce785 | |||
d1c09c015a | |||
8d61866b77 | |||
0831c748b1 | |||
b2a0bc3860 | |||
1f99345e7b | |||
89782bc94b | |||
155ff09280 | |||
132e6d3342 | |||
f02699158f | |||
be3462925d | |||
3d82230d10 | |||
c20c46fd86 | |||
6e63c72aa5 | |||
e059eec5ea | |||
a2d38c9076 | |||
8d507b2ee0 | |||
5e2979c283 | |||
84ec0de3cd |
16
.env.sample
16
.env.sample
@ -1,2 +1,16 @@
|
|||||||
WP_TEST_PATH="/var/www/wordpress"
|
WP_TEST_PATH="/var/www/wordpress"
|
||||||
|
WP_TEST_ENABLE_NETWORK_TESTS="true"
|
||||||
|
WP_TEST_IMPORT_MAILCHIMP_API=""
|
||||||
|
WP_TEST_IMPORT_MAILCHIMP_LISTS="" // (separated with comma)
|
||||||
|
WP_TEST_MAILER_ENABLE_SENDING="true"
|
||||||
|
WP_TEST_MAILER_AMAZON_ACCESS=""
|
||||||
|
WP_TEST_MAILER_AMAZON_SECRET=""
|
||||||
|
WP_TEST_MAILER_AMAZON_REGION=""
|
||||||
|
WP_TEST_MAILER_ELASTICEMAIL_API=""
|
||||||
|
WP_TEST_MAILER_MAILGUN_API=""
|
||||||
|
WP_TEST_MAILER_MAILGUN_DOMAIN=""
|
||||||
|
WP_TEST_MAILER_MAILPOET_API=""
|
||||||
|
WP_TEST_MAILER_SENDGRID_API=""
|
||||||
|
WP_TEST_MAILER_SMTP_HOST=""
|
||||||
|
WP_TEST_MAILER_SMTP_LOGIN=""
|
||||||
|
WP_TEST_MAILER_SMTP_PASSWORD=""
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,7 +1,7 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
TODO
|
TODO
|
||||||
composer.phar
|
composer.phar
|
||||||
vendor
|
/vendor
|
||||||
tests/_output/*
|
tests/_output/*
|
||||||
tests/acceptance.suite.yml
|
tests/acceptance.suite.yml
|
||||||
tests/_support/_generated/*
|
tests/_support/_generated/*
|
||||||
|
11
README.md
11
README.md
@ -8,7 +8,6 @@ MailPoet done the right way.
|
|||||||
```
|
```
|
||||||
php
|
php
|
||||||
nodejs
|
nodejs
|
||||||
phantomjs
|
|
||||||
wordpress
|
wordpress
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -47,16 +46,6 @@ $ ./do compile:all
|
|||||||
$ ./do test:unit
|
$ ./do test:unit
|
||||||
```
|
```
|
||||||
|
|
||||||
- Acceptance tests:
|
|
||||||
```sh
|
|
||||||
$ ./do test:acceptance
|
|
||||||
```
|
|
||||||
|
|
||||||
- Run all tests:
|
|
||||||
```sh
|
|
||||||
$ ./do test:all
|
|
||||||
```
|
|
||||||
|
|
||||||
- Debug tests:
|
- Debug tests:
|
||||||
```sh
|
```sh
|
||||||
$ ./do test:debug
|
$ ./do test:debug
|
||||||
|
13
RoboFile.php
13
RoboFile.php
@ -105,7 +105,18 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
function testUnit($file = null) {
|
function testUnit($file = null) {
|
||||||
$this->loadEnv();
|
$this->loadEnv();
|
||||||
$this->_exec('vendor/bin/codecept build');
|
$this->_exec('vendor/bin/codecept build');
|
||||||
$this->_exec('vendor/bin/codecept run unit '.(($file) ? $file : ''));
|
$this->_exec('vendor/bin/codecept run unit -f '.(($file) ? $file : ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testCoverage($file = null) {
|
||||||
|
$this->loadEnv();
|
||||||
|
$this->_exec('vendor/bin/codecept build');
|
||||||
|
$this->_exec(join(' ', array(
|
||||||
|
'vendor/bin/codecept run',
|
||||||
|
(($file) ? $file : ''),
|
||||||
|
'--coverage',
|
||||||
|
'--coverage-html'
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testJavascript() {
|
function testJavascript() {
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
bottom: 0
|
bottom: 0
|
||||||
background-color: rgba(255, 255, 255, 0.0)
|
background-color: rgba(255, 255, 255, 0.0)
|
||||||
opacity: 0
|
opacity: 0
|
||||||
transition: all 200ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
transition: all 250ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
||||||
|
|
||||||
&:hover
|
&:hover
|
||||||
background-color: rgba(255, 255, 255, 0.7)
|
background-color: rgba(255, 255, 255, 0.7)
|
||||||
@ -101,3 +101,6 @@
|
|||||||
[data-type="standard"] .mailpoet_thumbnail
|
[data-type="standard"] .mailpoet_thumbnail
|
||||||
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20viewBox%3D%220%200%2070%2070%22%20enable-background%3D%22new%200%200%2070%2070%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23ffffff%22%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M62.751%2C65.368L43.923%2C50.955l18.832-14.377l-5.395-4.118v-3.479l5.983%2C4.568%20v3.479l0.166%2C26.269C63.51%2C64.089%2C63.198%2C64.783%2C62.751%2C65.368z%20M31.433%2C49.5l-15.955-12v-30c0-1.657%2C1.339-3%2C2.992-3h33.905%20c1.652%2C0%2C2.992%2C1.343%2C2.992%2C3v30l-15.955%2C12H31.433z%20M18.469%2C35.5H33.5v-2H18.469V35.5z%20M18.469%2C31.5H33.5v-2H18.469V31.5z%20M18.469%2C27.5H33.5v-2H18.469V27.5z%20M38.406%2C7.5H18.469v14h19.937V7.5z%20M52.375%2C7.5H40.408v2h11.967V7.5z%20M52.375%2C11.5H40.408v2%20h11.967V11.5z%20M52.375%2C15.5H40.408v2h11.967V15.5z%20M52.375%2C19.5H40.408v2h11.967V19.5z%20M52.375%2C25.5H37.5v2h14.875V25.5z%20M52.375%2C29.5H37.5v2h14.875V29.5z%20M52.375%2C33.5H37.5v2h14.875V33.5z%20M26.14%2C17.192L28.442%2C9.5l3.277%2C6.571l1.71-2.571l2.992%2C6%20h-2.992h-3.989h-0.997H25.45h-4.986l3.989-4L26.14%2C17.192z%20M22.469%2C12.5h-1c-0.552%2C0-1-0.448-1-1v-1c0-0.552%2C0.448-1%2C1-1h1%20c0.552%2C0%2C1%2C0.448%2C1%2C1v1C23.469%2C12.052%2C23.021%2C12.5%2C22.469%2C12.5z%20M26.795%2C50.955L8.05%2C65.305c-0.419-0.574-0.55-1.41-0.55-2.174%20V37.015l-0.015%2C0.011v-3.479l5.998-4.579v3.479L8.017%2C36.62L26.795%2C50.955z%20M29.137%2C52.659v-0.157h12.462v0.144l0.047-0.036%20L59.73%2C66.5H10.989l18.084-13.889L29.137%2C52.659z%22%2F%3E%3C%2Fsvg%3E%0A")
|
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20viewBox%3D%220%200%2070%2070%22%20enable-background%3D%22new%200%200%2070%2070%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23ffffff%22%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M62.751%2C65.368L43.923%2C50.955l18.832-14.377l-5.395-4.118v-3.479l5.983%2C4.568%20v3.479l0.166%2C26.269C63.51%2C64.089%2C63.198%2C64.783%2C62.751%2C65.368z%20M31.433%2C49.5l-15.955-12v-30c0-1.657%2C1.339-3%2C2.992-3h33.905%20c1.652%2C0%2C2.992%2C1.343%2C2.992%2C3v30l-15.955%2C12H31.433z%20M18.469%2C35.5H33.5v-2H18.469V35.5z%20M18.469%2C31.5H33.5v-2H18.469V31.5z%20M18.469%2C27.5H33.5v-2H18.469V27.5z%20M38.406%2C7.5H18.469v14h19.937V7.5z%20M52.375%2C7.5H40.408v2h11.967V7.5z%20M52.375%2C11.5H40.408v2%20h11.967V11.5z%20M52.375%2C15.5H40.408v2h11.967V15.5z%20M52.375%2C19.5H40.408v2h11.967V19.5z%20M52.375%2C25.5H37.5v2h14.875V25.5z%20M52.375%2C29.5H37.5v2h14.875V29.5z%20M52.375%2C33.5H37.5v2h14.875V33.5z%20M26.14%2C17.192L28.442%2C9.5l3.277%2C6.571l1.71-2.571l2.992%2C6%20h-2.992h-3.989h-0.997H25.45h-4.986l3.989-4L26.14%2C17.192z%20M22.469%2C12.5h-1c-0.552%2C0-1-0.448-1-1v-1c0-0.552%2C0.448-1%2C1-1h1%20c0.552%2C0%2C1%2C0.448%2C1%2C1v1C23.469%2C12.052%2C23.021%2C12.5%2C22.469%2C12.5z%20M26.795%2C50.955L8.05%2C65.305c-0.419-0.574-0.55-1.41-0.55-2.174%20V37.015l-0.015%2C0.011v-3.479l5.998-4.579v3.479L8.017%2C36.62L26.795%2C50.955z%20M29.137%2C52.659v-0.157h12.462v0.144l0.047-0.036%20L59.73%2C66.5H10.989l18.084-13.889L29.137%2C52.659z%22%2F%3E%3C%2Fsvg%3E%0A")
|
||||||
|
|
||||||
|
.mailpoet_boxes_preview
|
||||||
|
margin: -10px
|
||||||
|
padding: 10px 20px
|
||||||
|
@ -19,6 +19,8 @@ a:focus
|
|||||||
|
|
||||||
// select 2
|
// select 2
|
||||||
.select2-container
|
.select2-container
|
||||||
|
width: 25em !important
|
||||||
|
|
||||||
// textareas
|
// textareas
|
||||||
textarea.regular-text
|
textarea.regular-text
|
||||||
width: 25em !important
|
width: 25em !important
|
||||||
|
@ -125,6 +125,7 @@ handle_icon = '../img/handle.png'
|
|||||||
float: none
|
float: none
|
||||||
|
|
||||||
#mailpoet_form_toolbar
|
#mailpoet_form_toolbar
|
||||||
|
z-index: 999
|
||||||
position: absolute
|
position: absolute
|
||||||
width: 400px
|
width: 400px
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ body.mailpoet_modal_opened
|
|||||||
padding: 0
|
padding: 0
|
||||||
margin: 0
|
margin: 0
|
||||||
width: 100%
|
width: 100%
|
||||||
transition: margin 0.3s ease-out
|
transition: margin 350ms ease-out
|
||||||
|
|
||||||
.mailpoet_panel_wrapper
|
.mailpoet_panel_wrapper
|
||||||
background-color: #f1f1f1
|
background-color: #f1f1f1
|
||||||
@ -200,4 +200,4 @@ body.mailpoet_modal_opened
|
|||||||
0%
|
0%
|
||||||
50%
|
50%
|
||||||
background-color: #064E6D
|
background-color: #064E6D
|
||||||
100%
|
100%
|
||||||
|
@ -7,7 +7,6 @@ $tool-active-secondary-color = #ffffff
|
|||||||
|
|
||||||
$tool-width = 20px
|
$tool-width = 20px
|
||||||
$master-column-tool-width = 24px
|
$master-column-tool-width = 24px
|
||||||
$layer-selector-width = 30px
|
|
||||||
|
|
||||||
.mailpoet_tools
|
.mailpoet_tools
|
||||||
position: absolute
|
position: absolute
|
||||||
@ -33,10 +32,35 @@ $layer-selector-width = 30px
|
|||||||
width: $master-column-tool-width
|
width: $master-column-tool-width
|
||||||
height: $master-column-tool-width
|
height: $master-column-tool-width
|
||||||
|
|
||||||
|
|
||||||
|
.mailpoet_delete_block_activate
|
||||||
|
max-width: 100%
|
||||||
|
max-height: $master-column-tool-width
|
||||||
|
opacity: 1
|
||||||
|
display: block
|
||||||
|
|
||||||
|
.mailpoet_delete_block_confirm,
|
||||||
|
.mailpoet_delete_block_cancel
|
||||||
|
max-width: 100%
|
||||||
|
max-height: 0
|
||||||
|
opacity: 0
|
||||||
|
overflow: hidden
|
||||||
|
display: block
|
||||||
|
|
||||||
.mailpoet_delete_block_activated
|
.mailpoet_delete_block_activated
|
||||||
width: auto
|
width: auto
|
||||||
height: auto
|
height: auto
|
||||||
|
|
||||||
|
.mailpoet_delete_block_activate
|
||||||
|
overflow: hidden
|
||||||
|
max-height: 0
|
||||||
|
opacity: 0
|
||||||
|
|
||||||
|
.mailpoet_delete_block_confirm,
|
||||||
|
.mailpoet_delete_block_cancel
|
||||||
|
max-height: $master-column-tool-width*2
|
||||||
|
opacity: 1
|
||||||
|
|
||||||
.mailpoet_tool
|
.mailpoet_tool
|
||||||
display: inline-block
|
display: inline-block
|
||||||
width: $tool-width
|
width: $tool-width
|
||||||
@ -82,7 +106,7 @@ $layer-selector-width = 30px
|
|||||||
padding: 0
|
padding: 0
|
||||||
|
|
||||||
.mailpoet_delete_block_activate
|
.mailpoet_delete_block_activate
|
||||||
max-width: 100%
|
max-width: $tool-width
|
||||||
display: inline-block
|
display: inline-block
|
||||||
opacity: 1
|
opacity: 1
|
||||||
animation-fade-in-and-scale-horizontally()
|
animation-fade-in-and-scale-horizontally()
|
||||||
@ -96,12 +120,12 @@ $layer-selector-width = 30px
|
|||||||
animation-fade-in-and-scale-horizontally()
|
animation-fade-in-and-scale-horizontally()
|
||||||
|
|
||||||
.mailpoet_delete_block_activated
|
.mailpoet_delete_block_activated
|
||||||
|
height: auto
|
||||||
width: auto
|
width: auto
|
||||||
border-radius(3px)
|
border-radius(3px)
|
||||||
background-color: $warning-background-color
|
background-color: $warning-background-color
|
||||||
padding: 3px 5px
|
padding: 3px 5px
|
||||||
line-height: 1.2em
|
line-height: 1.2em
|
||||||
height: auto
|
|
||||||
|
|
||||||
.mailpoet_delete_block_activate
|
.mailpoet_delete_block_activate
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
@ -113,6 +137,9 @@ $layer-selector-width = 30px
|
|||||||
max-width: 100%
|
max-width: 100%
|
||||||
opacity: 1
|
opacity: 1
|
||||||
|
|
||||||
|
.mailpoet_delete_block_cancel
|
||||||
|
margin-left: 3px
|
||||||
|
|
||||||
.mailpoet_delete_block_confirm
|
.mailpoet_delete_block_confirm
|
||||||
color: $warning-text-color
|
color: $warning-text-color
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ $draggable-widget-z-index = 2
|
|||||||
padding: 0
|
padding: 0
|
||||||
margin: 0
|
margin: 0
|
||||||
z-index: $draggable-widget-z-index
|
z-index: $draggable-widget-z-index
|
||||||
animation-fade-in-and-scale-up()
|
animation-fade-in()
|
||||||
|
|
||||||
.mailpoet_widget_icon
|
.mailpoet_widget_icon
|
||||||
padding: 0
|
padding: 0
|
||||||
|
@ -26,13 +26,9 @@ $widget-icon-width = 30px
|
|||||||
border-right: 0
|
border-right: 0
|
||||||
|
|
||||||
&.closed .mailpoet_region_content
|
&.closed .mailpoet_region_content
|
||||||
max-height: 0px
|
display: none
|
||||||
overflow: hidden
|
|
||||||
margin-top: 0
|
|
||||||
|
|
||||||
.mailpoet_region_content
|
.mailpoet_region_content
|
||||||
max-height: 2000px
|
|
||||||
transition: max-height 300ms ease
|
|
||||||
padding: 0 20px
|
padding: 0 20px
|
||||||
margin-top: 12px
|
margin-top: 12px
|
||||||
|
|
||||||
|
@ -30,8 +30,3 @@ $block-hover-highlight-color = $primary-active-color
|
|||||||
|
|
||||||
.mailpoet_content
|
.mailpoet_content
|
||||||
position: relative
|
position: relative
|
||||||
|
|
||||||
.mailpoet_block_transition_in
|
|
||||||
animation-fade-in-and-scale-up()
|
|
||||||
.mailpoet_block_transition_out
|
|
||||||
animation-fade-out-and-scale-down()
|
|
||||||
|
@ -129,3 +129,7 @@ body
|
|||||||
|
|
||||||
#mailpoet_modal_close
|
#mailpoet_modal_close
|
||||||
display: none
|
display: none
|
||||||
|
|
||||||
|
.wrap > .mailpoet_notice,
|
||||||
|
.update-nag
|
||||||
|
margin-left: 2px + 15px !important
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
animation-slide-open-downwards()
|
animation-slide-open-downwards()
|
||||||
transition: all 300ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
transition: all 250ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
||||||
max-height: 2000px
|
max-height: 2000px
|
||||||
opacity: 1
|
opacity: 1
|
||||||
|
|
||||||
@ -9,45 +9,23 @@ animation-slide-open-downwards()
|
|||||||
overflow-y: hidden
|
overflow-y: hidden
|
||||||
|
|
||||||
animation-background-color()
|
animation-background-color()
|
||||||
transition: background 300ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
transition: background 250ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
||||||
|
|
||||||
animation-fade-in-and-scale-up()
|
animation-fade-in()
|
||||||
animation-name: fadeInAndScaleUp
|
animation-name: fadeIn
|
||||||
animation-duration: 500ms
|
animation-duration: 300ms
|
||||||
animation-fill-mode: forwards
|
|
||||||
|
|
||||||
animation-fade-out-and-scale-down()
|
|
||||||
animation-name: fadeOutAndScaleDown
|
|
||||||
animation-duration: 500ms
|
|
||||||
animation-fill-mode: forwards
|
animation-fill-mode: forwards
|
||||||
|
animation-timing-function: ease-in
|
||||||
|
|
||||||
animation-fade-in-and-scale-horizontally()
|
animation-fade-in-and-scale-horizontally()
|
||||||
transition: all 300ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
transition: all 250ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
||||||
|
|
||||||
@keyframes fadeInAndScaleUp {
|
@keyframes fadeIn {
|
||||||
0% {
|
0% {
|
||||||
opacity: 0.3
|
opacity: 0.3
|
||||||
max-height: 0
|
|
||||||
overflow: hidden
|
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
opacity: 1
|
opacity: 1
|
||||||
max-height: 5000px
|
|
||||||
overflow: hidden
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeOutAndScaleDown {
|
|
||||||
0% {
|
|
||||||
opacity: 1
|
|
||||||
max-height: 5000px
|
|
||||||
overflow: hidden
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
opacity: 0.3
|
|
||||||
max-height: 0
|
|
||||||
overflow: hidden
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,10 @@ define(
|
|||||||
status: 'loading'
|
status: 'loading'
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getDaemonData: function() {
|
getCronData: function() {
|
||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: 'cron',
|
endpoint: 'cron',
|
||||||
action: 'getDaemonStatus'
|
action: 'getStatus'
|
||||||
})
|
})
|
||||||
.done(function(response) {
|
.done(function(response) {
|
||||||
jQuery('.button-primary')
|
jQuery('.button-primary')
|
||||||
@ -32,25 +32,23 @@ define(
|
|||||||
},
|
},
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
if(this.isMounted()) {
|
if(this.isMounted()) {
|
||||||
this.getDaemonData();
|
this.getCronData();
|
||||||
setInterval(this.getDaemonData, 5000);
|
setInterval(this.getCronData, 5000);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controlDaemon: function(action) {
|
controlCron: function(action) {
|
||||||
|
if(jQuery('.button-primary').hasClass('disabled')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
jQuery('.button-primary')
|
jQuery('.button-primary')
|
||||||
.addClass('disabled');
|
.addClass('disabled');
|
||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: 'cron',
|
endpoint: 'cron',
|
||||||
action: 'controlDaemon',
|
action: action,
|
||||||
data: {
|
|
||||||
'action': action
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.done(function(response) {
|
.done(function(response) {
|
||||||
if(!response.result) {
|
if(!response.result) {
|
||||||
//this.replaceState();
|
MailPoet.Notice.error(MailPoetI18n.daemonControlError);
|
||||||
} else {
|
|
||||||
//this.setState(response);
|
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
@ -71,19 +69,25 @@ define(
|
|||||||
<strong> {this.state.counter} </strong> times (once every 30 seconds, unless it was interrupted and restarted).
|
<strong> {this.state.counter} </strong> times (once every 30 seconds, unless it was interrupted and restarted).
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<a href="#" className="button-primary" onClick={this.controlDaemon.bind(null, 'stop')}>Stop</a>
|
<a href="#" className="button-primary" onClick={this.controlCron.bind(null, 'stop')}>Stop</a>
|
||||||
<a href="#" className="button-primary" onClick={this.controlDaemon.bind(null, 'pause')}>Pause</a>
|
</div>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'starting':
|
||||||
|
case 'stopping':
|
||||||
|
return(
|
||||||
|
<div>
|
||||||
|
Daemon is {this.state.status}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'paused':
|
|
||||||
case 'stopped':
|
case 'stopped':
|
||||||
return(
|
return(
|
||||||
<div>
|
<div>
|
||||||
Daemon is {this.state.status}
|
Daemon is {this.state.status}
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<a href="#" className="button-primary" onClick={this.controlDaemon.bind(null, 'start')}>Start</a>
|
<a href="#" className="button-primary" onClick={this.controlCron.bind(null, 'start')}>Start</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
@ -1,31 +1,31 @@
|
|||||||
define([
|
define([
|
||||||
'react',
|
'react'
|
||||||
'react-checkbox-group'
|
|
||||||
],
|
],
|
||||||
function(
|
function(
|
||||||
React,
|
React
|
||||||
CheckboxGroup
|
|
||||||
) {
|
) {
|
||||||
var FormFieldCheckbox = React.createClass({
|
const FormFieldCheckbox = React.createClass({
|
||||||
|
onValueChange: function(e) {
|
||||||
|
e.target.value = this.refs.checkbox.checked ? '1' : '';
|
||||||
|
return this.props.onValueChange(e);
|
||||||
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
var selected_values = this.props.item[this.props.field.name] || '';
|
const isChecked = !!(this.props.item[this.props.field.name]);
|
||||||
if(
|
|
||||||
selected_values !== undefined
|
|
||||||
&& selected_values.constructor !== Array
|
|
||||||
) {
|
|
||||||
selected_values = selected_values.split(';').map(function(value) {
|
|
||||||
return value.trim();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
var count = Object.keys(this.props.field.values).length;
|
|
||||||
|
|
||||||
var options = Object.keys(this.props.field.values).map(
|
const options = Object.keys(this.props.field.values).map(
|
||||||
function(value, index) {
|
function(value, index) {
|
||||||
return (
|
return (
|
||||||
<p key={ 'checkbox-' + index }>
|
<p key={ 'checkbox-' + index }>
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" value={ value } />
|
<input
|
||||||
{ this.props.field.values[value] }
|
ref="checkbox"
|
||||||
|
type="checkbox"
|
||||||
|
value="1"
|
||||||
|
checked={ isChecked }
|
||||||
|
onChange={ this.onValueChange }
|
||||||
|
name={ this.props.field.name }
|
||||||
|
/>
|
||||||
|
{ this.props.field.values[value] }
|
||||||
</label>
|
</label>
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
@ -33,30 +33,10 @@ function(
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CheckboxGroup
|
<div>
|
||||||
name={ this.props.field.name }
|
|
||||||
value={ selected_values }
|
|
||||||
ref={ this.props.field.name }
|
|
||||||
onChange={ this.handleValueChange }>
|
|
||||||
{ options }
|
{ options }
|
||||||
</CheckboxGroup>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
|
||||||
handleValueChange: function() {
|
|
||||||
var field = this.props.field.name;
|
|
||||||
var group = this.refs[field];
|
|
||||||
var selected_values = [];
|
|
||||||
|
|
||||||
if(group !== undefined) {
|
|
||||||
selected_values = group.getCheckedValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.props.onValueChange({
|
|
||||||
target: {
|
|
||||||
name: field,
|
|
||||||
value: selected_values.join(';')
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
196
assets/js/src/form/fields/date.jsx
Normal file
196
assets/js/src/form/fields/date.jsx
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
define([
|
||||||
|
'react',
|
||||||
|
'moment',
|
||||||
|
], function(
|
||||||
|
React,
|
||||||
|
Moment
|
||||||
|
) {
|
||||||
|
class FormFieldDateYear extends React.Component {
|
||||||
|
render() {
|
||||||
|
const yearsRange = 100;
|
||||||
|
const years = [];
|
||||||
|
const currentYear = Moment().year();
|
||||||
|
for (let i = currentYear; i >= currentYear - yearsRange; i--) {
|
||||||
|
years.push((
|
||||||
|
<option
|
||||||
|
key={ i }
|
||||||
|
value={ i }
|
||||||
|
>{ i }</option>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<select
|
||||||
|
name={ this.props.name + '[year]' }
|
||||||
|
value={ this.props.year }
|
||||||
|
onChange={ this.props.onValueChange }
|
||||||
|
>
|
||||||
|
{ years }
|
||||||
|
</select>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FormFieldDateMonth extends React.Component {
|
||||||
|
render() {
|
||||||
|
const months = [];
|
||||||
|
for (let i = 1; i <= 12; i++) {
|
||||||
|
months.push((
|
||||||
|
<option
|
||||||
|
key={ i }
|
||||||
|
value={ i }
|
||||||
|
>{ this.props.monthNames[i - 1] }</option>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<select
|
||||||
|
name={ this.props.name + '[month]' }
|
||||||
|
value={ this.props.month }
|
||||||
|
onChange={ this.props.onValueChange }
|
||||||
|
>
|
||||||
|
{ months }
|
||||||
|
</select>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FormFieldDateDay extends React.Component {
|
||||||
|
render() {
|
||||||
|
const days = [];
|
||||||
|
for (let i = 1; i <= 31; i++) {
|
||||||
|
days.push((
|
||||||
|
<option
|
||||||
|
key={ i }
|
||||||
|
value={ i }
|
||||||
|
>{ i }</option>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<select
|
||||||
|
name={ this.props.name + '[day]' }
|
||||||
|
value={ this.props.day }
|
||||||
|
onChange={ this.props.onValueChange }
|
||||||
|
>
|
||||||
|
{ days }
|
||||||
|
</select>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FormFieldDate extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
year: Moment().year(),
|
||||||
|
month: 1,
|
||||||
|
day: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
componentDidMount() {
|
||||||
|
}
|
||||||
|
componentDidUpdate(prevProps, prevState) {
|
||||||
|
if (
|
||||||
|
(this.props.item !== undefined && prevProps.item !== undefined)
|
||||||
|
&& (this.props.item.id !== prevProps.item.id)
|
||||||
|
) {
|
||||||
|
this.extractTimeStamp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extractTimeStamp() {
|
||||||
|
const timeStamp = parseInt(this.props.item[this.props.field.name], 10);
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
year: Moment.unix(timeStamp).year(),
|
||||||
|
// Moment returns the month as [0..11]
|
||||||
|
// We increment it to match PHP's mktime() which expects [1..12]
|
||||||
|
month: Moment.unix(timeStamp).month() + 1,
|
||||||
|
day: Moment.unix(timeStamp).date()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
updateTimeStamp(field) {
|
||||||
|
let newTimeStamp = Moment(
|
||||||
|
`${this.state.month}/${this.state.day}/${this.state.year}`,
|
||||||
|
'M/D/YYYY'
|
||||||
|
).valueOf();
|
||||||
|
if (!isNaN(newTimeStamp) && parseInt(newTimeStamp, 10) > 0) {
|
||||||
|
// convert milliseconds to seconds
|
||||||
|
newTimeStamp /= 1000;
|
||||||
|
return this.props.onValueChange({
|
||||||
|
target: {
|
||||||
|
name: field,
|
||||||
|
value: newTimeStamp
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onValueChange(e) {
|
||||||
|
// extract property from name
|
||||||
|
const matches = e.target.name.match(/(.*?)\[(.*?)\]/);
|
||||||
|
let field = null;
|
||||||
|
let property = null;
|
||||||
|
|
||||||
|
if (matches !== null && matches.length === 3) {
|
||||||
|
field = matches[1];
|
||||||
|
property = matches[2];
|
||||||
|
|
||||||
|
let value = parseInt(e.target.value, 10);
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
[`${property}`]: value
|
||||||
|
}, () => {
|
||||||
|
this.updateTimeStamp(field);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const monthNames = window.mailpoet_month_names || [];
|
||||||
|
|
||||||
|
const dateType = this.props.field.params.date_type;
|
||||||
|
|
||||||
|
const dateSelects = dateType.split('_');
|
||||||
|
|
||||||
|
const fields = dateSelects.map(type => {
|
||||||
|
switch(type) {
|
||||||
|
case 'year':
|
||||||
|
return (<FormFieldDateYear
|
||||||
|
onValueChange={ this.onValueChange.bind(this) }
|
||||||
|
ref={ 'year' }
|
||||||
|
key={ 'year' }
|
||||||
|
name={ this.props.field.name }
|
||||||
|
year={ this.state.year }
|
||||||
|
/>);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'month':
|
||||||
|
return (<FormFieldDateMonth
|
||||||
|
onValueChange={ this.onValueChange.bind(this) }
|
||||||
|
ref={ 'month' }
|
||||||
|
key={ 'month' }
|
||||||
|
name={ this.props.field.name }
|
||||||
|
month={ this.state.month }
|
||||||
|
monthNames={ monthNames }
|
||||||
|
/>);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'day':
|
||||||
|
return (<FormFieldDateDay
|
||||||
|
onValueChange={ this.onValueChange.bind(this) }
|
||||||
|
ref={ 'day' }
|
||||||
|
key={ 'day' }
|
||||||
|
name={ this.props.field.name }
|
||||||
|
day={ this.state.day }
|
||||||
|
/>);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{fields}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return FormFieldDate;
|
||||||
|
});
|
@ -5,7 +5,8 @@ define([
|
|||||||
'form/fields/select.jsx',
|
'form/fields/select.jsx',
|
||||||
'form/fields/radio.jsx',
|
'form/fields/radio.jsx',
|
||||||
'form/fields/checkbox.jsx',
|
'form/fields/checkbox.jsx',
|
||||||
'form/fields/selection.jsx'
|
'form/fields/selection.jsx',
|
||||||
|
'form/fields/date.jsx',
|
||||||
],
|
],
|
||||||
function(
|
function(
|
||||||
React,
|
React,
|
||||||
@ -14,7 +15,8 @@ function(
|
|||||||
FormFieldSelect,
|
FormFieldSelect,
|
||||||
FormFieldRadio,
|
FormFieldRadio,
|
||||||
FormFieldCheckbox,
|
FormFieldCheckbox,
|
||||||
FormFieldSelection
|
FormFieldSelection,
|
||||||
|
FormFieldDate
|
||||||
) {
|
) {
|
||||||
var FormField = React.createClass({
|
var FormField = React.createClass({
|
||||||
renderField: function(data, inline = false) {
|
renderField: function(data, inline = false) {
|
||||||
@ -55,6 +57,10 @@ function(
|
|||||||
case 'selection':
|
case 'selection':
|
||||||
field = (<FormFieldSelection {...data} />);
|
field = (<FormFieldSelection {...data} />);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'date':
|
||||||
|
field = (<FormFieldDate {...data} />);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(inline === true) {
|
if(inline === true) {
|
||||||
@ -66,10 +72,10 @@ function(
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<p key={ 'field-' + (data.index || 0) }>
|
<div key={ 'field-' + (data.index || 0) }>
|
||||||
{ field }
|
{ field }
|
||||||
{ description }
|
{ description }
|
||||||
</p>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -7,7 +7,6 @@ function(
|
|||||||
var FormFieldRadio = React.createClass({
|
var FormFieldRadio = React.createClass({
|
||||||
render: function() {
|
render: function() {
|
||||||
var selected_value = this.props.item[this.props.field.name];
|
var selected_value = this.props.item[this.props.field.name];
|
||||||
var count = Object.keys(this.props.field.values).length;
|
|
||||||
|
|
||||||
var options = Object.keys(this.props.field.values).map(
|
var options = Object.keys(this.props.field.values).map(
|
||||||
function(value, index) {
|
function(value, index) {
|
||||||
@ -20,7 +19,7 @@ function(
|
|||||||
value={ value }
|
value={ value }
|
||||||
onChange={ this.props.onValueChange }
|
onChange={ this.props.onValueChange }
|
||||||
name={ this.props.field.name } />
|
name={ this.props.field.name } />
|
||||||
{ this.props.field.values[value] }
|
{ this.props.field.values[value] }
|
||||||
</label>
|
</label>
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
|
@ -120,7 +120,7 @@ function(
|
|||||||
<select
|
<select
|
||||||
id={ this.props.field.id || this.props.field.name }
|
id={ this.props.field.id || this.props.field.name }
|
||||||
ref="select"
|
ref="select"
|
||||||
placeholder={ this.props.field.placeholder }
|
data-placeholder={ this.props.field.placeholder }
|
||||||
multiple={ this.props.field.multiple }
|
multiple={ this.props.field.multiple }
|
||||||
defaultValue={ default_value }
|
defaultValue={ default_value }
|
||||||
{...this.props.field.validation}
|
{...this.props.field.validation}
|
||||||
|
@ -48,7 +48,7 @@ define(
|
|||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: this.props.endpoint,
|
endpoint: this.props.endpoint,
|
||||||
action: 'get',
|
action: 'get',
|
||||||
data: { id: id }
|
data: id
|
||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
if(response === false) {
|
if(response === false) {
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -617,6 +617,28 @@ var WysijaForm = {
|
|||||||
// this is a url, so do not encode the protocol
|
// this is a url, so do not encode the protocol
|
||||||
return encodeURI(str).replace(/[!'()*]/g, escape);
|
return encodeURI(str).replace(/[!'()*]/g, escape);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
updateBlock: function(field) {
|
||||||
|
var hasUpdated = false;
|
||||||
|
WysijaForm.getBlocks().each(function(b) {
|
||||||
|
if(b.block.getData().id === field.id) {
|
||||||
|
hasUpdated = true;
|
||||||
|
b.block.redraw(field);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return hasUpdated;
|
||||||
|
},
|
||||||
|
removeBlock: function(field, callback) {
|
||||||
|
var hasRemoved = false;
|
||||||
|
WysijaForm.getBlocks().each(function(b) {
|
||||||
|
if(b.block.getData().id === field.id) {
|
||||||
|
hasRemoved = true;
|
||||||
|
b.block.removeBlock(callback);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return hasRemoved;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -825,10 +847,6 @@ WysijaForm.Block = Class.create({
|
|||||||
Effect.Fade(this.element.identify(), {
|
Effect.Fade(this.element.identify(), {
|
||||||
duration: 0.2,
|
duration: 0.2,
|
||||||
afterFinish: function(effect) {
|
afterFinish: function(effect) {
|
||||||
if(effect.element.next('.mailpoet_form_block') !== undefined && callback !== false) {
|
|
||||||
// show controls of next block to allow mass delete
|
|
||||||
WysijaForm.get(effect.element.next('.mailpoet_form_block')).block.showControls();
|
|
||||||
}
|
|
||||||
// remove placeholder
|
// remove placeholder
|
||||||
if(effect.element.previous('.block_placeholder') !== undefined) {
|
if(effect.element.previous('.block_placeholder') !== undefined) {
|
||||||
effect.element.previous('.block_placeholder').remove();
|
effect.element.previous('.block_placeholder').remove();
|
||||||
|
@ -25,58 +25,49 @@ const columns = [
|
|||||||
|
|
||||||
const messages = {
|
const messages = {
|
||||||
onTrash: function(response) {
|
onTrash: function(response) {
|
||||||
if(response) {
|
var count = ~~response;
|
||||||
let message = null;
|
var message = null;
|
||||||
if(~~response === 1) {
|
|
||||||
message = (
|
|
||||||
'1 form was moved to the trash.'
|
|
||||||
);
|
|
||||||
} else if(~~response > 1) {
|
|
||||||
message = (
|
|
||||||
'%$1d forms were moved to the trash.'
|
|
||||||
).replace('%$1d', ~~response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(message !== null) {
|
if(count === 1) {
|
||||||
MailPoet.Notice.success(message);
|
message = (
|
||||||
}
|
'1 form was moved to the trash.'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
'%$1d forms were moved to the trash.'
|
||||||
|
).replace('%$1d', count);
|
||||||
}
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
},
|
},
|
||||||
onDelete: function(response) {
|
onDelete: function(response) {
|
||||||
if(response) {
|
var count = ~~response;
|
||||||
let message = null;
|
var message = null;
|
||||||
if(~~response === 1) {
|
|
||||||
message = (
|
|
||||||
'1 form was permanently deleted.'
|
|
||||||
);
|
|
||||||
} else if(~~response > 1) {
|
|
||||||
message = (
|
|
||||||
'%$1d forms were permanently deleted.'
|
|
||||||
).replace('%$1d', ~~response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(message !== null) {
|
if(count === 1) {
|
||||||
MailPoet.Notice.success(message);
|
message = (
|
||||||
}
|
'1 form was permanently deleted.'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
'%$1d forms were permanently deleted.'
|
||||||
|
).replace('%$1d', count);
|
||||||
}
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
},
|
},
|
||||||
onRestore: function(response) {
|
onRestore: function(response) {
|
||||||
if(response) {
|
var count = ~~response;
|
||||||
let message = null;
|
var message = null;
|
||||||
if(~~response === 1) {
|
|
||||||
message = (
|
|
||||||
'1 form has been restored from the trash.'
|
|
||||||
);
|
|
||||||
} else if(~~response > 1) {
|
|
||||||
message = (
|
|
||||||
'%$1d forms have been restored from the trash.'
|
|
||||||
).replace('%$1d', ~~response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(message !== null) {
|
if(count === 1) {
|
||||||
MailPoet.Notice.success(message);
|
message = (
|
||||||
}
|
'1 form has been restored from the trash.'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
'%$1d forms have been restored from the trash.'
|
||||||
|
).replace('%$1d', count);
|
||||||
}
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -125,8 +116,8 @@ const FormList = React.createClass({
|
|||||||
endpoint: 'forms',
|
endpoint: 'forms',
|
||||||
action: 'create'
|
action: 'create'
|
||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
if(response !== false) {
|
if(response.result && response.form_id) {
|
||||||
window.location = response;
|
window.location = mailpoet_form_edit_url + response.form_id;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -14,6 +14,9 @@ function(
|
|||||||
})
|
})
|
||||||
return this.props.onSelectFilter(filters);
|
return this.props.onSelectFilter(filters);
|
||||||
},
|
},
|
||||||
|
handleEmptyTrash: function() {
|
||||||
|
return this.props.onEmptyTrash();
|
||||||
|
},
|
||||||
getAvailableFilters: function() {
|
getAvailableFilters: function() {
|
||||||
let filters = this.props.filters;
|
let filters = this.props.filters;
|
||||||
|
|
||||||
@ -34,7 +37,7 @@ function(
|
|||||||
const available_filters = this.getAvailableFilters()
|
const available_filters = this.getAvailableFilters()
|
||||||
.map(function(filter, i) {
|
.map(function(filter, i) {
|
||||||
let default_value = false;
|
let default_value = false;
|
||||||
if(selected_filters[filter] !== undefined && selected_filters[filter]) {
|
if (selected_filters[filter] !== undefined && selected_filters[filter]) {
|
||||||
default_value = selected_filters[filter]
|
default_value = selected_filters[filter]
|
||||||
} else {
|
} else {
|
||||||
jQuery(`select[name="${filter}"]`).val('');
|
jQuery(`select[name="${filter}"]`).val('');
|
||||||
@ -60,9 +63,10 @@ function(
|
|||||||
|
|
||||||
let button = false;
|
let button = false;
|
||||||
|
|
||||||
if(available_filters.length > 0) {
|
if (available_filters.length > 0) {
|
||||||
button = (
|
button = (
|
||||||
<input
|
<input
|
||||||
|
id="post-query-submit"
|
||||||
onClick={ this.handleFilterAction }
|
onClick={ this.handleFilterAction }
|
||||||
type="submit"
|
type="submit"
|
||||||
defaultValue="Filter"
|
defaultValue="Filter"
|
||||||
@ -70,10 +74,23 @@ function(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let empty_trash = false;
|
||||||
|
if (this.props.group === 'trash') {
|
||||||
|
empty_trash = (
|
||||||
|
<input
|
||||||
|
onClick={ this.handleEmptyTrash }
|
||||||
|
type="submit"
|
||||||
|
value="Empty Trash"
|
||||||
|
className="button"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="alignleft actions actions">
|
<div className="alignleft actions actions">
|
||||||
{ available_filters }
|
{ available_filters }
|
||||||
{ button }
|
{ button }
|
||||||
|
{ empty_trash }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -74,10 +74,11 @@ define(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var custom_actions = this.props.item_actions;
|
const custom_actions = this.props.item_actions;
|
||||||
var item_actions = false;
|
let item_actions = false;
|
||||||
|
|
||||||
if(custom_actions.length > 0) {
|
if(custom_actions.length > 0) {
|
||||||
|
let is_first = true;
|
||||||
item_actions = custom_actions.map(function(action, index) {
|
item_actions = custom_actions.map(function(action, index) {
|
||||||
if(action.display !== undefined) {
|
if(action.display !== undefined) {
|
||||||
if(action.display(this.props.item) === false) {
|
if(action.display(this.props.item) === false) {
|
||||||
@ -85,10 +86,12 @@ define(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let custom_action = null;
|
||||||
|
|
||||||
if(action.name === 'trash') {
|
if(action.name === 'trash') {
|
||||||
return (
|
custom_action = (
|
||||||
<span key={ 'action-'+index } className="trash">
|
<span key={ 'action-'+index } className="trash">
|
||||||
{(index > 0) ? ' | ' : ''}
|
{(!is_first) ? ' | ' : ''}
|
||||||
<a
|
<a
|
||||||
href="javascript:;"
|
href="javascript:;"
|
||||||
onClick={ this.handleTrashItem.bind(
|
onClick={ this.handleTrashItem.bind(
|
||||||
@ -100,27 +103,27 @@ define(
|
|||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
} else if(action.refresh) {
|
} else if(action.refresh) {
|
||||||
return (
|
custom_action = (
|
||||||
<span
|
<span
|
||||||
onClick={ this.props.onRefreshItems }
|
onClick={ this.props.onRefreshItems }
|
||||||
key={ 'action-'+index } className={ action.name }>
|
key={ 'action-'+index } className={ action.name }>
|
||||||
{(index > 0) ? ' | ' : ''}
|
{(!is_first) ? ' | ' : ''}
|
||||||
{ action.link(this.props.item) }
|
{ action.link(this.props.item) }
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
} else if(action.link) {
|
} else if(action.link) {
|
||||||
return (
|
custom_action = (
|
||||||
<span
|
<span
|
||||||
key={ 'action-'+index } className={ action.name }>
|
key={ 'action-'+index } className={ action.name }>
|
||||||
{(index > 0) ? ' | ' : ''}
|
{(!is_first) ? ' | ' : ''}
|
||||||
{ action.link(this.props.item) }
|
{ action.link(this.props.item) }
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
custom_action = (
|
||||||
<span
|
<span
|
||||||
key={ 'action-'+index } className={ action.name }>
|
key={ 'action-'+index } className={ action.name }>
|
||||||
{(index > 0) ? ' | ' : ''}
|
{(!is_first) ? ' | ' : ''}
|
||||||
<a href="javascript:;" onClick={
|
<a href="javascript:;" onClick={
|
||||||
(action.onClick !== undefined)
|
(action.onClick !== undefined)
|
||||||
? action.onClick.bind(null,
|
? action.onClick.bind(null,
|
||||||
@ -132,6 +135,12 @@ define(
|
|||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(custom_action !== null && is_first === true) {
|
||||||
|
is_first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return custom_action;
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
} else {
|
} else {
|
||||||
item_actions = (
|
item_actions = (
|
||||||
@ -504,10 +513,21 @@ define(
|
|||||||
this.getItems();
|
this.getItems();
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
handleEmptyTrash: function() {
|
||||||
|
this.handleBulkAction('all', {
|
||||||
|
action: 'delete',
|
||||||
|
group: 'trash'
|
||||||
|
}, function(response) {
|
||||||
|
MailPoet.Notice.success(
|
||||||
|
MailPoetI18n.permanentlyDeleted.replace('%d', response)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
handleBulkAction: function(selected_ids, params, callback) {
|
handleBulkAction: function(selected_ids, params, callback) {
|
||||||
if(
|
if(
|
||||||
this.state.selection === false
|
this.state.selection === false
|
||||||
&& this.state.selected_ids.length === 0
|
&& this.state.selected_ids.length === 0
|
||||||
|
&& selected_ids !== 'all'
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -520,8 +540,10 @@ define(
|
|||||||
limit: 0,
|
limit: 0,
|
||||||
filter: this.state.filter,
|
filter: this.state.filter,
|
||||||
group: this.state.group,
|
group: this.state.group,
|
||||||
search: this.state.search,
|
search: this.state.search
|
||||||
selection: selected_ids
|
}
|
||||||
|
if(selected_ids !== 'all') {
|
||||||
|
data.listing.selection = selected_ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
@ -715,7 +737,10 @@ define(
|
|||||||
<ListingFilters
|
<ListingFilters
|
||||||
filters={ this.state.filters }
|
filters={ this.state.filters }
|
||||||
filter={ this.state.filter }
|
filter={ this.state.filter }
|
||||||
onSelectFilter={ this.handleFilter } />
|
group={ this.state.group }
|
||||||
|
onSelectFilter={ this.handleFilter }
|
||||||
|
onEmptyTrash={ this.handleEmptyTrash }
|
||||||
|
/>
|
||||||
<ListingPages
|
<ListingPages
|
||||||
count={ this.state.count }
|
count={ this.state.count }
|
||||||
page={ this.state.page }
|
page={ this.state.page }
|
||||||
|
@ -7,7 +7,11 @@ define(['react', 'classnames'], function(React, classNames) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
setPage: function(page) {
|
setPage: function(page) {
|
||||||
this.props.onSetPage(page);
|
this.setState({
|
||||||
|
page: null
|
||||||
|
}, function () {
|
||||||
|
this.props.onSetPage(this.constrainPage(page));
|
||||||
|
}.bind(this));
|
||||||
},
|
},
|
||||||
setFirstPage: function() {
|
setFirstPage: function() {
|
||||||
this.setPage(1);
|
this.setPage(1);
|
||||||
@ -16,10 +20,14 @@ define(['react', 'classnames'], function(React, classNames) {
|
|||||||
this.setPage(this.getLastPage());
|
this.setPage(this.getLastPage());
|
||||||
},
|
},
|
||||||
setPreviousPage: function() {
|
setPreviousPage: function() {
|
||||||
this.setPage(this.constrainPage(this.props.page - 1));
|
this.setPage(this.constrainPage(
|
||||||
|
parseInt(this.props.page, 10) - 1)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
setNextPage: function() {
|
setNextPage: function() {
|
||||||
this.setPage(this.constrainPage(this.props.page + 1));
|
this.setPage(this.constrainPage(
|
||||||
|
parseInt(this.props.page, 10) + 1)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
constrainPage: function(page) {
|
constrainPage: function(page) {
|
||||||
return Math.min(Math.max(1, Math.abs(~~page)), this.getLastPage());
|
return Math.min(Math.max(1, Math.abs(~~page)), this.getLastPage());
|
||||||
@ -27,14 +35,16 @@ define(['react', 'classnames'], function(React, classNames) {
|
|||||||
handleSetManualPage: function(e) {
|
handleSetManualPage: function(e) {
|
||||||
if(e.which === 13) {
|
if(e.which === 13) {
|
||||||
this.setPage(this.state.page);
|
this.setPage(this.state.page);
|
||||||
this.setState({ page: null });
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleChangeManualPage: function(e) {
|
handleChangeManualPage: function(e) {
|
||||||
this.setState({
|
this.setState({
|
||||||
page: this.constrainPage(e.target.value)
|
page: e.target.value
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
handleBlurManualPage: function(e) {
|
||||||
|
this.setPage(e.target.value);
|
||||||
|
},
|
||||||
getLastPage: function() {
|
getLastPage: function() {
|
||||||
return Math.ceil(this.props.count / this.props.limit);
|
return Math.ceil(this.props.count / this.props.limit);
|
||||||
},
|
},
|
||||||
@ -101,6 +111,11 @@ define(['react', 'classnames'], function(React, classNames) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let pageValue = this.props.page;
|
||||||
|
if(this.state.page !== null) {
|
||||||
|
pageValue = this.state.page;
|
||||||
|
}
|
||||||
|
|
||||||
pagination = (
|
pagination = (
|
||||||
<span className="pagination-links">
|
<span className="pagination-links">
|
||||||
{firstPage}
|
{firstPage}
|
||||||
@ -115,10 +130,11 @@ define(['react', 'classnames'], function(React, classNames) {
|
|||||||
type="text"
|
type="text"
|
||||||
onChange={ this.handleChangeManualPage }
|
onChange={ this.handleChangeManualPage }
|
||||||
onKeyUp={ this.handleSetManualPage }
|
onKeyUp={ this.handleSetManualPage }
|
||||||
|
onBlur={ this.handleBlurManualPage }
|
||||||
aria-describedby="table-paging"
|
aria-describedby="table-paging"
|
||||||
size="1"
|
size="1"
|
||||||
ref="page"
|
ref="page"
|
||||||
value={ this.state.page || this.props.page }
|
value={ pageValue }
|
||||||
name="paged"
|
name="paged"
|
||||||
id="current-page-selector"
|
id="current-page-selector"
|
||||||
className="current-page" />
|
className="current-page" />
|
||||||
|
@ -47,7 +47,6 @@ define([
|
|||||||
autoScroll: true,
|
autoScroll: true,
|
||||||
|
|
||||||
onstart: function(event) {
|
onstart: function(event) {
|
||||||
console.log('Drag start', event, this);
|
|
||||||
|
|
||||||
if (that.options.cloneOriginal === true) {
|
if (that.options.cloneOriginal === true) {
|
||||||
// Use substitution instead of a clone
|
// Use substitution instead of a clone
|
||||||
|
@ -11,10 +11,10 @@ define([
|
|||||||
'newsletter_editor/blocks/base',
|
'newsletter_editor/blocks/base',
|
||||||
'newsletter_editor/blocks/button',
|
'newsletter_editor/blocks/button',
|
||||||
'newsletter_editor/blocks/divider',
|
'newsletter_editor/blocks/divider',
|
||||||
'newsletter_editor/components/wordpress',
|
'newsletter_editor/components/communication',
|
||||||
'underscore',
|
'underscore',
|
||||||
'jquery'
|
'jquery'
|
||||||
], function(App, BaseBlock, ButtonBlock, DividerBlock, WordpressComponent, _, jQuery) {
|
], function(App, BaseBlock, ButtonBlock, DividerBlock, CommunicationComponent, _, jQuery) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ define([
|
|||||||
titlePosition: 'inTextBlock', // 'inTextBlock'|'aboveBlock',
|
titlePosition: 'inTextBlock', // 'inTextBlock'|'aboveBlock',
|
||||||
titleAlignment: 'left', // 'left'|'center'|'right'
|
titleAlignment: 'left', // 'left'|'center'|'right'
|
||||||
titleIsLink: false, // false|true
|
titleIsLink: false, // false|true
|
||||||
imagePadded: true, // true|false
|
imageFullWidth: false, // true|false
|
||||||
//imageAlignment: 'centerPadded', // 'centerFull'|'centerPadded'|'left'|'right'|'alternate'|'none'
|
//imageAlignment: 'centerPadded', // 'centerFull'|'centerPadded'|'left'|'right'|'alternate'|'none'
|
||||||
showAuthor: 'no', // 'no'|'aboveText'|'belowText'
|
showAuthor: 'no', // 'no'|'aboveText'|'belowText'
|
||||||
authorPrecededBy: 'Author:',
|
authorPrecededBy: 'Author:',
|
||||||
@ -63,15 +63,15 @@ define([
|
|||||||
initialize: function() {
|
initialize: function() {
|
||||||
base.BlockView.prototype.initialize.apply(this, arguments);
|
base.BlockView.prototype.initialize.apply(this, arguments);
|
||||||
this.fetchPosts();
|
this.fetchPosts();
|
||||||
this.on('change:amount change:contentType change:terms change:inclusionType change:displayType change:titleFormat change:titlePosition change:titleAlignment change:titleIsLink change:imagePadded change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change:sortBy change:showDivider', this._scheduleFetchPosts, this);
|
this.on('change:amount change:contentType change:terms change:inclusionType change:displayType change:titleFormat change:titlePosition change:titleAlignment change:titleIsLink change:imageFullWidth change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change:sortBy change:showDivider', this._scheduleFetchPosts, this);
|
||||||
this.listenTo(this.get('readMoreButton'), 'change', this._scheduleFetchPosts);
|
this.listenTo(this.get('readMoreButton'), 'change', this._scheduleFetchPosts);
|
||||||
this.listenTo(this.get('divider'), 'change', this._scheduleFetchPosts);
|
this.listenTo(this.get('divider'), 'change', this._scheduleFetchPosts);
|
||||||
},
|
},
|
||||||
fetchPosts: function() {
|
fetchPosts: function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
WordpressComponent.getTransformedPosts(this.toJSON()).done(function(content) {
|
CommunicationComponent.getTransformedPosts(this.toJSON()).done(function(content) {
|
||||||
console.log('ALC fetched', arguments);
|
|
||||||
that.get('_container').get('blocks').reset(content, {parse: true});
|
that.get('_container').get('blocks').reset(content, {parse: true});
|
||||||
|
that.trigger('postsChanged');
|
||||||
}).fail(function(error) {
|
}).fail(function(error) {
|
||||||
console.log('ALC fetchPosts error', arguments);
|
console.log('ALC fetchPosts error', arguments);
|
||||||
});
|
});
|
||||||
@ -100,6 +100,11 @@ define([
|
|||||||
toolsRegion: '.mailpoet_tools',
|
toolsRegion: '.mailpoet_tools',
|
||||||
postsRegion: '.mailpoet_automated_latest_content_block_posts',
|
postsRegion: '.mailpoet_automated_latest_content_block_posts',
|
||||||
},
|
},
|
||||||
|
modelEvents: _.extend(
|
||||||
|
_.omit(base.BlockView.prototype.modelEvents, 'change'),
|
||||||
|
{
|
||||||
|
'postsChanged': 'render',
|
||||||
|
}),
|
||||||
events: _.extend(base.BlockView.prototype.events, {
|
events: _.extend(base.BlockView.prototype.events, {
|
||||||
'click .mailpoet_automated_latest_content_block_overlay': 'showSettings',
|
'click .mailpoet_automated_latest_content_block_overlay': 'showSettings',
|
||||||
}),
|
}),
|
||||||
@ -139,7 +144,7 @@ define([
|
|||||||
"change .mailpoet_automated_latest_content_include_or_exclude": _.partial(this.changeField, "inclusionType"),
|
"change .mailpoet_automated_latest_content_include_or_exclude": _.partial(this.changeField, "inclusionType"),
|
||||||
"change .mailpoet_automated_latest_content_title_position": _.partial(this.changeField, "titlePosition"),
|
"change .mailpoet_automated_latest_content_title_position": _.partial(this.changeField, "titlePosition"),
|
||||||
"change .mailpoet_automated_latest_content_title_alignment": _.partial(this.changeField, "titleAlignment"),
|
"change .mailpoet_automated_latest_content_title_alignment": _.partial(this.changeField, "titleAlignment"),
|
||||||
"change .mailpoet_automated_latest_content_image_padded": _.partial(this.changeBoolField, "imagePadded"),
|
"change .mailpoet_automated_latest_content_image_full_width": _.partial(this.changeBoolField, "imageFullWidth"),
|
||||||
"change .mailpoet_automated_latest_content_show_author": _.partial(this.changeField, "showAuthor"),
|
"change .mailpoet_automated_latest_content_show_author": _.partial(this.changeField, "showAuthor"),
|
||||||
"keyup .mailpoet_automated_latest_content_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
|
"keyup .mailpoet_automated_latest_content_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
|
||||||
"change .mailpoet_automated_latest_content_show_categories": _.partial(this.changeField, "showCategories"),
|
"change .mailpoet_automated_latest_content_show_categories": _.partial(this.changeField, "showCategories"),
|
||||||
@ -161,7 +166,7 @@ define([
|
|||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
// Dynamically update available post types
|
// Dynamically update available post types
|
||||||
WordpressComponent.getPostTypes().done(_.bind(this._updateContentTypes, this));
|
CommunicationComponent.getPostTypes().done(_.bind(this._updateContentTypes, this));
|
||||||
|
|
||||||
this.$('.mailpoet_automated_latest_content_categories_and_tags').select2({
|
this.$('.mailpoet_automated_latest_content_categories_and_tags').select2({
|
||||||
multiple: true,
|
multiple: true,
|
||||||
@ -174,10 +179,10 @@ define([
|
|||||||
},
|
},
|
||||||
transport: function(options, success, failure) {
|
transport: function(options, success, failure) {
|
||||||
var taxonomies,
|
var taxonomies,
|
||||||
promise = WordpressComponent.getTaxonomies(that.model.get('contentType')).then(function(tax) {
|
promise = CommunicationComponent.getTaxonomies(that.model.get('contentType')).then(function(tax) {
|
||||||
taxonomies = tax;
|
taxonomies = tax;
|
||||||
// Fetch available terms based on the list of taxonomies already fetched
|
// Fetch available terms based on the list of taxonomies already fetched
|
||||||
var promise = WordpressComponent.getTerms({
|
var promise = CommunicationComponent.getTerms({
|
||||||
search: options.data.term,
|
search: options.data.term,
|
||||||
taxonomies: _.keys(taxonomies)
|
taxonomies: _.keys(taxonomies)
|
||||||
}).then(function(terms) {
|
}).then(function(terms) {
|
||||||
|
@ -117,12 +117,9 @@ define([
|
|||||||
* Defines drop behavior of BlockView instance
|
* Defines drop behavior of BlockView instance
|
||||||
*/
|
*/
|
||||||
getDropFunc: function() {
|
getDropFunc: function() {
|
||||||
var that = this;
|
|
||||||
return function() {
|
return function() {
|
||||||
var newModel = that.model.clone();
|
return this.model.clone();
|
||||||
//that.model.destroy();
|
}.bind(this);
|
||||||
return newModel;
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
showBlock: function() {
|
showBlock: function() {
|
||||||
if (this._isFirstRender) {
|
if (this._isFirstRender) {
|
||||||
@ -131,25 +128,37 @@ define([
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
deleteBlock: function() {
|
deleteBlock: function() {
|
||||||
this.transitionOut().done(function() {
|
this.transitionOut().then(function() {
|
||||||
this.model.destroy();
|
this.model.destroy();
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
transitionIn: function() {
|
transitionIn: function() {
|
||||||
return this._transition('mailpoet_block_transition_in');
|
return this._transition('slideDown', 'fadeIn', 'easeOut');
|
||||||
},
|
},
|
||||||
transitionOut: function() {
|
transitionOut: function() {
|
||||||
return this._transition('mailpoet_block_transition_out');
|
return this._transition('slideUp', 'fadeOut', 'easeIn');
|
||||||
},
|
},
|
||||||
_transition: function(className) {
|
_transition: function(slideDirection, fadeDirection, easing) {
|
||||||
var that = this,
|
var promise = jQuery.Deferred();
|
||||||
promise = jQuery.Deferred();
|
|
||||||
|
this.$el.velocity(
|
||||||
|
slideDirection,
|
||||||
|
{
|
||||||
|
duration: 250,
|
||||||
|
easing: easing,
|
||||||
|
complete: function() {
|
||||||
|
promise.resolve();
|
||||||
|
}.bind(this),
|
||||||
|
}
|
||||||
|
).velocity(
|
||||||
|
fadeDirection,
|
||||||
|
{
|
||||||
|
duration: 250,
|
||||||
|
easing: easing,
|
||||||
|
queue: false, // Do not enqueue, trigger animation in parallel
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
this.$el.addClass(className);
|
|
||||||
this.$el.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd animationend', function() {
|
|
||||||
that.$el.removeClass(className);
|
|
||||||
promise.resolve();
|
|
||||||
});
|
|
||||||
return promise;
|
return promise;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -207,16 +216,14 @@ define([
|
|||||||
Module.BlockSettingsView = Marionette.LayoutView.extend({
|
Module.BlockSettingsView = Marionette.LayoutView.extend({
|
||||||
className: 'mailpoet_editor_settings',
|
className: 'mailpoet_editor_settings',
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
var that = this;
|
|
||||||
|
|
||||||
MailPoet.Modal.panel({
|
MailPoet.Modal.panel({
|
||||||
element: this.$el,
|
element: this.$el,
|
||||||
template: '',
|
template: '',
|
||||||
position: 'right',
|
position: 'right',
|
||||||
width: App.getConfig().get('sidepanelWidth'),
|
width: App.getConfig().get('sidepanelWidth'),
|
||||||
onCancel: function() {
|
onCancel: function() {
|
||||||
that.destroy();
|
this.destroy();
|
||||||
},
|
}.bind(this),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
close: function(event) {
|
close: function(event) {
|
||||||
|
@ -232,12 +232,9 @@ define([
|
|||||||
_.extend(this, this._buildRegions(this.regions));
|
_.extend(this, this._buildRegions(this.regions));
|
||||||
},
|
},
|
||||||
getDropFunc: function() {
|
getDropFunc: function() {
|
||||||
var that = this;
|
|
||||||
return function() {
|
return function() {
|
||||||
var newModel = that.model.clone();
|
return this.model.clone();
|
||||||
that.model.destroy();
|
}.bind(this);
|
||||||
return newModel;
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
showBlock: function() {
|
showBlock: function() {
|
||||||
if (this._isFirstRender) {
|
if (this._isFirstRender) {
|
||||||
@ -251,20 +248,32 @@ define([
|
|||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
transitionIn: function() {
|
transitionIn: function() {
|
||||||
return this._transition('mailpoet_block_transition_in');
|
return this._transition('slideDown', 'fadeIn', 'easeIn');
|
||||||
},
|
},
|
||||||
transitionOut: function() {
|
transitionOut: function() {
|
||||||
return this._transition('mailpoet_block_transition_out');
|
return this._transition('slideUp', 'fadeOut', 'easeOut');
|
||||||
},
|
},
|
||||||
_transition: function(className) {
|
_transition: function(slideDirection, fadeDirection, easing) {
|
||||||
var that = this,
|
var promise = jQuery.Deferred();
|
||||||
promise = jQuery.Deferred();
|
|
||||||
|
this.$el.velocity(
|
||||||
|
slideDirection,
|
||||||
|
{
|
||||||
|
duration: 250,
|
||||||
|
easing: easing,
|
||||||
|
complete: function() {
|
||||||
|
promise.resolve();
|
||||||
|
}.bind(this),
|
||||||
|
}
|
||||||
|
).velocity(
|
||||||
|
fadeDirection,
|
||||||
|
{
|
||||||
|
duration: 250,
|
||||||
|
easing: easing,
|
||||||
|
queue: false, // Do not enqueue, trigger animation in parallel
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
this.$el.addClass(className);
|
|
||||||
this.$el.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd animationend', function() {
|
|
||||||
that.$el.removeClass(className);
|
|
||||||
promise.resolve();
|
|
||||||
});
|
|
||||||
return promise;
|
return promise;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -57,11 +57,9 @@ define([
|
|||||||
this.listenTo(this.model, 'change:styles.block.padding', this.changePadding);
|
this.listenTo(this.model, 'change:styles.block.padding', this.changePadding);
|
||||||
},
|
},
|
||||||
templateHelpers: function() {
|
templateHelpers: function() {
|
||||||
return {
|
return _.extend({
|
||||||
model: this.model.toJSON(),
|
|
||||||
viewCid: this.cid,
|
|
||||||
totalHeight: parseInt(this.model.get('styles.block.padding'), 10)*2 + parseInt(this.model.get('styles.block.borderWidth')) + 'px',
|
totalHeight: parseInt(this.model.get('styles.block.padding'), 10)*2 + parseInt(this.model.get('styles.block.borderWidth')) + 'px',
|
||||||
};
|
}, base.BlockView.prototype.templateHelpers.apply(this));
|
||||||
},
|
},
|
||||||
onRender: function() {
|
onRender: function() {
|
||||||
this.toolsView = new Module.DividerBlockToolsView({ model: this.model });
|
this.toolsView = new Module.DividerBlockToolsView({ model: this.model });
|
||||||
|
@ -39,9 +39,9 @@ define([
|
|||||||
Module.FooterBlockView = base.BlockView.extend({
|
Module.FooterBlockView = base.BlockView.extend({
|
||||||
className: "mailpoet_block mailpoet_footer_block mailpoet_droppable_block",
|
className: "mailpoet_block mailpoet_footer_block mailpoet_droppable_block",
|
||||||
getTemplate: function() { return templates.footerBlock; },
|
getTemplate: function() { return templates.footerBlock; },
|
||||||
modelEvents: {
|
modelEvents: _.extend({
|
||||||
'change:styles.block.backgroundColor change:styles.text.fontColor change:styles.text.fontFamily change:styles.text.fontSize change:styles.text.textAlign change:styles.link.fontColor change:styles.link.textDecoration': 'render',
|
'change:styles.block.backgroundColor change:styles.text.fontColor change:styles.text.fontFamily change:styles.text.fontSize change:styles.text.textAlign change:styles.link.fontColor change:styles.link.textDecoration': 'render',
|
||||||
},
|
}, base.BlockView.prototype.modelEvents),
|
||||||
onDragSubstituteBy: function() { return Module.FooterWidgetView; },
|
onDragSubstituteBy: function() { return Module.FooterWidgetView; },
|
||||||
onRender: function() {
|
onRender: function() {
|
||||||
this.toolsView = new Module.FooterBlockToolsView({ model: this.model });
|
this.toolsView = new Module.FooterBlockToolsView({ model: this.model });
|
||||||
|
@ -39,9 +39,9 @@ define([
|
|||||||
Module.HeaderBlockView = base.BlockView.extend({
|
Module.HeaderBlockView = base.BlockView.extend({
|
||||||
className: "mailpoet_block mailpoet_header_block mailpoet_droppable_block",
|
className: "mailpoet_block mailpoet_header_block mailpoet_droppable_block",
|
||||||
getTemplate: function() { return templates.headerBlock; },
|
getTemplate: function() { return templates.headerBlock; },
|
||||||
modelEvents: {
|
modelEvents: _.extend({
|
||||||
'change:styles.block.backgroundColor change:styles.text.fontColor change:styles.text.fontFamily change:styles.text.fontSize change:styles.text.textAlign change:styles.link.fontColor change:styles.link.textDecoration': 'render',
|
'change:styles.block.backgroundColor change:styles.text.fontColor change:styles.text.fontFamily change:styles.text.fontSize change:styles.text.textAlign change:styles.link.fontColor change:styles.link.textDecoration': 'render',
|
||||||
},
|
}, base.BlockView.prototype.modelEvents),
|
||||||
onDragSubstituteBy: function() { return Module.HeaderWidgetView; },
|
onDragSubstituteBy: function() { return Module.HeaderWidgetView; },
|
||||||
onRender: function() {
|
onRender: function() {
|
||||||
this.toolsView = new Module.HeaderBlockToolsView({ model: this.model });
|
this.toolsView = new Module.HeaderBlockToolsView({ model: this.model });
|
||||||
|
@ -20,7 +20,7 @@ define([
|
|||||||
link: 'http://example.org',
|
link: 'http://example.org',
|
||||||
src: 'no-image.png',
|
src: 'no-image.png',
|
||||||
alt: 'An image of...',
|
alt: 'An image of...',
|
||||||
padded: true, // true | false - Padded or full width
|
fullWidth: true, // true | false
|
||||||
width: '64px',
|
width: '64px',
|
||||||
height: '64px',
|
height: '64px',
|
||||||
styles: {
|
styles: {
|
||||||
@ -37,20 +37,18 @@ define([
|
|||||||
getTemplate: function() { return templates.imageBlock; },
|
getTemplate: function() { return templates.imageBlock; },
|
||||||
onDragSubstituteBy: function() { return Module.ImageWidgetView; },
|
onDragSubstituteBy: function() { return Module.ImageWidgetView; },
|
||||||
templateHelpers: function() {
|
templateHelpers: function() {
|
||||||
return {
|
return _.extend({
|
||||||
model: this.model.toJSON(),
|
|
||||||
viewCid: this.cid,
|
|
||||||
imageMissingSrc: App.getConfig().get('urls.imageMissing'),
|
imageMissingSrc: App.getConfig().get('urls.imageMissing'),
|
||||||
};
|
}, base.BlockView.prototype.templateHelpers.apply(this));
|
||||||
},
|
},
|
||||||
onRender: function() {
|
onRender: function() {
|
||||||
this.toolsView = new Module.ImageBlockToolsView({ model: this.model });
|
this.toolsView = new Module.ImageBlockToolsView({ model: this.model });
|
||||||
this.toolsRegion.show(this.toolsView);
|
this.toolsRegion.show(this.toolsView);
|
||||||
|
|
||||||
if (this.model.get('padded')) {
|
if (this.model.get('fullWidth')) {
|
||||||
this.$el.removeClass('mailpoet_full_image');
|
|
||||||
} else {
|
|
||||||
this.$el.addClass('mailpoet_full_image');
|
this.$el.addClass('mailpoet_full_image');
|
||||||
|
} else {
|
||||||
|
this.$el.removeClass('mailpoet_full_image');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -66,7 +64,7 @@ define([
|
|||||||
"keyup .mailpoet_field_image_link": _.partial(this.changeField, "link"),
|
"keyup .mailpoet_field_image_link": _.partial(this.changeField, "link"),
|
||||||
"keyup .mailpoet_field_image_address": _.partial(this.changeField, "src"),
|
"keyup .mailpoet_field_image_address": _.partial(this.changeField, "src"),
|
||||||
"keyup .mailpoet_field_image_alt_text": _.partial(this.changeField, "alt"),
|
"keyup .mailpoet_field_image_alt_text": _.partial(this.changeField, "alt"),
|
||||||
"change .mailpoet_field_image_padded": _.partial(this.changeBoolCheckboxField, "padded"),
|
"change .mailpoet_field_image_full_width": _.partial(this.changeBoolCheckboxField, "fullWidth"),
|
||||||
"change .mailpoet_field_image_alignment": _.partial(this.changeField, "styles.block.textAlign"),
|
"change .mailpoet_field_image_alignment": _.partial(this.changeField, "styles.block.textAlign"),
|
||||||
"click .mailpoet_field_image_select_another_image": "showMediaManager",
|
"click .mailpoet_field_image_select_another_image": "showMediaManager",
|
||||||
"click .mailpoet_done_editing": "close",
|
"click .mailpoet_done_editing": "close",
|
||||||
|
@ -18,12 +18,12 @@ define([
|
|||||||
'jquery',
|
'jquery',
|
||||||
'mailpoet',
|
'mailpoet',
|
||||||
'newsletter_editor/App',
|
'newsletter_editor/App',
|
||||||
'newsletter_editor/components/wordpress',
|
'newsletter_editor/components/communication',
|
||||||
'newsletter_editor/blocks/base',
|
'newsletter_editor/blocks/base',
|
||||||
'newsletter_editor/blocks/button',
|
'newsletter_editor/blocks/button',
|
||||||
'newsletter_editor/blocks/divider',
|
'newsletter_editor/blocks/divider',
|
||||||
'select2'
|
'select2'
|
||||||
], function(Backbone, Marionette, Radio, _, jQuery, MailPoet, App, WordpressComponent, BaseBlock, ButtonBlock, DividerBlock) {
|
], function(Backbone, Marionette, Radio, _, jQuery, MailPoet, App, CommunicationComponent, BaseBlock, ButtonBlock, DividerBlock) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ define([
|
|||||||
titlePosition: 'inTextBlock', // 'inTextBlock'|'aboveBlock',
|
titlePosition: 'inTextBlock', // 'inTextBlock'|'aboveBlock',
|
||||||
titleAlignment: 'left', // 'left'|'center'|'right'
|
titleAlignment: 'left', // 'left'|'center'|'right'
|
||||||
titleIsLink: false, // false|true
|
titleIsLink: false, // false|true
|
||||||
imagePadded: true, // true|false
|
imageFullWidth: false, // true|false
|
||||||
//imageAlignment: 'centerPadded', // 'centerFull'|'centerPadded'|'left'|'right'|'alternate'|'none'
|
//imageAlignment: 'centerPadded', // 'centerFull'|'centerPadded'|'left'|'right'|'alternate'|'none'
|
||||||
showAuthor: 'no', // 'no'|'aboveText'|'belowText'
|
showAuthor: 'no', // 'no'|'aboveText'|'belowText'
|
||||||
authorPrecededBy: 'Author:',
|
authorPrecededBy: 'Author:',
|
||||||
@ -88,7 +88,7 @@ define([
|
|||||||
this.on('change:amount change:contentType change:terms change:inclusionType change:postStatus change:search change:sortBy', refreshAvailablePosts);
|
this.on('change:amount change:contentType change:terms change:inclusionType change:postStatus change:search change:sortBy', refreshAvailablePosts);
|
||||||
|
|
||||||
this.listenTo(this.get('_selectedPosts'), 'add remove reset', refreshTransformedPosts);
|
this.listenTo(this.get('_selectedPosts'), 'add remove reset', refreshTransformedPosts);
|
||||||
this.on('change:displayType change:titleFormat change:titlePosition change:titleAlignment change:titleIsLink change:imagePadded change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change:showDivider', refreshTransformedPosts);
|
this.on('change:displayType change:titleFormat change:titlePosition change:titleAlignment change:titleIsLink change:imageFullWidth change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change:showDivider', refreshTransformedPosts);
|
||||||
this.listenTo(this.get('readMoreButton'), 'change', refreshTransformedPosts);
|
this.listenTo(this.get('readMoreButton'), 'change', refreshTransformedPosts);
|
||||||
this.listenTo(this.get('divider'), 'change', refreshTransformedPosts);
|
this.listenTo(this.get('divider'), 'change', refreshTransformedPosts);
|
||||||
|
|
||||||
@ -96,8 +96,7 @@ define([
|
|||||||
},
|
},
|
||||||
fetchAvailablePosts: function() {
|
fetchAvailablePosts: function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
WordpressComponent.getPosts(this.toJSON()).done(function(posts) {
|
CommunicationComponent.getPosts(this.toJSON()).done(function(posts) {
|
||||||
console.log('Posts fetched', arguments);
|
|
||||||
that.get('_availablePosts').reset(posts);
|
that.get('_availablePosts').reset(posts);
|
||||||
that.get('_selectedPosts').reset(); // Empty out the collection
|
that.get('_selectedPosts').reset(); // Empty out the collection
|
||||||
that.trigger('change:_availablePosts');
|
that.trigger('change:_availablePosts');
|
||||||
@ -116,8 +115,7 @@ define([
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WordpressComponent.getTransformedPosts(data).done(function(posts) {
|
CommunicationComponent.getTransformedPosts(data).done(function(posts) {
|
||||||
console.log('Transformed posts fetched', arguments);
|
|
||||||
that.get('_transformedPosts').get('blocks').reset(posts, {parse: true});
|
that.get('_transformedPosts').get('blocks').reset(posts, {parse: true});
|
||||||
}).fail(function() {
|
}).fail(function() {
|
||||||
console.log('Posts _refreshTransformedPosts error', arguments);
|
console.log('Posts _refreshTransformedPosts error', arguments);
|
||||||
@ -133,8 +131,7 @@ define([
|
|||||||
|
|
||||||
if (data.posts.length === 0) return;
|
if (data.posts.length === 0) return;
|
||||||
|
|
||||||
WordpressComponent.getTransformedPosts(data).done(function(posts) {
|
CommunicationComponent.getTransformedPosts(data).done(function(posts) {
|
||||||
console.log('Available posts fetched', arguments);
|
|
||||||
collection.add(posts, { at: index });
|
collection.add(posts, { at: index });
|
||||||
}).fail(function() {
|
}).fail(function() {
|
||||||
console.log('Posts fetchPosts error', arguments);
|
console.log('Posts fetchPosts error', arguments);
|
||||||
@ -145,13 +142,14 @@ define([
|
|||||||
Module.PostsBlockView = base.BlockView.extend({
|
Module.PostsBlockView = base.BlockView.extend({
|
||||||
className: "mailpoet_block mailpoet_posts_block mailpoet_droppable_block",
|
className: "mailpoet_block mailpoet_posts_block mailpoet_droppable_block",
|
||||||
getTemplate: function() { return templates.postsBlock; },
|
getTemplate: function() { return templates.postsBlock; },
|
||||||
modelEvents: {},
|
modelEvents: {}, // Forcefully disable all events
|
||||||
regions: _.extend({
|
regions: _.extend({
|
||||||
postsRegion: '.mailpoet_posts_block_posts',
|
postsRegion: '.mailpoet_posts_block_posts',
|
||||||
}, base.BlockView.prototype.regions),
|
}, base.BlockView.prototype.regions),
|
||||||
onDragSubstituteBy: function() { return Module.PostsWidgetView; },
|
onDragSubstituteBy: function() { return Module.PostsWidgetView; },
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
base.BlockView.prototype.initialize.apply(this, arguments);
|
base.BlockView.prototype.initialize.apply(this, arguments);
|
||||||
|
|
||||||
this.toolsView = new Module.PostsBlockToolsView({ model: this.model });
|
this.toolsView = new Module.PostsBlockToolsView({ model: this.model });
|
||||||
this.model.reply('blockView', this.notifyAboutSelf, this);
|
this.model.reply('blockView', this.notifyAboutSelf, this);
|
||||||
},
|
},
|
||||||
@ -271,7 +269,7 @@ define([
|
|||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
// Dynamically update available post types
|
// Dynamically update available post types
|
||||||
WordpressComponent.getPostTypes().done(_.bind(this._updateContentTypes, this));
|
CommunicationComponent.getPostTypes().done(_.bind(this._updateContentTypes, this));
|
||||||
|
|
||||||
this.$('.mailpoet_posts_categories_and_tags').select2({
|
this.$('.mailpoet_posts_categories_and_tags').select2({
|
||||||
multiple: true,
|
multiple: true,
|
||||||
@ -284,10 +282,10 @@ define([
|
|||||||
},
|
},
|
||||||
transport: function(options, success, failure) {
|
transport: function(options, success, failure) {
|
||||||
var taxonomies,
|
var taxonomies,
|
||||||
promise = WordpressComponent.getTaxonomies(that.model.get('contentType')).then(function(tax) {
|
promise = CommunicationComponent.getTaxonomies(that.model.get('contentType')).then(function(tax) {
|
||||||
taxonomies = tax;
|
taxonomies = tax;
|
||||||
// Fetch available terms based on the list of taxonomies already fetched
|
// Fetch available terms based on the list of taxonomies already fetched
|
||||||
var promise = WordpressComponent.getTerms({
|
var promise = CommunicationComponent.getTerms({
|
||||||
search: options.data.term,
|
search: options.data.term,
|
||||||
taxonomies: _.keys(taxonomies)
|
taxonomies: _.keys(taxonomies)
|
||||||
}).then(function(terms) {
|
}).then(function(terms) {
|
||||||
@ -398,7 +396,7 @@ define([
|
|||||||
"change .mailpoet_posts_include_or_exclude": _.partial(this.changeField, "inclusionType"),
|
"change .mailpoet_posts_include_or_exclude": _.partial(this.changeField, "inclusionType"),
|
||||||
"change .mailpoet_posts_title_position": _.partial(this.changeField, "titlePosition"),
|
"change .mailpoet_posts_title_position": _.partial(this.changeField, "titlePosition"),
|
||||||
"change .mailpoet_posts_title_alignment": _.partial(this.changeField, "titleAlignment"),
|
"change .mailpoet_posts_title_alignment": _.partial(this.changeField, "titleAlignment"),
|
||||||
"change .mailpoet_posts_image_padded": _.partial(this.changeBoolField, "imagePadded"),
|
"change .mailpoet_posts_image_full_width": _.partial(this.changeBoolField, "imageFullWidth"),
|
||||||
"change .mailpoet_posts_show_author": _.partial(this.changeField, "showAuthor"),
|
"change .mailpoet_posts_show_author": _.partial(this.changeField, "showAuthor"),
|
||||||
"keyup .mailpoet_posts_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
|
"keyup .mailpoet_posts_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
|
||||||
"change .mailpoet_posts_show_categories": _.partial(this.changeField, "showCategories"),
|
"change .mailpoet_posts_show_categories": _.partial(this.changeField, "showCategories"),
|
||||||
|
@ -175,12 +175,9 @@ define([
|
|||||||
_event.stopPropagation();
|
_event.stopPropagation();
|
||||||
},
|
},
|
||||||
getDropFunc: function() {
|
getDropFunc: function() {
|
||||||
var that = this;
|
|
||||||
return function() {
|
return function() {
|
||||||
var newModel = that.model.clone();
|
return this.model.clone();
|
||||||
//that.model.destroy();
|
}.bind(this);
|
||||||
return newModel;
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
_buildRegions: function(regions) {
|
_buildRegions: function(regions) {
|
||||||
var that = this;
|
var that = this;
|
||||||
@ -211,20 +208,32 @@ define([
|
|||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
transitionIn: function() {
|
transitionIn: function() {
|
||||||
return this._transition('mailpoet_block_transition_in');
|
return this._transition('slideDown', 'fadeIn', 'easeIn');
|
||||||
},
|
},
|
||||||
transitionOut: function() {
|
transitionOut: function() {
|
||||||
return this._transition('mailpoet_block_transition_out');
|
return this._transition('slideUp', 'fadeOut', 'easeOut');
|
||||||
},
|
},
|
||||||
_transition: function(className) {
|
_transition: function(slideDirection, fadeDirection, easing) {
|
||||||
var that = this,
|
var promise = jQuery.Deferred();
|
||||||
promise = jQuery.Deferred();
|
|
||||||
|
this.$el.velocity(
|
||||||
|
slideDirection,
|
||||||
|
{
|
||||||
|
duration: 250,
|
||||||
|
easing: easing,
|
||||||
|
complete: function() {
|
||||||
|
promise.resolve();
|
||||||
|
}.bind(this),
|
||||||
|
}
|
||||||
|
).velocity(
|
||||||
|
fadeDirection,
|
||||||
|
{
|
||||||
|
duration: 250,
|
||||||
|
easing: easing,
|
||||||
|
queue: false, // Do not enqueue, trigger animation in parallel
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
this.$el.addClass(className);
|
|
||||||
this.$el.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd animationend', function() {
|
|
||||||
that.$el.removeClass(className);
|
|
||||||
promise.resolve();
|
|
||||||
});
|
|
||||||
return promise;
|
return promise;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -26,6 +26,8 @@ define([
|
|||||||
getTemplate: function() { return templates.textBlock; },
|
getTemplate: function() { return templates.textBlock; },
|
||||||
modelEvents: _.omit(base.BlockView.prototype.modelEvents, 'change'), // Prevent rerendering on model change due to text editor redrawing
|
modelEvents: _.omit(base.BlockView.prototype.modelEvents, 'change'), // Prevent rerendering on model change due to text editor redrawing
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
|
base.BlockView.prototype.initialize.apply(this, arguments);
|
||||||
|
|
||||||
this.renderOptions = _.defaults(options.renderOptions || {}, {
|
this.renderOptions = _.defaults(options.renderOptions || {}, {
|
||||||
disableTextEditor: false,
|
disableTextEditor: false,
|
||||||
});
|
});
|
||||||
|
@ -9,7 +9,7 @@ define([
|
|||||||
|
|
||||||
Module._query = function(args) {
|
Module._query = function(args) {
|
||||||
return MailPoet.Ajax.post({
|
return MailPoet.Ajax.post({
|
||||||
endpoint: 'wordpress',
|
endpoint: 'automatedLatestContent',
|
||||||
action: args.action,
|
action: args.action,
|
||||||
data: args.options || {},
|
data: args.options || {},
|
||||||
});
|
});
|
||||||
@ -63,16 +63,18 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
Module.saveNewsletter = function(options) {
|
Module.saveNewsletter = function(options) {
|
||||||
return Module._query({
|
return MailPoet.Ajax.post({
|
||||||
|
endpoint: 'newsletters',
|
||||||
action: 'save',
|
action: 'save',
|
||||||
options: options,
|
data: options || {},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Module.previewNewsletter = function(options) {
|
Module.previewNewsletter = function(options) {
|
||||||
return Module._query({
|
return MailPoet.Ajax.post({
|
||||||
action: 'preview',
|
endpoint: 'newsletters',
|
||||||
options: options,
|
action: 'sendPreview',
|
||||||
|
data: options || {},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -11,7 +11,7 @@ define([
|
|||||||
// Does not hold newsletter content nor newsletter styles, those are
|
// Does not hold newsletter content nor newsletter styles, those are
|
||||||
// handled by other components.
|
// handled by other components.
|
||||||
Module.NewsletterModel = SuperModel.extend({
|
Module.NewsletterModel = SuperModel.extend({
|
||||||
stale: ['body'],
|
stale: ['body', 'created_at', 'deleted_at', 'updated_at'],
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
this.on('change', function() {
|
this.on('change', function() {
|
||||||
App.getChannel().trigger('autoSave');
|
App.getChannel().trigger('autoSave');
|
||||||
@ -44,10 +44,10 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
Module.getBody = function() {
|
Module.getBody = function() {
|
||||||
return JSON.stringify({
|
return {
|
||||||
content: App._contentContainer.toJSON(),
|
content: App._contentContainer.toJSON(),
|
||||||
globalStyles: App.getGlobalStyles().toJSON(),
|
globalStyles: App.getGlobalStyles().toJSON(),
|
||||||
});
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
Module.toJSON = function() {
|
Module.toJSON = function() {
|
||||||
@ -73,8 +73,7 @@ define([
|
|||||||
});
|
});
|
||||||
|
|
||||||
App.on('start', function(options) {
|
App.on('start', function(options) {
|
||||||
// TODO: Other newsletter information will be needed as well.
|
var body = options.newsletter.body;
|
||||||
var body = JSON.parse(options.newsletter.body);
|
|
||||||
App._contentContainer = new (App.getBlockTypeModel('container'))(body.content, {parse: true});
|
App._contentContainer = new (App.getBlockTypeModel('container'))(body.content, {parse: true});
|
||||||
App._contentContainerView = new (App.getBlockTypeView('container'))({
|
App._contentContainerView = new (App.getBlockTypeView('container'))({
|
||||||
model: App._contentContainer,
|
model: App._contentContainer,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
define([
|
define([
|
||||||
'newsletter_editor/App',
|
'newsletter_editor/App',
|
||||||
|
'newsletter_editor/components/communication',
|
||||||
'mailpoet',
|
'mailpoet',
|
||||||
'notice',
|
'notice',
|
||||||
'backbone',
|
'backbone',
|
||||||
@ -8,7 +9,18 @@ define([
|
|||||||
'blob',
|
'blob',
|
||||||
'filesaver',
|
'filesaver',
|
||||||
'html2canvas'
|
'html2canvas'
|
||||||
], function(App, MailPoet, Notice, Backbone, Marionette, jQuery, Blob, FileSaver, html2canvas) {
|
], function(
|
||||||
|
App,
|
||||||
|
CommunicationComponent,
|
||||||
|
MailPoet,
|
||||||
|
Notice,
|
||||||
|
Backbone,
|
||||||
|
Marionette,
|
||||||
|
jQuery,
|
||||||
|
Blob,
|
||||||
|
FileSaver,
|
||||||
|
html2canvas
|
||||||
|
) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
@ -17,26 +29,33 @@ define([
|
|||||||
|
|
||||||
// Save editor contents to server
|
// Save editor contents to server
|
||||||
Module.save = function() {
|
Module.save = function() {
|
||||||
App.getChannel().trigger('beforeEditorSave');
|
|
||||||
|
|
||||||
var json = App.toJSON();
|
var json = App.toJSON();
|
||||||
|
|
||||||
|
// Stringify to enable transmission of primitive non-string value types
|
||||||
|
if (!_.isUndefined(json.body)) {
|
||||||
|
json.body = JSON.stringify(json.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
App.getChannel().trigger('beforeEditorSave', json);
|
||||||
|
|
||||||
// save newsletter
|
// save newsletter
|
||||||
MailPoet.Ajax.post({
|
CommunicationComponent.saveNewsletter(json).done(function(response) {
|
||||||
endpoint: 'newsletters',
|
|
||||||
action: 'save',
|
|
||||||
data: json,
|
|
||||||
}).done(function(response) {
|
|
||||||
if(response.success !== undefined && response.success === true) {
|
if(response.success !== undefined && response.success === true) {
|
||||||
// TODO: Handle translations
|
// TODO: Handle translations
|
||||||
//MailPoet.Notice.success("<?php _e('Newsletter has been saved.'); ?>");
|
//MailPoet.Notice.success("<?php _e('Newsletter has been saved.'); ?>");
|
||||||
} else if(response.error !== undefined) {
|
} else if(response.error !== undefined) {
|
||||||
if(response.error.length === 0) {
|
if(response.error.length === 0) {
|
||||||
// TODO: Handle translations
|
// TODO: Handle translations
|
||||||
MailPoet.Notice.error("<?php _e('An unknown error occurred, please check your settings.'); ?>");
|
MailPoet.Notice.error(
|
||||||
|
"An unknown error occurred, please check your settings.",
|
||||||
|
{
|
||||||
|
scroll: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
$(response.error).each(function(i, error) {
|
$(response.error).each(function(i, error) {
|
||||||
MailPoet.Notice.error(error);
|
MailPoet.Notice.error(error, { scroll: true });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,7 +77,7 @@ define([
|
|||||||
promise.then(function(thumbnail) {
|
promise.then(function(thumbnail) {
|
||||||
var data = _.extend(options || {}, {
|
var data = _.extend(options || {}, {
|
||||||
thumbnail: thumbnail.toDataURL('image/jpeg'),
|
thumbnail: thumbnail.toDataURL('image/jpeg'),
|
||||||
body: App.getBody(),
|
body: JSON.stringify(App.getBody()),
|
||||||
});
|
});
|
||||||
|
|
||||||
return MailPoet.Ajax.post({
|
return MailPoet.Ajax.post({
|
||||||
@ -154,6 +173,7 @@ define([
|
|||||||
App.getConfig().get('translations.templateNameMissing'),
|
App.getConfig().get('translations.templateNameMissing'),
|
||||||
{
|
{
|
||||||
positionAfter: that.$el,
|
positionAfter: that.$el,
|
||||||
|
scroll: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else if (templateDescription === '') {
|
} else if (templateDescription === '') {
|
||||||
@ -161,6 +181,7 @@ define([
|
|||||||
App.getConfig().get('translations.templateDescriptionMissing'),
|
App.getConfig().get('translations.templateDescriptionMissing'),
|
||||||
{
|
{
|
||||||
positionAfter: that.$el,
|
positionAfter: that.$el,
|
||||||
|
scroll: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -174,6 +195,7 @@ define([
|
|||||||
App.getConfig().get('translations.templateSaved'),
|
App.getConfig().get('translations.templateSaved'),
|
||||||
{
|
{
|
||||||
positionAfter: that.$el,
|
positionAfter: that.$el,
|
||||||
|
scroll: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}).fail(function() {
|
}).fail(function() {
|
||||||
@ -182,6 +204,7 @@ define([
|
|||||||
App.getConfig().get('translations.templateSaveFailed'),
|
App.getConfig().get('translations.templateSaveFailed'),
|
||||||
{
|
{
|
||||||
positionAfter: that.$el,
|
positionAfter: that.$el,
|
||||||
|
scroll: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -206,6 +229,7 @@ define([
|
|||||||
App.getConfig().get('translations.templateNameMissing'),
|
App.getConfig().get('translations.templateNameMissing'),
|
||||||
{
|
{
|
||||||
positionAfter: that.$el,
|
positionAfter: that.$el,
|
||||||
|
scroll: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else if (templateDescription === '') {
|
} else if (templateDescription === '') {
|
||||||
@ -213,6 +237,7 @@ define([
|
|||||||
App.getConfig().get('translations.templateDescriptionMissing'),
|
App.getConfig().get('translations.templateDescriptionMissing'),
|
||||||
{
|
{
|
||||||
positionAfter: that.$el,
|
positionAfter: that.$el,
|
||||||
|
scroll: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
define([
|
define([
|
||||||
'newsletter_editor/App',
|
'newsletter_editor/App',
|
||||||
|
'newsletter_editor/components/communication',
|
||||||
'backbone',
|
'backbone',
|
||||||
'backbone.marionette',
|
'backbone.marionette',
|
||||||
'backbone.supermodel',
|
'backbone.supermodel',
|
||||||
'underscore',
|
'underscore',
|
||||||
'jquery',
|
'jquery',
|
||||||
'sticky-kit'
|
'sticky-kit'
|
||||||
], function(App, Backbone, Marionette, SuperModel, _, jQuery, StickyKit) {
|
], function(App, CommunicationComponent, Backbone, Marionette, SuperModel, _, jQuery, StickyKit) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
@ -50,8 +51,33 @@ define([
|
|||||||
},
|
},
|
||||||
events: {
|
events: {
|
||||||
'click .mailpoet_sidebar_region h3, .mailpoet_sidebar_region .handlediv': function(event) {
|
'click .mailpoet_sidebar_region h3, .mailpoet_sidebar_region .handlediv': function(event) {
|
||||||
this.$el.find('.mailpoet_sidebar_region').addClass('closed');
|
var $openRegion = this.$el.find('.mailpoet_sidebar_region:not(.closed)'),
|
||||||
this.$el.find(event.target).parent().parent().removeClass('closed');
|
$targetRegion = this.$el.find(event.target).closest('.mailpoet_sidebar_region');
|
||||||
|
|
||||||
|
if ($openRegion.get(0) === $targetRegion.get(0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$openRegion.find('.mailpoet_region_content').velocity(
|
||||||
|
'slideUp',
|
||||||
|
{
|
||||||
|
duration: 250,
|
||||||
|
easing: "easeOut",
|
||||||
|
complete: function() {
|
||||||
|
$openRegion.addClass('closed');
|
||||||
|
}.bind(this)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$targetRegion.find('.mailpoet_region_content').velocity(
|
||||||
|
'slideDown',
|
||||||
|
{
|
||||||
|
duration: 250,
|
||||||
|
easing: "easeIn",
|
||||||
|
complete: function() {
|
||||||
|
$targetRegion.removeClass('closed');
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
@ -90,7 +116,6 @@ define([
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
onDomRefresh: function() {
|
onDomRefresh: function() {
|
||||||
var that = this;
|
|
||||||
this.$el.parent().stick_in_parent({
|
this.$el.parent().stick_in_parent({
|
||||||
offset_top: 32,
|
offset_top: 32,
|
||||||
});
|
});
|
||||||
@ -169,10 +194,8 @@ define([
|
|||||||
},
|
},
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
this.availableStyles = options.availableStyles;
|
this.availableStyles = options.availableStyles;
|
||||||
var that = this;
|
|
||||||
},
|
},
|
||||||
onRender: function() {
|
onRender: function() {
|
||||||
var that = this;
|
|
||||||
this.$('.mailpoet_color').spectrum({
|
this.$('.mailpoet_color').spectrum({
|
||||||
clickoutFiresChange: true,
|
clickoutFiresChange: true,
|
||||||
showInput: true,
|
showInput: true,
|
||||||
@ -202,6 +225,11 @@ define([
|
|||||||
showPreview: function() {
|
showPreview: function() {
|
||||||
var json = App.toJSON();
|
var json = App.toJSON();
|
||||||
|
|
||||||
|
// Stringify to enable transmission of primitive non-string value types
|
||||||
|
if (!_.isUndefined(json.body)) {
|
||||||
|
json.body = JSON.stringify(json.body);
|
||||||
|
}
|
||||||
|
|
||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: 'newsletters',
|
endpoint: 'newsletters',
|
||||||
action: 'render',
|
action: 'render',
|
||||||
@ -219,26 +247,29 @@ define([
|
|||||||
console.log('trying to send a preview');
|
console.log('trying to send a preview');
|
||||||
// get form data
|
// get form data
|
||||||
var data = {
|
var data = {
|
||||||
from_name: this.$('#mailpoet_preview_from_name').val(),
|
subscriber: this.$('#mailpoet_preview_to_email').val(),
|
||||||
from_email: this.$('#mailpoet_preview_from_email').val(),
|
id: App.getNewsletter().get('id'),
|
||||||
to_email: this.$('#mailpoet_preview_to_email').val(),
|
|
||||||
newsletter: App.newsletterId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// send test email
|
// send test email
|
||||||
MailPoet.Modal.loading(true);
|
MailPoet.Modal.loading(true);
|
||||||
|
|
||||||
// TODO: Migrate logic to new AJAX format
|
CommunicationComponent.previewNewsletter(data).done(function(response) {
|
||||||
Wordpress.previewNewsletter(data).done(function(response) {
|
if(response.result !== undefined && response.result === true) {
|
||||||
if(response.success !== undefined && response.success === true) {
|
MailPoet.Notice.success(App.getConfig().get('translations.newsletterPreviewSent'), { scroll: true });
|
||||||
MailPoet.Notice.success(App.getConfig().get('translations.testEmailSent'));
|
} else {
|
||||||
} else if(response.error !== undefined) {
|
if (_.isArray(response.errors)) {
|
||||||
if(response.error.length === 0) {
|
response.errors.map(function(error) {
|
||||||
MailPoet.Notice.error(App.getConfig().get('translations.unknownErrorOccurred'));
|
MailPoet.Notice.error(error, { scroll: true });
|
||||||
} else {
|
|
||||||
$(response.error).each(function(i, error) {
|
|
||||||
MailPoet.Notice.error(error);
|
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
MailPoet.Notice.error(
|
||||||
|
App.getConfig().get('translations.newsletterPreviewFailedToSend'),
|
||||||
|
{
|
||||||
|
scroll: true,
|
||||||
|
static: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MailPoet.Modal.loading(false);
|
MailPoet.Modal.loading(false);
|
||||||
|
@ -17,7 +17,7 @@ define([
|
|||||||
},
|
},
|
||||||
h1: {
|
h1: {
|
||||||
fontColor: '#111111',
|
fontColor: '#111111',
|
||||||
fontFamily: 'Arial Black',
|
fontFamily: 'Arial',
|
||||||
fontSize: '40px'
|
fontSize: '40px'
|
||||||
},
|
},
|
||||||
h2: {
|
h2: {
|
||||||
@ -72,7 +72,7 @@ define([
|
|||||||
|
|
||||||
App.getAvailableStyles = Module.getAvailableStyles;
|
App.getAvailableStyles = Module.getAvailableStyles;
|
||||||
|
|
||||||
var body = JSON.parse(options.newsletter.body);
|
var body = options.newsletter.body;
|
||||||
this.setGlobalStyles(body.globalStyles);
|
this.setGlobalStyles(body.globalStyles);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -43,58 +43,49 @@ define(
|
|||||||
|
|
||||||
var messages = {
|
var messages = {
|
||||||
onTrash: function(response) {
|
onTrash: function(response) {
|
||||||
var count = ~~response.newsletters;
|
var count = ~~response;
|
||||||
var message = null;
|
var message = null;
|
||||||
|
|
||||||
if(count === 1 || response === true) {
|
if(count === 1) {
|
||||||
message = (
|
message = (
|
||||||
'1 newsletter was moved to the trash.'
|
'1 newsletter was moved to the trash.'
|
||||||
);
|
);
|
||||||
} else if(count > 1) {
|
} else {
|
||||||
message = (
|
message = (
|
||||||
'%$1d newsletters were moved to the trash.'
|
'%$1d newsletters were moved to the trash.'
|
||||||
).replace('%$1d', count);
|
).replace('%$1d', count);
|
||||||
}
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
if(message !== null) {
|
|
||||||
MailPoet.Notice.success(message);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onDelete: function(response) {
|
onDelete: function(response) {
|
||||||
var count = ~~response.newsletters;
|
var count = ~~response;
|
||||||
var message = null;
|
var message = null;
|
||||||
|
|
||||||
if(count === 1 || response === true) {
|
if(count === 1) {
|
||||||
message = (
|
message = (
|
||||||
'1 newsletter was permanently deleted.'
|
'1 newsletter was permanently deleted.'
|
||||||
);
|
);
|
||||||
} else if(count > 1) {
|
} else {
|
||||||
message = (
|
message = (
|
||||||
'%$1d newsletters were permanently deleted.'
|
'%$1d newsletters were permanently deleted.'
|
||||||
).replace('%$1d', count);
|
).replace('%$1d', count);
|
||||||
}
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
if(message !== null) {
|
|
||||||
MailPoet.Notice.success(message);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onRestore: function(response) {
|
onRestore: function(response) {
|
||||||
var count = ~~response.newsletters;
|
var count = ~~response;
|
||||||
var message = null;
|
var message = null;
|
||||||
|
|
||||||
if(count === 1 || response === true) {
|
if(count === 1) {
|
||||||
message = (
|
message = (
|
||||||
'1 newsletter has been restored from the trash.'
|
'1 newsletter has been restored from the trash.'
|
||||||
);
|
);
|
||||||
} else if(count > 1) {
|
} else {
|
||||||
message = (
|
message = (
|
||||||
'%$1d newsletters have been restored from the trash.'
|
'%$1d newsletters have been restored from the trash.'
|
||||||
).replace('%$1d', count);
|
).replace('%$1d', count);
|
||||||
}
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
if(message !== null) {
|
|
||||||
MailPoet.Notice.success(message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ define(
|
|||||||
Breadcrumb
|
Breadcrumb
|
||||||
) {
|
) {
|
||||||
|
|
||||||
var settings = window.mailpoet_settings || {};
|
var settings = window.mailpoet_settings || {};
|
||||||
|
|
||||||
var fields = [
|
var fields = [
|
||||||
{
|
{
|
||||||
@ -24,14 +24,17 @@ define(
|
|||||||
label: 'Subject line',
|
label: 'Subject line',
|
||||||
tip: "Be creative! It's the first thing your subscribers see."+
|
tip: "Be creative! It's the first thing your subscribers see."+
|
||||||
"Tempt them to open your email.",
|
"Tempt them to open your email.",
|
||||||
type: 'text'
|
type: 'text',
|
||||||
|
validation: {
|
||||||
|
'data-parsley-required': true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'segments',
|
name: 'segments',
|
||||||
label: 'Lists',
|
label: 'Segments',
|
||||||
tip: "The subscriber list that will be used for this campaign.",
|
tip: "The subscriber segment that will be used for this campaign.",
|
||||||
type: 'selection',
|
type: 'selection',
|
||||||
placeholder: "Select a list",
|
placeholder: "Select a segment",
|
||||||
id: "mailpoet_segments",
|
id: "mailpoet_segments",
|
||||||
endpoint: "segments",
|
endpoint: "segments",
|
||||||
multiple: true,
|
multiple: true,
|
||||||
@ -111,12 +114,19 @@ define(
|
|||||||
action: 'add',
|
action: 'add',
|
||||||
data: {
|
data: {
|
||||||
newsletter_id: this.props.params.id,
|
newsletter_id: this.props.params.id,
|
||||||
segments: jQuery('#mailpoet_segments').val()
|
segments: jQuery('#mailpoet_segments').val(),
|
||||||
|
sender: {
|
||||||
|
'name': jQuery('#mailpoet_newsletter [name="sender_name"]').val(),
|
||||||
|
'address': jQuery('#mailpoet_newsletter [name="sender_address"]').val()
|
||||||
|
},
|
||||||
|
reply_to: {
|
||||||
|
'name': jQuery('#mailpoet_newsletter [name="reply_to_name"]').val(),
|
||||||
|
'address': jQuery('#mailpoet_newsletter [name="reply_to_address"]').val()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
if(response.result === true) {
|
if(response.result === true) {
|
||||||
this.history.pushState(null, '/');
|
this.history.pushState(null, '/');
|
||||||
|
|
||||||
MailPoet.Notice.success(
|
MailPoet.Notice.success(
|
||||||
'The newsletter is being sent...'
|
'The newsletter is being sent...'
|
||||||
);
|
);
|
||||||
@ -135,14 +145,6 @@ define(
|
|||||||
}.bind(this));
|
}.bind(this));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
componentDidMount: function() {
|
|
||||||
if(this.isMounted()) {
|
|
||||||
jQuery('#mailpoet_newsletter').parsley();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
isValid: function() {
|
|
||||||
return (jQuery('#mailpoet_newsletter').parsley().validate());
|
|
||||||
},
|
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@ -156,8 +158,7 @@ define(
|
|||||||
fields={ fields }
|
fields={ fields }
|
||||||
params={ this.props.params }
|
params={ this.props.params }
|
||||||
messages={ messages }
|
messages={ messages }
|
||||||
isValid={ this.isValid }>
|
>
|
||||||
|
|
||||||
<p className="submit">
|
<p className="submit">
|
||||||
<input
|
<input
|
||||||
className="button button-primary"
|
className="button button-primary"
|
||||||
|
@ -18,12 +18,18 @@ define(
|
|||||||
|
|
||||||
var ImportTemplate = React.createClass({
|
var ImportTemplate = React.createClass({
|
||||||
saveTemplate: function(template) {
|
saveTemplate: function(template) {
|
||||||
|
|
||||||
|
// Stringify to enable transmission of primitive non-string value types
|
||||||
|
if (!_.isUndefined(template.body)) {
|
||||||
|
template.body = JSON.stringify(template.body);
|
||||||
|
}
|
||||||
|
|
||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: 'newsletterTemplates',
|
endpoint: 'newsletterTemplates',
|
||||||
action: 'save',
|
action: 'save',
|
||||||
data: template
|
data: template
|
||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
if(response === true) {
|
if(response.result === true) {
|
||||||
this.props.onImport(template);
|
this.props.onImport(template);
|
||||||
} else {
|
} else {
|
||||||
response.map(function(error) {
|
response.map(function(error) {
|
||||||
@ -111,12 +117,19 @@ define(
|
|||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
handleSelectTemplate: function(template) {
|
handleSelectTemplate: function(template) {
|
||||||
|
var body = template.body;
|
||||||
|
|
||||||
|
// Stringify to enable transmission of primitive non-string value types
|
||||||
|
if (!_.isUndefined(body)) {
|
||||||
|
body = JSON.stringify(body);
|
||||||
|
}
|
||||||
|
|
||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: 'newsletters',
|
endpoint: 'newsletters',
|
||||||
action: 'save',
|
action: 'save',
|
||||||
data: {
|
data: {
|
||||||
id: this.props.params.id,
|
id: this.props.params.id,
|
||||||
body: template.body
|
body: body
|
||||||
}
|
}
|
||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
if(response.result === true) {
|
if(response.result === true) {
|
||||||
@ -153,7 +166,7 @@ define(
|
|||||||
handleShowTemplate: function(template) {
|
handleShowTemplate: function(template) {
|
||||||
MailPoet.Modal.popup({
|
MailPoet.Modal.popup({
|
||||||
title: template.name,
|
title: template.name,
|
||||||
template: '<img src="{{ thumbnail }}" />',
|
template: '<div class="mailpoet_boxes_preview" style="background-color: {{ body.globalStyles.body.backgroundColor }}"><img src="{{ thumbnail }}" /></div>',
|
||||||
data: template,
|
data: template,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -29,12 +29,14 @@ define(
|
|||||||
subject: 'Draft newsletter',
|
subject: 'Draft newsletter',
|
||||||
}
|
}
|
||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
if(response.id !== undefined) {
|
if(response.result && response.newsletter.id) {
|
||||||
this.history.pushState(null, `/template/${response.id}`);
|
this.history.pushState(null, `/template/${response.newsletter.id}`);
|
||||||
} else {
|
} else {
|
||||||
response.map(function(error) {
|
if(response.errors.length > 0) {
|
||||||
MailPoet.Notice.error(error);
|
response.errors.map(function(error) {
|
||||||
});
|
MailPoet.Notice.error(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
@ -138,12 +138,14 @@ define(
|
|||||||
options: this.state,
|
options: this.state,
|
||||||
},
|
},
|
||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
if(response.id !== undefined) {
|
if(response.result && response.newsletter.id) {
|
||||||
this.showTemplateSelection(response.id);
|
this.showTemplateSelection(response.newsletter.id);
|
||||||
} else {
|
} else {
|
||||||
response.map(function(error) {
|
if(response.errors.length > 0) {
|
||||||
MailPoet.Notice.error(error);
|
response.errors.map(function(error) {
|
||||||
});
|
MailPoet.Notice.error(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
@ -32,12 +32,15 @@ define(
|
|||||||
type: 'standard',
|
type: 'standard',
|
||||||
}
|
}
|
||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
if(response.id !== undefined) {
|
console.log(response);
|
||||||
this.showTemplateSelection(response.id);
|
if(response.result && response.newsletter.id) {
|
||||||
|
this.showTemplateSelection(response.newsletter.id);
|
||||||
} else {
|
} else {
|
||||||
response.map(function(error) {
|
if(response.errors.length > 0) {
|
||||||
MailPoet.Notice.error(error);
|
response.errors.map(function(error) {
|
||||||
});
|
MailPoet.Notice.error(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
@ -111,12 +111,14 @@ define(
|
|||||||
options: this.state,
|
options: this.state,
|
||||||
},
|
},
|
||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
if(response.id !== undefined) {
|
if(response.result && response.newsletter.id) {
|
||||||
this.showTemplateSelection(response.id);
|
this.showTemplateSelection(response.newsletter.id);
|
||||||
} else {
|
} else {
|
||||||
response.map(function(error) {
|
if(response.errors.length > 0) {
|
||||||
MailPoet.Notice.error(error);
|
response.errors.map(function(error) {
|
||||||
});
|
MailPoet.Notice.error(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
@ -1,75 +1,75 @@
|
|||||||
define('notice', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
define('notice', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
||||||
"use strict";
|
"use strict";
|
||||||
/*==================================================================================================
|
/*==================================================================================================
|
||||||
|
|
||||||
MailPoet Notice:
|
MailPoet Notice:
|
||||||
|
|
||||||
description: Handles notices
|
description: Handles notices
|
||||||
version: 0.2
|
version: 0.2
|
||||||
author: Jonathan Labreuille
|
author: Jonathan Labreuille
|
||||||
company: Wysija
|
company: Wysija
|
||||||
dependencies: jQuery
|
dependencies: jQuery
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
// success message (static: false)
|
// success message (static: false)
|
||||||
MailPoet.Notice.success('Yatta!');
|
MailPoet.Notice.success('Yatta!');
|
||||||
|
|
||||||
// error message (static: false)
|
// error message (static: false)
|
||||||
MailPoet.Notice.error('Boo!');
|
MailPoet.Notice.error('Boo!');
|
||||||
|
|
||||||
// system message (static: true)
|
// system message (static: true)
|
||||||
MailPoet.Notice.system('You need to updated ASAP!');
|
MailPoet.Notice.system('You need to updated ASAP!');
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
MailPoet.Notice.success('- success #1 -');
|
MailPoet.Notice.success('- success #1 -');
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
MailPoet.Notice.success('- success #2 -');
|
MailPoet.Notice.success('- success #2 -');
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
MailPoet.Notice.error('- error -');
|
MailPoet.Notice.error('- error -');
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
MailPoet.Notice.system('- system -');
|
MailPoet.Notice.system('- system -');
|
||||||
|
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
MailPoet.Notice.hide();
|
MailPoet.Notice.hide();
|
||||||
}, 2500);
|
}, 2500);
|
||||||
}, 300);
|
}, 300);
|
||||||
}, 400);
|
}, 400);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
==================================================================================================*/
|
==================================================================================================*/
|
||||||
|
|
||||||
MailPoet.Notice = {
|
MailPoet.Notice = {
|
||||||
version: 0.2,
|
version: 0.2,
|
||||||
// default options
|
// default options
|
||||||
defaults: {
|
defaults: {
|
||||||
type: 'success',
|
type: 'success',
|
||||||
message: '',
|
message: '',
|
||||||
static: false,
|
static: false,
|
||||||
hideClose: false,
|
hideClose: false,
|
||||||
id: null,
|
id: null,
|
||||||
positionAfter: false,
|
positionAfter: false,
|
||||||
scroll: false,
|
scroll: false,
|
||||||
timeout: 2000,
|
timeout: 2000,
|
||||||
onOpen: null,
|
onOpen: null,
|
||||||
onClose: null
|
onClose: null
|
||||||
},
|
},
|
||||||
options: {},
|
options: {},
|
||||||
init: function(options) {
|
init: function(options) {
|
||||||
// set options
|
// set options
|
||||||
this.options = jQuery.extend({}, this.defaults, options);
|
this.options = jQuery.extend({}, this.defaults, options);
|
||||||
|
|
||||||
// clone element
|
// clone element
|
||||||
this.element = jQuery('#mailpoet_notice_'+this.options.type).clone();
|
this.element = jQuery('#mailpoet_notice_'+this.options.type).clone();
|
||||||
|
|
||||||
// add data-id to the element
|
// add data-id to the element
|
||||||
if (this.options.id) this.element.attr('data-id', 'notice_' + this.options.id);
|
if (this.options.id) this.element.attr('data-id', 'notice_' + this.options.id);
|
||||||
|
|
||||||
// remove id from clone
|
// remove id from clone
|
||||||
this.element.removeAttr('id');
|
this.element.removeAttr('id');
|
||||||
|
|
||||||
// insert notice after its parent
|
// insert notice after its parent
|
||||||
var positionAfter;
|
var positionAfter;
|
||||||
if (typeof this.options.positionAfter === 'object') {
|
if (typeof this.options.positionAfter === 'object') {
|
||||||
positionAfter = this.options.positionAfter;
|
positionAfter = this.options.positionAfter;
|
||||||
@ -78,136 +78,142 @@ define('notice', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
|||||||
} else {
|
} else {
|
||||||
positionAfter = jQuery('#mailpoet_notice_'+this.options.type);
|
positionAfter = jQuery('#mailpoet_notice_'+this.options.type);
|
||||||
}
|
}
|
||||||
console.log('positionAfter', typeof this.options.positionAfter);
|
positionAfter.after(this.element);
|
||||||
positionAfter.after(this.element);
|
|
||||||
|
// setup onClose callback
|
||||||
// setup onClose callback
|
var onClose = null;
|
||||||
var onClose = null;
|
if(this.options.onClose !== null) {
|
||||||
if(this.options.onClose !== null) {
|
onClose = this.options.onClose;
|
||||||
onClose = this.options.onClose;
|
}
|
||||||
}
|
|
||||||
|
// listen to remove event
|
||||||
// listen to remove event
|
jQuery(this.element).on('close', function() {
|
||||||
jQuery(this.element).on('close', function() {
|
jQuery(this).fadeOut(200, function() {
|
||||||
jQuery(this).fadeOut(200, function() {
|
// on close callback
|
||||||
// on close callback
|
if(onClose !== null) {
|
||||||
if(onClose !== null) {
|
onClose();
|
||||||
onClose();
|
}
|
||||||
}
|
// remove notice
|
||||||
// remove notice
|
jQuery(this).remove();
|
||||||
jQuery(this).remove();
|
});
|
||||||
});
|
}.bind(this.element));
|
||||||
}.bind(this.element));
|
|
||||||
|
// listen to message event
|
||||||
// listen to message event
|
jQuery(this.element).on('message', function(e, message) {
|
||||||
jQuery(this.element).on('message', function(e, message) {
|
MailPoet.Notice.setMessage(message);
|
||||||
MailPoet.Notice.setMessage(message);
|
}.bind(this.element));
|
||||||
}.bind(this.element));
|
|
||||||
|
return this;
|
||||||
return this;
|
},
|
||||||
},
|
isHTML: function(str) {
|
||||||
isHTML: function(str) {
|
var a = document.createElement('div');
|
||||||
var a = document.createElement('div');
|
a.innerHTML = str;
|
||||||
a.innerHTML = str;
|
for(var c = a.childNodes, i = c.length; i--;) {
|
||||||
for(var c = a.childNodes, i = c.length; i--;) {
|
if(c[i].nodeType == 1) return true;
|
||||||
if(c[i].nodeType == 1) return true;
|
}
|
||||||
}
|
return false;
|
||||||
return false;
|
},
|
||||||
},
|
setMessage: function(message) {
|
||||||
setMessage: function(message) {
|
// if it's not an html message, let's sugar coat the message with a fancy <p>
|
||||||
// if it's not an html message, let's sugar coat the message with a fancy <p>
|
if(this.isHTML(message) === false) {
|
||||||
if(this.isHTML(message) === false) {
|
message = '<p>'+message+'</p>';
|
||||||
message = '<p>'+message+'</p>';
|
}
|
||||||
}
|
// set message
|
||||||
// set message
|
return this.element.html(message);
|
||||||
return this.element.html(message);
|
},
|
||||||
},
|
show: function(options) {
|
||||||
show: function(options) {
|
// initialize
|
||||||
// initialize
|
this.init(options);
|
||||||
this.init(options);
|
|
||||||
|
// show notice
|
||||||
// show notice
|
this.showNotice();
|
||||||
this.showNotice();
|
|
||||||
|
// return this;
|
||||||
// return this;
|
},
|
||||||
},
|
showNotice: function() {
|
||||||
showNotice: function() {
|
// set message
|
||||||
// set message
|
this.setMessage(this.options.message);
|
||||||
this.setMessage(this.options.message);
|
|
||||||
|
// position notice
|
||||||
// position notice
|
this.element.insertAfter(jQuery('h2.title'));
|
||||||
this.element.insertAfter(jQuery('h2.title'));
|
|
||||||
|
// set class name
|
||||||
// set class name
|
switch(this.options.type) {
|
||||||
switch(this.options.type) {
|
case 'success':
|
||||||
case 'success':
|
this.element.addClass('updated');
|
||||||
this.element.addClass('updated');
|
break;
|
||||||
break;
|
case 'system':
|
||||||
case 'system':
|
this.element.addClass('update-nag');
|
||||||
this.element.addClass('update-nag');
|
break;
|
||||||
break;
|
case 'error':
|
||||||
case 'error':
|
this.element.addClass('error');
|
||||||
this.element.addClass('error');
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
// make the notice appear
|
||||||
// make the notice appear
|
this.element.fadeIn(200);
|
||||||
this.element.fadeIn(200);
|
|
||||||
|
// if scroll option is enabled, scroll to the notice
|
||||||
// if scroll option is enabled, scroll to the notice
|
if(this.options.scroll === true) {
|
||||||
if(this.options.scroll === true) {
|
this.element.get(0).scrollIntoView(false);
|
||||||
this.element.get(0).scrollIntoView(false);
|
}
|
||||||
}
|
|
||||||
|
// if the notice is not static, it has to disappear after a timeout
|
||||||
// if the notice is not static, it has to disappear after a timeout
|
if(this.options.static === false) {
|
||||||
if(this.options.static === false) {
|
this.element.delay(this.options.timeout).trigger('close');
|
||||||
this.element.delay(this.options.timeout).trigger('close');
|
} else if (this.options.hideClose === false) {
|
||||||
} else if (this.options.hideClose === false) {
|
this.element.append('<a href="javascript:;" class="mailpoet_notice_close"><span class="dashicons dashicons-dismiss"></span></a>');
|
||||||
this.element.append('<a href="javascript:;" class="mailpoet_notice_close"><span class="dashicons dashicons-dismiss"></span></a>');
|
this.element.find('.mailpoet_notice_close').on('click', function() {
|
||||||
this.element.find('.mailpoet_notice_close').on('click', function() {
|
jQuery(this).trigger('close');
|
||||||
jQuery(this).trigger('close');
|
});
|
||||||
});
|
}
|
||||||
}
|
|
||||||
|
// call onOpen callback
|
||||||
// call onOpen callback
|
if(this.options.onOpen !== null) {
|
||||||
if(this.options.onOpen !== null) {
|
this.options.onOpen(this.element);
|
||||||
this.options.onOpen(this.element);
|
}
|
||||||
}
|
},
|
||||||
},
|
hide: function(all) {
|
||||||
hide: function(all) {
|
if(all !== undefined && all === true) {
|
||||||
if(all !== undefined && all === true) {
|
jQuery('.mailpoet_notice:not([id])').trigger('close');
|
||||||
jQuery('.mailpoet_notice:not([id])').trigger('close');
|
} else if (all !== undefined && jQuery.isArray(all)) {
|
||||||
} else if (all !== undefined && jQuery.isArray(all)) {
|
for (var id in all) {
|
||||||
for (var id in all) {
|
jQuery('[data-id="notice_' + all[id] + '"]')
|
||||||
jQuery('[data-id="notice_' + all[id] + '"]')
|
.trigger('close');
|
||||||
.trigger('close');
|
}
|
||||||
}
|
} if (all !== undefined) {
|
||||||
} if (all !== undefined) {
|
jQuery('[data-id="notice_' + all + '"]')
|
||||||
jQuery('[data-id="notice_' + all + '"]')
|
.trigger('close');
|
||||||
.trigger('close');
|
} else {
|
||||||
} else {
|
jQuery('.mailpoet_notice.updated:not([id]), .mailpoet_notice.error:not([id])')
|
||||||
jQuery('.mailpoet_notice.updated:not([id]), .mailpoet_notice.error:not([id])')
|
.trigger('close');
|
||||||
.trigger('close');
|
}
|
||||||
}
|
},
|
||||||
},
|
error: function(message, options) {
|
||||||
error: function(message, options) {
|
this.show(jQuery.extend({}, {
|
||||||
this.show(jQuery.extend({}, {
|
type: 'error',
|
||||||
type: 'error',
|
message: '<p>'+this.formatMessage(message)+'</p>'
|
||||||
message: '<p>'+message+'</p>'
|
}, options));
|
||||||
}, options));
|
},
|
||||||
},
|
success: function(message, options) {
|
||||||
success: function(message, options) {
|
this.show(jQuery.extend({}, {
|
||||||
this.show(jQuery.extend({}, {
|
type: 'success',
|
||||||
type: 'success',
|
message: '<p>'+this.formatMessage(message)+'</p>'
|
||||||
message: '<p>'+message+'</p>'
|
}, options));
|
||||||
}, options));
|
},
|
||||||
},
|
system: function(message, options) {
|
||||||
system: function(message, options) {
|
this.show(jQuery.extend({}, {
|
||||||
this.show(jQuery.extend({}, {
|
type: 'system',
|
||||||
type: 'system',
|
static: true,
|
||||||
static: true,
|
message: '<p>'+this.formatMessage(message)+'</p>'
|
||||||
message: message
|
}, options));
|
||||||
}, options));
|
},
|
||||||
}
|
formatMessage: function(message) {
|
||||||
};
|
if(Array.isArray(message)) {
|
||||||
|
return message.join('<br />');
|
||||||
|
} else {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
@ -20,10 +20,7 @@ function(
|
|||||||
$('form.mailpoet_form').each(function() {
|
$('form.mailpoet_form').each(function() {
|
||||||
var form = $(this);
|
var form = $(this);
|
||||||
|
|
||||||
form.parsley({
|
form.parsley().on('form:submit', function(parsley) {
|
||||||
errorsWrapper: '<p></p>',
|
|
||||||
errorTemplate: '<span></span>'
|
|
||||||
}).on('form:submit', function(parsley) {
|
|
||||||
|
|
||||||
var data = form.serializeObject() || {};
|
var data = form.serializeObject() || {};
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ define(
|
|||||||
Form
|
Form
|
||||||
) {
|
) {
|
||||||
|
|
||||||
var fields = [
|
let fields = [
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
label: 'Name',
|
label: 'Name',
|
||||||
@ -25,7 +25,7 @@ define(
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
var messages = {
|
const messages = {
|
||||||
onUpdate: function() {
|
onUpdate: function() {
|
||||||
MailPoet.Notice.success('Segment successfully updated!');
|
MailPoet.Notice.success('Segment successfully updated!');
|
||||||
},
|
},
|
||||||
@ -34,7 +34,7 @@ define(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var SegmentForm = React.createClass({
|
const SegmentForm = React.createClass({
|
||||||
mixins: [
|
mixins: [
|
||||||
Router.History
|
Router.History
|
||||||
],
|
],
|
||||||
|
@ -42,58 +42,49 @@ var columns = [
|
|||||||
|
|
||||||
const messages = {
|
const messages = {
|
||||||
onTrash: function(response) {
|
onTrash: function(response) {
|
||||||
if(response) {
|
var count = ~~response;
|
||||||
let message = null;
|
var message = null;
|
||||||
if(~~response === 1) {
|
|
||||||
message = (
|
|
||||||
'1 segment was moved to the trash.'
|
|
||||||
);
|
|
||||||
} else if(~~response > 1) {
|
|
||||||
message = (
|
|
||||||
'%$1d segments were moved to the trash.'
|
|
||||||
).replace('%$1d', ~~response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(message !== null) {
|
if(count === 1) {
|
||||||
MailPoet.Notice.success(message);
|
message = (
|
||||||
}
|
'1 segment was moved to the trash.'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
'%$1d segments were moved to the trash.'
|
||||||
|
).replace('%$1d', count);
|
||||||
}
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
},
|
},
|
||||||
onDelete: function(response) {
|
onDelete: function(response) {
|
||||||
if(response) {
|
var count = ~~response;
|
||||||
let message = null;
|
var message = null;
|
||||||
if(~~response === 1) {
|
|
||||||
message = (
|
|
||||||
'1 segment was permanently deleted.'
|
|
||||||
);
|
|
||||||
} else if(~~response > 1) {
|
|
||||||
message = (
|
|
||||||
'%$1d segments were permanently deleted.'
|
|
||||||
).replace('%$1d', ~~response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(message !== null) {
|
if(count === 1) {
|
||||||
MailPoet.Notice.success(message);
|
message = (
|
||||||
}
|
'1 segment was permanently deleted.'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
'%$1d segments were permanently deleted.'
|
||||||
|
).replace('%$1d', count);
|
||||||
}
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
},
|
},
|
||||||
onRestore: function(response) {
|
onRestore: function(response) {
|
||||||
if(response) {
|
var count = ~~response;
|
||||||
let message = null;
|
var message = null;
|
||||||
if(~~response === 1) {
|
|
||||||
message = (
|
|
||||||
'1 segment has been restored from the trash.'
|
|
||||||
);
|
|
||||||
} else if(~~response > 1) {
|
|
||||||
message = (
|
|
||||||
'%$1d segments have been restored from the trash.'
|
|
||||||
).replace('%$1d', ~~response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(message !== null) {
|
if(count === 1) {
|
||||||
MailPoet.Notice.success(message);
|
message = (
|
||||||
}
|
'1 segment has been restored from the trash.'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
'%$1d segments have been restored from the trash.'
|
||||||
|
).replace('%$1d', count);
|
||||||
}
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -105,6 +96,9 @@ const item_actions = [
|
|||||||
return (
|
return (
|
||||||
<Link to={ `/edit/${item.id}` }>Edit</Link>
|
<Link to={ `/edit/${item.id}` }>Edit</Link>
|
||||||
);
|
);
|
||||||
|
},
|
||||||
|
display: function(segment) {
|
||||||
|
return (segment.type !== 'wp_users');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -51,6 +51,24 @@ define(
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
var custom_fields = window.mailpoet_custom_fields || [];
|
||||||
|
custom_fields.map(custom_field => {
|
||||||
|
let field = {
|
||||||
|
name: 'cf_' + custom_field.id,
|
||||||
|
label: custom_field.name,
|
||||||
|
type: custom_field.type
|
||||||
|
};
|
||||||
|
if(custom_field.params) {
|
||||||
|
field.params = custom_field.params;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(custom_field.params.values) {
|
||||||
|
field.values = custom_field.params.values;
|
||||||
|
}
|
||||||
|
|
||||||
|
fields.push(field);
|
||||||
|
});
|
||||||
|
|
||||||
var messages = {
|
var messages = {
|
||||||
onUpdate: function() {
|
onUpdate: function() {
|
||||||
MailPoet.Notice.success('Subscriber successfully updated!');
|
MailPoet.Notice.success('Subscriber successfully updated!');
|
||||||
|
@ -62,7 +62,7 @@ define(
|
|||||||
if (_.contains(fieldsToExclude, selectedOptionId)) {
|
if (_.contains(fieldsToExclude, selectedOptionId)) {
|
||||||
selectEvent.preventDefault();
|
selectEvent.preventDefault();
|
||||||
if (selectedOptionId === 'deselect') {
|
if (selectedOptionId === 'deselect') {
|
||||||
jQuery(selectElement).select2('val', '');
|
jQuery(selectElement).val('').trigger('change');
|
||||||
} else {
|
} else {
|
||||||
var allOptions = [];
|
var allOptions = [];
|
||||||
_.each(container.find('option'), function (field) {
|
_.each(container.find('option'), function (field) {
|
||||||
@ -70,7 +70,7 @@ define(
|
|||||||
allOptions.push(field.value);
|
allOptions.push(field.value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
jQuery(selectElement).select2('val', allOptions);
|
jQuery(selectElement).val(allOptions).trigger('change');
|
||||||
}
|
}
|
||||||
jQuery(selectElement).select2('close');
|
jQuery(selectElement).select2('close');
|
||||||
}
|
}
|
||||||
@ -138,11 +138,11 @@ define(
|
|||||||
endpoint: 'ImportExport',
|
endpoint: 'ImportExport',
|
||||||
action: 'processExport',
|
action: 'processExport',
|
||||||
data: JSON.stringify({
|
data: JSON.stringify({
|
||||||
'exportConfirmedOption': exportData.exportConfirmedOption,
|
'export_confirmed_option': exportData.exportConfirmedOption,
|
||||||
'exportFormatOption': jQuery(':radio[name="option_format"]:checked').val(),
|
'export_format_option': jQuery(':radio[name="option_format"]:checked').val(),
|
||||||
'groupBySegmentOption': (groupBySegmentOptionElement.is(":visible")) ? groupBySegmentOptionElement.prop('checked') : false,
|
'group_by_segment_option': (groupBySegmentOptionElement.is(":visible")) ? groupBySegmentOptionElement.prop('checked') : false,
|
||||||
'segments': (exportData.segments) ? segmentsContainerElement.val() : false,
|
'segments': (exportData.segments) ? segmentsContainerElement.val() : false,
|
||||||
'subscriberFields': subscriberFieldsContainerElement.val()
|
'subscriber_fields': subscriberFieldsContainerElement.val()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.done(function (response) {
|
.done(function (response) {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -19,3 +19,12 @@ modules:
|
|||||||
user: ''
|
user: ''
|
||||||
password: ''
|
password: ''
|
||||||
dump: tests/_data/dump.sql
|
dump: tests/_data/dump.sql
|
||||||
|
coverage:
|
||||||
|
enabled: true
|
||||||
|
whitelist:
|
||||||
|
include:
|
||||||
|
- lib/*
|
||||||
|
exclude:
|
||||||
|
blacklist:
|
||||||
|
include:
|
||||||
|
exclude:
|
@ -10,7 +10,8 @@
|
|||||||
"swiftmailer/swiftmailer": "^5.4",
|
"swiftmailer/swiftmailer": "^5.4",
|
||||||
"phpseclib/phpseclib": "*",
|
"phpseclib/phpseclib": "*",
|
||||||
"mtdowling/cron-expression": "^1.0",
|
"mtdowling/cron-expression": "^1.0",
|
||||||
"nesbot/carbon": "^1.21"
|
"nesbot/carbon": "^1.21",
|
||||||
|
"soundasleep/html2text": "^0.3.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"codeception/codeception": "*",
|
"codeception/codeception": "*",
|
||||||
|
672
composer.lock
generated
672
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -9,13 +9,6 @@ class Activator {
|
|||||||
function __construct() {
|
function __construct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
|
||||||
register_activation_hook(
|
|
||||||
Env::$file,
|
|
||||||
array($this, 'activate')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function activate() {
|
function activate() {
|
||||||
$migrator = new Migrator();
|
$migrator = new Migrator();
|
||||||
$migrator->up();
|
$migrator->up();
|
||||||
@ -23,4 +16,9 @@ class Activator {
|
|||||||
$populator = new Populator();
|
$populator = new Populator();
|
||||||
$populator->up();
|
$populator->up();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function deactivate() {
|
||||||
|
$migrator = new Migrator();
|
||||||
|
$migrator->down();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,8 @@ class Analytics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
add_action('admin_enqueue_scripts', array($this, 'setupAdminDependencies'));
|
// review: this creates a fatal error when mailpoet tables are dropped.
|
||||||
|
//add_action('admin_enqueue_scripts', array($this, 'setupAdminDependencies'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupAdminDependencies() {
|
function setupAdminDependencies() {
|
||||||
|
@ -6,15 +6,14 @@ if(!defined('ABSPATH')) exit;
|
|||||||
class Env {
|
class Env {
|
||||||
static $version;
|
static $version;
|
||||||
static $plugin_name;
|
static $plugin_name;
|
||||||
static $plugin_url;
|
|
||||||
static $plugin_path;
|
static $plugin_path;
|
||||||
static $file;
|
static $file;
|
||||||
static $path;
|
static $path;
|
||||||
static $views_path;
|
static $views_path;
|
||||||
static $assets_path;
|
static $assets_path;
|
||||||
static $assets_url;
|
static $assets_url;
|
||||||
static $temp_name;
|
|
||||||
static $temp_path;
|
static $temp_path;
|
||||||
|
static $temp_URL;
|
||||||
static $languages_path;
|
static $languages_path;
|
||||||
static $lib_path;
|
static $lib_path;
|
||||||
static $plugin_prefix;
|
static $plugin_prefix;
|
||||||
@ -34,12 +33,12 @@ class Env {
|
|||||||
self::$file = $file;
|
self::$file = $file;
|
||||||
self::$path = dirname(self::$file);
|
self::$path = dirname(self::$file);
|
||||||
self::$plugin_name = 'mailpoet';
|
self::$plugin_name = 'mailpoet';
|
||||||
self::$plugin_url = plugin_dir_url(__FILE__);
|
|
||||||
self::$views_path = self::$path . '/views';
|
self::$views_path = self::$path . '/views';
|
||||||
self::$assets_path = self::$path . '/assets';
|
self::$assets_path = self::$path . '/assets';
|
||||||
self::$assets_url = plugins_url('/assets', $file);
|
self::$assets_url = plugins_url('/assets', $file);
|
||||||
self::$temp_name = 'temp';
|
$wp_upload_dir = wp_upload_dir();
|
||||||
self::$temp_path = self::$path . '/' . self::$temp_name;
|
self::$temp_path = $wp_upload_dir['path'];
|
||||||
|
self::$temp_URL = $wp_upload_dir['url'];
|
||||||
self::$languages_path = self::$path . '/lang';
|
self::$languages_path = self::$path . '/lang';
|
||||||
self::$lib_path = self::$path . '/lib';
|
self::$lib_path = self::$path . '/lib';
|
||||||
self::$plugin_prefix = 'mailpoet_';
|
self::$plugin_prefix = 'mailpoet_';
|
||||||
@ -74,19 +73,4 @@ class Env {
|
|||||||
);
|
);
|
||||||
return implode('', $source_name);
|
return implode('', $source_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static function isPluginActivated() {
|
|
||||||
$activatesPlugins = get_option('active_plugins');
|
|
||||||
$isActivated = (
|
|
||||||
in_array(
|
|
||||||
sprintf('%s/%s.php', basename(self::$path), self::$plugin_name),
|
|
||||||
$activatesPlugins
|
|
||||||
) ||
|
|
||||||
in_array(
|
|
||||||
sprintf('%s/%s.php', explode('/', plugin_basename(__FILE__))[0], self::$plugin_name),
|
|
||||||
$activatesPlugins
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return ($isActivated) ? true : false;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,11 +1,68 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Config;
|
namespace MailPoet\Config;
|
||||||
|
use \MailPoet\Models\Setting;
|
||||||
|
|
||||||
class Hooks {
|
class Hooks {
|
||||||
function __construct() {
|
function __construct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
|
// Subscribe in comments
|
||||||
|
if((bool)Setting::getValue('subscribe.on_comment.enabled')) {
|
||||||
|
if(is_user_logged_in()) {
|
||||||
|
add_action(
|
||||||
|
'comment_form_field_comment',
|
||||||
|
'\MailPoet\Subscription\Comment::extendLoggedInForm'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
add_action(
|
||||||
|
'comment_form_after_fields',
|
||||||
|
'\MailPoet\Subscription\Comment::extendLoggedOutForm'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
add_action(
|
||||||
|
'comment_post',
|
||||||
|
'\MailPoet\Subscription\Comment::onSubmit',
|
||||||
|
60,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
|
||||||
|
add_action(
|
||||||
|
'wp_set_comment_status',
|
||||||
|
'\MailPoet\Subscription\Comment::onStatusUpdate',
|
||||||
|
60,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subscribe in registration form
|
||||||
|
if((bool)Setting::getValue('subscribe.on_register.enabled')) {
|
||||||
|
if(is_multisite()) {
|
||||||
|
add_action(
|
||||||
|
'signup_extra_fields',
|
||||||
|
'\MailPoet\Subscription\Registration::extendForm'
|
||||||
|
);
|
||||||
|
add_action(
|
||||||
|
'wpmu_validate_user_signup',
|
||||||
|
'\MailPoet\Subscription\Registration::onMultiSiteRegister',
|
||||||
|
60,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
add_action(
|
||||||
|
'register_form',
|
||||||
|
'\MailPoet\Subscription\Registration::extendForm'
|
||||||
|
);
|
||||||
|
add_action(
|
||||||
|
'register_post',
|
||||||
|
'\MailPoet\Subscription\Registration::onRegister',
|
||||||
|
60,
|
||||||
|
3
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WP Users synchronization
|
// WP Users synchronization
|
||||||
add_action(
|
add_action(
|
||||||
'user_register',
|
'user_register',
|
||||||
|
@ -5,9 +5,12 @@ use MailPoet\Models;
|
|||||||
use MailPoet\Cron\Supervisor;
|
use MailPoet\Cron\Supervisor;
|
||||||
use MailPoet\Router;
|
use MailPoet\Router;
|
||||||
use MailPoet\Models\Setting;
|
use MailPoet\Models\Setting;
|
||||||
|
use MailPoet\Settings\Pages;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
|
||||||
|
|
||||||
class Initializer {
|
class Initializer {
|
||||||
function __construct($params = array(
|
function __construct($params = array(
|
||||||
'file' => '',
|
'file' => '',
|
||||||
@ -18,20 +21,34 @@ class Initializer {
|
|||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
$this->setupDB();
|
$this->setupDB();
|
||||||
$this->setupActivator();
|
|
||||||
$this->setupRenderer();
|
register_activation_hook(Env::$file, array($this, 'runMigrator'));
|
||||||
$this->setupLocalizer();
|
register_activation_hook(Env::$file, array($this, 'runPopulator'));
|
||||||
$this->setupMenu();
|
|
||||||
$this->setupRouter();
|
add_action('plugins_loaded', array($this, 'setup'));
|
||||||
$this->setupWidget();
|
add_action('widgets_init', array($this, 'setupWidget'));
|
||||||
$this->setupAnalytics();
|
}
|
||||||
$this->setupPermissions();
|
|
||||||
$this->setupChangelog();
|
function setup() {
|
||||||
$this->setupPublicAPI();
|
try {
|
||||||
$this->runQueueSupervisor();
|
$this->setupRenderer();
|
||||||
$this->setupShortcodes();
|
$this->setupLocalizer();
|
||||||
$this->setupHooks();
|
$this->setupMenu();
|
||||||
$this->setupImages();
|
$this->setupRouter();
|
||||||
|
$this->setupPermissions();
|
||||||
|
$this->setupPublicAPI();
|
||||||
|
$this->setupAnalytics();
|
||||||
|
$this->setupChangelog();
|
||||||
|
$this->runQueueSupervisor();
|
||||||
|
$this->setupShortcodes();
|
||||||
|
$this->setupHooks();
|
||||||
|
$this->setupPages();
|
||||||
|
$this->setupImages();
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
// if anything goes wrong during init
|
||||||
|
// automatically deactivate the plugin
|
||||||
|
deactivate_plugins(Env::$file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupDB() {
|
function setupDB() {
|
||||||
@ -49,8 +66,6 @@ class Initializer {
|
|||||||
$newsletters = Env::$db_prefix . 'newsletters';
|
$newsletters = Env::$db_prefix . 'newsletters';
|
||||||
$newsletter_templates = Env::$db_prefix . 'newsletter_templates';
|
$newsletter_templates = Env::$db_prefix . 'newsletter_templates';
|
||||||
$segments = Env::$db_prefix . 'segments';
|
$segments = Env::$db_prefix . 'segments';
|
||||||
$filters = Env::$db_prefix . 'filters';
|
|
||||||
$segment_filter = Env::$db_prefix . 'segment_filter';
|
|
||||||
$forms = Env::$db_prefix . 'forms';
|
$forms = Env::$db_prefix . 'forms';
|
||||||
$subscriber_segment = Env::$db_prefix . 'subscriber_segment';
|
$subscriber_segment = Env::$db_prefix . 'subscriber_segment';
|
||||||
$newsletter_segment = Env::$db_prefix . 'newsletter_segment';
|
$newsletter_segment = Env::$db_prefix . 'newsletter_segment';
|
||||||
@ -65,8 +80,6 @@ class Initializer {
|
|||||||
define('MP_SETTINGS_TABLE', $settings);
|
define('MP_SETTINGS_TABLE', $settings);
|
||||||
define('MP_NEWSLETTERS_TABLE', $newsletters);
|
define('MP_NEWSLETTERS_TABLE', $newsletters);
|
||||||
define('MP_SEGMENTS_TABLE', $segments);
|
define('MP_SEGMENTS_TABLE', $segments);
|
||||||
define('MP_FILTERS_TABLE', $filters);
|
|
||||||
define('MP_SEGMENT_FILTER_TABLE', $segment_filter);
|
|
||||||
define('MP_FORMS_TABLE', $forms);
|
define('MP_FORMS_TABLE', $forms);
|
||||||
define('MP_SUBSCRIBER_SEGMENT_TABLE', $subscriber_segment);
|
define('MP_SUBSCRIBER_SEGMENT_TABLE', $subscriber_segment);
|
||||||
define('MP_NEWSLETTER_TEMPLATES_TABLE', $newsletter_templates);
|
define('MP_NEWSLETTER_TEMPLATES_TABLE', $newsletter_templates);
|
||||||
@ -75,13 +88,18 @@ class Initializer {
|
|||||||
define('MP_SUBSCRIBER_CUSTOM_FIELD_TABLE', $subscriber_custom_field);
|
define('MP_SUBSCRIBER_CUSTOM_FIELD_TABLE', $subscriber_custom_field);
|
||||||
define('MP_NEWSLETTER_OPTION_FIELDS_TABLE', $newsletter_option_fields);
|
define('MP_NEWSLETTER_OPTION_FIELDS_TABLE', $newsletter_option_fields);
|
||||||
define('MP_NEWSLETTER_OPTION_TABLE', $newsletter_option);
|
define('MP_NEWSLETTER_OPTION_TABLE', $newsletter_option);
|
||||||
define('MP_SENDING_QUEUE_TABLE', $sending_queues);
|
define('MP_SENDING_QUEUES_TABLE', $sending_queues);
|
||||||
define('MP_NEWSLETTER_STATISTICS_TABLE', $newsletter_statistics);
|
define('MP_NEWSLETTER_STATISTICS_TABLE', $newsletter_statistics);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupActivator() {
|
function runMigrator() {
|
||||||
$activator = new Activator();
|
$migrator = new Migrator();
|
||||||
$activator->init();
|
$migrator->up();
|
||||||
|
}
|
||||||
|
|
||||||
|
function runPopulator() {
|
||||||
|
$populator = new Populator();
|
||||||
|
$populator->up();
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupRenderer() {
|
function setupRenderer() {
|
||||||
@ -95,10 +113,7 @@ class Initializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setupMenu() {
|
function setupMenu() {
|
||||||
$menu = new Menu(
|
$menu = new Menu($this->renderer, Env::$assets_url);
|
||||||
$this->renderer,
|
|
||||||
Env::$assets_url
|
|
||||||
);
|
|
||||||
$menu->init();
|
$menu->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,10 +142,16 @@ class Initializer {
|
|||||||
$changelog->init();
|
$changelog->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setupPages() {
|
||||||
|
$pages = new Pages();
|
||||||
|
$pages->init();
|
||||||
|
}
|
||||||
|
|
||||||
function setupShortcodes() {
|
function setupShortcodes() {
|
||||||
$shortcodes = new Shortcodes();
|
$shortcodes = new Shortcodes();
|
||||||
$shortcodes->init();
|
$shortcodes->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupHooks() {
|
function setupHooks() {
|
||||||
$hooks = new Hooks();
|
$hooks = new Hooks();
|
||||||
$hooks->init();
|
$hooks->init();
|
||||||
@ -142,13 +163,15 @@ class Initializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function runQueueSupervisor() {
|
function runQueueSupervisor() {
|
||||||
|
if(php_sapi_name() === 'cli') return;
|
||||||
try {
|
try {
|
||||||
$supervisor = new Supervisor();
|
$supervisor = new Supervisor();
|
||||||
$supervisor->checkDaemon();
|
$supervisor->checkDaemon();
|
||||||
} catch (\Exception $e) {}
|
} catch(\Exception $e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupImages() {
|
function setupImages() {
|
||||||
add_image_size('mailpoet_newsletter_max', 1320);
|
add_image_size('mailpoet_newsletter_max', 1320);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,8 +11,7 @@ class Localizer {
|
|||||||
function init() {
|
function init() {
|
||||||
add_action(
|
add_action(
|
||||||
'init',
|
'init',
|
||||||
array($this, 'setup'),
|
array($this, 'setup')
|
||||||
0
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,6 +190,8 @@ class Menu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function welcome() {
|
function welcome() {
|
||||||
|
if((bool)(defined('DOING_AJAX') && DOING_AJAX)) return;
|
||||||
|
|
||||||
global $wp;
|
global $wp;
|
||||||
$current_url = home_url(add_query_arg($wp->query_string, $wp->request));
|
$current_url = home_url(add_query_arg($wp->query_string, $wp->request));
|
||||||
$redirect_url =
|
$redirect_url =
|
||||||
@ -240,6 +242,7 @@ class Menu {
|
|||||||
|
|
||||||
function settings() {
|
function settings() {
|
||||||
$settings = Setting::getAll();
|
$settings = Setting::getAll();
|
||||||
|
$flags = $this->_getFlags();
|
||||||
|
|
||||||
// dkim: check if public/private keys have been generated
|
// dkim: check if public/private keys have been generated
|
||||||
if(
|
if(
|
||||||
@ -258,10 +261,9 @@ class Menu {
|
|||||||
|
|
||||||
$data = array(
|
$data = array(
|
||||||
'settings' => $settings,
|
'settings' => $settings,
|
||||||
'segments' => Segment::getPublished()
|
'segments' => Segment::getPublic()->findArray(),
|
||||||
->findArray(),
|
|
||||||
'pages' => Pages::getAll(),
|
'pages' => Pages::getAll(),
|
||||||
'flags' => $this->_getFlags(),
|
'flags' => $flags,
|
||||||
'charsets' => Charsets::getAll(),
|
'charsets' => Charsets::getAll(),
|
||||||
'current_user' => wp_get_current_user(),
|
'current_user' => wp_get_current_user(),
|
||||||
'permissions' => Permissions::getAll(),
|
'permissions' => Permissions::getAll(),
|
||||||
@ -294,7 +296,7 @@ class Menu {
|
|||||||
} else {
|
} else {
|
||||||
// check if users can register
|
// check if users can register
|
||||||
$flags['registration_enabled'] =
|
$flags['registration_enabled'] =
|
||||||
(bool) get_option('users_can_register', false);
|
(bool)get_option('users_can_register', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $flags;
|
return $flags;
|
||||||
@ -305,6 +307,23 @@ class Menu {
|
|||||||
|
|
||||||
$data['segments'] = Segment::findArray();
|
$data['segments'] = Segment::findArray();
|
||||||
|
|
||||||
|
$data['custom_fields'] = array_map(function($field) {
|
||||||
|
$field['params'] = unserialize($field['params']);
|
||||||
|
|
||||||
|
if(!empty($field['params']['values'])) {
|
||||||
|
$values = array();
|
||||||
|
|
||||||
|
foreach($field['params']['values'] as $value) {
|
||||||
|
$values[$value['value']] = $value['value'];
|
||||||
|
}
|
||||||
|
$field['params']['values'] = $values;
|
||||||
|
}
|
||||||
|
return $field;
|
||||||
|
}, CustomField::findArray());
|
||||||
|
|
||||||
|
$data['date_formats'] = Block\Date::getDateFormats();
|
||||||
|
$data['month_names'] = Block\Date::getMonthNames();
|
||||||
|
|
||||||
echo $this->renderer->render('subscribers/subscribers.html', $data);
|
echo $this->renderer->render('subscribers/subscribers.html', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Config;
|
namespace MailPoet\Config;
|
||||||
|
|
||||||
if (!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ class Migrator {
|
|||||||
function down() {
|
function down() {
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
|
|
||||||
$drop_table = function($model) {
|
$drop_table = function($model) use($wpdb) {
|
||||||
$table = $this->prefix . $model;
|
$table = $this->prefix . $model;
|
||||||
$wpdb->query("DROP TABLE {$table}");
|
$wpdb->query("DROP TABLE {$table}");
|
||||||
};
|
};
|
||||||
@ -236,10 +236,7 @@ class Migrator {
|
|||||||
'newsletter_id mediumint(9) NOT NULL,',
|
'newsletter_id mediumint(9) NOT NULL,',
|
||||||
'subscriber_id mediumint(9) NOT NULL,',
|
'subscriber_id mediumint(9) NOT NULL,',
|
||||||
'queue_id mediumint(9) NOT NULL,',
|
'queue_id mediumint(9) NOT NULL,',
|
||||||
'sent_at TIMESTAMP NOT NULL DEFAULT 0,',
|
'sent_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
|
||||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
|
||||||
'deleted_at TIMESTAMP NULL DEFAULT NULL,',
|
|
||||||
'PRIMARY KEY (id)',
|
'PRIMARY KEY (id)',
|
||||||
);
|
);
|
||||||
return $this->sqlify(__FUNCTION__, $attributes);
|
return $this->sqlify(__FUNCTION__, $attributes);
|
||||||
|
@ -8,6 +8,7 @@ use MailPoet\Config\PopulatorData\Templates\PostNotificationsBlankTemplate;
|
|||||||
use \MailPoet\Models\Segment;
|
use \MailPoet\Models\Segment;
|
||||||
use \MailPoet\Segments\WP;
|
use \MailPoet\Segments\WP;
|
||||||
use \MailPoet\Models\Setting;
|
use \MailPoet\Models\Setting;
|
||||||
|
use \MailPoet\Settings\Pages;
|
||||||
|
|
||||||
if (!defined('ABSPATH')) exit;
|
if (!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
@ -48,6 +49,29 @@ class Populator {
|
|||||||
|
|
||||||
$this->createDefaultSegments();
|
$this->createDefaultSegments();
|
||||||
$this->createDefaultSettings();
|
$this->createDefaultSettings();
|
||||||
|
$this->createMailPoetPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createMailPoetPage() {
|
||||||
|
$pages = get_posts(array(
|
||||||
|
'posts_per_page' => 1,
|
||||||
|
'orderby' => 'date',
|
||||||
|
'order' => 'DESC',
|
||||||
|
'post_type' => 'mailpoet_page'
|
||||||
|
));
|
||||||
|
|
||||||
|
$page = null;
|
||||||
|
if(!empty($pages)) {
|
||||||
|
$page = array_shift($pages);
|
||||||
|
if(strpos($page->post_content, '[mailpoet_page]') === false) {
|
||||||
|
$page = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($page === null) {
|
||||||
|
$mailpoet_page_id = Pages::createMailPoetPage();
|
||||||
|
Setting::setValue('subscription.page', $mailpoet_page_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createDefaultSettings() {
|
private function createDefaultSettings() {
|
||||||
@ -72,6 +96,9 @@ class Populator {
|
|||||||
'name' => $user_name,
|
'name' => $user_name,
|
||||||
'address' => $current_user->user_email
|
'address' => $current_user->user_email
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// enable signup confirmation by default
|
||||||
|
Setting::setValue('signup_confirmation.enabled', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createDefaultSegments() {
|
private function createDefaultSegments() {
|
||||||
|
@ -179,7 +179,7 @@ class BlankTemplate {
|
|||||||
),
|
),
|
||||||
"h1" => array(
|
"h1" => array(
|
||||||
"fontColor" => "#111111",
|
"fontColor" => "#111111",
|
||||||
"fontFamily" => "Arial Black",
|
"fontFamily" => "Arial",
|
||||||
"fontSize" => "24px"
|
"fontSize" => "24px"
|
||||||
),
|
),
|
||||||
"h2" => array(
|
"h2" => array(
|
||||||
|
@ -68,7 +68,7 @@ class FranksRoastHouseTemplate {
|
|||||||
"link" => "http://www.example.com",
|
"link" => "http://www.example.com",
|
||||||
"src" => $this->template_image_url . "/header-v2.jpg",
|
"src" => $this->template_image_url . "/header-v2.jpg",
|
||||||
"alt" => __("Frank's Roast House"),
|
"alt" => __("Frank's Roast House"),
|
||||||
"padded" => false,
|
"fullWidth" => true,
|
||||||
"width" => "600px",
|
"width" => "600px",
|
||||||
"height" => "220px",
|
"height" => "220px",
|
||||||
"styles" => array(
|
"styles" => array(
|
||||||
@ -95,7 +95,7 @@ class FranksRoastHouseTemplate {
|
|||||||
"link" => "http://example.org",
|
"link" => "http://example.org",
|
||||||
"src" => $this->template_image_url . "/coffee-grain.jpg",
|
"src" => $this->template_image_url . "/coffee-grain.jpg",
|
||||||
"alt" => __("coffee-grain-3-1329675-1599x941"),
|
"alt" => __("coffee-grain-3-1329675-1599x941"),
|
||||||
"padded" => true,
|
"fullWidth" => false,
|
||||||
"width" => "1599px",
|
"width" => "1599px",
|
||||||
"height" => "777px",
|
"height" => "777px",
|
||||||
"styles" => array(
|
"styles" => array(
|
||||||
@ -139,7 +139,7 @@ class FranksRoastHouseTemplate {
|
|||||||
"link" => "http://example.org",
|
"link" => "http://example.org",
|
||||||
"src" => $this->template_image_url . "/sandwich.jpg",
|
"src" => $this->template_image_url . "/sandwich.jpg",
|
||||||
"alt" => "sandwich",
|
"alt" => "sandwich",
|
||||||
"padded" => true,
|
"fullWidth" => false,
|
||||||
"width" => "640px",
|
"width" => "640px",
|
||||||
"height" => "344px",
|
"height" => "344px",
|
||||||
"styles" => array(
|
"styles" => array(
|
||||||
@ -238,7 +238,7 @@ class FranksRoastHouseTemplate {
|
|||||||
"link" => "http://example.org",
|
"link" => "http://example.org",
|
||||||
"src" => $this->template_image_url . "/map-v2.jpg",
|
"src" => $this->template_image_url . "/map-v2.jpg",
|
||||||
"alt" => __("map-v2"),
|
"alt" => __("map-v2"),
|
||||||
"padded" => true,
|
"fullWidth" => false,
|
||||||
"width" => "636px",
|
"width" => "636px",
|
||||||
"height" => "342px",
|
"height" => "342px",
|
||||||
"styles" => array(
|
"styles" => array(
|
||||||
@ -279,19 +279,19 @@ class FranksRoastHouseTemplate {
|
|||||||
"blocks" => array(
|
"blocks" => array(
|
||||||
array(
|
array(
|
||||||
"type" => "footer",
|
"type" => "footer",
|
||||||
"text" => __("<p><span style=\"color: #000000;\"><a href=\"[unsubscribeUrl]\" style=\"color: #000000;\">Unsubscribe</a> | <a href=\"[manageSubscriptionUrl]\" style=\"color: #000000;\">Manage subscription</a></span><br /><span style=\"color: #000000;\">12345 MailPoet Drive, EmailVille, 76543</span></p>"),
|
"text" => __("<p><a href=\"[unsubscribeUrl]\">Unsubscribe</a> | <a href=\"[manageSubscriptionUrl]\">Manage subscription</a><br />12345 MailPoet Drive, EmailVille, 76543</p>"),
|
||||||
"styles" => array(
|
"styles" => array(
|
||||||
"block" => array(
|
"block" => array(
|
||||||
"backgroundColor" => "#a9a7a7"
|
"backgroundColor" => "#a9a7a7"
|
||||||
),
|
),
|
||||||
"text" => array(
|
"text" => array(
|
||||||
"fontColor" => "#ffffff",
|
"fontColor" => "#000000",
|
||||||
"fontFamily" => "Arial",
|
"fontFamily" => "Arial",
|
||||||
"fontSize" => "12px",
|
"fontSize" => "12px",
|
||||||
"textAlign" => "center"
|
"textAlign" => "center"
|
||||||
),
|
),
|
||||||
"link" => array(
|
"link" => array(
|
||||||
"fontColor" => "#ffffff",
|
"fontColor" => "#000000",
|
||||||
"textDecoration" => "underline"
|
"textDecoration" => "underline"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -90,7 +90,7 @@ class PostNotificationsBlankTemplate {
|
|||||||
"link" => "http://example.org",
|
"link" => "http://example.org",
|
||||||
"src" => $this->template_image_url . "/ALC-widget-icon.png",
|
"src" => $this->template_image_url . "/ALC-widget-icon.png",
|
||||||
"alt" => __("ALC-widget-icon"),
|
"alt" => __("ALC-widget-icon"),
|
||||||
"padded" => true,
|
"fullWidth" => false,
|
||||||
"width" => "200px",
|
"width" => "200px",
|
||||||
"height" => "134px",
|
"height" => "134px",
|
||||||
"styles" => array(
|
"styles" => array(
|
||||||
|
@ -68,7 +68,7 @@ class WelcomeTemplate {
|
|||||||
"link" => "http://example.org",
|
"link" => "http://example.org",
|
||||||
"src" => $this->template_image_url . "/logo-header.gif",
|
"src" => $this->template_image_url . "/logo-header.gif",
|
||||||
"alt" => "logo-header",
|
"alt" => "logo-header",
|
||||||
"padded" => true,
|
"fullWidth" => false,
|
||||||
"width" => "233px",
|
"width" => "233px",
|
||||||
"height" => "118px",
|
"height" => "118px",
|
||||||
"styles" => array(
|
"styles" => array(
|
||||||
|
@ -7,15 +7,20 @@ use MailPoet\Util\Helpers;
|
|||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class PublicAPI {
|
class PublicAPI {
|
||||||
|
public $api;
|
||||||
|
public $section;
|
||||||
|
public $action;
|
||||||
|
public $request_payload;
|
||||||
|
|
||||||
function __construct() {
|
function __construct() {
|
||||||
# http://example.com/?mailpoet-api§ion=&action=&payload=
|
# http://example.com/?mailpoet-api§ion=&action=&request_payload=
|
||||||
$this->api = isset($_GET['mailpoet-api']) ? true : false;
|
$this->api = isset($_GET['mailpoet-api']) ? true : false;
|
||||||
$this->section = isset($_GET['section']) ? $_GET['section'] : false;
|
$this->section = isset($_GET['section']) ? $_GET['section'] : false;
|
||||||
$this->action = isset($_GET['action']) ?
|
$this->action = isset($_GET['action']) ?
|
||||||
Helpers::underscoreToCamelCase($_GET['action']) :
|
Helpers::underscoreToCamelCase($_GET['action']) :
|
||||||
false;
|
false;
|
||||||
$this->payload = isset($_GET['payload']) ?
|
$this->request_payload = isset($_GET['request_payload']) ?
|
||||||
json_decode(urldecode($_GET['payload']), true) :
|
unserialize(base64_decode($_GET['request_payload'])) :
|
||||||
false;
|
false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,10 +31,9 @@ class PublicAPI {
|
|||||||
|
|
||||||
function queue() {
|
function queue() {
|
||||||
try {
|
try {
|
||||||
$queue = new Daemon($this->payload);
|
$queue = new Daemon($this->request_payload);
|
||||||
$this->_checkAndCallMethod($queue, $this->action);
|
$this->_checkAndCallMethod($queue, $this->action);
|
||||||
} catch(\Exception $e) {
|
} catch(\Exception $e) {
|
||||||
// mailer configuration error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Config;
|
namespace MailPoet\Config;
|
||||||
|
use \MailPoet\Models\Newsletter;
|
||||||
|
use \MailPoet\Models\Subscriber;
|
||||||
|
use \MailPoet\Models\SubscriberSegment;
|
||||||
|
|
||||||
class Shortcodes {
|
class Shortcodes {
|
||||||
function __construct() {
|
function __construct() {
|
||||||
@ -9,6 +12,26 @@ class Shortcodes {
|
|||||||
// form widget shortcode
|
// form widget shortcode
|
||||||
add_shortcode('mailpoet_form', array($this, 'formWidget'));
|
add_shortcode('mailpoet_form', array($this, 'formWidget'));
|
||||||
add_shortcode('wysija_form', array($this, 'formWidget'));
|
add_shortcode('wysija_form', array($this, 'formWidget'));
|
||||||
|
|
||||||
|
// subscribers count shortcode
|
||||||
|
add_shortcode('mailpoet_subscribers_count', array(
|
||||||
|
$this, 'getSubscribersCount'
|
||||||
|
));
|
||||||
|
add_shortcode('wysija_subscribers_count', array(
|
||||||
|
$this, 'getSubscribersCount'
|
||||||
|
));
|
||||||
|
|
||||||
|
// archives page
|
||||||
|
add_shortcode('mailpoet_archive', array(
|
||||||
|
$this, 'getArchive'
|
||||||
|
));
|
||||||
|
|
||||||
|
add_filter('mailpoet_archive_date', array(
|
||||||
|
$this, 'renderArchiveDate'
|
||||||
|
), 2);
|
||||||
|
add_filter('mailpoet_archive_subject', array(
|
||||||
|
$this, 'renderArchiveSubject'
|
||||||
|
), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function formWidget($params = array()) {
|
function formWidget($params = array()) {
|
||||||
@ -23,4 +46,76 @@ class Shortcodes {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSubscribersCount($params) {
|
||||||
|
if(!empty($params['segments'])) {
|
||||||
|
$segment_ids = array_map(function($segment_id) {
|
||||||
|
return (int)trim($segment_id);
|
||||||
|
}, explode(',', $params['segments']));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(empty($segment_ids)) {
|
||||||
|
return Subscriber::filter('subscribed')->count();
|
||||||
|
} else {
|
||||||
|
return SubscriberSegment::whereIn('segment_id', $segment_ids)
|
||||||
|
->select('subscriber_id')->distinct()
|
||||||
|
->filter('subscribed')
|
||||||
|
->findResultSet()->count();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getArchive($params) {
|
||||||
|
if(!empty($params['segments'])) {
|
||||||
|
$segment_ids = array_map(function($segment_id) {
|
||||||
|
return (int)trim($segment_id);
|
||||||
|
}, explode(',', $params['segments']));
|
||||||
|
}
|
||||||
|
|
||||||
|
$newsletters = array();
|
||||||
|
$html = '';
|
||||||
|
|
||||||
|
// TODO: needs more advanced newsletters in order to finish
|
||||||
|
$newsletters = Newsletter::limit(10)->orderByDesc('created_at')->findMany();
|
||||||
|
|
||||||
|
if(empty($newsletters)) {
|
||||||
|
return apply_filters(
|
||||||
|
'mailpoet_archive_no_newsletters',
|
||||||
|
__('Oops! There are no newsletters to display.')
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$title = apply_filters('mailpoet_archive_title', '');
|
||||||
|
if(!empty($title)) {
|
||||||
|
$html .= '<h3 class="mailpoet_archive_title">'.$title.'</h3>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$html .= '<ul class="mailpoet_archive">';
|
||||||
|
foreach($newsletters as $newsletter) {
|
||||||
|
$html .= '<li>'.
|
||||||
|
'<span class="mailpoet_archive_date">'.
|
||||||
|
apply_filters('mailpoet_archive_date', $newsletter).
|
||||||
|
'</span>
|
||||||
|
<span class="mailpoet_archive_subject">'.
|
||||||
|
apply_filters('mailpoet_archive_subject', $newsletter).
|
||||||
|
'</span>
|
||||||
|
</li>';
|
||||||
|
}
|
||||||
|
$html .= '</ul>';
|
||||||
|
}
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderArchiveDate($newsletter) {
|
||||||
|
return date_i18n(
|
||||||
|
get_option('date_format'),
|
||||||
|
strtotime($newsletter->created_at)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderArchiveSubject($newsletter) {
|
||||||
|
return '<a href="TODO" target="_blank" title="'
|
||||||
|
.esc_attr(__('Preview in new tab')).'">'
|
||||||
|
.esc_attr($newsletter->subject).
|
||||||
|
'</a>';
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Config;
|
namespace MailPoet\Config;
|
||||||
use \MailPoet\Models\Subscriber;
|
|
||||||
use \MailPoet\Util\Security;
|
use \MailPoet\Util\Security;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
@ -10,30 +9,17 @@ class Widget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
add_action('widgets_init', array($this, 'registerWidget'));
|
$this->registerWidget();
|
||||||
|
|
||||||
if(!is_admin()) {
|
if(!is_admin()) {
|
||||||
//$this->setupActions();
|
$this->setupDependencies();
|
||||||
add_action('widgets_init', array($this, 'setupDependencies'));
|
|
||||||
} else {
|
} else {
|
||||||
add_action('widgets_init', array($this, 'setupAdminDependencies'));
|
$this->setupAdminDependencies();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerWidget() {
|
function registerWidget() {
|
||||||
register_widget('\MailPoet\Form\Widget');
|
register_widget('\MailPoet\Form\Widget');
|
||||||
|
|
||||||
// subscribers count shortcode
|
|
||||||
add_shortcode('mailpoet_subscribers_count', array(
|
|
||||||
$this, 'getSubscribersCount'
|
|
||||||
));
|
|
||||||
add_shortcode('wysija_subscribers_count', array(
|
|
||||||
$this, 'getSubscribersCount'
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSubscribersCount($params) {
|
|
||||||
return Subscriber::filter('subscribed')->count();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupDependencies() {
|
function setupDependencies() {
|
||||||
@ -82,6 +68,9 @@ class Widget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: extract this method into an Initializer
|
||||||
|
// - the "ajax" part might probably be useless
|
||||||
|
// - the "post" (non-ajax) part needs to be redone properly
|
||||||
function setupActions() {
|
function setupActions() {
|
||||||
// ajax requests
|
// ajax requests
|
||||||
add_action(
|
add_action(
|
||||||
|
71
lib/Cron/CronHelper.php
Normal file
71
lib/Cron/CronHelper.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Cron;
|
||||||
|
|
||||||
|
use MailPoet\Models\Setting;
|
||||||
|
use MailPoet\Util\Security;
|
||||||
|
|
||||||
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class CronHelper {
|
||||||
|
const daemon_execution_limit = 20;
|
||||||
|
const daemon_execution_timeout = 35;
|
||||||
|
const daemon_request_timeout = 2;
|
||||||
|
|
||||||
|
static function createDaemon($token) {
|
||||||
|
$daemon = array(
|
||||||
|
'status' => 'starting',
|
||||||
|
'counter' => 0,
|
||||||
|
'token' => $token
|
||||||
|
);
|
||||||
|
self::saveDaemon($daemon);
|
||||||
|
return $daemon;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function getDaemon() {
|
||||||
|
return Setting::getValue('cron_daemon');
|
||||||
|
}
|
||||||
|
|
||||||
|
static function saveDaemon($daemon) {
|
||||||
|
$daemon['updated_at'] = time();
|
||||||
|
return Setting::setValue(
|
||||||
|
'cron_daemon',
|
||||||
|
$daemon
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function createToken() {
|
||||||
|
return Security::generateRandomString();
|
||||||
|
}
|
||||||
|
|
||||||
|
static function accessDaemon($token, $timeout = self::daemon_request_timeout) {
|
||||||
|
$payload = serialize(array('token' => $token));
|
||||||
|
$url = '/?mailpoet-api§ion=queue&action=run&request_payload=' .
|
||||||
|
base64_encode($payload);
|
||||||
|
$args = array(
|
||||||
|
'timeout' => $timeout,
|
||||||
|
'user-agent' => 'MailPoet (www.mailpoet.com) Cron'
|
||||||
|
);
|
||||||
|
$result = wp_remote_get(
|
||||||
|
self::getSiteUrl() . $url,
|
||||||
|
$args
|
||||||
|
);
|
||||||
|
return wp_remote_retrieve_body($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getSiteUrl() {
|
||||||
|
// additional check for some sites running on a virtual machine or behind
|
||||||
|
// proxy where there could be different ports (e.g., host:8080 => guest:80)
|
||||||
|
|
||||||
|
// if the site URL does not contain a port, return the URL
|
||||||
|
if(!preg_match('!^https?://.*?:\d+!', site_url())) return site_url();
|
||||||
|
preg_match('!://(?P<host>.*?):(?P<port>\d+)!', site_url(), $server);
|
||||||
|
// connect to the URL with port
|
||||||
|
$fp = @fsockopen($server['host'], $server['port'], $errno, $errstr, 1);
|
||||||
|
if($fp) return site_url();
|
||||||
|
// connect to the URL without port
|
||||||
|
$fp = @fsockopen($server['host'], $server['port'], $errno, $errstr, 1);
|
||||||
|
if($fp) return preg_replace('!(?=:\d+):\d+!', '$1', site_url());
|
||||||
|
// throw an error if all connection attempts failed
|
||||||
|
throw new \Exception(__('Site URL is unreachable.'));
|
||||||
|
}
|
||||||
|
}
|
@ -2,131 +2,78 @@
|
|||||||
namespace MailPoet\Cron;
|
namespace MailPoet\Cron;
|
||||||
|
|
||||||
use MailPoet\Cron\Workers\SendingQueue;
|
use MailPoet\Cron\Workers\SendingQueue;
|
||||||
use MailPoet\Models\Setting;
|
|
||||||
use MailPoet\Util\Security;
|
|
||||||
|
|
||||||
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class Daemon {
|
class Daemon {
|
||||||
function __construct($payload = array()) {
|
public $daemon;
|
||||||
|
public $request_payload;
|
||||||
|
public $refreshed_token;
|
||||||
|
const daemon_request_timeout = 5;
|
||||||
|
private $timer;
|
||||||
|
|
||||||
|
function __construct($request_payload = array()) {
|
||||||
set_time_limit(0);
|
set_time_limit(0);
|
||||||
ignore_user_abort();
|
ignore_user_abort();
|
||||||
list ($this->daemon, $this->daemonData) = $this->getDaemon();
|
$this->daemon = CronHelper::getDaemon();
|
||||||
$this->refreshedToken = $this->refreshToken();
|
$this->token = CronHelper::createToken();
|
||||||
$this->payload = $payload;
|
$this->request_payload = $request_payload;
|
||||||
$this->timer = microtime(true);
|
$this->timer = microtime(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function start() {
|
|
||||||
if(!isset($this->payload['session'])) {
|
|
||||||
$this->abortWithError('missing session ID');
|
|
||||||
}
|
|
||||||
$this->manageSession('start');
|
|
||||||
$daemon = $this->daemon;
|
|
||||||
$daemonData = $this->daemonData;
|
|
||||||
if(!$daemon) {
|
|
||||||
$daemon = Setting::create();
|
|
||||||
$daemon->name = 'cron_daemon';
|
|
||||||
$daemonData = array(
|
|
||||||
'status' => null,
|
|
||||||
'counter' => 0
|
|
||||||
);
|
|
||||||
$daemon->value = json_encode($daemonData);
|
|
||||||
$daemon->save();
|
|
||||||
}
|
|
||||||
if($daemonData['status'] !== 'started') {
|
|
||||||
$_SESSION['cron_daemon'] = 'started';
|
|
||||||
$daemonData['status'] = 'started';
|
|
||||||
$daemonData['token'] = $this->refreshedToken;
|
|
||||||
$_SESSION['cron_daemon'] = array('result' => true);
|
|
||||||
$this->manageSession('end');
|
|
||||||
$daemon->value = json_encode($daemonData);
|
|
||||||
$daemon->save();
|
|
||||||
$this->callSelf();
|
|
||||||
} else {
|
|
||||||
$_SESSION['cron_daemon'] = array(
|
|
||||||
'result' => false,
|
|
||||||
'error' => 'already started'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$this->manageSession('end');
|
|
||||||
}
|
|
||||||
|
|
||||||
function run() {
|
function run() {
|
||||||
if(!$this->daemon || $this->daemonData['status'] !== 'started') {
|
$daemon = $this->daemon;
|
||||||
$this->abortWithError('not running');
|
if(!$daemon) {
|
||||||
|
$this->abortWithError(__('Daemon does not exist.'));
|
||||||
}
|
}
|
||||||
if(!isset($this->payload['token']) ||
|
if(!isset($this->request_payload['token']) ||
|
||||||
$this->payload['token'] !== $this->daemonData['token']
|
$this->request_payload['token'] !== $daemon['token']
|
||||||
) {
|
) {
|
||||||
$this->abortWithError('invalid token');
|
$this->abortWithError(__('Invalid or missing token.'));
|
||||||
}
|
}
|
||||||
|
$this->abortIfStopped($daemon);
|
||||||
try {
|
try {
|
||||||
$sendingQueue = new SendingQueue($this->timer);
|
$sending_queue = new SendingQueue($this->timer);
|
||||||
$sendingQueue->process();
|
$sending_queue->process();
|
||||||
} catch(Exception $e) {
|
} catch(\Exception $e) {
|
||||||
}
|
}
|
||||||
|
$elapsed_time = microtime(true) - $this->timer;
|
||||||
$elapsedTime = microtime(true) - $this->timer;
|
if($elapsed_time < CronHelper::daemon_execution_limit) {
|
||||||
if($elapsedTime < 30) {
|
sleep(CronHelper::daemon_execution_limit - $elapsed_time);
|
||||||
sleep(30 - $elapsedTime);
|
|
||||||
}
|
}
|
||||||
|
// after each execution, re-read daemon data in case it was deleted or
|
||||||
// after each execution, read daemon in case it's status was modified
|
// its status has changed
|
||||||
list($daemon, $daemonData) = $this->getDaemon();
|
$daemon = CronHelper::getDaemon();
|
||||||
$daemonData['counter']++;
|
if(!$daemon || $daemon['token'] !== $this->request_payload['token']) {
|
||||||
$daemonData['token'] = $this->refreshedToken;
|
exit;
|
||||||
$daemon->value = json_encode($daemonData);
|
}
|
||||||
$daemon->save();
|
$daemon['counter']++;
|
||||||
if($daemonData['status'] === 'strated') $this->callSelf();
|
$this->abortIfStopped($daemon);
|
||||||
|
if($daemon['status'] === 'starting') {
|
||||||
|
$daemon['status'] = 'started';
|
||||||
|
}
|
||||||
|
$daemon['token'] = $this->token;
|
||||||
|
CronHelper::saveDaemon($daemon);
|
||||||
|
$this->callSelf();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDaemon() {
|
function abortIfStopped($daemon) {
|
||||||
$daemon = Setting::where('name', 'cron_daemon')
|
if($daemon['status'] === 'stopped') exit;
|
||||||
->findOne();
|
if($daemon['status'] === 'stopping') {
|
||||||
return array(
|
$daemon['status'] = 'stopped';
|
||||||
($daemon) ? $daemon : null,
|
CronHelper::saveDaemon($daemon);
|
||||||
($daemon) ? json_decode($daemon->value, true) : null
|
exit;
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function refreshToken() {
|
|
||||||
return Security::generateRandomString();
|
|
||||||
}
|
|
||||||
|
|
||||||
function manageSession($action) {
|
|
||||||
switch($action) {
|
|
||||||
case 'start':
|
|
||||||
if(session_id()) {
|
|
||||||
session_write_close();
|
|
||||||
}
|
|
||||||
session_id($this->payload['session']);
|
|
||||||
session_start();
|
|
||||||
break;
|
|
||||||
case 'end':
|
|
||||||
session_write_close();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function abortWithError($message) {
|
||||||
|
exit('[mailpoet_cron_error:' . base64_encode($message) . ']');
|
||||||
|
}
|
||||||
|
|
||||||
function callSelf() {
|
function callSelf() {
|
||||||
$payload = json_encode(array('token' => $this->refreshedToken));
|
CronHelper::accessDaemon($this->token, self::daemon_request_timeout);
|
||||||
Supervisor::getRemoteUrl(
|
|
||||||
'/?mailpoet-api§ion=queue&action=run&payload=' . urlencode($payload)
|
|
||||||
|
|
||||||
);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
function abortWithError($error) {
|
|
||||||
wp_send_json(
|
|
||||||
array(
|
|
||||||
'result' => false,
|
|
||||||
'error' => $error
|
|
||||||
));
|
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,84 +1,94 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Cron;
|
namespace MailPoet\Cron;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use MailPoet\Config\Env;
|
|
||||||
use MailPoet\Models\Setting;
|
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class Supervisor {
|
class Supervisor {
|
||||||
function __construct($forceStart = false) {
|
public $daemon;
|
||||||
$this->forceStart = $forceStart;
|
public $token;
|
||||||
if(!Env::isPluginActivated()) {
|
public $force_run;
|
||||||
throw new \Exception('Database has not been configured.');
|
|
||||||
}
|
function __construct($force_run = false) {
|
||||||
list ($this->daemon, $this->daemonData) = $this->getDaemon();
|
$this->daemon = CronHelper::getDaemon();
|
||||||
|
$this->token = CronHelper::createToken();
|
||||||
|
$this->force_run = $force_run;
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkDaemon() {
|
function checkDaemon() {
|
||||||
if(!$this->daemon) {
|
$daemon = $this->daemon;
|
||||||
return $this->startDaemon();
|
if(!$daemon) {
|
||||||
|
$daemon = CronHelper::createDaemon($this->token);
|
||||||
|
return $this->runDaemon($daemon);
|
||||||
}
|
}
|
||||||
if(!$this->forceStart && $this->daemonData['status'] === 'stopped') {
|
// if the daemon is stopped, return its status and do nothing
|
||||||
return;
|
if(!$this->force_run &&
|
||||||
|
isset($daemon['status']) &&
|
||||||
|
$daemon['status'] === 'stopped'
|
||||||
|
) {
|
||||||
|
return $this->formatDaemonStatusMessage($daemon['status']);
|
||||||
|
|
||||||
}
|
}
|
||||||
$currentTime = Carbon::now('UTC');
|
$elapsed_time = time() - (int) $daemon['updated_at'];
|
||||||
$lastUpdateTime = Carbon::createFromFormat(
|
// if it's been less than 40 seconds since last execution and we're not
|
||||||
'Y-m-d H:i:s',
|
// force-running the daemon, return its status and do nothing
|
||||||
$this->daemon->updated_at, 'UTC'
|
if($elapsed_time < CronHelper::daemon_execution_timeout && !$this->force_run) {
|
||||||
);
|
return $this->formatDaemonStatusMessage($daemon['status']);
|
||||||
$timeSinceLastStart = $currentTime->diffInSeconds($lastUpdateTime);
|
}
|
||||||
if($timeSinceLastStart < 40) return;
|
// if it's been less than 40 seconds since last execution, we are
|
||||||
$this->daemonData['status'] = null;
|
// force-running the daemon and it's either being started or stopped,
|
||||||
$this->daemon->value = json_encode($this->daemonData);
|
// return its status and do nothing
|
||||||
$this->daemon->save();
|
elseif($elapsed_time < CronHelper::daemon_execution_timeout &&
|
||||||
return $this->startDaemon();
|
$this->force_run &&
|
||||||
|
in_array($daemon['status'], array(
|
||||||
|
'stopping',
|
||||||
|
'starting'
|
||||||
|
))
|
||||||
|
) {
|
||||||
|
return $this->formatDaemonStatusMessage($daemon['status']);
|
||||||
|
}
|
||||||
|
// re-create (restart) daemon
|
||||||
|
CronHelper::createDaemon($this->token);
|
||||||
|
return $this->runDaemon();
|
||||||
}
|
}
|
||||||
|
|
||||||
function startDaemon() {
|
function runDaemon() {
|
||||||
if(!session_id()) session_start();
|
$request = CronHelper::accessDaemon($this->token);
|
||||||
$sessionId = session_id();
|
preg_match('/\[(mailpoet_cron_error:.*?)\]/i', $request, $status);
|
||||||
session_write_close();
|
$daemon = CronHelper::getDaemon();
|
||||||
$_SESSION['cron_daemon'] = null;
|
if(!empty($status) || !$daemon) {
|
||||||
$payload = json_encode(array('session' => $sessionId));
|
if(!$daemon) {
|
||||||
self::getRemoteUrl(
|
$message = __('Daemon failed to run.');
|
||||||
'/?mailpoet-api§ion=queue&action=start&payload=' . urlencode($payload)
|
} else {
|
||||||
);
|
list(, $message) = explode(':', $status[0]);
|
||||||
session_start();
|
$message = base64_decode($message);
|
||||||
$daemonStatus = $_SESSION['cron_daemon'];
|
}
|
||||||
unset($_SESSION['daemon']);
|
return $this->formatResultMessage(
|
||||||
session_write_close();
|
false,
|
||||||
return $daemonStatus;
|
$message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $this->formatDaemonStatusMessage($daemon['status']);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDaemon() {
|
private function formatDaemonStatusMessage($status) {
|
||||||
$daemon = Setting::where('name', 'cron_daemon')
|
return $this->formatResultMessage(
|
||||||
->findOne();
|
true,
|
||||||
$daemonData = ($daemon) ? json_decode($daemon->value, true) : false;
|
sprintf(
|
||||||
return array(
|
__('Daemon is currently %s.'),
|
||||||
$daemon,
|
__($status)
|
||||||
$daemonData
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static function getRemoteUrl($url) {
|
private function formatResultMessage($result, $message) {
|
||||||
$args = array(
|
$formattedResult = array(
|
||||||
'timeout' => 1,
|
'result' => $result
|
||||||
'user-agent' => 'MailPoet (www.mailpoet.com)'
|
|
||||||
);
|
);
|
||||||
wp_remote_get(
|
if(!$result) {
|
||||||
self::getSiteUrl() . $url,
|
$formattedResult['errors'] = array($message);
|
||||||
$args
|
} else {
|
||||||
);
|
$formattedResult['message'] = $message;
|
||||||
}
|
}
|
||||||
|
return $formattedResult;
|
||||||
static function getSiteUrl() {
|
|
||||||
if(preg_match('!:\d+/!', site_url())) return site_url();
|
|
||||||
preg_match('!http://(?P<host>.*?):(?P<port>\d+)!', site_url(), $server);
|
|
||||||
$fp = @fsockopen($server['host'], $server['port'], $errno, $errstr, 1);
|
|
||||||
return ($fp) ?
|
|
||||||
site_url() :
|
|
||||||
preg_replace('/(?=:\d+):\d+/', '$1', site_url());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,114 +1,269 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Cron\Workers;
|
namespace MailPoet\Cron\Workers;
|
||||||
|
|
||||||
|
use MailPoet\Cron\CronHelper;
|
||||||
|
use MailPoet\Mailer\Mailer;
|
||||||
use MailPoet\Models\Newsletter;
|
use MailPoet\Models\Newsletter;
|
||||||
use MailPoet\Models\NewsletterStatistics;
|
use MailPoet\Models\NewsletterStatistics;
|
||||||
|
use MailPoet\Models\Setting;
|
||||||
use MailPoet\Models\Subscriber;
|
use MailPoet\Models\Subscriber;
|
||||||
use MailPoet\Newsletter\Renderer\Renderer;
|
use MailPoet\Newsletter\Renderer\Renderer;
|
||||||
use MailPoet\Router\Mailer;
|
use MailPoet\Newsletter\Shortcodes\Shortcodes;
|
||||||
|
use MailPoet\Util\Helpers;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class SendingQueue {
|
class SendingQueue {
|
||||||
|
public $mta_config;
|
||||||
|
public $mta_log;
|
||||||
|
public $processing_method;
|
||||||
|
private $timer;
|
||||||
|
const batch_size = 50;
|
||||||
|
|
||||||
function __construct($timer = false) {
|
function __construct($timer = false) {
|
||||||
|
$this->mta_config = $this->getMailerConfig();
|
||||||
|
$this->mta_log = $this->getMailerLog();
|
||||||
|
$this->processing_method = ($this->mta_config['method'] === 'MailPoet') ?
|
||||||
|
'processBulkSubscribers' :
|
||||||
|
'processIndividualSubscriber';
|
||||||
$this->timer = ($timer) ? $timer : microtime(true);
|
$this->timer = ($timer) ? $timer : microtime(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function process() {
|
function process() {
|
||||||
$queues =
|
foreach($this->getQueues() as $queue) {
|
||||||
\MailPoet\Models\SendingQueue::orderByDesc('priority')
|
|
||||||
->whereNull('deleted_at')
|
|
||||||
->whereNull('status')
|
|
||||||
->findResultSet();
|
|
||||||
foreach($queues as $queue) {
|
|
||||||
$newsletter = Newsletter::findOne($queue->newsletter_id);
|
$newsletter = Newsletter::findOne($queue->newsletter_id);
|
||||||
if(!$newsletter) {
|
if(!$newsletter) {
|
||||||
continue;
|
continue;
|
||||||
};
|
}
|
||||||
|
$queue->subscribers = (object) unserialize($queue->subscribers);
|
||||||
|
if(!isset($queue->subscribers->processed)) {
|
||||||
|
$queue->subscribers->processed = array();
|
||||||
|
}
|
||||||
|
if(!isset($queue->subscribers->failed)) {
|
||||||
|
$queue->subscribers->failed = array();
|
||||||
|
}
|
||||||
$newsletter = $newsletter->asArray();
|
$newsletter = $newsletter->asArray();
|
||||||
$mailer = new Mailer($httpRequest = false);
|
$newsletter['body'] = $this->renderNewsletter($newsletter);
|
||||||
if(!empty($newsletter['sender_address']) &&
|
$mailer = $this->configureMailer($newsletter);
|
||||||
!empty($newsletter['sender_name'])
|
foreach(array_chunk($queue->subscribers->to_process, self::batch_size) as
|
||||||
) {
|
$subscribers_ids) {
|
||||||
$mailer->fromName = $newsletter['sender_name'];
|
$subscribers = Subscriber::whereIn('id', $subscribers_ids)
|
||||||
$mailer->fromEmail = $newsletter['sender_address'];
|
|
||||||
$mailer->fromNameEmail = sprintf(
|
|
||||||
'%s <%s>',
|
|
||||||
$mailer->fromName,
|
|
||||||
$mailer->fromEmail
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if(!empty($newsletter['reply_to_address']) &&
|
|
||||||
!empty($newsletter['reply_to_name'])
|
|
||||||
) {
|
|
||||||
$mailer->replyToName = $newsletter['reply_to_name'];
|
|
||||||
$mailer->replyToEmail = $newsletter['reply_to_address'];
|
|
||||||
$mailer->replyToNameEmail = sprintf(
|
|
||||||
'%s <%s>',
|
|
||||||
$mailer->replyToName,
|
|
||||||
$mailer->replyToEmail
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$mailer->mailer = $mailer->buildMailer();
|
|
||||||
$renderer = new Renderer(json_decode($newsletter['body'], true));
|
|
||||||
$newsletter = array(
|
|
||||||
'subject' => $newsletter['subject'],
|
|
||||||
'id' => $newsletter['id'],
|
|
||||||
'body' => array(
|
|
||||||
'html' => $renderer->renderAll(),
|
|
||||||
'text' => ''
|
|
||||||
// TODO: add text body
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$subscribers = json_decode($queue->subscribers, true);
|
|
||||||
$subscribersToProcess = $subscribers['to_process'];
|
|
||||||
if(!isset($subscribers['failed'])) $subscribers['failed'] = array();
|
|
||||||
if(!isset($subscribers['processed'])) $subscribers['processed'] = array();
|
|
||||||
foreach(array_chunk($subscribersToProcess, 200) as $subscriberIds) {
|
|
||||||
$dbSubscribers = Subscriber::whereIn('id', $subscriberIds)
|
|
||||||
->findArray();
|
->findArray();
|
||||||
foreach($dbSubscribers as $i => $dbSubscriber) {
|
$queue->subscribers = call_user_func_array(
|
||||||
$this->checkExecutionTimer();
|
array(
|
||||||
// TODO: replace shortcodes in the newsletter
|
$this,
|
||||||
$result = $mailer->mailer->send(
|
$this->processing_method
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
$mailer,
|
||||||
$newsletter,
|
$newsletter,
|
||||||
$mailer->transformSubscriber($dbSubscriber)
|
$subscribers,
|
||||||
);
|
$queue
|
||||||
$newsletterStatistics = NewsletterStatistics::create();
|
)
|
||||||
$newsletterStatistics->subscriber_id = $dbSubscriber['id'];
|
);
|
||||||
$newsletterStatistics->newsletter_id = $newsletter['id'];
|
|
||||||
$newsletterStatistics->queue_id = $queue->id;
|
|
||||||
$newsletterStatistics->save();
|
|
||||||
if($result) {
|
|
||||||
$subscribers['processed'][] = $dbSubscriber['id'];
|
|
||||||
} else {
|
|
||||||
$subscribers['failed'][] = $dbSubscriber['id'];
|
|
||||||
}
|
|
||||||
$subscribers['to_process'] = array_values(
|
|
||||||
array_diff(
|
|
||||||
$subscribers['to_process'],
|
|
||||||
array_merge($subscribers['processed'], $subscribers['failed'])
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$queue->count_processed =
|
|
||||||
count($subscribers['processed']) + count($subscribers['failed']);
|
|
||||||
$queue->count_to_process = count($subscribers['to_process']);
|
|
||||||
$queue->count_failed = count($subscribers['failed']);
|
|
||||||
$queue->count_total =
|
|
||||||
$queue->count_processed + $queue->count_to_process;
|
|
||||||
if(!$queue->count_to_process) {
|
|
||||||
$queue->processed_at = date('Y-m-d H:i:s');
|
|
||||||
$queue->status = 'completed';
|
|
||||||
}
|
|
||||||
$queue->subscribers = json_encode($subscribers);
|
|
||||||
$queue->save();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function processBulkSubscribers($mailer, $newsletter, $subscribers, $queue) {
|
||||||
|
foreach($subscribers as $subscriber) {
|
||||||
|
$processed_newsletters[] =
|
||||||
|
$this->processNewsletter($newsletter, $subscriber);
|
||||||
|
$transformed_subscribers[] =
|
||||||
|
$mailer->transformSubscriber($subscriber);
|
||||||
|
}
|
||||||
|
$result = $this->sendNewsletter(
|
||||||
|
$mailer,
|
||||||
|
$processed_newsletters,
|
||||||
|
$transformed_subscribers
|
||||||
|
);
|
||||||
|
$subscribers_ids = Helpers::arrayColumn($subscribers, 'id');
|
||||||
|
if(!$result) {
|
||||||
|
$queue->subscribers->failed = array_merge(
|
||||||
|
$queue->subscribers->failed,
|
||||||
|
$subscribers_ids
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$newsletter_statistics =
|
||||||
|
array_map(function ($data) use ($newsletter, $subscribers_ids, $queue) {
|
||||||
|
return array(
|
||||||
|
$newsletter['id'],
|
||||||
|
$subscribers_ids[$data],
|
||||||
|
$queue->id
|
||||||
|
);
|
||||||
|
}, range(0, count($transformed_subscribers) - 1));
|
||||||
|
$newsletter_statistics = Helpers::flattenArray($newsletter_statistics);
|
||||||
|
$this->updateMailerLog();
|
||||||
|
$this->updateNewsletterStatistics($newsletter_statistics);
|
||||||
|
$queue->subscribers->processed = array_merge(
|
||||||
|
$queue->subscribers->processed,
|
||||||
|
$subscribers_ids
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$this->updateQueue($queue);
|
||||||
|
$this->checkSendingLimit();
|
||||||
|
$this->checkExecutionTimer();
|
||||||
|
return $queue->subscribers;
|
||||||
|
}
|
||||||
|
|
||||||
|
function processIndividualSubscriber($mailer, $newsletter, $subscribers, $queue) {
|
||||||
|
foreach($subscribers as $subscriber) {
|
||||||
|
$this->checkSendingLimit();
|
||||||
|
$processed_newsletter = $this->processNewsletter($newsletter, $subscriber);
|
||||||
|
$transformed_subscriber = $mailer->transformSubscriber($subscriber);
|
||||||
|
$result = $this->sendNewsletter(
|
||||||
|
$mailer,
|
||||||
|
$processed_newsletter,
|
||||||
|
$transformed_subscriber
|
||||||
|
);
|
||||||
|
if(!$result) {
|
||||||
|
$queue->subscribers->failed[] = $subscriber['id'];;
|
||||||
|
} else {
|
||||||
|
$queue->subscribers->processed[] = $subscriber['id'];
|
||||||
|
$newsletter_statistics = array(
|
||||||
|
$newsletter['id'],
|
||||||
|
$subscriber['id'],
|
||||||
|
$queue->id
|
||||||
|
);
|
||||||
|
$this->updateMailerLog();
|
||||||
|
$this->updateNewsletterStatistics($newsletter_statistics);
|
||||||
|
}
|
||||||
|
$this->updateQueue($queue);
|
||||||
|
$this->checkExecutionTimer();
|
||||||
|
}
|
||||||
|
return $queue->subscribers;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateNewsletterStatistics($data) {
|
||||||
|
return NewsletterStatistics::createMultiple($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderNewsletter($newsletter) {
|
||||||
|
$renderer = new Renderer($newsletter);
|
||||||
|
return $renderer->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
function processNewsletter($newsletter, $subscriber = false) {
|
||||||
|
$divider = '***MailPoet***';
|
||||||
|
$shortcodes = new Shortcodes(
|
||||||
|
implode($divider, $newsletter['body']),
|
||||||
|
$newsletter,
|
||||||
|
$subscriber
|
||||||
|
);
|
||||||
|
list($newsletter['body']['html'], $newsletter['body']['text']) =
|
||||||
|
explode($divider, $shortcodes->replace());
|
||||||
|
return $newsletter;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendNewsletter($mailer, $newsletter, $subscriber) {
|
||||||
|
return $mailer->mailer_instance->send(
|
||||||
|
$newsletter,
|
||||||
|
$subscriber
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureMailer($newsletter) {
|
||||||
|
$sender['address'] = (!empty($newsletter['sender_address'])) ?
|
||||||
|
$newsletter['sender_address'] :
|
||||||
|
false;
|
||||||
|
$sender['name'] = (!empty($newsletter['sender_name'])) ?
|
||||||
|
$newsletter['sender_name'] :
|
||||||
|
false;
|
||||||
|
$reply_to['address'] = (!empty($newsletter['reply_to_address'])) ?
|
||||||
|
$newsletter['reply_to_address'] :
|
||||||
|
false;
|
||||||
|
$reply_to['name'] = (!empty($newsletter['reply_to_name'])) ?
|
||||||
|
$newsletter['reply_to_name'] :
|
||||||
|
false;
|
||||||
|
if(!$sender['address']) {
|
||||||
|
$sender = false;
|
||||||
|
}
|
||||||
|
if(!$reply_to['address']) {
|
||||||
|
$reply_to = false;
|
||||||
|
}
|
||||||
|
$mailer = new Mailer($method = false, $sender, $reply_to);
|
||||||
|
return $mailer;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getQueues() {
|
||||||
|
return \MailPoet\Models\SendingQueue::orderByDesc('priority')
|
||||||
|
->whereNull('deleted_at')
|
||||||
|
->whereNull('status')
|
||||||
|
->findResultSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateQueue($queue) {
|
||||||
|
$queue = clone($queue);
|
||||||
|
$queue->subscribers->to_process = array_diff(
|
||||||
|
$queue->subscribers->to_process,
|
||||||
|
array_merge(
|
||||||
|
$queue->subscribers->processed,
|
||||||
|
$queue->subscribers->failed
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$queue->subscribers->to_process = array_values($queue->subscribers->to_process);
|
||||||
|
$queue->count_processed =
|
||||||
|
count($queue->subscribers->processed) + count($queue->subscribers->failed);
|
||||||
|
$queue->count_to_process = count($queue->subscribers->to_process);
|
||||||
|
$queue->count_failed = count($queue->subscribers->failed);
|
||||||
|
$queue->count_total =
|
||||||
|
$queue->count_processed + $queue->count_to_process;
|
||||||
|
if(!$queue->count_to_process) {
|
||||||
|
$queue->processed_at = date('Y-m-d H:i:s');
|
||||||
|
$queue->status = 'completed';
|
||||||
|
}
|
||||||
|
$queue->subscribers = serialize((array) $queue->subscribers);
|
||||||
|
$queue->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateMailerLog() {
|
||||||
|
$this->mta_log['sent']++;
|
||||||
|
return Setting::setValue('mta_log', $this->mta_log);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMailerConfig() {
|
||||||
|
$mta_config = Setting::getValue('mta');
|
||||||
|
if(!$mta_config) {
|
||||||
|
throw new \Exception(__('Mailer is not configured.'));
|
||||||
|
}
|
||||||
|
return $mta_config;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMailerLog() {
|
||||||
|
$mta_log = Setting::getValue('mta_log');
|
||||||
|
if(!$mta_log) {
|
||||||
|
$mta_log = array(
|
||||||
|
'sent' => 0,
|
||||||
|
'started' => time()
|
||||||
|
);
|
||||||
|
Setting::setValue('mta_log', $mta_log);
|
||||||
|
}
|
||||||
|
return $mta_log;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkSendingLimit() {
|
||||||
|
$frequency_interval = (int) $this->mta_config['frequency']['interval'] * 60;
|
||||||
|
$frequency_limit = (int) $this->mta_config['frequency']['emails'];
|
||||||
|
$elapsed_time = time() - (int) $this->mta_log['started'];
|
||||||
|
if($this->mta_log['sent'] === $frequency_limit &&
|
||||||
|
$elapsed_time <= $frequency_interval
|
||||||
|
) {
|
||||||
|
throw new \Exception(__('Sending frequency limit reached.'));
|
||||||
|
}
|
||||||
|
if($elapsed_time > $frequency_interval) {
|
||||||
|
$this->mta_log = array(
|
||||||
|
'sent' => 0,
|
||||||
|
'started' => time()
|
||||||
|
);
|
||||||
|
Setting::setValue('mta_log', $this->mta_log);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
function checkExecutionTimer() {
|
function checkExecutionTimer() {
|
||||||
$elapsedTime = microtime(true) - $this->timer;
|
$elapsed_time = microtime(true) - $this->timer;
|
||||||
if($elapsedTime >= 28) throw new \Exception('Maximum execution time reached.');
|
if($elapsed_time >= CronHelper::daemon_execution_limit) {
|
||||||
|
throw new \Exception(__('Maximum execution time reached.'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,7 +13,9 @@ abstract class Base {
|
|||||||
if($block['id'] === 'segments') {
|
if($block['id'] === 'segments') {
|
||||||
$rules['required'] = true;
|
$rules['required'] = true;
|
||||||
$rules['mincheck'] = 1;
|
$rules['mincheck'] = 1;
|
||||||
$rules['error-message'] = __('You need to select a list');
|
$rules['group'] = $block['id'];
|
||||||
|
$rules['errors-container'] = '.mailpoet_error_'.$block['id'];
|
||||||
|
$rules['required-message'] = __('You need to select a list');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!empty($block['params']['required'])) {
|
if(!empty($block['params']['required'])) {
|
||||||
@ -29,7 +31,7 @@ abstract class Base {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($block['type'] === 'radio') {
|
if(in_array($block['type'], array('radio', 'checkbox'))) {
|
||||||
$rules['group'] = 'custom_field_'.$block['id'];
|
$rules['group'] = 'custom_field_'.$block['id'];
|
||||||
$rules['errors-container'] = '.mailpoet_error_'.$block['id'];
|
$rules['errors-container'] = '.mailpoet_error_'.$block['id'];
|
||||||
$rules['required-message'] = __('You need to select at least one option.');
|
$rules['required-message'] = __('You need to select at least one option.');
|
||||||
|
@ -9,15 +9,16 @@ class Checkbox extends Base {
|
|||||||
$field_name = static::getFieldName($block);
|
$field_name = static::getFieldName($block);
|
||||||
$field_validation = static::getInputValidation($block);
|
$field_validation = static::getInputValidation($block);
|
||||||
|
|
||||||
// TODO: check if it still makes sense
|
|
||||||
// create hidden default value
|
|
||||||
// $html .= '<input type="hidden"name="'.$field_name.'" value="0" '.static::getInputValidation($block).'/>';
|
|
||||||
|
|
||||||
$html .= '<p class="mailpoet_paragraph">';
|
$html .= '<p class="mailpoet_paragraph">';
|
||||||
|
|
||||||
$html .= static::renderLabel($block);
|
$html .= static::renderLabel($block);
|
||||||
|
|
||||||
foreach($block['params']['values'] as $option) {
|
$options = (!empty($block['params']['values'])
|
||||||
|
? $block['params']['values']
|
||||||
|
: array()
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach($options as $option) {
|
||||||
$html .= '<label class="mailpoet_checkbox_label">';
|
$html .= '<label class="mailpoet_checkbox_label">';
|
||||||
|
|
||||||
$html .= '<input type="checkbox" class="mailpoet_checkbox" ';
|
$html .= '<input type="checkbox" class="mailpoet_checkbox" ';
|
||||||
@ -35,6 +36,8 @@ class Checkbox extends Base {
|
|||||||
$html .= '</label>';
|
$html .= '</label>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$html .= '<span class="mailpoet_error_'.$block['id'].'"></span>';
|
||||||
|
|
||||||
$html .= '</p>';
|
$html .= '</p>';
|
||||||
|
|
||||||
return $html;
|
return $html;
|
||||||
|
@ -13,9 +13,12 @@ class Radio extends Base {
|
|||||||
|
|
||||||
$html .= static::renderLabel($block);
|
$html .= static::renderLabel($block);
|
||||||
|
|
||||||
$html .= '<span class="mailpoet_error_'.$block['id'].'"></span>';
|
$options = (!empty($block['params']['values'])
|
||||||
|
? $block['params']['values']
|
||||||
|
: array()
|
||||||
|
);
|
||||||
|
|
||||||
foreach($block['params']['values'] as $option) {
|
foreach($options as $option) {
|
||||||
$html .= '<label class="mailpoet_radio_label">';
|
$html .= '<label class="mailpoet_radio_label">';
|
||||||
|
|
||||||
$html .= '<input type="radio" class="mailpoet_radio" ';
|
$html .= '<input type="radio" class="mailpoet_radio" ';
|
||||||
@ -33,6 +36,8 @@ class Radio extends Base {
|
|||||||
$html .= '</label>';
|
$html .= '</label>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$html .= '<span class="mailpoet_error_'.$block['id'].'"></span>';
|
||||||
|
|
||||||
$html .= '</p>';
|
$html .= '</p>';
|
||||||
|
|
||||||
return $html;
|
return $html;
|
||||||
|
@ -13,23 +13,27 @@ class Segment extends Base {
|
|||||||
|
|
||||||
$html .= static::renderLabel($block);
|
$html .= static::renderLabel($block);
|
||||||
|
|
||||||
if(!empty($block['params']['values'])) {
|
$options = (!empty($block['params']['values'])
|
||||||
// display values
|
? $block['params']['values']
|
||||||
foreach($block['params']['values'] as $segment) {
|
: array()
|
||||||
if(!isset($segment['id']) || !isset($segment['name'])) continue;
|
);
|
||||||
|
|
||||||
$is_checked = (isset($segment['is_checked']) && $segment['is_checked']) ? 'checked="checked"' : '';
|
foreach($options as $option) {
|
||||||
|
if(!isset($option['id']) || !isset($option['name'])) continue;
|
||||||
|
|
||||||
$html .= '<label class="mailpoet_checkbox_label">';
|
$is_checked = (isset($option['is_checked']) && $option['is_checked']) ? 'checked="checked"' : '';
|
||||||
$html .= '<input type="checkbox" class="mailpoet_checkbox" ';
|
|
||||||
$html .= 'name="'.$field_name.'[]" ';
|
$html .= '<label class="mailpoet_checkbox_label">';
|
||||||
$html .= 'value="'.$segment['id'].'" '.$is_checked.' ';
|
$html .= '<input type="checkbox" class="mailpoet_checkbox" ';
|
||||||
$html .= $field_validation;
|
$html .= 'name="'.$field_name.'[]" ';
|
||||||
$html .= ' />'.$segment['name'];
|
$html .= 'value="'.$option['id'].'" '.$is_checked.' ';
|
||||||
$html .= '</label>';
|
$html .= $field_validation;
|
||||||
}
|
$html .= ' />'.$option['name'];
|
||||||
|
$html .= '</label>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$html .= '<span class="mailpoet_error_'.$block['id'].'"></span>';
|
||||||
|
|
||||||
$html .= '</p>';
|
$html .= '</p>';
|
||||||
|
|
||||||
return $html;
|
return $html;
|
||||||
|
@ -6,11 +6,11 @@ class Submit extends Base {
|
|||||||
static function render($block) {
|
static function render($block) {
|
||||||
$html = '';
|
$html = '';
|
||||||
|
|
||||||
$html .= '<input class="mailpoet_submit" type="submit" ';
|
$html .= '<p class="mailpoet_submit"><input type="submit" ';
|
||||||
|
|
||||||
$html .= 'value="'.static::getFieldLabel($block).'" ';
|
$html .= 'value="'.static::getFieldLabel($block).'" ';
|
||||||
|
|
||||||
$html .= '/>';
|
$html .= '/></p>';
|
||||||
|
|
||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Form\Block;
|
namespace MailPoet\Form\Block;
|
||||||
|
|
||||||
class Input extends Base {
|
class Text extends Base {
|
||||||
|
|
||||||
static function render($block) {
|
static function render($block) {
|
||||||
$type = 'text';
|
$type = 'text';
|
||||||
@ -15,7 +15,7 @@ class Input extends Base {
|
|||||||
|
|
||||||
$html .= static::renderLabel($block);
|
$html .= static::renderLabel($block);
|
||||||
|
|
||||||
$html .= '<input type="'.$type.'" class="mailpoet_input" ';
|
$html .= '<input type="'.$type.'" class="mailpoet_text" ';
|
||||||
|
|
||||||
$html .= 'name="'.static::getFieldName($block).'" ';
|
$html .= 'name="'.static::getFieldName($block).'" ';
|
||||||
|
|
@ -13,9 +13,11 @@ class Renderer {
|
|||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
static function renderStyles($form = array()) {
|
static function renderStyles($form = array(), $prefix = null) {
|
||||||
|
$styles = new Util\Styles(static::getStyles($form));
|
||||||
|
|
||||||
$html = '<style type="text/css">';
|
$html = '<style type="text/css">';
|
||||||
$html .= static::getStyles($form);
|
$html .= $styles->render($prefix);
|
||||||
$html .= '</style>';
|
$html .= '</style>';
|
||||||
|
|
||||||
return $html;
|
return $html;
|
||||||
@ -49,7 +51,7 @@ class Renderer {
|
|||||||
|
|
||||||
private static function renderBlock($block = array()) {
|
private static function renderBlock($block = array()) {
|
||||||
$html = '';
|
$html = '';
|
||||||
switch ($block['type']) {
|
switch($block['type']) {
|
||||||
case 'html':
|
case 'html':
|
||||||
$html .= Block\Html::render($block);
|
$html .= Block\Html::render($block);
|
||||||
break;
|
break;
|
||||||
@ -78,8 +80,8 @@ class Renderer {
|
|||||||
$html .= Block\Select::render($block);
|
$html .= Block\Select::render($block);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'input':
|
case 'text':
|
||||||
$html .= Block\Input::render($block);
|
$html .= Block\Text::render($block);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'textarea':
|
case 'textarea':
|
||||||
|
@ -101,7 +101,7 @@ EOL;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function stripComments($stylesheet) {
|
private function stripComments($stylesheet) {
|
||||||
// remove comments
|
// remove comments
|
||||||
return preg_replace('!/\*.*?\*/!s', '', $stylesheet);
|
return preg_replace('!/\*.*?\*/!s', '', $stylesheet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +111,6 @@ EOL;
|
|||||||
|
|
||||||
private function setStyles($styles) {
|
private function setStyles($styles) {
|
||||||
$this->_styles = $styles;
|
$this->_styles = $styles;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +65,8 @@ class Widget extends \WP_Widget {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$form_edit_url = admin_url('admin.php?page=mailpoet-form-editor&id=');
|
||||||
|
|
||||||
// set title
|
// set title
|
||||||
$title = isset($instance['title']) ? strip_tags($instance['title']) : '';
|
$title = isset($instance['title']) ? strip_tags($instance['title']) : '';
|
||||||
|
|
||||||
@ -102,8 +104,9 @@ class Widget extends \WP_Widget {
|
|||||||
endpoint: 'forms',
|
endpoint: 'forms',
|
||||||
action: 'create'
|
action: 'create'
|
||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
if(response !== false) {
|
if(response.result && response.form_id) {
|
||||||
window.location = response;
|
window.location =
|
||||||
|
"<?php echo $form_edit_url; ?>" + response.form_id;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
@ -151,12 +154,14 @@ class Widget extends \WP_Widget {
|
|||||||
$output = '';
|
$output = '';
|
||||||
|
|
||||||
if(!empty($body)) {
|
if(!empty($body)) {
|
||||||
|
$form_id = $this->id_base.'_'.$this->number;
|
||||||
|
|
||||||
$data = array(
|
$data = array(
|
||||||
'form_id' => $this->id_base.'_'.$this->number,
|
'form_id' => $form_id,
|
||||||
'form_type' => $form_type,
|
'form_type' => $form_type,
|
||||||
'form' => $form,
|
'form' => $form,
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'styles' => FormRenderer::renderStyles($form),
|
'styles' => FormRenderer::renderStyles($form, '#'.$form_id),
|
||||||
'html' => FormRenderer::renderHTML($form),
|
'html' => FormRenderer::renderHTML($form),
|
||||||
'before_widget' => (!empty($before_widget) ? $before_widget : ''),
|
'before_widget' => (!empty($before_widget) ? $before_widget : ''),
|
||||||
'after_widget' => (!empty($after_widget) ? $after_widget : ''),
|
'after_widget' => (!empty($after_widget) ? $after_widget : ''),
|
||||||
@ -194,96 +199,4 @@ class Widget extends \WP_Widget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// set the content filter to replace the shortcode
|
|
||||||
if(isset($_GET['mailpoet_page']) && strlen(trim($_GET['mailpoet_page'])) > 0) {
|
|
||||||
switch($_GET['mailpoet_page']) {
|
|
||||||
|
|
||||||
case 'mailpoet_form_iframe':
|
|
||||||
$id = (isset($_GET['mailpoet_form']) && (int)$_GET['mailpoet_form'] > 0) ? (int)$_GET['mailpoet_form'] : null;
|
|
||||||
$form = Form::findOne($id);
|
|
||||||
|
|
||||||
if($form !== false) {
|
|
||||||
// render form
|
|
||||||
$output = Util\Export::get('html', $form->asArray());
|
|
||||||
// $output = do_shortcode($output);
|
|
||||||
print $output;
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// add_filter('wp_title', 'mailpoet_meta_page_title'));
|
|
||||||
add_filter('the_title', 'mailpoet_page_title', 10, 2);
|
|
||||||
add_filter('the_content', 'mailpoet_page_content', 98, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function mailpoet_page_title($title = '', $id = null) {
|
|
||||||
// get signup confirmation page id
|
|
||||||
$signup_confirmation = Setting::getValue('signup_confirmation');
|
|
||||||
$page_id = $signup_confirmation['page'];
|
|
||||||
|
|
||||||
// check if we're on the signup confirmation page
|
|
||||||
if((int)$page_id === (int)$id) {
|
|
||||||
global $post;
|
|
||||||
|
|
||||||
// disable comments
|
|
||||||
$post->comment_status = 'close';
|
|
||||||
// disable password
|
|
||||||
$post->post_password = '';
|
|
||||||
|
|
||||||
$subscriber = null;
|
|
||||||
|
|
||||||
// get subscriber key from url
|
|
||||||
$subscriber_digest = (isset($_GET['mailpoet_key']) && strlen(trim($_GET['mailpoet_key'])) === 32) ? trim($_GET['mailpoet_key']) : null;
|
|
||||||
|
|
||||||
if($subscriber_digest !== null) {
|
|
||||||
// get subscriber
|
|
||||||
// TODO: change select() to selectOne() once it's implemented
|
|
||||||
$subscribers = $mailpoet->subscribers()->select(array(
|
|
||||||
'filter' => array(
|
|
||||||
'subscriber_digest' => $subscriber_digest
|
|
||||||
),
|
|
||||||
'limit' => 1
|
|
||||||
));
|
|
||||||
|
|
||||||
if(!empty($subscribers)) {
|
|
||||||
$subscriber = array_shift($subscribers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if we have a subscriber record
|
|
||||||
if($subscriber === null) {
|
|
||||||
return __('Your confirmation link expired, please subscribe again.');
|
|
||||||
} else {
|
|
||||||
// we have a subscriber, let's check its state
|
|
||||||
switch($subscriber['subscriber_state']) {
|
|
||||||
case MailPoetSubscribers::STATE_UNCONFIRMED:
|
|
||||||
case MailPoetSubscribers::STATE_UNSUBSCRIBED:
|
|
||||||
// set subscriber state as confirmed
|
|
||||||
$mailpoet->subscribers()->update(array(
|
|
||||||
'subscriber' => $subscriber['subscriber'],
|
|
||||||
'subscriber_state' => MailPoetSubscribers::STATE_SUBSCRIBED,
|
|
||||||
'subscriber_confirmed_at' => time()
|
|
||||||
));
|
|
||||||
return __("You've subscribed");
|
|
||||||
break;
|
|
||||||
case MailPoetSubscribers::STATE_SUBSCRIBED:
|
|
||||||
return __("You've already subscribed");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return $title;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function mailpoet_page_content($content = '') {
|
|
||||||
if(strpos($content, '[mailpoet_page]') !== FALSE) {
|
|
||||||
$content = str_replace('[mailpoet_page]', '', $content);
|
|
||||||
}
|
|
||||||
return $content;
|
|
||||||
}
|
}
|
@ -1,113 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace MailPoet\Mailer\API;
|
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
|
||||||
|
|
||||||
class AmazonSES {
|
|
||||||
function __construct($region, $accessKey, $secretKey, $from) {
|
|
||||||
$this->awsAccessKey = $accessKey;
|
|
||||||
$this->awsSecret_key = $secretKey;
|
|
||||||
$this->awsRegion = $region;
|
|
||||||
$this->awsEndpoint = sprintf('email.%s.amazonaws.com', $region);
|
|
||||||
$this->awsSigningAlgorithm = 'AWS4-HMAC-SHA256';
|
|
||||||
$this->awsService = 'ses';
|
|
||||||
$this->awsTerminationString = 'aws4_request';
|
|
||||||
$this->hashAlgorithm = 'sha256';
|
|
||||||
$this->url = 'https://' . $this->awsEndpoint;
|
|
||||||
$this->from = $from;
|
|
||||||
$this->date = gmdate('Ymd\THis\Z');
|
|
||||||
$this->dateWithoutTime = gmdate('Ymd');
|
|
||||||
}
|
|
||||||
|
|
||||||
function send($newsletter, $subscriber) {
|
|
||||||
$result = wp_remote_post(
|
|
||||||
$this->url,
|
|
||||||
$this->request($newsletter, $subscriber)
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
!is_wp_error($result) === true &&
|
|
||||||
wp_remote_retrieve_response_code($result) === 200
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBody($newsletter, $subscriber) {
|
|
||||||
$body = array(
|
|
||||||
'Action' => 'SendEmail',
|
|
||||||
'Version' => '2010-12-01',
|
|
||||||
'Source' => $this->from,
|
|
||||||
'Destination.ToAddresses.member.1' => $subscriber,
|
|
||||||
'Message.Subject.Data' => $newsletter['subject'],
|
|
||||||
'ReturnPath' => $this->from
|
|
||||||
);
|
|
||||||
if(!empty($newsletter['body']['html'])) {
|
|
||||||
$body['Message.Body.Html.Data'] = $newsletter['body']['html'];
|
|
||||||
}
|
|
||||||
if(!empty($newsletter['body']['text'])) {
|
|
||||||
$body['Message.Body.Text.Data'] = $newsletter['body']['text'];
|
|
||||||
}
|
|
||||||
return $body;
|
|
||||||
}
|
|
||||||
|
|
||||||
function request($newsletter, $subscriber) {
|
|
||||||
$body = $this->getBody($newsletter, $subscriber);
|
|
||||||
return array(
|
|
||||||
'timeout' => 10,
|
|
||||||
'httpversion' => '1.1',
|
|
||||||
'method' => 'POST',
|
|
||||||
'headers' => array(
|
|
||||||
'Host' => $this->awsEndpoint,
|
|
||||||
'Authorization' => $this->signRequest($body),
|
|
||||||
'X-Amz-Date' => $this->date
|
|
||||||
),
|
|
||||||
'body' => urldecode(http_build_query($body))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function signRequest($body) {
|
|
||||||
$stringToSign = $this->createStringToSign(
|
|
||||||
$this->getCredentialScope(),
|
|
||||||
$this->getCanonicalRequest($body)
|
|
||||||
);
|
|
||||||
$signature = hash_hmac($this->hashAlgorithm, $stringToSign, $this->getSigningKey());
|
|
||||||
|
|
||||||
return sprintf(
|
|
||||||
'%s Credential=%s/%s, SignedHeaders=host;x-amz-date, Signature=%s',
|
|
||||||
$this->awsSigningAlgorithm,
|
|
||||||
$this->awsAccessKey,
|
|
||||||
$this->getCredentialScope(),
|
|
||||||
$signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCredentialScope() {
|
|
||||||
return sprintf('%s/%s/%s/%s', $this->dateWithoutTime, $this->awsRegion, $this->awsService, $this->awsTerminationString);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCanonicalRequest($body) {
|
|
||||||
return implode("\n", array(
|
|
||||||
'POST',
|
|
||||||
'/',
|
|
||||||
'',
|
|
||||||
'host:' . $this->awsEndpoint,
|
|
||||||
'x-amz-date:' . $this->date,
|
|
||||||
'',
|
|
||||||
'host;x-amz-date',
|
|
||||||
hash($this->hashAlgorithm, urldecode(http_build_query($body)))
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
function createStringToSign($credentialScope, $canonicalRequest) {
|
|
||||||
return implode("\n", array(
|
|
||||||
$this->awsSigningAlgorithm,
|
|
||||||
$this->date,
|
|
||||||
$credentialScope,
|
|
||||||
hash($this->hashAlgorithm, $canonicalRequest)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSigningKey() {
|
|
||||||
$dateKey = hash_hmac($this->hashAlgorithm, $this->dateWithoutTime, 'AWS4' . $this->awsSecret_key, true);
|
|
||||||
$regionKey = hash_hmac($this->hashAlgorithm, $this->awsRegion, $dateKey, true);
|
|
||||||
$serviceKey = hash_hmac($this->hashAlgorithm, $this->awsService, $regionKey, true);
|
|
||||||
return hash_hmac($this->hashAlgorithm, $this->awsTerminationString, $serviceKey, true);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace MailPoet\Mailer\API;
|
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
|
||||||
|
|
||||||
class Mandrill {
|
|
||||||
function __construct($apiKey, $fromEmail, $fromName) {
|
|
||||||
$this->url = 'https://mandrillapp.com/api/1.0/messages/send.json';
|
|
||||||
$this->apiKey = $apiKey;
|
|
||||||
$this->fromName = $fromName;
|
|
||||||
$this->fromEmail = $fromEmail;
|
|
||||||
}
|
|
||||||
|
|
||||||
function send($newsletter, $subscriber) {
|
|
||||||
$result = wp_remote_post(
|
|
||||||
$this->url,
|
|
||||||
$this->request($newsletter, $this->processSubscriber($subscriber))
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
!is_wp_error($result) === true &&
|
|
||||||
!preg_match('!invalid!', $result['body']) === true &&
|
|
||||||
wp_remote_retrieve_response_code($result) === 200
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function processSubscriber($subscriber) {
|
|
||||||
preg_match('!(?P<name>.*?)\s<(?P<email>.*?)>!', $subscriber, $subscriberData);
|
|
||||||
if(!isset($subscriberData['email'])) {
|
|
||||||
$subscriberData = array(
|
|
||||||
'email' => $subscriber,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return array(
|
|
||||||
'email' => $subscriberData['email'],
|
|
||||||
'name' => (isset($subscriberData['name'])) ? $subscriberData['name'] : ''
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBody($newsletter, $subscriber) {
|
|
||||||
$body = array(
|
|
||||||
'key' => $this->apiKey,
|
|
||||||
'message' => array(
|
|
||||||
'from_email' => $this->fromEmail,
|
|
||||||
'from_name' => $this->fromName,
|
|
||||||
'to' => array($subscriber),
|
|
||||||
'subject' => $newsletter['subject']
|
|
||||||
),
|
|
||||||
'async' => false,
|
|
||||||
);
|
|
||||||
if(!empty($newsletter['body']['html'])) {
|
|
||||||
$body['message']['html'] = $newsletter['body']['html'];
|
|
||||||
}
|
|
||||||
if(!empty($newsletter['body']['text'])) {
|
|
||||||
$body['message']['text'] = $newsletter['body']['text'];
|
|
||||||
}
|
|
||||||
return $body;
|
|
||||||
}
|
|
||||||
|
|
||||||
function request($newsletter, $subscriber) {
|
|
||||||
$body = $this->getBody($newsletter, $subscriber);
|
|
||||||
return array(
|
|
||||||
'timeout' => 10,
|
|
||||||
'httpversion' => '1.0',
|
|
||||||
'method' => 'POST',
|
|
||||||
'headers' => array(
|
|
||||||
'Content-Type' => 'application/json'
|
|
||||||
),
|
|
||||||
'body' => json_encode($body)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace MailPoet\Mailer;
|
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
|
||||||
|
|
||||||
class MailPoet {
|
|
||||||
function __construct($apiKey, $fromEmail, $fromName) {
|
|
||||||
$this->url = 'https://bridge.mailpoet.com/api/messages';
|
|
||||||
$this->apiKey = $apiKey;
|
|
||||||
$this->fromEmail = $fromEmail;
|
|
||||||
$this->fromName = $fromName;
|
|
||||||
}
|
|
||||||
|
|
||||||
function send($newsletter, $subscriber) {
|
|
||||||
$result = wp_remote_post(
|
|
||||||
$this->url,
|
|
||||||
$this->request($newsletter, $this->processSubscriber($subscriber))
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
!is_wp_error($result) === true &&
|
|
||||||
wp_remote_retrieve_response_code($result) === 201
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function processSubscriber($subscriber) {
|
|
||||||
preg_match('!(?P<name>.*?)\s<(?P<email>.*?)>!', $subscriber, $subscriberData);
|
|
||||||
if(!isset($subscriberData['email'])) {
|
|
||||||
$subscriberData = array(
|
|
||||||
'email' => $subscriber,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return array(
|
|
||||||
'email' => $subscriberData['email'],
|
|
||||||
'name' => (isset($subscriberData['name'])) ? $subscriberData['name'] : ''
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBody($newsletter, $subscriber) {
|
|
||||||
$body = array(
|
|
||||||
'to' => (array(
|
|
||||||
'address' => $subscriber['email'],
|
|
||||||
'name' => $subscriber['name']
|
|
||||||
)),
|
|
||||||
'from' => (array(
|
|
||||||
'address' => $this->fromEmail,
|
|
||||||
'name' => $this->fromName
|
|
||||||
)),
|
|
||||||
'subject' => $newsletter['subject']
|
|
||||||
);
|
|
||||||
if(!empty($newsletter['body']['html'])) {
|
|
||||||
$body['html'] = $newsletter['body']['html'];
|
|
||||||
}
|
|
||||||
if(!empty($newsletter['body']['text'])) {
|
|
||||||
$body['text'] = $newsletter['body']['text'];
|
|
||||||
}
|
|
||||||
return $body;
|
|
||||||
}
|
|
||||||
|
|
||||||
function auth() {
|
|
||||||
return 'Basic ' . base64_encode('api:' . $this->apiKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
function request($newsletter, $subscriber) {
|
|
||||||
$body = array($this->getBody($newsletter, $subscriber));
|
|
||||||
return array(
|
|
||||||
'timeout' => 10,
|
|
||||||
'httpversion' => '1.0',
|
|
||||||
'method' => 'POST',
|
|
||||||
'headers' => array(
|
|
||||||
'Content-Type' => 'application/json',
|
|
||||||
'Authorization' => $this->auth()
|
|
||||||
),
|
|
||||||
'body' => $body
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
144
lib/Mailer/Mailer.php
Normal file
144
lib/Mailer/Mailer.php
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Mailer;
|
||||||
|
|
||||||
|
use MailPoet\Models\Setting;
|
||||||
|
|
||||||
|
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||||
|
|
||||||
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class Mailer {
|
||||||
|
public $mailer;
|
||||||
|
public $sender;
|
||||||
|
public $reply_to;
|
||||||
|
public $mailer_instance;
|
||||||
|
|
||||||
|
function __construct($mailer = false, $sender = false, $reply_to = false) {
|
||||||
|
$this->mailer = $this->getMailer($mailer);
|
||||||
|
$this->sender = $this->getSender($sender);
|
||||||
|
$this->reply_to = $this->getReplyTo($reply_to);
|
||||||
|
$this->mailer_instance = $this->buildMailer();
|
||||||
|
}
|
||||||
|
|
||||||
|
function send($newsletter, $subscriber) {
|
||||||
|
$subscriber = $this->transformSubscriber($subscriber);
|
||||||
|
return $this->mailer_instance->send($newsletter, $subscriber);
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildMailer() {
|
||||||
|
switch($this->mailer['method']) {
|
||||||
|
case 'AmazonSES':
|
||||||
|
$mailer_instance = new $this->mailer['class'](
|
||||||
|
$this->mailer['region'],
|
||||||
|
$this->mailer['access_key'],
|
||||||
|
$this->mailer['secret_key'],
|
||||||
|
$this->sender,
|
||||||
|
$this->reply_to
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'ElasticEmail':
|
||||||
|
$mailer_instance = new $this->mailer['class'](
|
||||||
|
$this->mailer['api_key'],
|
||||||
|
$this->sender,
|
||||||
|
$this->reply_to
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'MailGun':
|
||||||
|
$mailer_instance = new $this->mailer['class'](
|
||||||
|
$this->mailer['domain'],
|
||||||
|
$this->mailer['api_key'],
|
||||||
|
$this->sender,
|
||||||
|
$this->reply_to
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'MailPoet':
|
||||||
|
$mailer_instance = new $this->mailer['class'](
|
||||||
|
$this->mailer['mailpoet_api_key'],
|
||||||
|
$this->sender,
|
||||||
|
$this->reply_to
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'SendGrid':
|
||||||
|
$mailer_instance = new $this->mailer['class'](
|
||||||
|
$this->mailer['api_key'],
|
||||||
|
$this->sender,
|
||||||
|
$this->reply_to
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'PHPMail':
|
||||||
|
$mailer_instance = new $this->mailer['class'](
|
||||||
|
$this->sender,
|
||||||
|
$this->reply_to
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'SMTP':
|
||||||
|
$mailer_instance = new $this->mailer['class'](
|
||||||
|
$this->mailer['host'],
|
||||||
|
$this->mailer['port'],
|
||||||
|
$this->mailer['authentication'],
|
||||||
|
$this->mailer['login'],
|
||||||
|
$this->mailer['password'],
|
||||||
|
$this->mailer['encryption'],
|
||||||
|
$this->sender,
|
||||||
|
$this->reply_to
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new \Exception(__('Mailing method does not exist.'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return $mailer_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMailer($mailer = false) {
|
||||||
|
if(!$mailer) {
|
||||||
|
$mailer = Setting::getValue('mta', null);
|
||||||
|
if(!$mailer || !isset($mailer['method'])) throw new \Exception(__('Mailer is not configured.'));
|
||||||
|
}
|
||||||
|
$mailer['class'] = 'MailPoet\\Mailer\\Methods\\' . $mailer['method'];
|
||||||
|
return $mailer;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSender($sender = false) {
|
||||||
|
if(!$sender) {
|
||||||
|
$sender = Setting::getValue('sender', null);
|
||||||
|
if(!$sender['address']) throw new \Exception(__('Sender name and email are not configured.'));
|
||||||
|
}
|
||||||
|
return array(
|
||||||
|
'from_name' => $sender['name'],
|
||||||
|
'from_email' => $sender['address'],
|
||||||
|
'from_name_email' => sprintf('%s <%s>', $sender['name'], $sender['address'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getReplyTo($reply_to = false) {
|
||||||
|
if(!$reply_to) {
|
||||||
|
$reply_to = Setting::getValue('reply_to', null);
|
||||||
|
if(!$reply_to) {
|
||||||
|
$reply_to = array(
|
||||||
|
'name' => $this->sender['from_name'],
|
||||||
|
'address' => $this->sender['from_email']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!$reply_to['address']) {
|
||||||
|
$reply_to['address'] = $this->sender['from_email'];
|
||||||
|
}
|
||||||
|
return array(
|
||||||
|
'reply_to_name' => $reply_to['name'],
|
||||||
|
'reply_to_email' => $reply_to['address'],
|
||||||
|
'reply_to_name_email' => sprintf('%s <%s>', $reply_to['name'], $reply_to['address'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function transformSubscriber($subscriber) {
|
||||||
|
if(!is_array($subscriber)) return $subscriber;
|
||||||
|
if(isset($subscriber['address'])) $subscriber['email'] = $subscriber['address'];
|
||||||
|
$first_name = (isset($subscriber['first_name'])) ? $subscriber['first_name'] : '';
|
||||||
|
$last_name = (isset($subscriber['last_name'])) ? $subscriber['last_name'] : '';
|
||||||
|
if(!$first_name && !$last_name) return $subscriber['email'];
|
||||||
|
$subscriber = sprintf('%s %s <%s>', $first_name, $last_name, $subscriber['email']);
|
||||||
|
$subscriber = trim(preg_replace('!\s\s+!', ' ', $subscriber));
|
||||||
|
return $subscriber;
|
||||||
|
}
|
||||||
|
}
|
158
lib/Mailer/Methods/AmazonSES.php
Normal file
158
lib/Mailer/Methods/AmazonSES.php
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Mailer\Methods;
|
||||||
|
|
||||||
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class AmazonSES {
|
||||||
|
public $aws_access_key;
|
||||||
|
public $aws_secret_key;
|
||||||
|
public $aws_region;
|
||||||
|
public $aws_endpoint;
|
||||||
|
public $aws_signing_algorithm;
|
||||||
|
public $aws_service;
|
||||||
|
public $aws_termination_string;
|
||||||
|
public $hash_algorithm;
|
||||||
|
public $url;
|
||||||
|
public $sender;
|
||||||
|
public $reply_to;
|
||||||
|
public $date;
|
||||||
|
public $date_without_time;
|
||||||
|
|
||||||
|
function __construct($region, $access_key, $secret_key, $sender, $reply_to) {
|
||||||
|
$this->aws_access_key = $access_key;
|
||||||
|
$this->aws_secret_key = $secret_key;
|
||||||
|
$this->aws_region = $region;
|
||||||
|
$this->aws_endpoint = sprintf('email.%s.amazonaws.com', $this->aws_region);
|
||||||
|
$this->aws_signing_algorithm = 'AWS4-HMAC-SHA256';
|
||||||
|
$this->aws_service = 'ses';
|
||||||
|
$this->aws_termination_string = 'aws4_request';
|
||||||
|
$this->hash_algorithm = 'sha256';
|
||||||
|
$this->url = 'https://' . $this->aws_endpoint;
|
||||||
|
$this->sender = $sender;
|
||||||
|
$this->reply_to = $reply_to;
|
||||||
|
$this->date = gmdate('Ymd\THis\Z');
|
||||||
|
$this->date_without_time = gmdate('Ymd');
|
||||||
|
}
|
||||||
|
|
||||||
|
function send($newsletter, $subscriber) {
|
||||||
|
$result = wp_remote_post(
|
||||||
|
$this->url,
|
||||||
|
$this->request($newsletter, $subscriber)
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
!is_wp_error($result) === true &&
|
||||||
|
wp_remote_retrieve_response_code($result) === 200
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBody($newsletter, $subscriber) {
|
||||||
|
$body = array(
|
||||||
|
'Action' => 'SendEmail',
|
||||||
|
'Version' => '2010-12-01',
|
||||||
|
'Destination.ToAddresses.member.1' => $subscriber,
|
||||||
|
'Source' => $this->sender['from_name_email'],
|
||||||
|
'ReplyToAddresses.member.1' => $this->reply_to['reply_to_name_email'],
|
||||||
|
'Message.Subject.Data' => $newsletter['subject'],
|
||||||
|
'ReturnPath' => $this->sender['from_name_email'],
|
||||||
|
);
|
||||||
|
if(!empty($newsletter['body']['html'])) {
|
||||||
|
$body['Message.Body.Html.Data'] = $newsletter['body']['html'];
|
||||||
|
}
|
||||||
|
if(!empty($newsletter['body']['text'])) {
|
||||||
|
$body['Message.Body.Text.Data'] = $newsletter['body']['text'];
|
||||||
|
}
|
||||||
|
return $body;
|
||||||
|
}
|
||||||
|
|
||||||
|
function request($newsletter, $subscriber) {
|
||||||
|
$body = $this->getBody($newsletter, $subscriber);
|
||||||
|
return array(
|
||||||
|
'timeout' => 10,
|
||||||
|
'httpversion' => '1.1',
|
||||||
|
'method' => 'POST',
|
||||||
|
'headers' => array(
|
||||||
|
'Host' => $this->aws_endpoint,
|
||||||
|
'Authorization' => $this->signRequest($body),
|
||||||
|
'X-Amz-Date' => $this->date
|
||||||
|
),
|
||||||
|
'body' => urldecode(http_build_query($body))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function signRequest($body) {
|
||||||
|
$string_to_sign = $this->createStringToSign(
|
||||||
|
$this->getCredentialScope(),
|
||||||
|
$this->getCanonicalRequest($body)
|
||||||
|
);
|
||||||
|
$signature = hash_hmac(
|
||||||
|
$this->hash_algorithm,
|
||||||
|
$string_to_sign,
|
||||||
|
$this->getSigningKey()
|
||||||
|
);
|
||||||
|
|
||||||
|
return sprintf(
|
||||||
|
'%s Credential=%s/%s, SignedHeaders=host;x-amz-date, Signature=%s',
|
||||||
|
$this->aws_signing_algorithm,
|
||||||
|
$this->aws_access_key,
|
||||||
|
$this->getCredentialScope(),
|
||||||
|
$signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCredentialScope() {
|
||||||
|
return sprintf(
|
||||||
|
'%s/%s/%s/%s',
|
||||||
|
$this->date_without_time,
|
||||||
|
$this->aws_region,
|
||||||
|
$this->aws_service,
|
||||||
|
$this->aws_termination_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCanonicalRequest($body) {
|
||||||
|
return implode("\n", array(
|
||||||
|
'POST',
|
||||||
|
'/',
|
||||||
|
'',
|
||||||
|
'host:' . $this->aws_endpoint,
|
||||||
|
'x-amz-date:' . $this->date,
|
||||||
|
'',
|
||||||
|
'host;x-amz-date',
|
||||||
|
hash($this->hash_algorithm, urldecode(http_build_query($body)))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
function createStringToSign($credential_scope, $canonical_request) {
|
||||||
|
return implode("\n", array(
|
||||||
|
$this->aws_signing_algorithm,
|
||||||
|
$this->date,
|
||||||
|
$credential_scope,
|
||||||
|
hash($this->hash_algorithm, $canonical_request)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSigningKey() {
|
||||||
|
$date_key = hash_hmac(
|
||||||
|
$this->hash_algorithm,
|
||||||
|
$this->date_without_time,
|
||||||
|
'AWS4' . $this->aws_secret_key,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
$region_key = hash_hmac(
|
||||||
|
$this->hash_algorithm,
|
||||||
|
$this->aws_region,
|
||||||
|
$date_key,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
$service_key = hash_hmac(
|
||||||
|
$this->hash_algorithm,
|
||||||
|
$this->aws_service,
|
||||||
|
$region_key,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
return hash_hmac(
|
||||||
|
$this->hash_algorithm,
|
||||||
|
$this->aws_termination_string,
|
||||||
|
$service_key,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +1,18 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Mailer\API;
|
namespace MailPoet\Mailer\Methods;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class ElasticEmail {
|
class ElasticEmail {
|
||||||
function __construct($apiKey, $fromEmail, $fromName) {
|
public $url = 'https://api.elasticemail.com/mailer/send';
|
||||||
$this->url = 'https://api.elasticemail.com/mailer/send';
|
public $api_key;
|
||||||
$this->apiKey = $apiKey;
|
public $sender;
|
||||||
$this->fromEmail = $fromEmail;
|
public $reply_to;
|
||||||
$this->fromName = $fromName;
|
|
||||||
|
function __construct($api_key, $sender, $reply_to) {
|
||||||
|
$this->api_key = $api_key;
|
||||||
|
$this->sender = $sender;
|
||||||
|
$this->reply_to = $reply_to;
|
||||||
}
|
}
|
||||||
|
|
||||||
function send($newsletter, $subscriber) {
|
function send($newsletter, $subscriber) {
|
||||||
@ -23,10 +27,12 @@ class ElasticEmail {
|
|||||||
|
|
||||||
function getBody($newsletter, $subscriber) {
|
function getBody($newsletter, $subscriber) {
|
||||||
$body = array(
|
$body = array(
|
||||||
'api_key' => $this->apiKey,
|
'api_key' => $this->api_key,
|
||||||
'from' => $this->fromEmail,
|
|
||||||
'from_name' => $this->fromName,
|
|
||||||
'to' => $subscriber,
|
'to' => $subscriber,
|
||||||
|
'from' => $this->sender['from_email'],
|
||||||
|
'from_name' => $this->sender['from_name'],
|
||||||
|
'reply_to' => $this->reply_to['reply_to_email'],
|
||||||
|
'reply_to_name' => $this->reply_to['reply_to_name'],
|
||||||
'subject' => $newsletter['subject']
|
'subject' => $newsletter['subject']
|
||||||
);
|
);
|
||||||
if(!empty($newsletter['body']['html'])) {
|
if(!empty($newsletter['body']['html'])) {
|
@ -1,13 +1,19 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Mailer\API;
|
namespace MailPoet\Mailer\Methods;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class MailGun {
|
class MailGun {
|
||||||
function __construct($domain, $apiKey, $from) {
|
public $url;
|
||||||
|
public $api_key;
|
||||||
|
public $sender;
|
||||||
|
public $reply_to;
|
||||||
|
|
||||||
|
function __construct($domain, $api_key, $sender, $reply_to) {
|
||||||
$this->url = sprintf('https://api.mailgun.net/v3/%s/messages', $domain);
|
$this->url = sprintf('https://api.mailgun.net/v3/%s/messages', $domain);
|
||||||
$this->apiKey = $apiKey;
|
$this->api_key = $api_key;
|
||||||
$this->from = $from;
|
$this->sender = $sender;
|
||||||
|
$this->reply_to = $reply_to;
|
||||||
}
|
}
|
||||||
|
|
||||||
function send($newsletter, $subscriber) {
|
function send($newsletter, $subscriber) {
|
||||||
@ -23,8 +29,9 @@ class MailGun {
|
|||||||
|
|
||||||
function getBody($newsletter, $subscriber) {
|
function getBody($newsletter, $subscriber) {
|
||||||
$body = array(
|
$body = array(
|
||||||
'from' => $this->from,
|
|
||||||
'to' => $subscriber,
|
'to' => $subscriber,
|
||||||
|
'from' => $this->sender['from_name_email'],
|
||||||
|
'h:Reply-To' => $this->reply_to['reply_to_name_email'],
|
||||||
'subject' => $newsletter['subject']
|
'subject' => $newsletter['subject']
|
||||||
);
|
);
|
||||||
if(!empty($newsletter['body']['html'])) {
|
if(!empty($newsletter['body']['html'])) {
|
||||||
@ -37,7 +44,7 @@ class MailGun {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function auth() {
|
function auth() {
|
||||||
return 'Basic ' . base64_encode('api:' . $this->apiKey);
|
return 'Basic ' . base64_encode('api:' . $this->api_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
function request($newsletter, $subscriber) {
|
function request($newsletter, $subscriber) {
|
98
lib/Mailer/Methods/MailPoet.php
Normal file
98
lib/Mailer/Methods/MailPoet.php
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Mailer\Methods;
|
||||||
|
|
||||||
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class MailPoet {
|
||||||
|
public $url = 'https://bridge.mailpoet.com/api/messages';
|
||||||
|
public $api_key;
|
||||||
|
public $sender;
|
||||||
|
public $reply_to;
|
||||||
|
|
||||||
|
function __construct($api_key, $sender, $reply_to) {
|
||||||
|
$this->api_key = $api_key;
|
||||||
|
$this->sender = $sender;
|
||||||
|
$this->reply_to = $reply_to;
|
||||||
|
}
|
||||||
|
|
||||||
|
function send($newsletter, $subscriber) {
|
||||||
|
$message_body = $this->getBody($newsletter, $subscriber);
|
||||||
|
$result = wp_remote_post(
|
||||||
|
$this->url,
|
||||||
|
$this->request($message_body)
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
!is_wp_error($result) === true &&
|
||||||
|
wp_remote_retrieve_response_code($result) === 201
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function processSubscriber($subscriber) {
|
||||||
|
preg_match('!(?P<name>.*?)\s<(?P<email>.*?)>!', $subscriber, $subscriber_data);
|
||||||
|
if(!isset($subscriber_data['email'])) {
|
||||||
|
$subscriber_data = array(
|
||||||
|
'email' => $subscriber,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return array(
|
||||||
|
'email' => $subscriber_data['email'],
|
||||||
|
'name' => (isset($subscriber_data['name'])) ? $subscriber_data['name'] : ''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBody($newsletter, $subscriber) {
|
||||||
|
$composeBody = function ($newsletter, $subscriber) {
|
||||||
|
$body = array(
|
||||||
|
'to' => (array(
|
||||||
|
'address' => $subscriber['email'],
|
||||||
|
'name' => $subscriber['name']
|
||||||
|
)),
|
||||||
|
'from' => (array(
|
||||||
|
'address' => $this->sender['from_email'],
|
||||||
|
'name' => $this->sender['from_name']
|
||||||
|
)),
|
||||||
|
'reply_to' => (array(
|
||||||
|
'address' => $this->reply_to['reply_to_email'],
|
||||||
|
'name' => $this->reply_to['reply_to_name']
|
||||||
|
)),
|
||||||
|
'subject' => $newsletter['subject']
|
||||||
|
);
|
||||||
|
if(!empty($newsletter['body']['html'])) {
|
||||||
|
$body['html'] = $newsletter['body']['html'];
|
||||||
|
}
|
||||||
|
if(!empty($newsletter['body']['text'])) {
|
||||||
|
$body['text'] = $newsletter['body']['text'];
|
||||||
|
}
|
||||||
|
return $body;
|
||||||
|
};
|
||||||
|
if(is_array($newsletter) && is_array($subscriber)) {
|
||||||
|
$body = array();
|
||||||
|
for($record = 0; $record < count($newsletter); $record++) {
|
||||||
|
$body[] = $composeBody(
|
||||||
|
$newsletter[$record],
|
||||||
|
$this->processSubscriber($subscriber[$record])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$body[] = $composeBody($newsletter, $this->processSubscriber($subscriber));
|
||||||
|
}
|
||||||
|
return $body;
|
||||||
|
}
|
||||||
|
|
||||||
|
function auth() {
|
||||||
|
return 'Basic ' . base64_encode('api:' . $this->api_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
function request($body) {
|
||||||
|
return array(
|
||||||
|
'timeout' => 10,
|
||||||
|
'httpversion' => '1.0',
|
||||||
|
'method' => 'POST',
|
||||||
|
'headers' => array(
|
||||||
|
'Content-Type' => 'application/json',
|
||||||
|
'Authorization' => $this->auth()
|
||||||
|
),
|
||||||
|
'body' => json_encode($body)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
64
lib/Mailer/Methods/PHPMail.php
Normal file
64
lib/Mailer/Methods/PHPMail.php
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Mailer\Methods;
|
||||||
|
|
||||||
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class PHPMail {
|
||||||
|
public $sender;
|
||||||
|
public $reply_to;
|
||||||
|
public $mailer;
|
||||||
|
|
||||||
|
function __construct($sender, $reply_to) {
|
||||||
|
$this->sender = $sender;
|
||||||
|
$this->reply_to = $reply_to;
|
||||||
|
$this->mailer = $this->buildMailer();
|
||||||
|
}
|
||||||
|
|
||||||
|
function send($newsletter, $subscriber) {
|
||||||
|
try {
|
||||||
|
$message = $this->createMessage($newsletter, $subscriber);
|
||||||
|
$result = $this->mailer->send($message);
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
$result = false;
|
||||||
|
}
|
||||||
|
return ($result === 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildMailer() {
|
||||||
|
$transport = \Swift_SmtpTransport::newInstance();
|
||||||
|
$transport->setTimeout(10);
|
||||||
|
return \Swift_Mailer::newInstance($transport);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMessage($newsletter, $subscriber) {
|
||||||
|
$message = \Swift_Message::newInstance()
|
||||||
|
->setTo($this->processSubscriber($subscriber))
|
||||||
|
->setFrom(array(
|
||||||
|
$this->sender['from_email'] => $this->sender['from_name']
|
||||||
|
))
|
||||||
|
->setReplyTo(array(
|
||||||
|
$this->reply_to['reply_to_email'] => $this->reply_to['reply_to_name']
|
||||||
|
))
|
||||||
|
->setSubject($newsletter['subject']);
|
||||||
|
if(!empty($newsletter['body']['html'])) {
|
||||||
|
$message = $message->setBody($newsletter['body']['html'], 'text/html');
|
||||||
|
}
|
||||||
|
if(!empty($newsletter['body']['text'])) {
|
||||||
|
$message = $message->addPart($newsletter['body']['text'], 'text/plain');
|
||||||
|
}
|
||||||
|
return $message;
|
||||||
|
}
|
||||||
|
|
||||||
|
function processSubscriber($subscriber) {
|
||||||
|
preg_match('!(?P<name>.*?)\s<(?P<email>.*?)>!', $subscriber, $subscriber_data);
|
||||||
|
if(!isset($subscriber_data['email'])) {
|
||||||
|
$subscriber_data = array(
|
||||||
|
'email' => $subscriber,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return array(
|
||||||
|
$subscriber_data['email'] =>
|
||||||
|
(isset($subscriber_data['name'])) ? $subscriber_data['name'] : ''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,19 +1,30 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Mailer;
|
namespace MailPoet\Mailer\Methods;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class SMTP {
|
class SMTP {
|
||||||
function __construct($host, $port, $authentication, $login = null, $password = null, $encryption,
|
public $host;
|
||||||
$fromEmail, $fromName) {
|
public $port;
|
||||||
|
public $authentication;
|
||||||
|
public $login;
|
||||||
|
public $password;
|
||||||
|
public $encryption;
|
||||||
|
public $sender;
|
||||||
|
public $reply_to;
|
||||||
|
public $mailer;
|
||||||
|
|
||||||
|
function __construct(
|
||||||
|
$host, $port, $authentication, $login = null, $password = null, $encryption,
|
||||||
|
$sender, $reply_to) {
|
||||||
$this->host = $host;
|
$this->host = $host;
|
||||||
$this->port = $port;
|
$this->port = $port;
|
||||||
$this->authentication = $authentication;
|
$this->authentication = $authentication;
|
||||||
$this->login = $login;
|
$this->login = $login;
|
||||||
$this->password = $password;
|
$this->password = $password;
|
||||||
$this->encryption = $encryption;
|
$this->encryption = $encryption;
|
||||||
$this->fromName = $fromName;
|
$this->sender = $sender;
|
||||||
$this->fromEmail = $fromEmail;
|
$this->reply_to = $reply_to;
|
||||||
$this->mailer = $this->buildMailer();
|
$this->mailer = $this->buildMailer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,7 +33,6 @@ class SMTP {
|
|||||||
$message = $this->createMessage($newsletter, $subscriber);
|
$message = $this->createMessage($newsletter, $subscriber);
|
||||||
$result = $this->mailer->send($message);
|
$result = $this->mailer->send($message);
|
||||||
} catch(\Exception $e) {
|
} catch(\Exception $e) {
|
||||||
!d($e->getMessage());exit;
|
|
||||||
$result = false;
|
$result = false;
|
||||||
}
|
}
|
||||||
return ($result === 1);
|
return ($result === 1);
|
||||||
@ -40,11 +50,15 @@ class SMTP {
|
|||||||
return \Swift_Mailer::newInstance($transport);
|
return \Swift_Mailer::newInstance($transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function createMessage($newsletter, $subscriber) {
|
function createMessage($newsletter, $subscriber) {
|
||||||
$message = \Swift_Message::newInstance()
|
$message = \Swift_Message::newInstance()
|
||||||
->setFrom(array($this->fromEmail => $this->fromName))
|
|
||||||
->setTo($this->processSubscriber($subscriber))
|
->setTo($this->processSubscriber($subscriber))
|
||||||
|
->setFrom(array(
|
||||||
|
$this->sender['from_email'] => $this->sender['from_name']
|
||||||
|
))
|
||||||
|
->setReplyTo(array(
|
||||||
|
$this->reply_to['reply_to_email'] => $this->reply_to['reply_to_name']
|
||||||
|
))
|
||||||
->setSubject($newsletter['subject']);
|
->setSubject($newsletter['subject']);
|
||||||
if(!empty($newsletter['body']['html'])) {
|
if(!empty($newsletter['body']['html'])) {
|
||||||
$message = $message->setBody($newsletter['body']['html'], 'text/html');
|
$message = $message->setBody($newsletter['body']['html'], 'text/html');
|
||||||
@ -56,15 +70,15 @@ class SMTP {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function processSubscriber($subscriber) {
|
function processSubscriber($subscriber) {
|
||||||
preg_match('!(?P<name>.*?)\s<(?P<email>.*?)>!', $subscriber, $subscriberData);
|
preg_match('!(?P<name>.*?)\s<(?P<email>.*?)>!', $subscriber, $subscriber_data);
|
||||||
if(!isset($subscriberData['email'])) {
|
if(!isset($subscriber_data['email'])) {
|
||||||
$subscriberData = array(
|
$subscriber_data = array(
|
||||||
'email' => $subscriber,
|
'email' => $subscriber,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return array(
|
return array(
|
||||||
$subscriberData['email'] =>
|
$subscriber_data['email'] =>
|
||||||
(isset($subscriberData['name'])) ? $subscriberData['name'] : '',
|
(isset($subscriber_data['name'])) ? $subscriber_data['name'] : ''
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,14 +1,18 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Mailer\API;
|
namespace MailPoet\Mailer\Methods;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class SendGrid {
|
class SendGrid {
|
||||||
function __construct($apiKey, $fromEmail, $fromName) {
|
public $url = 'https://api.sendgrid.com/api/mail.send.json';
|
||||||
$this->url = 'https://api.sendgrid.com/api/mail.send.json';
|
public $api_key;
|
||||||
$this->apiKey = $apiKey;
|
public $sender;
|
||||||
$this->fromEmail = $fromEmail;
|
public $reply_to;
|
||||||
$this->fromName = $fromName;
|
|
||||||
|
function __construct($api_key, $sender, $reply_to) {
|
||||||
|
$this->api_key = $api_key;
|
||||||
|
$this->sender = $sender;
|
||||||
|
$this->reply_to = $reply_to;
|
||||||
}
|
}
|
||||||
|
|
||||||
function send($newsletter, $subscriber) {
|
function send($newsletter, $subscriber) {
|
||||||
@ -16,10 +20,11 @@ class SendGrid {
|
|||||||
$this->url,
|
$this->url,
|
||||||
$this->request($newsletter, $subscriber)
|
$this->request($newsletter, $subscriber)
|
||||||
);
|
);
|
||||||
|
$result_body = json_decode($result['body'], true);
|
||||||
return (
|
return (
|
||||||
!is_wp_error($result) === true &&
|
!is_wp_error($result) === true &&
|
||||||
!preg_match('!invalid!', $result['body']) === true &&
|
!preg_match('!invalid!', $result['body']) === true &&
|
||||||
!isset(json_decode($result['body'], true)['errors']) === true &&
|
!isset($result_body['errors']) === true &&
|
||||||
wp_remote_retrieve_response_code($result) === 200
|
wp_remote_retrieve_response_code($result) === 200
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -27,8 +32,9 @@ class SendGrid {
|
|||||||
function getBody($newsletter, $subscriber) {
|
function getBody($newsletter, $subscriber) {
|
||||||
$body = array(
|
$body = array(
|
||||||
'to' => $subscriber,
|
'to' => $subscriber,
|
||||||
'from' => $this->fromEmail,
|
'from' => $this->sender['from_email'],
|
||||||
'fromname' => $this->fromName,
|
'fromname' => $this->sender['from_name'],
|
||||||
|
'replyto' => $this->reply_to['reply_to_email'],
|
||||||
'subject' => $newsletter['subject']
|
'subject' => $newsletter['subject']
|
||||||
);
|
);
|
||||||
if(!empty($newsletter['body']['html'])) {
|
if(!empty($newsletter['body']['html'])) {
|
||||||
@ -41,7 +47,7 @@ class SendGrid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function auth() {
|
function auth() {
|
||||||
return 'Bearer ' . $this->apiKey;
|
return 'Bearer ' . $this->api_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
function request($newsletter, $subscriber) {
|
function request($newsletter, $subscriber) {
|
||||||
@ -53,7 +59,7 @@ class SendGrid {
|
|||||||
'headers' => array(
|
'headers' => array(
|
||||||
'Authorization' => $this->auth()
|
'Authorization' => $this->auth()
|
||||||
),
|
),
|
||||||
'body' => urldecode(http_build_query($body))
|
'body' => http_build_query($body)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user