├── preview.html ├── .gitignore ├── assets ├── img │ ├── date-button.gif │ └── comment-grey-bubble.png ├── slick │ ├── ajax-loader.gif │ ├── fonts │ │ ├── slick.eot │ │ ├── slick.ttf │ │ ├── slick.woff │ │ └── slick.svg │ ├── slick.css │ └── slick.min.js ├── css │ └── htmlemail.css └── js │ └── htmlemail.js ├── lib ├── templates │ ├── Disco │ │ ├── screenshot.jpg │ │ ├── images │ │ │ └── disco.gif │ │ ├── style_header.css │ │ ├── index.php │ │ ├── style.css │ │ └── template.html │ ├── Hero │ │ ├── screenshot.png │ │ ├── index.php │ │ ├── template.html │ │ └── style.css │ ├── Promy │ │ ├── screenshot.jpg │ │ ├── images │ │ │ └── header_image.jpg │ │ ├── style_header.css │ │ ├── index.php │ │ ├── style.css │ │ └── template.html │ ├── default_footer.html │ ├── Iletter │ │ ├── screenshot.jpg │ │ ├── style_header.css │ │ ├── index.php │ │ ├── style.css │ │ └── template.html │ ├── Sidebar │ │ ├── screenshot.png │ │ ├── index.php │ │ ├── template.html │ │ └── style.css │ ├── Minimise │ │ ├── screenshot.jpg │ │ ├── style_header.css │ │ ├── index.php │ │ ├── style.css │ │ └── template.html │ ├── Handwritten │ │ ├── screenshot.jpg │ │ ├── images │ │ │ ├── footer.png │ │ │ ├── header.jpg │ │ │ ├── middle.jpg │ │ │ └── background.jpg │ │ ├── style_header.css │ │ ├── index.php │ │ ├── style.css │ │ └── template.html │ ├── Simplicitydark │ │ ├── screenshot.jpg │ │ ├── images │ │ │ └── disco.gif │ │ ├── style_header.css │ │ ├── index.php │ │ ├── style.css │ │ └── template.html │ ├── Simplicitylight │ │ ├── screenshot.jpg │ │ ├── images │ │ │ └── disco.gif │ │ ├── style_header.css │ │ ├── index.php │ │ ├── style.css │ │ └── template.html │ ├── default_header.html │ ├── default_style_header.css │ └── default_style.css └── builder │ └── css-inline.php ├── .gitmodules ├── changelog.txt ├── languages └── htmlemail.pot ├── README.md └── htmlemail.php /preview.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | .DS_Store* 3 | -------------------------------------------------------------------------------- /assets/img/date-button.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/assets/img/date-button.gif -------------------------------------------------------------------------------- /assets/slick/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/assets/slick/ajax-loader.gif -------------------------------------------------------------------------------- /assets/slick/fonts/slick.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/assets/slick/fonts/slick.eot -------------------------------------------------------------------------------- /assets/slick/fonts/slick.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/assets/slick/fonts/slick.ttf -------------------------------------------------------------------------------- /assets/slick/fonts/slick.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/assets/slick/fonts/slick.woff -------------------------------------------------------------------------------- /assets/img/comment-grey-bubble.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/assets/img/comment-grey-bubble.png -------------------------------------------------------------------------------- /lib/templates/Disco/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/lib/templates/Disco/screenshot.jpg -------------------------------------------------------------------------------- /lib/templates/Hero/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/lib/templates/Hero/screenshot.png -------------------------------------------------------------------------------- /lib/templates/Promy/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/lib/templates/Promy/screenshot.jpg -------------------------------------------------------------------------------- /lib/templates/default_footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /lib/templates/Disco/images/disco.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/lib/templates/Disco/images/disco.gif -------------------------------------------------------------------------------- /lib/templates/Iletter/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/lib/templates/Iletter/screenshot.jpg -------------------------------------------------------------------------------- /lib/templates/Sidebar/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/lib/templates/Sidebar/screenshot.png -------------------------------------------------------------------------------- /lib/templates/Minimise/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/lib/templates/Minimise/screenshot.jpg -------------------------------------------------------------------------------- /lib/templates/Handwritten/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/lib/templates/Handwritten/screenshot.jpg -------------------------------------------------------------------------------- /lib/templates/Handwritten/images/footer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/lib/templates/Handwritten/images/footer.png -------------------------------------------------------------------------------- /lib/templates/Handwritten/images/header.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/lib/templates/Handwritten/images/header.jpg -------------------------------------------------------------------------------- /lib/templates/Handwritten/images/middle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/lib/templates/Handwritten/images/middle.jpg -------------------------------------------------------------------------------- /lib/templates/Promy/images/header_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/lib/templates/Promy/images/header_image.jpg -------------------------------------------------------------------------------- /lib/templates/Simplicitydark/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/lib/templates/Simplicitydark/screenshot.jpg -------------------------------------------------------------------------------- /lib/templates/Simplicitylight/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/lib/templates/Simplicitylight/screenshot.jpg -------------------------------------------------------------------------------- /lib/templates/Simplicitydark/images/disco.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/lib/templates/Simplicitydark/images/disco.gif -------------------------------------------------------------------------------- /lib/templates/Simplicitylight/images/disco.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/lib/templates/Simplicitylight/images/disco.gif -------------------------------------------------------------------------------- /lib/templates/Handwritten/images/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/htmlemail/master/lib/templates/Handwritten/images/background.jpg -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "includes/dash-notice"] 2 | path = includes/dash-notice 3 | url = git@bitbucket.org:incsub/wpmudev-dashboard-notification.git 4 | branch = master 5 | -------------------------------------------------------------------------------- /lib/templates/Hero/index.php: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | font-family:Arial, Helvetica, sans-serif; 4 | } 5 | 6 | -------------------------------------------------------------------------------- /lib/templates/Iletter/style_header.css: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /lib/templates/Promy/style_header.css: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /lib/templates/Minimise/style_header.css: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /lib/templates/Handwritten/style_header.css: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /lib/templates/Simplicitydark/style_header.css: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /lib/templates/Simplicitylight/style_header.css: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /lib/templates/Minimise/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {EMAIL_TITLE} 6 | 7 | 8 |
9 | 14 | 15 | 16 |
17 | -------------------------------------------------------------------------------- /lib/templates/Disco/index.php: -------------------------------------------------------------------------------- 1 | 2 | .ExternalClass {width:100%;} 3 | .ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div { 4 | line-height: 100%;} 5 | 6 | body {-webkit-text-size-adjust:none; -ms-text-size-adjust:none;} 7 | body {margin:0; padding:0;} 8 | table td, table {border-collapse:collapse;} 9 | 10 | p {margin:0; padding:0; margin-bottom:0;} 11 | 12 | .ExternalClass h1, .ExternalClass h2, .ExternalClass h3, .ExternalClass h4, .ExternalClass h5, .ExternalClass h6 {padding:0.5em 0 0.5em 0 !important;} 13 | 14 | span.yshortcuts { color:#LINK_COLOR; background-color:none; border:none;} 15 | span.yshortcuts:hover, 16 | span.yshortcuts:active, 17 | span.yshortcuts:focus {color:#LINK_COLOR; background-color:none; border:none;} 18 | -------------------------------------------------------------------------------- /lib/templates/default_style.css: -------------------------------------------------------------------------------- 1 | html { background: white; } 2 | h1, h2, h3, h4, h5, h6 {padding: 0;margin:0; line-height: 100%;} 3 | a:link, a, a:visited, a:link {color:#LINK_COLOR;} 4 | p {margin: 0 0 1.35em 0;} 5 | h1, h2, h3, h4, h5, h6 {margin:0.5em 0 0.5em 0;} 6 | h1 {font-size: 2em;} h2 {font-size: 1.5em;} h3 {font-size: 1.17em;} h4 {font-size: 1em;} h5 {font-size: 0.83em;} h6 {font-size: 0.67em;} 7 | img { max-width: 95%; height: auto; } 8 | .header_image img {max-width: 100%;} 9 | .alignleft { display: inline; float: left;} 10 | .alignright { display: inline; float: right;} 11 | .aligncenter { clear: both; display: block; margin-left: auto; margin-right: auto; } 12 | img.alignleft, img.alignright, img.alignnone { margin: 7px; } 13 | 14 | .width {width:100%;} 15 | .container, .content {min-width:100%;} 16 | .title {color: #TITLE_COLOR;} 17 | .text_right {text-align: right;} -------------------------------------------------------------------------------- /lib/templates/Simplicitydark/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | Theme Name: Simplicity Dark 3 | Theme URI: http://premium.wpmudev.org 4 | Author: Cole (Incsub), Maniu(Incsub) 5 | Author URI: http://premium.wpmudev.org 6 | Description: Responsive theme with: max width 700px, max content width 700px 7 | Version: 1.5 8 | License: GNU General Public License v2 or later 9 | License URI: http://www.gnu.org/licenses/gpl-2.0.html 10 | */ 11 | body, .body_style, h1, h2, h3, h4, h5, h6, td { 12 | font-family:Arial, Helvetica, sans-serif; 13 | } 14 | body, .body_style { 15 | font-size:12px; 16 | color:#ALTERNATIVE_COLOR; 17 | } 18 | .body_style { 19 | background-color:#BG_COLOR; 20 | } 21 | 22 | 23 | .width { 24 | max-width:700px; 25 | } 26 | .holder { 27 | padding:1.5%; 28 | } 29 | 30 | 31 | .title { 32 | font-size: 55px; 33 | line-height: 55px; 34 | margin:0px; 35 | font-weight: bold; 36 | } 37 | .email_content, .email_content table, .contact_info, .email_content h1, .email_content h2, .email_content h3, .email_content h4, .email_content h5, .email_content h6 { 38 | color: #BODY_COLOR; 39 | } 40 | .from, .branding_html { 41 | padding:15px 0 35px; 42 | font-weight: bold; 43 | font-size: 18px; 44 | } 45 | p { 46 | font-size:12px; 47 | line-height:22px; 48 | } 49 | .view_link { 50 | text-align: center; 51 | } 52 | .view_link a { 53 | line-height: 25px; 54 | } 55 | .site-link { 56 | padding: 20px 0; 57 | text-align: center; 58 | font-size: 11px; 59 | } -------------------------------------------------------------------------------- /lib/templates/Simplicitylight/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | Theme Name: Simplicity Light 3 | Theme URI: http://premium.wpmudev.org 4 | Author: Cole (Incsub), Maniu(Incsub) 5 | Author URI: http://premium.wpmudev.org 6 | Description: Responsive theme with: max width 700px, max content width 700px 7 | Version: 1.5 8 | License: GNU General Public License v2 or later 9 | License URI: http://www.gnu.org/licenses/gpl-2.0.html 10 | */ 11 | body, .body_style, h1, h2, h3, h4, h5, h6, td { 12 | font-family:Arial, Helvetica, sans-serif; 13 | } 14 | body, .body_style { 15 | font-size:12px; 16 | color:#ALTERNATIVE_COLOR; 17 | } 18 | .body_style { 19 | background-color:#BG_COLOR; 20 | } 21 | 22 | 23 | .width { 24 | max-width:700px; 25 | } 26 | .holder { 27 | padding:1.5%; 28 | } 29 | 30 | 31 | .title { 32 | font-size: 55px; 33 | line-height: 55px; 34 | margin:0px; 35 | font-weight: bold; 36 | } 37 | .email_content, .email_content table, .contact_info, .email_content h1, .email_content h2, .email_content h3, .email_content h4, .email_content h5, .email_content h6 { 38 | color: #BODY_COLOR; 39 | } 40 | .from, .branding_html { 41 | padding:15px 0 35px; 42 | font-weight: bold; 43 | font-size: 18px; 44 | } 45 | p { 46 | font-size:12px; 47 | line-height:22px; 48 | } 49 | .view_link { 50 | text-align: center; 51 | } 52 | .view_link a { 53 | line-height: 25px; 54 | } 55 | .site-link { 56 | padding: 20px 0; 57 | text-align: center; 58 | font-size: 11px; 59 | } -------------------------------------------------------------------------------- /lib/templates/Iletter/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | Theme Name: iLetter 3 | Theme URI: http://premium.wpmudev.org 4 | Author: Cole (Incsub) 5 | Author URI: http://premium.wpmudev.org 6 | Description: Responsive theme with: max width 640px, max content width 600px, header image support 7 | Version: 1.5 8 | License: GNU General Public License v2 or later 9 | License URI: http://www.gnu.org/licenses/gpl-2.0.html 10 | */ 11 | body, .body_style, h1, h2, h3, h4, h5, h6, td { 12 | font-family:Arial, Helvetica, sans-serif; 13 | } 14 | body, .body_style { 15 | font-size:12px; 16 | color:#ALTERNATIVE_COLOR; 17 | } 18 | .body_style { 19 | background-color:#BG_COLOR; 20 | } 21 | 22 | 23 | .holder { 24 | padding:1.5%; 25 | } 26 | .width { 27 | max-width:640px; 28 | } 29 | .content_main { 30 | background-color:#ffffff; 31 | border-radius: 10px; 32 | } 33 | 34 | 35 | .title { 36 | font-size: 29px; 37 | line-height: 29px; 38 | margin:0px; 39 | padding:15px 20px 15px 20px; 40 | font-weight: bold; 41 | } 42 | .email_content, .email_content table, .contact_info, .email_content h1, .email_content h2, .email_content h3, .email_content h4, .email_content h5, .email_content h6 { 43 | color: #BODY_COLOR; 44 | } 45 | .email_content, .contact_info { 46 | padding:5px 20px; 47 | } 48 | p { 49 | font-size:12px; 50 | line-height:22px; 51 | } 52 | .view_link { 53 | text-align: center; 54 | } 55 | .view_link a { 56 | line-height: 25px; 57 | } 58 | .site-link { 59 | padding: 10px; 60 | text-align: center; 61 | font-size: 11px; 62 | } 63 | .branding_html { 64 | margin:0px; 65 | padding:15px 20px 15px 20px; 66 | } -------------------------------------------------------------------------------- /lib/templates/Promy/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | Theme Name: Promy 3 | Theme URI: http://premium.wpmudev.org 4 | Author: Cole (Incsub) 5 | Author URI: http://premium.wpmudev.org 6 | Description: Responsive theme with: max width 600px, max content width 560px, header image support 7 | Version: 1 8 | License: GNU General Public License v2 or later 9 | License URI: http://www.gnu.org/licenses/gpl-2.0.html 10 | */ 11 | body, .body_style, h1, h2, h3, h4, h5, h6, td { 12 | font-family:Arial, Helvetica, sans-serif; 13 | } 14 | body, .body_style { 15 | font-size:12px; 16 | color:#ALTERNATIVE_COLOR; 17 | } 18 | .body_style { 19 | background-color:#BG_COLOR; 20 | } 21 | 22 | 23 | .holder { 24 | padding:1.5%; 25 | } 26 | .width { 27 | max-width:600px; 28 | } 29 | .content_main { 30 | background-color:#2C8FD6; 31 | border-radius: 8px; 32 | } 33 | 34 | 35 | .header_image img { 36 | border-radius: 8px 8px 0 0; 37 | } 38 | .title { 39 | font-size: 29px; 40 | line-height: 29px; 41 | margin:0px; 42 | padding: 10px 0; 43 | text-align: left; 44 | } 45 | .email_content, .email_content table, .email_content h1, .email_content h2, .email_content h3, .email_content h4, .email_content h5, .email_content h6 { 46 | color: #BODY_COLOR; 47 | } 48 | .email_content { 49 | padding:5px 20px 15px 20px; 50 | font-size: 14px; 51 | } 52 | .email_content img { 53 | border-radius: 8px; 54 | } 55 | .contact_info { 56 | padding: 20px 10px 30px 10px; 57 | text-align: center; 58 | font-size: 13px; 59 | } 60 | p { 61 | font-size:12px; 62 | line-height:22px; 63 | } 64 | .view_link { 65 | text-align: right; 66 | padding: 16px 20px 0 0; 67 | } 68 | .site-link { 69 | text-align: center; 70 | font-size: 11px; 71 | } -------------------------------------------------------------------------------- /lib/templates/Disco/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | Theme Name: Disco 3 | Theme URI: http://premium.wpmudev.org 4 | Author: Cole (Incsub), Maniu(Incsub) 5 | Author URI: http://premium.wpmudev.org 6 | Description: Responsive theme with: max width 500px, max content width 449px, header image support 7 | Version: 1.5 8 | License: GNU General Public License v2 or later 9 | License URI: http://www.gnu.org/licenses/gpl-2.0.html 10 | */ 11 | body, .body_style, h1, h2, h3, h4, h5, h6, td { 12 | font-family:Arial, Helvetica, sans-serif; 13 | } 14 | body, .body_style { 15 | font-size:12px; 16 | color:#ALTERNATIVE_COLOR; 17 | } 18 | body, .body_style { 19 | background-color:#BG_COLOR; 20 | } 21 | table { 22 | width: 100%; 23 | } 24 | 25 | .holder { 26 | padding:1.5%; 27 | } 28 | .width { 29 | max-width:500px; 30 | } 31 | .content_main { 32 | background-color: #181818; 33 | border: 1px solid #303030; 34 | } 35 | 36 | 37 | .title { 38 | font-size: 40px; 39 | line-height: 40px; 40 | margin:0px; 41 | padding:15px 0; 42 | font-weight: bold; 43 | } 44 | .header_image { 45 | text-align: center; 46 | } 47 | .header_image img { 48 | vertical-align: bottom; 49 | max-width: 100%; 50 | height: auto; 51 | } 52 | .email_content, .email_content table, .contact_info, .email_content h1, .email_content h2, .email_content h3, .email_content h4, .email_content h5, .email_content h6 { 53 | color: #BODY_COLOR; 54 | } 55 | .email_content { 56 | padding:5px 25px; 57 | } 58 | .contact_info { 59 | padding:0 25px 25px 25px; 60 | } 61 | .from { 62 | padding:25px 25px 10px; 63 | font-weight: bold; 64 | font-size: 18px; 65 | } 66 | p { 67 | font-size:12px; 68 | line-height:22px; 69 | } 70 | .view_link a { 71 | line-height: 25px; 72 | } 73 | .site-link { 74 | padding: 10px; 75 | text-align: center; 76 | font-size: 11px; 77 | } -------------------------------------------------------------------------------- /lib/templates/Handwritten/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | Theme Name: Handwritten 3 | Theme URI: http://premium.wpmudev.org 4 | Author: Cole (Incsub), Maniu (Incsub) 5 | Author URI: http://premium.wpmudev.org 6 | Description: Responsive theme with: max width 650px, max content width 580px, header image support 7 | Version: 1.5 8 | License: GNU General Public License v2 or later 9 | License URI: http://www.gnu.org/licenses/gpl-2.0.html 10 | */ 11 | 12 | body, .body_style, h1, h2, h3, h4, h5, h6, td { 13 | font-family:Georgia, Arial, Sans-serif; 14 | } 15 | body, .body_style { 16 | font-size:12px; 17 | color:#ALTERNATIVE_COLOR; 18 | } 19 | .body_style { 20 | background-color:#BG_COLOR; 21 | } 22 | 23 | 24 | .holder { 25 | padding:2.5%; 26 | } 27 | .width { 28 | max-width:650px; 29 | } 30 | .content_main { 31 | border:1px solid #cccccc; 32 | background:url('images/header.jpg') top right no-repeat #ffffff; 33 | } 34 | 35 | 36 | .from, .branding_html { 37 | font-size:16px; 38 | font-weight: bold; 39 | padding:15px 14% 20px 5%; 40 | } 41 | .title { 42 | font-size: 40px; 43 | line-height: 50px; 44 | margin:0px; 45 | padding:20px 14% 0 5%; 46 | font-weight: bold; 47 | } 48 | .separator_holder { 49 | padding:15px 5%; 50 | } 51 | .separator { 52 | border-bottom:1px solid #cccccc; 53 | } 54 | .email_content, .email_content table, .email_content h1, .email_content h2, .email_content h3, .email_content h4, .email_content h5, .email_content h6 { 55 | color: #BODY_COLOR; 56 | } 57 | .email_content, .contact_info { 58 | padding:15px 35px 10px; 59 | } 60 | p { 61 | font-size:12px; 62 | line-height:22px; 63 | } 64 | .contact_info { 65 | font-family: monospace; 66 | padding: 0 5% 35px; 67 | } 68 | .view_link { 69 | text-align: center; 70 | } 71 | .view_link a { 72 | line-height: 25px; 73 | } 74 | 75 | 76 | .content_footer { 77 | text-align: center; 78 | text-shadow: -1px -1px 0px #ffffff; 79 | font-weight: bold; 80 | } 81 | .site-link { 82 | padding-top:20px; 83 | } -------------------------------------------------------------------------------- /lib/templates/Minimise/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | Theme Name: Minimise 3 | Theme URI: http://premium.wpmudev.org 4 | Author: Cole (Incsub), Maniu (Incsub) 5 | Author URI: http://premium.wpmudev.org 6 | Description: Responsive theme with: max width 700px, max content width 628px 7 | Version: 1.5 8 | License: GNU General Public License v2 or later 9 | License URI: http://www.gnu.org/licenses/gpl-2.0.html 10 | */ 11 | 12 | body, .body_style, h1, h2, h3, h4, h5, h6, td { 13 | font-family:Georgia, Arial, Sans-serif; 14 | } 15 | body, .body_style { 16 | font-size:12px; 17 | color:#ALTERNATIVE_COLOR; 18 | } 19 | .body_style { 20 | background-color:#BG_COLOR; 21 | } 22 | 23 | 24 | .holder { 25 | padding:2.5%; 26 | } 27 | .width { 28 | max-width:700px; 29 | } 30 | .content_main { 31 | background-color:#ffffff; 32 | border:1px solid #cccccc; 33 | } 34 | 35 | 36 | .from, .branding_html { 37 | font-size:14px; 38 | padding:15px 5% 10px; 39 | } 40 | .title { 41 | font-size: 50px; 42 | line-height: 60px; 43 | margin:0px; 44 | padding:0px 5%; 45 | font-weight: bold; 46 | text-shadow: -1px -1px 0px #000000; 47 | color: #TITLE_COLOR; 48 | } 49 | .separator_holder { 50 | padding:15px 5%; 51 | } 52 | .separator { 53 | width:630px; 54 | max-width: 100%; 55 | border-bottom:1px solid #cccccc; 56 | } 57 | .email_content, .email_content table, .email_content h1, .email_content h2, .email_content h3, .email_content h4, .email_content h5, .email_content h6 { 58 | color: #BODY_COLOR; 59 | } 60 | .email_content, .contact_info { 61 | padding:5px 35px; 62 | } 63 | p { 64 | font-size:12px; 65 | line-height:22px; 66 | } 67 | .contact_info { 68 | font-family: monospace; 69 | padding: 0 5% 35px; 70 | } 71 | .view_link { 72 | text-align: center; 73 | } 74 | .view_link a { 75 | line-height: 25px; 76 | } 77 | 78 | 79 | .content_site-link { 80 | width: 100%; 81 | text-align: center; 82 | text-transform: uppercase; 83 | font-weight:bold; 84 | } 85 | .site-link { 86 | padding-top:20px; 87 | } -------------------------------------------------------------------------------- /assets/slick/fonts/slick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by Fontastic.me 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- 1 | Plugin Name: HTML Email Templates 2 | Author: Aaron Edwards (incsub) 3 | http://premium.wpmudev.org/project/html-email-templates/ 4 | 5 | Change Log: 6 | ---------------------------------------------------------------------- 7 | ---------------------------------------------------------------------- 8 | 9 | 2.0.6 - 10/23/2015 - Umesh Kumar 10 | ---------------------------------------------------------------------- 11 | 12 | -Fixed: Compatibility with Subscribe by email 13 | -Updated: wp_htmlemail_nl2br` is set to false by default nowonwards 14 | 15 | 2.0.5 - 10/1/2015 - Umesh Kumar 16 | ---------------------------------------------------------------------- 17 | - Fixed: Password reset link missing for New users 18 | - Added: Convert Next line to line breaks (Use filter `wp_htmlemail_nl2br` to disable conversion ) 19 | 20 | 2.0.4 - 6/25/2015 - Umesh Kumar 21 | ---------------------------------------------------------------------- 22 | - Fixed: Pro Sites compatibility 23 | - New: Option to switch off HTML Emails overwrite for existing HTML Email 24 | 25 | 2.0.3 - 5/7/2015 - Umesh Kumar 26 | ---------------------------------------------------------------------- 27 | - Fix: Show only published recent posts 28 | 29 | 2.0.2 - 7/30/2014 - Umesh Kumar 30 | ---------------------------------------------------------------------- 31 | - Fix: WooCommerce text emails being broken 32 | 33 | 2.0.1 - 7/23/2014 - Umesh Kumar 34 | ---------------------------------------------------------------------- 35 | - New: Send preview emil using ajax, instead of form submit 36 | - Fix: remove wpautop for html messages 37 | - Fix: mail not being site, if template is empty 38 | - Fix: content being replace multiple times for some templates 39 | 40 | 2.0 - 5/31/2014 - Umesh Kumar 41 | ---------------------------------------------------------------------- 42 | - New: Site wise template selection option 43 | - New: Added Templates and Instant Preview option 44 | - Filters: Works for template with sidebar: 45 | htmlemail_sidebar_posts => List of posts to be displayed, 46 | htmlemail_sidebar_title => Tile of sidebar 47 | 48 | 1.1 - 3/6/2014 49 | ---------------------------------------------------------------------- 50 | - Fix: Preserve other email headers 51 | 52 | 1.0 - 3/6/2013 53 | ---------------------------------------------------------------------- 54 | - Initial release -------------------------------------------------------------------------------- /lib/templates/Iletter/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 54 | 55 |
4 |
5 | 6 | 7 | 8 | 13 | 14 | 15 | 22 | 23 | 24 | 28 | 29 | 30 | 36 | 37 | 38 | 44 | 45 | 46 | 49 | 50 |
9 | 11 | {BLOG_DESCRIPTION} 12 |
16 |
17 | 19 | {BLOG_NAME} 20 |
21 |
25 | 26 | {HEADER_IMAGE} 27 |
39 |
40 |
Datum Email sent {DATE} @ {TIME}
41 |
Contact For any requests, please contact {ADMIN_EMAIL}
42 |
43 |
51 | 52 |
53 |
-------------------------------------------------------------------------------- /lib/templates/Promy/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 60 | 61 |
4 |
5 | 6 | 7 | 8 | 13 | 14 | 15 | 22 | 23 |
9 | 11 | {BLOG_DESCRIPTION} 12 |
16 |
17 | 19 | {BLOG_NAME} 20 |
21 |
24 | 25 | 26 | 27 | 31 | 32 | 33 | 39 | 40 |
28 | 29 | {HEADER_IMAGE} 30 |
41 | 42 | 43 | 44 | 50 | 51 | 52 | 55 | 56 |
45 |
46 |
Datum Email sent {DATE} @ {TIME}
47 |
Contact For any requests, please contact {ADMIN_EMAIL}
48 |
49 |
57 | 58 |
59 |
-------------------------------------------------------------------------------- /lib/templates/Simplicitylight/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 64 | 65 |
4 |
5 | 6 | 7 | 8 | 13 | 14 | 15 | 22 | 23 | 24 | 27 | 30 | 33 | 34 |
9 | 11 | {BLOG_DESCRIPTION} 12 |
16 |
17 | 19 | {BLOG_NAME} 20 |
21 |
28 | {FROM_NAME} 29 | 31 | {FROM_EMAIL} 32 |
35 | 36 | 37 | 43 | 44 | 45 | 51 | 52 |
46 |
47 |
Datum Email sent {DATE} @ {TIME}
48 |
Contact For any requests, please contact {ADMIN_EMAIL}
49 |
50 |
53 | 54 | 55 | 56 | 59 | 60 | 61 | 62 |
63 |
-------------------------------------------------------------------------------- /lib/templates/Simplicitydark/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 64 | 65 |
4 |
5 | 6 | 7 | 8 | 13 | 14 | 15 | 22 | 23 | 24 | 27 | 30 | 33 | 34 |
9 | 11 | {BLOG_DESCRIPTION} 12 |
16 |
17 | 19 | {BLOG_NAME} 20 |
21 |
28 | {FROM_NAME} 29 | 31 | {FROM_EMAIL} 32 |
35 | 36 | 37 | 43 | 44 | 45 | 51 | 52 |
46 |
47 |
Datum Email sent {DATE} @ {TIME}
48 |
Contact For any requests, please contact {ADMIN_EMAIL}
49 |
50 |
53 | 54 | 55 | 56 | 59 | 60 | 61 | 62 |
63 |
-------------------------------------------------------------------------------- /lib/templates/Minimise/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 64 | 65 |
4 |
5 | 6 | 7 | 8 | 13 | 14 | 15 | 21 | 22 | 23 | 30 | 31 | 32 | 35 | 36 | 37 | 43 | 44 | 45 | 51 | 52 |
9 | 11 | {BLOG_DESCRIPTION} 12 |
16 | 19 | From {FROM_NAME} ({FROM_EMAIL}) 20 |
24 |
25 | 27 | {BLOG_NAME} 28 |
29 |
33 |
34 |
46 |
47 |
Datum Email sent {DATE} @ {TIME}
48 |
Contact For any requests, please contact {ADMIN_EMAIL}
49 |
50 |
53 | 54 | 55 | 56 | 59 | 60 | 61 | 62 |
63 |
-------------------------------------------------------------------------------- /lib/templates/Handwritten/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 67 | 68 |
4 |
5 | 6 | 7 | 8 | 13 | 14 | 15 | 22 | 23 | 24 | 30 | 31 | 32 | 36 | 37 | 38 | 44 | 45 | 46 | 52 | 53 |
9 | 11 | {BLOG_DESCRIPTION} 12 |
16 |
17 | 19 | {BLOG_NAME} 20 |
21 |
25 | 28 | From {FROM_NAME} ({FROM_EMAIL}) 29 |
33 | 34 | {HEADER_IMAGE} 35 |
47 |
48 |
Datum Email sent {DATE} @ {TIME}
49 |
Contact For any requests, please contact {ADMIN_EMAIL}
50 |
51 |
54 | 55 | 56 | 57 | 62 | 63 | 64 | 65 |
66 |
-------------------------------------------------------------------------------- /assets/slick/slick.css: -------------------------------------------------------------------------------- 1 | /* Slider */ 2 | .slick-slider { position: relative; display: block; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -ms-touch-action: none; touch-action: none; -webkit-tap-highlight-color: transparent; } 3 | 4 | .slick-list { position: relative; overflow: hidden; display: block; margin: 0; padding: 0; } 5 | .slick-list:focus { outline: none; } 6 | .slick-loading .slick-list { background: white url(./ajax-loader.gif) center center no-repeat; } 7 | .slick-list.dragging { cursor: pointer; cursor: hand; } 8 | 9 | .slick-slider .slick-list, .slick-track, .slick-slide, .slick-slide img { -webkit-transform: translate3d(0, 0, 0); -moz-transform: translate3d(0, 0, 0); -ms-transform: translate3d(0, 0, 0); -o-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } 10 | 11 | .slick-track { position: relative; left: 0; top: 0; display: block; zoom: 1; } 12 | .slick-track:before, .slick-track:after { content: ""; display: table; } 13 | .slick-track:after { clear: both; } 14 | .slick-loading .slick-track { visibility: hidden; } 15 | 16 | .slick-slide { float: left; height: 100%; min-height: 1px; display: none; } 17 | .slick-slide img { display: block; } 18 | .slick-slide.slick-loading img { display: none; } 19 | .slick-slide.dragging img { pointer-events: none; } 20 | .slick-initialized .slick-slide { display: block; } 21 | .slick-loading .slick-slide { visibility: hidden; } 22 | .slick-vertical .slick-slide { display: block; height: auto; border: 1px solid transparent; } 23 | 24 | /* Icons */ 25 | @font-face { font-family: "slick"; src: url("./fonts/slick.eot"); src: url("./fonts/slick.eot?#iefix") format("embedded-opentype"), url("./fonts/slick.woff") format("woff"), url("./fonts/slick.ttf") format("truetype"), url("./fonts/slick.svg#slick") format("svg"); font-weight: normal; font-style: normal; } 26 | /* Arrows */ 27 | .slick-prev, .slick-next { position: absolute; display: block; height: 20px; width: 20px; line-height: 0; font-size: 0; cursor: pointer; background: transparent; color: transparent; top: 50%; margin-top: -10px; padding: 0; border: none; outline: none; } 28 | .slick-prev:focus, .slick-next:focus { outline: none; } 29 | .slick-prev.slick-disabled:before, .slick-next.slick-disabled:before { opacity: 0.25; } 30 | 31 | .slick-prev:before, .slick-next:before { font-family: "slick"; font-size: 20px; line-height: 1; color: white; opacity: 0.85; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } 32 | 33 | .slick-prev { left: -25px; } 34 | .slick-prev:before { content: "\2190"; } 35 | 36 | .slick-next { right: -25px; } 37 | .slick-next:before { content: "\2192"; } 38 | 39 | /* Dots */ 40 | .slick-slider { margin-bottom: 30px; } 41 | 42 | .slick-dots { position: absolute; bottom: -45px; list-style: none; display: block; text-align: center; padding: 0px; width: 100%; } 43 | .slick-dots li { position: relative; display: inline-block; height: 20px; width: 20px; margin: 0px 5px; padding: 0px; cursor: pointer; } 44 | .slick-dots li button { border: 0; background: transparent; display: block; height: 20px; width: 20px; outline: none; line-height: 0; font-size: 0; color: transparent; padding: 5px; cursor: pointer; outline: none; } 45 | .slick-dots li button:focus { outline: none; } 46 | .slick-dots li button:before { position: absolute; top: 0; left: 0; content: "\2022"; width: 20px; height: 20px; font-family: "slick"; font-size: 6px; line-height: 20px; text-align: center; color: black; opacity: 0.25; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } 47 | .slick-dots li.slick-active button:before { opacity: 0.75; } 48 | -------------------------------------------------------------------------------- /lib/templates/Disco/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 75 | 76 |
4 |
5 | 6 | 7 | 8 | 13 | 14 | 15 | 22 | 23 | 24 | 28 | 29 |
9 | 11 | {BLOG_DESCRIPTION} 12 |
16 |
17 | 19 | {BLOG_NAME} 20 |
21 |
25 | 26 | {HEADER_IMAGE} 27 |
30 | 31 | 32 | 39 | 40 | 41 | 47 | 48 | 49 | 60 | 61 |
33 | 37 | From {FROM_NAME} ({FROM_EMAIL}) 38 |
50 |
51 |
52 | Datum 53 | Email sent {DATE} @ {TIME} 54 |
55 |
56 | Contact 57 | For any requests, please contact {ADMIN_EMAIL}
58 |
59 |
62 | 63 | 64 | 65 | 70 | 71 | 72 | 73 |
74 |
-------------------------------------------------------------------------------- /lib/templates/Hero/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {EMAIL_SUBJECT} 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 37 | 38 | 39 |
19 | 20 |
21 | 22 | 23 | 27 | 32 | 33 |
24 | 25 | 26 | 28 | 30 |
{BLOG_NAME}
31 |
34 |
35 | 36 |
40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 119 | 120 | 121 |
48 | 49 |
50 | 51 | 52 | 114 | 115 |
53 | 55 |

Hey, {USER_NAME}

56 | 57 |

{MESSAGE}

58 | 59 | 60 |

61 | 62 |

63 |
64 | 65 | 66 | 67 | 68 | 108 | 109 | 110 | 111 | 112 | 113 |
116 |
117 | 118 |
122 | 123 | 124 | 125 | 126 | 127 | 128 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /assets/css/htmlemail.css: -------------------------------------------------------------------------------- 1 | /* 2 | Created on : 14 May, 2014, 4:08:11 PM 3 | Author : umesh 4 | */ 5 | .email-templates-wrapper{ 6 | max-height: 300px; 7 | overflow: hidden; 8 | padding: 0 30px 20px; 9 | } 10 | /* Templates Wrapper */ 11 | .template-wrapper { 12 | display: none; 13 | padding: 10px 0; 14 | } 15 | .template-toggle{ 16 | font-size: 13px; 17 | font-weight: normal; 18 | text-decoration: none; 19 | } 20 | .template-toggle:active, .template-toggle:focus { 21 | outline: none; 22 | } 23 | .toggle-indicator{ 24 | display: inline-block; 25 | } 26 | /* Slider Styling */ 27 | .template-holder { 28 | float: left; 29 | text-align: center; 30 | padding-bottom: 10px; 31 | } 32 | 33 | .template-holder:hover{ 34 | opacity: 1; 35 | transition: opacity .25s ease; 36 | -moz-transition: opacity .25s ease; 37 | -webkit-transition: opacity .25s ease; 38 | background: #ddd; 39 | } 40 | 41 | .template-holder img.theme-preview { 42 | max-width: 220px; 43 | max-height: 220px; 44 | } 45 | .template-holder a{ 46 | font-size: medium; 47 | line-height: 1.5; 48 | } 49 | .template-selector{ 50 | float: none; 51 | display: block; 52 | margin: 0 10px; 53 | text-align: center; 54 | text-decoration: none; 55 | color: #555; 56 | font-weight: bold; 57 | } 58 | 59 | .template-holder a img { 60 | border: 2px solid transparent; 61 | margin: 5px 0 0 0; 62 | display: inline-block; 63 | } 64 | .template-holder.active-theme { 65 | opacity: 1; 66 | } 67 | .template-holder.active-theme img { 68 | border: 2px solid #2ea2cc; 69 | box-shadow: 0 2px 4px rgba(0,0,0,0.6); 70 | } 71 | /* Fixes arrow position */ 72 | .slick-next { 73 | margin-right: 22px; 74 | } 75 | .slick-prev:before, .slick-next:before { 76 | color: #2ea2cc; 77 | font-size: 30px; 78 | } 79 | .slick-list { 80 | /*margin-left: 12px;*/ 81 | } 82 | .slick-slide { 83 | opacity: 0.6; 84 | } 85 | .template-holder.slick-slide a:focus, .template-holder.slick-slide a:active { 86 | box-shadow: none; 87 | outline: 0; 88 | } 89 | /*Refernce Link */ 90 | .list-ref { 91 | display: none; 92 | } 93 | /* Buttons Styling*/ 94 | .action-wrapper { 95 | overflow: hidden; 96 | } 97 | .action-wrapper .spinner { 98 | float: none; 99 | margin-top: 4px; 100 | margin-bottom: 0; 101 | } 102 | .action-wrapper .button-primary, .action-wrapper .button-secondary, .action-wrapper #preview_template { 103 | float: left; 104 | } 105 | .action-wrapper .button-secondary, .action-wrapper #preview_template { 106 | margin-left: 5px; 107 | } 108 | .load_template.button-primary { 109 | margin: 0 auto; 110 | margin-top: 10px; 111 | width: 80%; 112 | display: block; 113 | text-align: center; 114 | } 115 | .preview-email { 116 | clear: left; 117 | display: none; 118 | float: left; 119 | margin-top: 25px; 120 | overflow: hidden; 121 | } 122 | .preview-email .button-primary { 123 | float: none; 124 | } 125 | .preview-email .button-primary:active, .preview-email .button-primary:focus { 126 | vertical-align: 0; 127 | } 128 | .preview-email input[name="preview_html_email_address"] { 129 | line-height: 1.5; 130 | padding: 4px; 131 | width: 220px; 132 | } 133 | 134 | .template-settings-options .options-label{ 135 | display: inline-block; 136 | width: 180px; 137 | } 138 | .wrap .updated.preview-email-status, .wrap .error.preview-email-status { 139 | margin: 20px 0 0; 140 | } 141 | /* Placeholder list table styling */ 142 | #placeholder-list-wrapper, 143 | #template-images-wrapper { 144 | display: none; 145 | } 146 | .template-placeholders-list { 147 | background: white; 148 | border: 1px solid #c1c1c1; 149 | width: 60%; 150 | } 151 | .template-placeholders-list tr:nth-child(even) { 152 | background: #F3F3F3; 153 | } 154 | .template-placeholders-list tr:nth-child(odd) { 155 | background: white; 156 | } 157 | .template-placeholders-list th, .template-placeholders-list td { 158 | padding: 5px; 159 | text-align: left; 160 | } 161 | .template-placeholders-list td:first-child { 162 | width: 24%; 163 | } 164 | /*Configuration guide */ 165 | .config-guide { 166 | padding: 1px 5px; 167 | } 168 | .config-guide h3 { 169 | padding: 4px 4px 4px 0; 170 | } 171 | li.config-step { 172 | display: inline-block; 173 | overflow: hidden; 174 | margin: 0 5px 0 0; 175 | padding: 5px 0; 176 | vertical-align: top; 177 | width: 24%; 178 | } 179 | li.config-step:last-child{ 180 | margin: 0; 181 | } 182 | li .step-count { 183 | display: block; 184 | font-weight: bold; 185 | padding: 5px 0; 186 | width: 45px; 187 | } 188 | -------------------------------------------------------------------------------- /lib/templates/Sidebar/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {EMAIL_SUBJECT} 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 36 | 37 | 38 |
18 | 19 |
20 | 21 | 22 | 26 | 31 | 32 |
23 | 24 | 25 | 27 | 29 |
{BLOG_NAME}
30 |
33 |
34 | 35 |
39 | 40 | 41 | 42 | 43 | 44 | 45 | 141 | 142 | 143 |
46 | 47 |
48 | 49 |
50 | 51 | 52 | 60 | 61 |
53 | 55 |

Hello, {USER_NAME}

56 | 57 |

{MESSAGE}

58 | 59 |
62 |
63 | 64 |
65 | 66 | 67 | 86 | 87 |
88 |
89 |
90 | 91 | 92 | 93 | 131 | 132 | 133 | 134 |
135 | 136 |
137 | 138 |
139 | 140 |
144 | 145 | 146 | 147 | 148 | 149 | 150 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | -------------------------------------------------------------------------------- /lib/templates/Hero/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | Theme Name: Hero 3 | Theme URI: http://zurb.com/playground/responsive-email-templates 4 | Author: Zurb 5 | Author URI: http://zurb.com/ 6 | Description: Responsive email template with sidebar 7 | */ 8 | /* ------------------------------------- 9 | GLOBAL 10 | ------------------------------------- */ 11 | * { 12 | margin:0; 13 | padding:0; 14 | } 15 | * { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; } 16 | 17 | img { 18 | max-width: 100%; 19 | } 20 | .collapse { 21 | margin:0; 22 | padding:0; 23 | } 24 | body { 25 | -webkit-font-smoothing:antialiased; 26 | -webkit-text-size-adjust:none; 27 | width: 100%!important; 28 | height: 100%; 29 | } 30 | 31 | 32 | /* ------------------------------------- 33 | ELEMENTS 34 | ------------------------------------- */ 35 | a { color: #2BA6CB;} 36 | 37 | .btn { 38 | text-decoration:none; 39 | color: #FFF; 40 | background-color: #666; 41 | padding:10px 16px; 42 | font-weight:bold; 43 | margin-right:10px; 44 | text-align:center; 45 | cursor:pointer; 46 | display: inline-block; 47 | } 48 | 49 | p.callout { 50 | padding:15px; 51 | background-color:#ECF8FF; 52 | margin-bottom: 15px; 53 | } 54 | .callout a { 55 | font-weight:bold; 56 | color: #2BA6CB; 57 | } 58 | 59 | table.social { 60 | /* padding:15px; */ 61 | background-color: #ebebeb; 62 | 63 | } 64 | .social .soc-btn { 65 | padding: 3px 7px; 66 | font-size:12px; 67 | margin-bottom:10px; 68 | text-decoration:none; 69 | color: #FFF;font-weight:bold; 70 | display:block; 71 | text-align:center; 72 | } 73 | a.fb { background-color: #3B5998!important; } 74 | a.tw { background-color: #1daced!important; } 75 | a.gp { background-color: #DB4A39!important; } 76 | a.ms { background-color: #000!important; } 77 | 78 | .sidebar .soc-btn { 79 | display:block; 80 | width:100%; 81 | } 82 | 83 | /* ------------------------------------- 84 | HEADER 85 | ------------------------------------- */ 86 | table.head-wrap { width: 100%;} 87 | 88 | .header.container table td.logo { padding: 15px; } 89 | .header.container table td.label { padding: 15px; padding-left:0px;} 90 | 91 | 92 | /* ------------------------------------- 93 | BODY 94 | ------------------------------------- */ 95 | table.body-wrap { width: 100%;} 96 | 97 | 98 | /* ------------------------------------- 99 | FOOTER 100 | ------------------------------------- */ 101 | table.footer-wrap { width: 100%; clear:both!important; 102 | } 103 | .footer-wrap .container td.content p { border-top: 1px solid rgb(215,215,215); padding-top:15px;} 104 | .footer-wrap .container td.content p { 105 | font-size:10px; 106 | font-weight: bold; 107 | 108 | } 109 | 110 | 111 | /* ------------------------------------- 112 | TYPOGRAPHY 113 | ------------------------------------- */ 114 | h1,h2,h3,h4,h5,h6 { 115 | font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; color:#000; 116 | } 117 | h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; } 118 | 119 | h1 { font-weight:200; font-size: 44px;} 120 | h2 { font-weight:200; font-size: 37px;} 121 | h3 { font-weight:500; font-size: 27px;} 122 | h4 { font-weight:500; font-size: 23px;} 123 | h5 { font-weight:900; font-size: 17px;} 124 | h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;} 125 | 126 | .collapse { margin:0!important;} 127 | 128 | p, ul { 129 | margin-bottom: 10px; 130 | font-weight: normal; 131 | font-size:14px; 132 | line-height:1.6; 133 | } 134 | p.lead { font-size:17px; } 135 | p.last { margin-bottom:0px;} 136 | 137 | ul li { 138 | margin-left:5px; 139 | list-style-position: inside; 140 | } 141 | 142 | /* ------------------------------------- 143 | SIDEBAR 144 | ------------------------------------- */ 145 | ul.sidebar { 146 | background:#ebebeb; 147 | display:block; 148 | list-style-type: none; 149 | } 150 | ul.sidebar li { display: block; margin:0;} 151 | ul.sidebar li a { 152 | text-decoration:none; 153 | color: #666; 154 | padding:10px 16px; 155 | /* font-weight:bold; */ 156 | margin-right:10px; 157 | /* text-align:center; */ 158 | cursor:pointer; 159 | border-bottom: 1px solid #777777; 160 | border-top: 1px solid #FFFFFF; 161 | display:block; 162 | margin:0; 163 | } 164 | ul.sidebar li a.last { border-bottom-width:0px;} 165 | ul.sidebar li a h1,ul.sidebar li a h2,ul.sidebar li a h3,ul.sidebar li a h4,ul.sidebar li a h5,ul.sidebar li a h6,ul.sidebar li a p { margin-bottom:0!important;} 166 | 167 | 168 | 169 | /* --------------------------------------------------- 170 | RESPONSIVENESS 171 | Nuke it from orbit. It's the only way to be sure. 172 | ------------------------------------------------------ */ 173 | 174 | /* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */ 175 | .container { 176 | display:block!important; 177 | max-width:600px!important; 178 | margin:0 auto!important; /* makes it centered */ 179 | clear:both!important; 180 | } 181 | 182 | /* This should also be a block element, so that it will fill 100% of the .container */ 183 | .content { 184 | padding:15px; 185 | max-width:600px; 186 | margin:0 auto; 187 | display:block; 188 | } 189 | 190 | /* Let's make sure tables in the content area are 100% wide */ 191 | .content table { width: 100%; } 192 | 193 | 194 | /* Odds and ends */ 195 | .column { 196 | width: 300px; 197 | float:left; 198 | } 199 | .column tr td { padding: 15px; } 200 | .column-wrap { 201 | padding:0!important; 202 | margin:0 auto; 203 | max-width:600px!important; 204 | } 205 | .column table { width:100%;} 206 | .social .column { 207 | width: 280px; 208 | min-width: 279px; 209 | float:left; 210 | } 211 | 212 | /* Be sure to place a .clear element after each set of columns, just to be safe */ 213 | .clear { display: block; clear: both; } 214 | 215 | 216 | /* ------------------------------------------- 217 | PHONE 218 | For clients that support media queries. 219 | Nothing fancy. 220 | -------------------------------------------- */ 221 | @media only screen and (max-width: 600px) { 222 | 223 | a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;} 224 | 225 | div[class="column"] { width: auto!important; float:none!important;} 226 | 227 | table.social div[class="column"] { 228 | width:auto!important; 229 | } 230 | 231 | } -------------------------------------------------------------------------------- /lib/templates/Sidebar/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | Theme Name: Sidebar 3 | Theme URI: http://zurb.com/playground/responsive-email-templates 4 | Author: Zurb 5 | Author URI: http://zurb.com/ 6 | Description: Responsive email template with sidebar 7 | */ 8 | /* ------------------------------------- 9 | GLOBAL 10 | ------------------------------------- */ 11 | * { 12 | margin:0; 13 | padding:0; 14 | } 15 | * { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; } 16 | 17 | img { 18 | max-width: 100%; 19 | } 20 | .collapse { 21 | margin:0; 22 | padding:0; 23 | } 24 | body { 25 | -webkit-font-smoothing:antialiased; 26 | -webkit-text-size-adjust:none; 27 | width: 100%!important; 28 | height: 100%; 29 | } 30 | 31 | 32 | /* ------------------------------------- 33 | ELEMENTS 34 | ------------------------------------- */ 35 | a { color: #2BA6CB;} 36 | 37 | .btn { 38 | text-decoration:none; 39 | color: #FFF; 40 | background-color: #666; 41 | padding:10px 16px; 42 | font-weight:bold; 43 | margin-right:10px; 44 | text-align:center; 45 | cursor:pointer; 46 | display: inline-block; 47 | } 48 | 49 | p.callout { 50 | padding:15px; 51 | background-color:#ECF8FF; 52 | margin-bottom: 15px; 53 | } 54 | .callout a { 55 | font-weight:bold; 56 | color: #2BA6CB; 57 | } 58 | 59 | table.social { 60 | /* padding:15px; */ 61 | background-color: #ebebeb; 62 | 63 | } 64 | .social .soc-btn { 65 | padding: 3px 7px; 66 | font-size:12px; 67 | margin-bottom:10px; 68 | text-decoration:none; 69 | color: #FFF;font-weight:bold; 70 | display:block; 71 | text-align:center; 72 | } 73 | a.fb { background-color: #3B5998!important; } 74 | a.tw { background-color: #1daced!important; } 75 | a.gp { background-color: #DB4A39!important; } 76 | a.ms { background-color: #000!important; } 77 | 78 | .sidebar .soc-btn { 79 | display:block; 80 | width:100%; 81 | } 82 | 83 | /* ------------------------------------- 84 | HEADER 85 | ------------------------------------- */ 86 | table.head-wrap { width: 100%;} 87 | 88 | .header.container table td.logo { padding: 15px; } 89 | .header.container table td.label { padding: 15px; padding-left:0px;} 90 | 91 | 92 | /* ------------------------------------- 93 | BODY 94 | ------------------------------------- */ 95 | table.body-wrap { width: 100%;} 96 | 97 | 98 | /* ------------------------------------- 99 | FOOTER 100 | ------------------------------------- */ 101 | table.footer-wrap { width: 100%; clear:both!important; 102 | } 103 | .footer-wrap .container td.content p { border-top: 1px solid rgb(215,215,215); padding-top:15px;} 104 | .footer-wrap .container td.content p { 105 | font-size:10px; 106 | font-weight: bold; 107 | 108 | } 109 | 110 | 111 | /* ------------------------------------- 112 | TYPOGRAPHY 113 | ------------------------------------- */ 114 | h1,h2,h3,h4,h5,h6 { 115 | font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; color:#000; 116 | } 117 | h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; } 118 | 119 | h1 { font-weight:200; font-size: 44px;} 120 | h2 { font-weight:200; font-size: 37px;} 121 | h3 { font-weight:500; font-size: 27px;} 122 | h4 { font-weight:500; font-size: 23px;} 123 | h5 { font-weight:900; font-size: 17px;} 124 | h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;} 125 | 126 | .collapse { margin:0!important;} 127 | 128 | p, ul { 129 | margin-bottom: 10px; 130 | font-weight: normal; 131 | font-size:14px; 132 | line-height:1.6; 133 | } 134 | p.lead { font-size:17px; } 135 | p.last { margin-bottom:0px;} 136 | 137 | ul li { 138 | margin-left:5px; 139 | list-style-position: inside; 140 | } 141 | 142 | /* ------------------------------------- 143 | SIDEBAR 144 | ------------------------------------- */ 145 | ul.sidebar { 146 | background:#ebebeb; 147 | display:block; 148 | list-style-type: none; 149 | } 150 | ul.sidebar li { display: block; margin:0;} 151 | ul.sidebar li a { 152 | text-decoration:none; 153 | color: #666; 154 | padding:10px 16px; 155 | /* font-weight:bold; */ 156 | margin-right:10px; 157 | /* text-align:center; */ 158 | cursor:pointer; 159 | border-bottom: 1px solid #777777; 160 | border-top: 1px solid #FFFFFF; 161 | display:block; 162 | margin:0; 163 | } 164 | ul.sidebar li a.last { border-bottom-width:0px;} 165 | ul.sidebar li a h1,ul.sidebar li a h2,ul.sidebar li a h3,ul.sidebar li a h4,ul.sidebar li a h5,ul.sidebar li a h6,ul.sidebar li a p { margin-bottom:0!important;} 166 | 167 | /* --------------------------------------------------- 168 | RESPONSIVENESS 169 | Nuke it from orbit. It's the only way to be sure. 170 | ------------------------------------------------------ */ 171 | 172 | /* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */ 173 | .container { 174 | display:block!important; 175 | max-width:600px!important; 176 | margin:0 auto!important; /* makes it centered */ 177 | clear:both!important; 178 | } 179 | 180 | /* This should also be a block element, so that it will fill 100% of the .container */ 181 | .content { 182 | padding:15px; 183 | max-width:600px; 184 | margin:0 auto; 185 | display:block; 186 | } 187 | 188 | /* Let's make sure tables in the content area are 100% wide */ 189 | .content table { width: 100%; } 190 | 191 | 192 | /* Odds and ends */ 193 | .column { 194 | width: 300px; 195 | float:left; 196 | } 197 | .column tr td { padding: 15px; } 198 | .column tr td.sidebar-td { padding: 0 15px; } 199 | .column-wrap { 200 | padding:0!important; 201 | margin:0 auto; 202 | max-width:600px!important; 203 | } 204 | .column table { width:100%;} 205 | .social .column { 206 | width: 280px; 207 | min-width: 279px; 208 | float:left; 209 | } 210 | 211 | /* Be sure to place a .clear element after each set of columns, just to be safe */ 212 | .clear { display: block; clear: both; } 213 | 214 | 215 | /* ------------------------------------------- 216 | PHONE 217 | For clients that support media queries. 218 | Nothing fancy. 219 | -------------------------------------------- */ 220 | @media only screen and (max-width: 600px) { 221 | 222 | a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;} 223 | 224 | div[class="column"] { width: auto!important; float:none!important;} 225 | 226 | table.social div[class="column"] { 227 | width:auto!important; 228 | } 229 | 230 | } -------------------------------------------------------------------------------- /languages/htmlemail.pot: -------------------------------------------------------------------------------- 1 | #, fuzzy 2 | msgid "" 3 | msgstr "" 4 | "Project-Id-Version: HTML Email Templates\n" 5 | "POT-Creation-Date: 2015-10-23 15:48+0530\n" 6 | "PO-Revision-Date: 2015-10-01 12:45+0530\n" 7 | "Last-Translator: Umesh \n" 8 | "Language-Team: Umesh \n" 9 | "MIME-Version: 1.0\n" 10 | "Content-Type: text/plain; charset=UTF-8\n" 11 | "Content-Transfer-Encoding: 8bit\n" 12 | "X-Generator: Poedit 1.8.1\n" 13 | "X-Poedit-Basepath: ..\n" 14 | "X-Poedit-WPHeader: htmlemail.php\n" 15 | "X-Poedit-SourceCharset: UTF-8\n" 16 | "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;" 17 | "esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;" 18 | "_nx_noop:3c,1,2;__ngettext_noop:1,2\n" 19 | "X-Poedit-SearchPath-0: .\n" 20 | "X-Poedit-SearchPathExcluded-0: *.js\n" 21 | 22 | #: htmlemail.php:120 23 | msgid "" 24 | "There was an issue determining where HTML Email is installed. Please " 25 | "reinstall." 26 | msgstr "" 27 | 28 | #: htmlemail.php:298 htmlemail.php:308 htmlemail.php:316 htmlemail.php:374 29 | msgid "HTML Email Template" 30 | msgstr "" 31 | 32 | #: htmlemail.php:334 htmlemail.php:336 33 | msgid "Settings" 34 | msgstr "" 35 | 36 | #: htmlemail.php:376 37 | msgid "" 38 | "This plugin will wrap every WordPress email sent within an HTML template." 39 | msgstr "" 40 | 41 | #: htmlemail.php:379 42 | msgid "Four easy steps to send better emails:" 43 | msgstr "" 44 | 45 | #: htmlemail.php:382 46 | msgid "" 47 | "Either select a pre-designed template below by clicking over a " 49 | "template and then click over the load template button or type/paste your own " 50 | "HTML into the textarea." 51 | msgstr "" 52 | 53 | #: htmlemail.php:383 54 | msgid "" 55 | "Click \"Preview\" to quickly see what your emails will look like in a popup." 56 | msgstr "" 57 | 58 | #: htmlemail.php:384 59 | msgid "" 60 | "Send a \"Test Email\" to preview your template in actual email clients. You " 61 | "can specify an email address for this to be sent to." 62 | msgstr "" 63 | 64 | #: htmlemail.php:385 65 | msgid "" 66 | "Select \"Save\" and the HTML you have below will be used as your HTML Email " 67 | "Template for all transactional emails from your site." 68 | msgstr "" 69 | 70 | #: htmlemail.php:392 71 | #, php-format 72 | msgid "Step %d" 73 | msgstr "" 74 | 75 | #: htmlemail.php:400 76 | msgid "Modify HTML Emails" 77 | msgstr "" 78 | 79 | #: htmlemail.php:402 80 | msgid "Click to toggle templates" 81 | msgstr "" 82 | 83 | #: htmlemail.php:402 84 | msgid "Choose from sample Templates" 85 | msgstr "" 86 | 87 | #: htmlemail.php:419 88 | msgid "Click over the template to select it" 89 | msgstr "" 90 | 91 | #: htmlemail.php:422 92 | msgid "Load template html" 93 | msgstr "" 94 | 95 | #: htmlemail.php:422 96 | msgid "Load Template " 97 | msgstr "" 98 | 99 | #: htmlemail.php:433 100 | msgid "Save" 101 | msgstr "" 102 | 103 | #: htmlemail.php:438 104 | msgid "Live Preview" 105 | msgstr "" 106 | 107 | #: htmlemail.php:438 108 | msgid "Preview" 109 | msgstr "" 110 | 111 | #: htmlemail.php:442 112 | msgid "Test Email" 113 | msgstr "" 114 | 115 | #: htmlemail.php:447 116 | msgid "Send" 117 | msgstr "" 118 | 119 | #: htmlemail.php:452 120 | msgid "" 121 | "Edit the HTML of your email template here. You need to place {MESSAGE} " 122 | "somewhere in the template, preferably a main content section. That will be " 123 | "replaced with the email message." 124 | msgstr "" 125 | 126 | #: htmlemail.php:460 127 | msgid "Allow subsites to override this template with their own." 128 | msgstr "" 129 | 130 | #: htmlemail.php:479 131 | msgid "" 132 | "Your custom template changes will be lost, are you sure you want to continue?" 133 | msgstr "" 134 | 135 | #: htmlemail.php:480 136 | msgid "" 137 | "You need to place {MESSAGE} somewhere in the template, preferably a main " 138 | "content section." 139 | msgstr "" 140 | 141 | #: htmlemail.php:776 142 | msgid "Email content (required)" 143 | msgstr "" 144 | 145 | #: htmlemail.php:777 146 | msgid "Title for the sidebar in email e.g. What's trending" 147 | msgstr "" 148 | 149 | #: htmlemail.php:778 150 | msgid "Sender's name if sender's email is associated with a user account" 151 | msgstr "" 152 | 153 | #: htmlemail.php:779 154 | msgid "Sender's email, email specified in site settings" 155 | msgstr "" 156 | 157 | #: htmlemail.php:780 158 | msgid "Blog / Site URL" 159 | msgstr "" 160 | 161 | #: htmlemail.php:781 162 | msgid "Blog / Site name" 163 | msgstr "" 164 | 165 | #: htmlemail.php:782 166 | msgid "Email address of the support or contact person. Same as {FROM_EMAIL}" 167 | msgstr "" 168 | 169 | #: htmlemail.php:783 170 | msgid "Blog Description" 171 | msgstr "" 172 | 173 | #: htmlemail.php:784 174 | msgid "Current date" 175 | msgstr "" 176 | 177 | #: htmlemail.php:785 178 | msgid "Current time" 179 | msgstr "" 180 | 181 | #: htmlemail.php:788 182 | msgid "Variable list" 183 | msgstr "" 184 | 185 | #: htmlemail.php:788 186 | msgid "List of variables that can be used in template" 187 | msgstr "" 188 | 189 | #: htmlemail.php:949 190 | msgid "Whoops, you don't have permissions to preview html." 191 | msgstr "" 192 | 193 | #: htmlemail.php:952 htmlemail.php:959 194 | msgid "Whoops, you need to enter some html to preview it!" 195 | msgstr "" 196 | 197 | #: htmlemail.php:1014 198 | msgid "Missing Parameters" 199 | msgstr "" 200 | 201 | #: htmlemail.php:1019 202 | msgid "Nonce verification failed" 203 | msgstr "" 204 | 205 | #: htmlemail.php:1027 206 | #, php-format 207 | msgid "Preview email was mailed to %s!" 208 | msgstr "" 209 | 210 | #: htmlemail.php:1030 211 | msgid "Unable to send test email" 212 | msgstr "" 213 | 214 | #: htmlemail.php:1066 215 | msgid "" 216 | "Whoops! There was a problem with the data you posted. Please go back and try " 217 | "again." 218 | msgstr "" 219 | 220 | #: htmlemail.php:1085 221 | msgid "Success! Your changes were sucessfully saved!" 222 | msgstr "" 223 | 224 | #. Plugin Name of the plugin/theme 225 | msgid "HTML Email Templates" 226 | msgstr "" 227 | 228 | #. Plugin URI of the plugin/theme 229 | msgid "https://premium.wpmudev.org/project/html-email-templates/" 230 | msgstr "" 231 | 232 | #. Description of the plugin/theme 233 | msgid "" 234 | "Allows you to add HTML templates for all of the standard Wordpress emails. " 235 | "In Multisite templates can be set network wide or can be allowed to set site " 236 | "wise template, if template override for the site is enabled and template is " 237 | "not specified for a site, network template will be used." 238 | msgstr "" 239 | 240 | #. Author of the plugin/theme 241 | msgid "WPMU DEV" 242 | msgstr "" 243 | 244 | #. Author URI of the plugin/theme 245 | msgid "http://premium.wpmudev.org/" 246 | msgstr "" 247 | -------------------------------------------------------------------------------- /assets/js/htmlemail.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JS for HTML Email templates Plugin 3 | */ 4 | /** 5 | * Load the SLider 6 | * @param {type} param 7 | */ 8 | jQuery( document ).ready( function($) { 9 | /** 10 | * Add the templat name to load button, on clicking over a template 11 | */ 12 | jQuery('body').on('click', '.template-holder.slick-slide a.template-selector', function(e){ 13 | e.preventDefault(); 14 | 15 | //Remove active class from other templates 16 | jQuery('.template-holder').removeClass('active-theme'); 17 | 18 | //Add active class to current theme 19 | jQuery(this).parent(). addClass('active-theme'); 20 | 21 | //hide all other load template buttons 22 | jQuery('.load_template').addClass('disabled'); 23 | 24 | $theme_name = jQuery(this).attr('href'); 25 | //remove space from theme name 26 | $theme_name = $theme_name.replace(/\s+/g, ''); 27 | $theme_name = $theme_name.substr($theme_name.indexOf("#") + 1); 28 | 29 | $load_button = jQuery('#load_template_' + $theme_name ); 30 | 31 | $load_button.removeClass('disabled').attr('href', '#' + $theme_name).css('display', 'inline-block'); 32 | }); 33 | /** 34 | * On click of load template button get template default data and add it to textarea 35 | */ 36 | jQuery('body').on('click', '.load_template', function(e){ 37 | e.preventDefault(); 38 | if( jQuery(this).hasClass('disabled') ){ 39 | return false; 40 | } 41 | $textarea = jQuery('#template-content'); 42 | var current_template_name = jQuery( '#current_template_name' ); 43 | // if there is already some template content as for confirmation to override the remplate 44 | if( $textarea.val() != '' ){ 45 | if( ! confirm( htmlemail_text['load_template'] ) ) { 46 | return false; 47 | } 48 | } 49 | 50 | $theme_name = jQuery(this).attr('href'); 51 | $theme_name = $theme_name.substr($theme_name.indexOf("#") + 1); 52 | jQuery('#html_theme').val($theme_name); 53 | jQuery.get( ajaxurl, { 'action': 'htmlemail_get_template_data', 'theme': $theme_name }, function(res){ 54 | 55 | //Append the template content 56 | $textarea.val(res.data); 57 | current_template_name.val( $theme_name ); 58 | 59 | }); 60 | }); 61 | /** 62 | * On clicking over preview button, Show a preview dialog 63 | * 64 | */ 65 | jQuery('body').on('click', '#preview_template', function(e){ 66 | e.preventDefault(); 67 | $this = jQuery(this); 68 | //Show content in popup iframe 69 | title = $this.attr('title'), 70 | href = $this.attr('href'); 71 | //Show loading gif 72 | jQuery('.action-wrapper .spinner').css('display', 'inline-block'); 73 | // Open TB 74 | tb_show(title, href); 75 | var $previewIframe = $('#TB_iframeContent'); 76 | 77 | if( !$previewIframe.length ) 78 | return; 79 | 80 | $template = jQuery('#template-content').val(); 81 | //Replace placeholders 82 | jQuery.post( ajaxurl, { 'action': 'get_preview_data', 'content': $template }, function(res){ 83 | $template = res.data; 84 | 85 | $previewIframe = $previewIframe[$previewIframe.length - 1].contentWindow || frame[$previewIframe.length - 1]; 86 | $previewIframe.document.open(); 87 | $previewIframe.document.write( $template ); 88 | $previewIframe.document.close(); 89 | //Show loading gif 90 | jQuery('.action-wrapper .spinner').hide(); 91 | }, 'json'); 92 | 93 | }); 94 | /** 95 | * On click over save, check if template contains 'MESSAGE', otherwise alert and return 96 | */ 97 | jQuery('body').on('click', 'input[name="save_html_email_options"]', function (e) { 98 | $template_content = jQuery('#template-content').val(); 99 | if( $template_content == '' ){ 100 | return true; 101 | } 102 | $message = $template_content.indexOf("{MESSAGE}"); 103 | if (!$message || $message == -1) { 104 | alert(htmlemail_text['message_missing']); 105 | return false; 106 | } 107 | return true; 108 | }); 109 | /** 110 | * On click toggle templates 111 | */ 112 | jQuery('.template-toggle').click ( function( e ){ 113 | e.preventDefault(); 114 | $this = jQuery(this); 115 | $wrapper_div = $this.attr('href'); 116 | jQuery($wrapper_div).dequeue().stop().toggle('slow', '', function () { 117 | if (jQuery($wrapper_div).css('display') == 'none') { 118 | $this.find('span').html('+') 119 | } else { 120 | $this.find('span').html('-') 121 | } 122 | if ($wrapper_div == '#template-wrapper') { 123 | load_templates_slider(); 124 | } 125 | }); 126 | }); 127 | /** 128 | * Show email address input field 129 | * @returns {undefined} 130 | */ 131 | jQuery('.specify_email').click( function() { 132 | jQuery('.preview-email').toggle(); 133 | }); 134 | //Send previe email using ajax 135 | jQuery('input[name="preview_html_email"]').on( 'click', function(e){ 136 | 137 | //Do not submit form 138 | e.preventDefault(); 139 | 140 | //Remove previous message 141 | jQuery('.preview-email-status').remove(); 142 | 143 | $preview_html_email_address = jQuery('input[name="preview_html_email_address"]').val(); 144 | if($preview_html_email_address == '' ){ 145 | return false; 146 | } 147 | var preview_nonce = jQuery('#preview_email').val(); 148 | var param = { 149 | action: 'preview_email', 150 | _ajax_nonce: preview_nonce, 151 | preview_html_email_address : $preview_html_email_address 152 | }; 153 | 154 | jQuery.post(ajaxurl, param, function (res) { 155 | $message = res.data; 156 | if (res.success == true) { 157 | jQuery('.preview-email').append('

' + $message + '

'); 158 | } else { 159 | jQuery('.preview-email').append('

' + $message + '

'); 160 | } 161 | 162 | }); 163 | }); 164 | 165 | jQuery('body').on( 'click', '.template-image-upload', function(e) { 166 | e.preventDefault(); 167 | 168 | var image_box = jQuery( '#' + jQuery( this ).data( 'image-box' ) ); 169 | var title = jQuery( this ).attr("title"); 170 | 171 | var image = wp.media({ 172 | title: title, 173 | // mutiple: true if we want to upload multiple files at once 174 | multiple: false 175 | }).open() 176 | .on('select', function(e){ 177 | // This will return the selected image from the Media Uploader, the result is an object 178 | var uploaded_image = image.state().get('selection').first(); 179 | // We convert uploaded_image to a JSON object to make accessing it easier 180 | var image_url = uploaded_image.toJSON().url; 181 | image_box.val(image_url); 182 | }); 183 | }); 184 | 185 | }); 186 | function load_templates_slider(){ 187 | jQuery('.email-templates').slick({ 188 | infinite: false, 189 | speed: 300, 190 | slidesToShow: 4, 191 | slidesToScroll: 1, 192 | arrows: true, 193 | responsive: [ 194 | { 195 | breakpoint: 1024, 196 | settings: { 197 | slidesToShow: 3, 198 | slidesToScroll: 1 199 | } 200 | }, 201 | { 202 | breakpoint: 600, 203 | settings: { 204 | slidesToShow: 2, 205 | slidesToScroll: 1 206 | } 207 | }, 208 | { 209 | breakpoint: 480, 210 | settings: { 211 | slidesToShow: 1, 212 | slidesToScroll: 1 213 | } 214 | } 215 | ] 216 | }); 217 | } 218 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HTML Email Templates 2 | 3 | **INACTIVE NOTICE: This plugin is unsupported by WPMUDEV, we've published it here for those technical types who might want to fork and maintain it for their needs.** 4 | 5 | 6 | Add an HTML header and footer to your WordPress system emails for better brand integration. Use built-in templates or create your own layout. Plus with Multisite integration, you can set custom templates for each site on your network. 7 | 8 | * Style WordPress system emails 9 | * Includes 8 starter templates 10 | * Make notification responsive 11 | * Style preview and send a test email 12 | * Add custom branding to system emails 13 | * Embed social links 14 | 15 | ## HTML Email Templates allows you to use your beautiful HTML email templates for emails WordPress sends. 16 | 17 | By default, WordPress sends out plain boring email notifications for events such as new comments, comments in moderation and new users. 18 | 19 | ### Spice Up System Notifications 20 | 21 | This plugin is for any brand-freak that loves completely white-labelled products, or for those who just want WordPress to send nice emails. 22 | 23 | ![html-email-templates-2][40] 24 | 25 | Get WordPress to send beautiful emails to you! 26 | 27 | ### Complete Email Branding 28 | 29 | Enable template override and choose different templates for each site on your network.You can even preview your styles and changes to see what they will look like. 30 | 31 | HTML Email Templates for WordPress lets you brand one of the most important parts of your Website – Email Notifications. 32 | 33 | ### To Get Started: 34 | 35 | _Note for Multisite installs: this plugin is designed to be network activated and, by default, it rebrands the emails for all sites network-wide. However, you can enable a template override option in network settings to allow different templates per site. More on this below._ 36 | 37 | Once installed and network-activated, you’ll see a new menu item in the Settings menu in your network admin: HTML Email Template. 38 | 39 | ![HTML Email Templates Network Menu][43] 40 | 41 | When activated on a single site install, you’ll see the new menu item under Settings in your wp-admin. Note that if you enable the template override option in a network install, each sub-site in your network can access the settings here too. 42 | 43 | ![HTML Email Templates Single Site Menu][44] 44 | 45 | ### Configuring Your Email Template 46 | 47 | The first thing you’ll likely notice is that are really no settings for this plugin; it just works. :) 48 | 49 | All you need to do is configure the HTML that will be used to rebrand all emails sent by your WordPress install, even the ones from BuddyPress if you have that installed. 50 | 51 | If you’re not very handy with HTML, don’t worry, we’ve got you covered with several pre-made templates you can choose from. Simply click the “Choose from sample Templates” toggle located just beneath Step 1 in the instructions to pop open a slider where you can scroll through the available templates. 52 | 53 | ![HTML Email Templates Template Select][45] 54 | 55 | Click the thumbnail of any template you like to highlight it, then click the “Load Template…” button to populate the large text area below with all the glorious pre-made HTML. 56 | 57 | ![HTML Email Templates Template Load][46] 58 | 59 | Now click the “Preview” button to pop open a live preview of what your emails will look like with your selected template. 60 | 61 | ![HTML Email Templates Template Preview][47] 62 | 63 | If you are happy with how your template looks out-of-the-box, click the “Save” button. Then click the “Test Email” button, enter your own email address and click “Send” to see your work pay off in your own inbox. Now all your WordPress emails will be sent using your selected template. How cool is that? 64 | 65 | ### Allow Subsite Templates 66 | 67 | If you are running a multisite install and want to allow your subsite admins to override your network template with their own custom stuff, check the box at the bottom of the network settings screen. 68 | 69 | ![HTML Email Templates Network Override][48] 70 | 71 | Every site in your network will now have a settings screen enabling admins to customize the template to be used for all emails from their sites. 72 | 73 | ### Customizing a Template 74 | 75 | If you are not quite happy with how your selected template looks by default, you can customize it to your heart’s content by simply editing the HTML in the large textarea. 76 | 77 | If you do not want to use any of the pre-made templates, you can enter your own custom HTML instead. Simply delete what is already there, and paste in your own. 78 | 79 | You’ll notice that there are several variable placeholders throughout the HTML in each template, enclosed in parentheses like so: 80 | `{MESSAGE} ` 81 | 82 | To see all the available variables you can use when customizing your template, click the “List of variables that can be used in template” toggle located just beneath Step 1 in the instructions. 83 | 84 | ![HTML Email Templates Template Variables][50] 85 | 86 | Each of those variables can be used anywhere you need them in your template. The one that must be used somewhere in your template to ensure that all your WordPress emails work properly is: 87 | 88 | * `{MESSAGE}` Outputs the email content (required) 89 | 90 | All of these are optional: 91 | 92 | * `{SIDEBAR_TITLE}` Title for the sidebar in templates with a sidebar. Default is “What’s New?”. 93 | * `{FROM_NAME}` Sender’s name if sender’s email is associated with a user account. 94 | * `{FROM_EMAIL}` Sender’s email, email specified in site Settings. 95 | * `{BLOG_URL}` Blog / Site URL. 96 | * `{BLOG_NAME}` Blog / Site name. 97 | * `{ADMIN_EMAIL}` Email address of the support or contact person. Same as `{FROM_EMAIL}` 98 | * `{BLOG_DESCRIPTION}` Taken from the Tagline as entered in the site Settings. 99 | * `{DATE}` Current date as configured in the site Settings. 100 | * `{TIME}` Current time as configured in the site Settings. 101 | 102 | ### Additional Customization Options 103 | 104 | You may have noticed that there is one sample template that has a sidebar in it. That template also has something special that can be used in other templates too: a linked list of your most recent blog posts. 105 | 106 | Go ahead and select that template now; you can’t miss it, it’s called “Sidebar”. :) 107 | 108 | Scroll down to about halfway through the HTML until you see 4 list items like this: 109 | ` 110 | https://premium.wpmudev.org/%7BPOST_1_LINK%7D" style="margin: 0; padding: 10px 16px; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; color: #666; border-bottom: 1px solid #777777; border-top: 1px solid #FFFFFF; cursor: pointer; display: block; margin-right: 10px; text-decoration: none;">{POST_1} » 111 | ` 112 | 113 | Those 4 list items will include the titles of the 4 most recent posts in your blog, and link back to them on your site. 114 | 115 | The code can be copied to any other template, or used in your own custom HTML too. You can modify the HTML & CSS to fit your branding, but there are 2 things that must be present in each one for this feature to work: 116 | `href="https://premium.wpmudev.org/%7BPOST_1_LINK%7D" 117 | {POST_1}` 118 | 119 | Those are the filters & placeholders that fetch the permalink & title of the posts. You can have up to 4 of them as seen in the “Sidebar” template, but if you only want 1, 2 or 3, simply remove what you don’t need. 120 | 121 | Advanced: there are also 2 filters you can use in case you want to include some other posts in your emails: 122 | 123 | * `htmlemail_sidebar_title` to change the sidebar title (takes a string). 124 | * `htmlemail_sidebar_posts` to change the post list (takes an array of posts containing ID and post_title). 125 | 126 | [40]: https://premium.wpmudev.org/wp-content/uploads/2010/06/html-email-templates-2.jpg 127 | [43]: https://premium.wpmudev.org/wp-content/uploads/2010/06/html-email-templates-2000-menu-network.png 128 | [44]: https://premium.wpmudev.org/wp-content/uploads/2010/06/html-email-templates-2000-menu-single.png 129 | [45]: https://premium.wpmudev.org/wp-content/uploads/2010/06/html-email-templates-2000-template-select.png 130 | [46]: https://premium.wpmudev.org/wp-content/uploads/2010/06/html-email-templates-2000-template-load.png 131 | [47]: https://premium.wpmudev.org/wp-content/uploads/2010/06/html-email-templates-2000-template-preview.png 132 | [48]: https://premium.wpmudev.org/wp-content/uploads/2010/06/html-email-templates-2000-network-override.png 133 | [50]: https://premium.wpmudev.org/wp-content/uploads/2010/06/html-email-templates-2000-template-variables.png 134 | -------------------------------------------------------------------------------- /assets/slick/slick.min.js: -------------------------------------------------------------------------------- 1 | !function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){"use strict";var b=window.Slick||{};b=function(){function c(c,d){var f,g,e=this;if(e.defaults={accessibility:!0,arrows:!0,autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(a,b){return'"},dots:!1,draggable:!0,easing:"linear",fade:!1,infinite:!0,lazyLoad:"ondemand",onBeforeChange:null,onAfterChange:null,onInit:null,onReInit:null,pauseOnHover:!0,responsive:null,slide:"div",slidesToShow:1,slidesToScroll:1,speed:300,swipe:!0,touchMove:!0,touchThreshold:5,useCSS:!0,vertical:!1},e.initials={animating:!1,autoPlayTimer:null,currentSlide:0,currentLeft:null,direction:1,$dots:null,listWidth:null,listHeight:null,loadIndex:0,$nextArrow:null,$prevArrow:null,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,sliding:!1,slideOffset:0,swipeLeft:null,$list:null,touchObject:{},transformsEnabled:!1},a.extend(e,e.initials),e.activeBreakpoint=null,e.animType=null,e.animProp=null,e.breakpoints=[],e.breakpointSettings=[],e.cssTransitions=!1,e.paused=!1,e.positionProp=null,e.$slider=a(c),e.$slidesCache=null,e.transformType=null,e.transitionType=null,e.windowWidth=0,e.windowTimer=null,e.options=a.extend({},e.defaults,d),e.originalSettings=e.options,f=e.options.responsive||null,f&&f.length>-1){for(g in f)f.hasOwnProperty(g)&&(e.breakpoints.push(f[g].breakpoint),e.breakpointSettings[f[g].breakpoint]=f[g].settings);e.breakpoints.sort(function(a,b){return b-a})}e.autoPlay=a.proxy(e.autoPlay,e),e.autoPlayClear=a.proxy(e.autoPlayClear,e),e.changeSlide=a.proxy(e.changeSlide,e),e.setPosition=a.proxy(e.setPosition,e),e.swipeHandler=a.proxy(e.swipeHandler,e),e.dragHandler=a.proxy(e.dragHandler,e),e.keyHandler=a.proxy(e.keyHandler,e),e.autoPlayIterator=a.proxy(e.autoPlayIterator,e),e.instanceUid=b++,e.init()}var b=0;return c}(),b.prototype.addSlide=function(b,c,d){var e=this;if("boolean"==typeof c)d=c,c=null;else if(0>c||c>=e.slideCount)return!1;e.unload(),"number"==typeof c?0===c&&0===e.$slides.length?a(b).appendTo(e.$slideTrack):d?a(b).insertBefore(e.$slides.eq(c)):a(b).insertAfter(e.$slides.eq(c)):d===!0?a(b).prependTo(e.$slideTrack):a(b).appendTo(e.$slideTrack),e.$slides=e.$slideTrack.children(this.options.slide),e.$slideTrack.children(this.options.slide).remove(),e.$slideTrack.append(e.$slides),e.$slidesCache=e.$slides,e.reinit()},b.prototype.animateSlide=function(b,c){var d={},e=this;e.transformsEnabled===!1?e.options.vertical===!1?e.$slideTrack.animate({left:b},e.options.speed,e.options.easing,c):e.$slideTrack.animate({top:b},e.options.speed,e.options.easing,c):e.cssTransitions===!1?a({animStart:e.currentLeft}).animate({animStart:b},{duration:e.options.speed,easing:e.options.easing,step:function(a){e.options.vertical===!1?(d[e.animType]="translate("+a+"px, 0px)",e.$slideTrack.css(d)):(d[e.animType]="translate(0px,"+a+"px)",e.$slideTrack.css(d))},complete:function(){c&&c.call()}}):(e.applyTransition(),d[e.animType]=e.options.vertical===!1?"translate3d("+b+"px, 0px, 0px)":"translate3d(0px,"+b+"px, 0px)",e.$slideTrack.css(d),c&&setTimeout(function(){e.disableTransition(),c.call()},e.options.speed))},b.prototype.applyTransition=function(a){var b=this,c={};c[b.transitionType]=b.options.fade===!1?b.transformType+" "+b.options.speed+"ms "+b.options.cssEase:"opacity "+b.options.speed+"ms "+b.options.cssEase,b.options.fade===!1?b.$slideTrack.css(c):b.$slides.eq(a).css(c)},b.prototype.autoPlay=function(){var a=this;a.autoPlayTimer&&clearInterval(a.autoPlayTimer),a.slideCount>a.options.slidesToShow&&a.paused!==!0&&(a.autoPlayTimer=setInterval(a.autoPlayIterator,a.options.autoplaySpeed))},b.prototype.autoPlayClear=function(){var a=this;a.autoPlayTimer&&clearInterval(a.autoPlayTimer)},b.prototype.autoPlayIterator=function(){var a=this;a.options.infinite===!1?1===a.direction?(a.currentSlide+1===a.slideCount-1&&(a.direction=0),a.slideHandler(a.currentSlide+a.options.slidesToScroll)):(0===a.currentSlide-1&&(a.direction=1),a.slideHandler(a.currentSlide-a.options.slidesToScroll)):a.slideHandler(a.currentSlide+a.options.slidesToScroll)},b.prototype.buildArrows=function(){var b=this;b.options.arrows===!0&&b.slideCount>b.options.slidesToShow&&(b.$prevArrow=a('').appendTo(b.$slider),b.$nextArrow=a('').appendTo(b.$slider),b.options.infinite!==!0&&b.$prevArrow.addClass("slick-disabled"))},b.prototype.buildDots=function(){var c,d,b=this;if(b.options.dots===!0&&b.slideCount>b.options.slidesToShow){for(d='
    ',c=0;c<=b.getDotCount();c+=1)d+="
  • "+b.options.customPaging.call(this,b,c)+"
  • ";d+="
",b.$dots=a(d).appendTo(b.$slider),b.$dots.find("li").first().addClass("slick-active")}},b.prototype.buildOut=function(){var b=this;b.$slides=b.$slider.children(b.options.slide+":not(.slick-cloned)").addClass("slick-slide"),b.slideCount=b.$slides.length,b.$slidesCache=b.$slides,b.$slider.addClass("slick-slider"),b.$slideTrack=0===b.slideCount?a('
').appendTo(b.$slider):b.$slides.wrapAll('
').parent(),b.$list=b.$slideTrack.wrap('
').parent(),b.$slideTrack.css("opacity",0),b.options.centerMode===!0&&(b.options.infinite=!0,b.options.slidesToScroll=1,0===b.options.slidesToShow%2&&(b.options.slidesToShow=3)),a("img[data-lazy]",b.$slider).not("[src]").addClass("slick-loading"),b.setupInfinite(),b.buildArrows(),b.buildDots(),b.options.accessibility===!0&&b.$list.prop("tabIndex",0),b.setSlideClasses(0),b.options.draggable===!0&&b.$list.addClass("draggable")},b.prototype.checkResponsive=function(){var c,d,b=this;if(b.originalSettings.responsive&&b.originalSettings.responsive.length>-1&&null!==b.originalSettings.responsive){d=null;for(c in b.breakpoints)b.breakpoints.hasOwnProperty(c)&&a(window).width()b;)d++,c+=a.options.slidesToScroll,b=c+a.options.slidesToShow;return d},b.prototype.getLeft=function(a){var c,d,b=this,e=0;return b.slideOffset=0,d=b.$slides.first().outerHeight(),b.options.infinite===!0?(b.slideCount>b.options.slidesToShow&&(b.slideOffset=-1*b.slideWidth*b.options.slidesToShow,e=-1*d*b.options.slidesToShow),0!==b.slideCount%b.options.slidesToScroll&&a+b.options.slidesToScroll>b.slideCount&&b.slideCount>b.options.slidesToShow&&(b.slideOffset=-1*b.slideCount%b.options.slidesToShow*b.slideWidth,e=-1*b.slideCount%b.options.slidesToShow*d)):0!==b.slideCount%b.options.slidesToShow&&a+b.options.slidesToScroll>b.slideCount&&b.slideCount>b.options.slidesToShow&&(b.slideOffset=b.options.slidesToShow*b.slideWidth-b.slideCount%b.options.slidesToShow*b.slideWidth,e=b.slideCount%b.options.slidesToShow*d),b.options.centerMode===!0&&(b.slideOffset+=b.slideWidth*Math.floor(b.options.slidesToShow/2)-b.slideWidth),c=b.options.vertical===!1?-1*a*b.slideWidth+b.slideOffset:-1*a*d+e},b.prototype.init=function(){var b=this;a(b.$slider).hasClass("slick-initialized")||(a(b.$slider).addClass("slick-initialized"),b.buildOut(),b.setProps(),b.startLoad(),b.loadSlider(),b.initializeEvents(),b.checkResponsive()),null!==b.options.onInit&&b.options.onInit.call(this,b)},b.prototype.initArrowEvents=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.on("click.slick",{message:"previous"},a.changeSlide),a.$nextArrow.on("click.slick",{message:"next"},a.changeSlide))},b.prototype.initDotEvents=function(){var b=this;b.options.dots===!0&&b.slideCount>b.options.slidesToShow&&a("li",b.$dots).on("click.slick",{message:"index"},b.changeSlide)},b.prototype.initializeEvents=function(){var b=this;b.initArrowEvents(),b.initDotEvents(),b.$list.on("touchstart.slick mousedown.slick",{action:"start"},b.swipeHandler),b.$list.on("touchmove.slick mousemove.slick",{action:"move"},b.swipeHandler),b.$list.on("touchend.slick mouseup.slick",{action:"end"},b.swipeHandler),b.$list.on("touchcancel.slick mouseleave.slick",{action:"end"},b.swipeHandler),b.options.pauseOnHover===!0&&b.options.autoplay===!0&&(b.$list.on("mouseenter.slick",b.autoPlayClear),b.$list.on("mouseleave.slick",b.autoPlay)),b.options.accessibility===!0&&b.$list.on("keydown.slick",b.keyHandler),a(window).on("orientationchange.slick.slick-"+b.instanceUid,function(){b.checkResponsive(),b.setPosition()}),a(window).on("resize.slick.slick-"+b.instanceUid,function(){a(window).width!==b.windowWidth&&(clearTimeout(b.windowDelay),b.windowDelay=window.setTimeout(function(){b.windowWidth=a(window).width(),b.checkResponsive(),b.setPosition()},50))}),a(window).on("load.slick.slick-"+b.instanceUid,b.setPosition)},b.prototype.initUI=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.show(),a.$nextArrow.show()),a.options.dots===!0&&a.slideCount>a.options.slidesToShow&&a.$dots.show(),a.options.autoplay===!0&&a.autoPlay()},b.prototype.keyHandler=function(a){var b=this;37===a.keyCode?b.changeSlide({data:{message:"previous"}}):39===a.keyCode&&b.changeSlide({data:{message:"next"}})},b.prototype.lazyLoad=function(){var c,d,e,f,b=this;b.options.centerMode===!0?(e=b.options.slidesToShow+b.currentSlide-1,f=e+b.options.slidesToShow+2):(e=b.options.infinite?b.options.slidesToShow+b.currentSlide:b.currentSlide,f=e+b.options.slidesToShow),c=b.$slider.find(".slick-slide").slice(e,f),a("img[data-lazy]",c).not("[src]").each(function(){a(this).css({opacity:0}).attr("src",a(this).attr("data-lazy")).removeClass("slick-loading").load(function(){a(this).animate({opacity:1},200)})}),b.currentSlide>=b.slideCount-b.options.slidesToShow?(d=b.$slider.find(".slick-cloned").slice(0,b.options.slidesToShow),a("img[data-lazy]",d).not("[src]").each(function(){a(this).css({opacity:0}).attr("src",a(this).attr("data-lazy")).removeClass("slick-loading").load(function(){a(this).animate({opacity:1},200)})})):0===b.currentSlide&&(d=b.$slider.find(".slick-cloned").slice(-1*b.options.slidesToShow),a("img[data-lazy]",d).not("[src]").each(function(){a(this).css({opacity:0}).attr("src",a(this).attr("data-lazy")).removeClass("slick-loading").load(function(){a(this).animate({opacity:1},200)})}))},b.prototype.loadSlider=function(){var a=this;a.setPosition(),a.$slideTrack.css({opacity:1}),a.$slider.removeClass("slick-loading"),a.initUI(),"progressive"===a.options.lazyLoad&&a.progressiveLazyLoad()},b.prototype.postSlide=function(a){var b=this;null!==b.options.onAfterChange&&b.options.onAfterChange.call(this,b,a),b.animating=!1,b.setPosition(),b.swipeLeft=null,b.options.autoplay===!0&&b.paused===!1&&b.autoPlay()},b.prototype.progressiveLazyLoad=function(){var c,d,b=this;c=a("img[data-lazy]").not("[src]").length,c>0&&(d=a(a("img[data-lazy]",b.$slider).not("[src]").get(0)),d.attr("src",d.attr("data-lazy")).removeClass("slick-loading").load(function(){b.progressiveLazyLoad()}))},b.prototype.refresh=function(){var b=this;b.destroy(),a.extend(b,b.initials),b.init()},b.prototype.reinit=function(){var a=this;a.$slides=a.$slideTrack.children(a.options.slide).addClass("slick-slide"),a.slideCount=a.$slides.length,a.currentSlide>=a.slideCount&&0!==a.currentSlide&&(a.currentSlide=a.currentSlide-a.options.slidesToScroll),a.setProps(),a.setupInfinite(),a.buildArrows(),a.updateArrows(),a.initArrowEvents(),a.buildDots(),a.updateDots(),a.initDotEvents(),a.setSlideClasses(0),a.setPosition(),null!==a.options.onReInit&&a.options.onReInit.call(this,a)},b.prototype.removeSlide=function(a,b){var c=this;return"boolean"==typeof a?(b=a,a=b===!0?0:c.slideCount-1):a=b===!0?--a:a,c.slideCount<1||0>a||a>c.slideCount-1?!1:(c.unload(),c.$slideTrack.children(this.options.slide).eq(a).remove(),c.$slides=c.$slideTrack.children(this.options.slide),c.$slideTrack.children(this.options.slide).remove(),c.$slideTrack.append(c.$slides),c.$slidesCache=c.$slides,c.reinit(),void 0)},b.prototype.setCSS=function(a){var d,e,b=this,c={};d="left"==b.positionProp?a+"px":"0px",e="top"==b.positionProp?a+"px":"0px",c[b.positionProp]=a,b.transformsEnabled===!1?b.$slideTrack.css(c):(c={},b.cssTransitions===!1?(c[b.animType]="translate("+d+", "+e+")",b.$slideTrack.css(c)):(c[b.animType]="translate3d("+d+", "+e+", 0px)",b.$slideTrack.css(c)))},b.prototype.setDimensions=function(){var a=this;a.options.centerMode===!0?a.$slideTrack.children(".slick-slide").width(a.slideWidth):a.$slideTrack.children(".slick-slide").width(a.slideWidth),a.options.vertical===!1?(a.$slideTrack.width(Math.ceil(a.slideWidth*a.$slideTrack.children(".slick-slide").length)),a.options.centerMode===!0&&a.$list.css({padding:"0px "+a.options.centerPadding})):(a.$list.height(a.$slides.first().outerHeight()*a.options.slidesToShow),a.$slideTrack.height(Math.ceil(a.$slides.first().outerHeight()*a.$slideTrack.children(".slick-slide").length)),a.options.centerMode===!0&&a.$list.css({padding:a.options.centerPadding+" 0px"}))},b.prototype.setFade=function(){var c,b=this;b.$slides.each(function(d,e){c=-1*b.slideWidth*d,a(e).css({position:"relative",left:c,top:0,zIndex:800,opacity:0})}),b.$slides.eq(b.currentSlide).css({zIndex:900,opacity:1})},b.prototype.setPosition=function(){var a=this;a.setValues(),a.setDimensions(),a.options.fade===!1?a.setCSS(a.getLeft(a.currentSlide)):a.setFade()},b.prototype.setProps=function(){var a=this;a.positionProp=a.options.vertical===!0?"top":"left","top"===a.positionProp?a.$slider.addClass("slick-vertical"):a.$slider.removeClass("slick-vertical"),(void 0!==document.body.style.WebkitTransition||void 0!==document.body.style.MozTransition||void 0!==document.body.style.msTransition)&&a.options.useCSS===!0&&(a.cssTransitions=!0),void 0!==document.body.style.MozTransform&&(a.animType="MozTransform",a.transformType="-moz-transform",a.transitionType="MozTransition"),void 0!==document.body.style.webkitTransform&&(a.animType="webkitTransform",a.transformType="-webkit-transform",a.transitionType="webkitTransition"),void 0!==document.body.style.msTransform&&(a.animType="transform",a.transformType="transform",a.transitionType="transition"),a.transformsEnabled=null!==a.animType},b.prototype.setValues=function(){var a=this;a.listWidth=a.$list.width(),a.listHeight=a.$list.height(),a.slideWidth=a.options.vertical===!1?Math.ceil(a.listWidth/a.options.slidesToShow):Math.ceil(a.listWidth)},b.prototype.setSlideClasses=function(a){var c,d,e,b=this;b.$slider.find(".slick-slide").removeClass("slick-active").removeClass("slick-center"),d=b.$slider.find(".slick-slide"),b.options.centerMode===!0?(c=Math.floor(b.options.slidesToShow/2),a>=c&&a<=b.slideCount-1-c?b.$slides.slice(a-c,a+c+1).addClass("slick-active"):(e=b.options.slidesToShow+a,d.slice(e-c+1,e+c+2).addClass("slick-active")),0===a?d.eq(d.length-1-b.options.slidesToShow).addClass("slick-center"):a===b.slideCount-1&&d.eq(b.options.slidesToShow).addClass("slick-center"),b.$slides.eq(a).addClass("slick-center")):a>0&&ab.options.slidesToShow)){for(e=b.options.centerMode===!0?b.options.slidesToShow+1:b.options.slidesToShow,c=b.slideCount;c>b.slideCount-e;c-=1)d=c-1,a(b.$slides[d]).clone().attr("id","").prependTo(b.$slideTrack).addClass("slick-cloned");for(c=0;e>c;c+=1)d=c,a(b.$slides[d]).clone().attr("id","").appendTo(b.$slideTrack).addClass("slick-cloned");b.$slideTrack.find(".slick-cloned").find("[id]").each(function(){a(this).attr("id","")})}},b.prototype.slideHandler=function(a){var b,c,d,e,f=null,g=this;return g.animating===!0?!1:(b=a,f=g.getLeft(b),d=g.getLeft(g.currentSlide),e=0!==g.slideCount%g.options.slidesToScroll?g.options.slidesToScroll:0,g.currentLeft=null===g.swipeLeft?d:g.swipeLeft,g.options.infinite===!1&&(0>a||a>g.slideCount-g.options.slidesToShow+e)?(g.options.fade===!1&&(b=g.currentSlide,g.animateSlide(d,function(){g.postSlide(b)})),!1):(g.options.autoplay===!0&&clearInterval(g.autoPlayTimer),c=0>b?0!==g.slideCount%g.options.slidesToScroll?g.slideCount-g.slideCount%g.options.slidesToScroll:g.slideCount-g.options.slidesToScroll:b>g.slideCount-1?0:b,g.animating=!0,null!==g.options.onBeforeChange&&a!==g.currentSlide&&g.options.onBeforeChange.call(this,g,g.currentSlide,c),g.currentSlide=c,g.setSlideClasses(g.currentSlide),g.updateDots(),g.updateArrows(),g.options.fade===!0?(g.fadeSlide(c,function(){g.postSlide(c)}),!1):(g.animateSlide(f,function(){g.postSlide(c)}),void 0)))},b.prototype.startLoad=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.hide(),a.$nextArrow.hide()),a.options.dots===!0&&a.slideCount>a.options.slidesToShow&&a.$dots.hide(),a.$slider.addClass("slick-loading")},b.prototype.swipeDirection=function(){var a,b,c,d,e=this;return a=e.touchObject.startX-e.touchObject.curX,b=e.touchObject.startY-e.touchObject.curY,c=Math.atan2(b,a),d=Math.round(180*c/Math.PI),0>d&&(d=360-Math.abs(d)),45>=d&&d>=0?"left":360>=d&&d>=315?"left":d>=135&&225>=d?"right":"vertical"},b.prototype.swipeEnd=function(b){var c=this;if(c.$list.removeClass("dragging"),void 0===c.touchObject.curX)return!1;if(c.touchObject.swipeLength>=c.touchObject.minSwipe)switch(a(b.target).on("click.slick",function(b){b.stopImmediatePropagation(),b.stopPropagation(),b.preventDefault(),a(b.target).off("click.slick")}),c.swipeDirection()){case"left":c.slideHandler(c.currentSlide+c.options.slidesToScroll),c.touchObject={};break;case"right":c.slideHandler(c.currentSlide-c.options.slidesToScroll),c.touchObject={}}else c.touchObject.startX!==c.touchObject.curX&&(c.slideHandler(c.currentSlide),c.touchObject={})},b.prototype.swipeHandler=function(a){var b=this;if("ontouchend"in document&&b.options.swipe===!1)return!1;if(b.options.draggable===!1&&!a.originalEvent.touches)return!0;switch(b.touchObject.fingerCount=a.originalEvent&&void 0!==a.originalEvent.touches?a.originalEvent.touches.length:1,b.touchObject.minSwipe=b.listWidth/b.options.touchThreshold,a.data.action){case"start":b.swipeStart(a);break;case"move":b.swipeMove(a);break;case"end":b.swipeEnd(a)}},b.prototype.swipeMove=function(a){var c,d,e,f,b=this;return f=void 0!==a.originalEvent?a.originalEvent.touches:null,c=b.getLeft(b.currentSlide),!b.$list.hasClass("dragging")||f&&1!==f.length?!1:(b.touchObject.curX=void 0!==f?f[0].pageX:a.clientX,b.touchObject.curY=void 0!==f?f[0].pageY:a.clientY,b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curX-b.touchObject.startX,2))),d=b.swipeDirection(),"vertical"!==d?(void 0!==a.originalEvent&&b.touchObject.swipeLength>4&&a.preventDefault(),e=b.touchObject.curX>b.touchObject.startX?1:-1,b.swipeLeft=b.options.vertical===!1?c+b.touchObject.swipeLength*e:c+b.touchObject.swipeLength*(b.$list.height()/b.listWidth)*e,b.options.fade===!0||b.options.touchMove===!1?!1:b.animating===!0?(b.swipeLeft=null,!1):(b.setCSS(b.swipeLeft),void 0)):void 0)},b.prototype.swipeStart=function(a){var c,b=this;return 1!==b.touchObject.fingerCount||b.slideCount<=b.options.slidesToShow?(b.touchObject={},!1):(void 0!==a.originalEvent&&void 0!==a.originalEvent.touches&&(c=a.originalEvent.touches[0]),b.touchObject.startX=b.touchObject.curX=void 0!==c?c.pageX:a.clientX,b.touchObject.startY=b.touchObject.curY=void 0!==c?c.pageY:a.clientY,b.$list.addClass("dragging"),void 0)},b.prototype.unfilterSlides=function(){var a=this;null!==a.$slidesCache&&(a.unload(),a.$slideTrack.children(this.options.slide).remove(),a.$slidesCache.appendTo(a.$slideTrack),a.reinit())},b.prototype.unload=function(){var b=this;a(".slick-cloned",b.$slider).remove(),b.$dots&&b.$dots.remove(),b.$prevArrow&&(b.$prevArrow.remove(),b.$nextArrow.remove()),b.$slides.removeClass("slick-slide slick-active slick-visible").removeAttr("style")},b.prototype.updateArrows=function(){var a=this;a.options.arrows===!0&&a.options.infinite!==!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.removeClass("slick-disabled"),a.$nextArrow.removeClass("slick-disabled"),0===a.currentSlide?(a.$prevArrow.addClass("slick-disabled"),a.$nextArrow.removeClass("slick-disabled")):a.currentSlide>=a.slideCount-a.options.slidesToShow&&(a.$nextArrow.addClass("slick-disabled"),a.$prevArrow.removeClass("slick-disabled")))},b.prototype.updateDots=function(){var a=this;null!==a.$dots&&(a.$dots.find("li").removeClass("slick-active"),a.$dots.find("li").eq(a.currentSlide/a.options.slidesToScroll).addClass("slick-active"))},a.fn.slick=function(a){var c=this;return c.each(function(c,d){d.slick=new b(d,a)})},a.fn.slickAdd=function(a,b,c){var d=this;return d.each(function(d,e){e.slick.addSlide(a,b,c)})},a.fn.slickCurrentSlide=function(){var a=this;return a.get(0).slick.getCurrent()},a.fn.slickFilter=function(a){var b=this;return b.each(function(b,c){c.slick.filterSlides(a)})},a.fn.slickGoTo=function(a){var b=this;return b.each(function(b,c){c.slick.slideHandler(a)})},a.fn.slickNext=function(){var a=this;return a.each(function(a,b){b.slick.changeSlide({data:{message:"next"}})})},a.fn.slickPause=function(){var a=this;return a.each(function(a,b){b.slick.autoPlayClear(),b.slick.paused=!0})},a.fn.slickPlay=function(){var a=this;return a.each(function(a,b){b.slick.paused=!1,b.slick.autoPlay()})},a.fn.slickPrev=function(){var a=this;return a.each(function(a,b){b.slick.changeSlide({data:{message:"previous"}})})},a.fn.slickRemove=function(a,b){var c=this;return c.each(function(c,d){d.slick.removeSlide(a,b)})},a.fn.slickSetOption=function(a,b,c){var d=this;return d.each(function(d,e){e.slick.options[a]=b,c===!0&&(e.slick.unload(),e.slick.reinit())})},a.fn.slickUnfilter=function(){var a=this;return a.each(function(a,b){b.slick.unfilterSlides()})},a.fn.unslick=function(){var a=this;return a.each(function(a,b){b.slick.destroy()})}}); -------------------------------------------------------------------------------- /lib/builder/css-inline.php: -------------------------------------------------------------------------------- 1 | 8 | * @version 1.2.1 9 | * @copyright Copyright (c), Tijs Verkoyen. All rights reserved. 10 | * @license BSD License 11 | */ 12 | class CssToInlineStyles 13 | { 14 | /** 15 | * The CSS to use 16 | * 17 | * @var string 18 | */ 19 | private $css; 20 | 21 | /** 22 | * The processed CSS rules 23 | * 24 | * @var array 25 | */ 26 | private $cssRules; 27 | 28 | /** 29 | * Should the generated HTML be cleaned 30 | * 31 | * @var bool 32 | */ 33 | private $cleanup = false; 34 | 35 | /** 36 | * The encoding to use. 37 | * 38 | * @var string 39 | */ 40 | private $encoding = 'UTF-8'; 41 | 42 | /** 43 | * The HTML to process 44 | * 45 | * @var string 46 | */ 47 | private $html; 48 | 49 | /** 50 | * Use inline-styles block as CSS 51 | * 52 | * @var bool 53 | */ 54 | private $useInlineStylesBlock = false; 55 | 56 | /** 57 | * Strip original style tags 58 | * 59 | * @var bool 60 | */ 61 | private $stripOriginalStyleTags = false; 62 | 63 | /** 64 | * Exclude the media queries from the inlined styles 65 | * 66 | * @var bool 67 | */ 68 | private $excludeMediaQueries = false; 69 | 70 | /** 71 | * Creates an instance, you could set the HTML and CSS here, or load it 72 | * later. 73 | * 74 | * @return void 75 | * @param string[optional] $html The HTML to process. 76 | * @param string[optional] $css The CSS to use. 77 | */ 78 | public function __construct($html = null, $css = null) 79 | { 80 | if($html !== null) $this->setHTML($html); 81 | if($css !== null) $this->setCSS($css); 82 | } 83 | 84 | /** 85 | * Convert a CSS-selector into an xPath-query 86 | * 87 | * @return string 88 | * @param string $selector The CSS-selector. 89 | */ 90 | private function buildXPathQuery($selector) 91 | { 92 | // redefine 93 | $selector = (string) $selector; 94 | 95 | // the CSS selector 96 | $cssSelector = array( 97 | // E F, Matches any F element that is a descendant of an E element 98 | '/(\w)\s+([\w\*])/', 99 | // E > F, Matches any F element that is a child of an element E 100 | '/(\w)\s*>\s*([\w\*])/', 101 | // E:first-child, Matches element E when E is the first child of its parent 102 | '/(\w):first-child/', 103 | // E + F, Matches any F element immediately preceded by an element 104 | '/(\w)\s*\+\s*(\w)/', 105 | // E[foo], Matches any E element with the "foo" attribute set (whatever the value) 106 | '/(\w)\[([\w\-]+)]/', 107 | // E[foo="warning"], Matches any E element whose "foo" attribute value is exactly equal to "warning" 108 | '/(\w)\[([\w\-]+)\=\"(.*)\"]/', 109 | // div.warning, HTML only. The same as DIV[class~="warning"] 110 | '/(\w+|\*)+\.([\w\-]+)+/', 111 | // .warning, HTML only. The same as *[class~="warning"] 112 | '/\.([\w\-]+)/', 113 | // E#myid, Matches any E element with id-attribute equal to "myid" 114 | '/(\w+)+\#([\w\-]+)/', 115 | // #myid, Matches any element with id-attribute equal to "myid" 116 | '/\#([\w\-]+)/' 117 | ); 118 | 119 | // the xPath-equivalent 120 | $xPathQuery = array( 121 | // E F, Matches any F element that is a descendant of an E element 122 | '\1//\2', 123 | // E > F, Matches any F element that is a child of an element E 124 | '\1/\2', 125 | // E:first-child, Matches element E when E is the first child of its parent 126 | '*[1]/self::\1', 127 | // E + F, Matches any F element immediately preceded by an element 128 | '\1/following-sibling::*[1]/self::\2', 129 | // E[foo], Matches any E element with the "foo" attribute set (whatever the value) 130 | '\1 [ @\2 ]', 131 | // E[foo="warning"], Matches any E element whose "foo" attribute value is exactly equal to "warning" 132 | '\1[ contains( concat( " ", @\2, " " ), concat( " ", "\3", " " ) ) ]', 133 | // div.warning, HTML only. The same as DIV[class~="warning"] 134 | '\1[ contains( concat( " ", @class, " " ), concat( " ", "\2", " " ) ) ]', 135 | // .warning, HTML only. The same as *[class~="warning"] 136 | '*[ contains( concat( " ", @class, " " ), concat( " ", "\1", " " ) ) ]', 137 | // E#myid, Matches any E element with id-attribute equal to "myid" 138 | '\1[ @id = "\2" ]', 139 | // #myid, Matches any element with id-attribute equal to "myid" 140 | '*[ @id = "\1" ]' 141 | ); 142 | 143 | // return 144 | $xPath = (string) '//' . preg_replace($cssSelector, $xPathQuery, $selector); 145 | 146 | return str_replace('] *', ']//*', $xPath); 147 | } 148 | 149 | /** 150 | * Calculate the specifity for the CSS-selector 151 | * 152 | * @return int 153 | * @param string $selector The selector to calculate the specifity for. 154 | */ 155 | private function calculateCSSSpecifity($selector) 156 | { 157 | // cleanup selector 158 | $selector = str_replace(array('>', '+'), array(' > ', ' + '), $selector); 159 | 160 | // init var 161 | $specifity = 0; 162 | 163 | // split the selector into chunks based on spaces 164 | $chunks = explode(' ', $selector); 165 | 166 | // loop chunks 167 | foreach ($chunks as $chunk) { 168 | // an ID is important, so give it a high specifity 169 | if(strstr($chunk, '#') !== false) $specifity += 100; 170 | 171 | // classes are more important than a tag, but less important then an ID 172 | elseif(strstr($chunk, '.')) $specifity += 10; 173 | 174 | // anything else isn't that important 175 | else $specifity += 1; 176 | } 177 | 178 | // return 179 | return $specifity; 180 | } 181 | 182 | 183 | /** 184 | * Cleanup the generated HTML 185 | * 186 | * @return string 187 | * @param string $html The HTML to cleanup. 188 | */ 189 | private function cleanupHTML($html) 190 | { 191 | // remove classes 192 | $html = preg_replace('/(\s)+class="(.*)"(\s)+/U', ' ', $html); 193 | 194 | // remove IDs 195 | $html = preg_replace('/(\s)+id="(.*)"(\s)+/U', ' ', $html); 196 | 197 | // return 198 | return $html; 199 | } 200 | 201 | 202 | /** 203 | * Converts the loaded HTML into an HTML-string with inline styles based on the loaded CSS 204 | * 205 | * @return string 206 | * @param bool[optional] $outputXHTML Should we output valid XHTML? 207 | */ 208 | public function convert($outputXHTML = false) 209 | { 210 | // redefine 211 | $outputXHTML = (bool) $outputXHTML; 212 | 213 | // validate 214 | if($this->html == null) throw new Exception('No HTML provided.'); 215 | 216 | // should we use inline style-block 217 | if ($this->useInlineStylesBlock) { 218 | // init var 219 | $matches = array(); 220 | 221 | // match the style blocks 222 | preg_match_all('|(.*)|isU', $this->html, $matches); 223 | 224 | // any style-blocks found? 225 | if (!empty($matches[2])) { 226 | // add 227 | foreach($matches[2] as $match) $this->css .= trim($match) ."\n"; 228 | } 229 | } 230 | 231 | // process css 232 | $this->processCSS(); 233 | 234 | // create new DOMDocument 235 | $document = new DOMDocument('1.0', $this->getEncoding()); 236 | 237 | // set error level 238 | libxml_use_internal_errors(true); 239 | 240 | // load HTML 241 | $document->loadHTML($this->html); 242 | 243 | // create new XPath 244 | $xPath = new DOMXPath($document); 245 | 246 | // any rules? 247 | if (!empty($this->cssRules)) { 248 | // loop rules 249 | foreach ($this->cssRules as $rule) { 250 | // init var 251 | $query = $this->buildXPathQuery($rule['selector']); 252 | 253 | // validate query 254 | if($query === false) continue; 255 | 256 | // search elements 257 | $elements = $xPath->query($query); 258 | 259 | // validate elements 260 | if($elements === false) continue; 261 | 262 | // loop found elements 263 | foreach ($elements as $element) { 264 | // no styles stored? 265 | if ($element->attributes->getNamedItem( 266 | 'data-css-to-inline-styles-original-styles' 267 | ) == null) { 268 | // init var 269 | $originalStyle = ''; 270 | if ($element->attributes->getNamedItem('style') !== null) { 271 | $originalStyle = $element->attributes->getNamedItem('style')->value; 272 | } 273 | 274 | // store original styles 275 | $element->setAttribute( 276 | 'data-css-to-inline-styles-original-styles', 277 | $originalStyle 278 | ); 279 | 280 | // clear the styles 281 | $element->setAttribute('style', ''); 282 | } 283 | 284 | // init var 285 | $properties = array(); 286 | 287 | // get current styles 288 | $stylesAttribute = $element->attributes->getNamedItem('style'); 289 | 290 | // any styles defined before? 291 | if ($stylesAttribute !== null) { 292 | // get value for the styles attribute 293 | $definedStyles = (string) $stylesAttribute->value; 294 | 295 | // split into properties 296 | $definedProperties = (array) explode(';', $definedStyles); 297 | 298 | // loop properties 299 | foreach ($definedProperties as $property) { 300 | // validate property 301 | if($property == '') continue; 302 | 303 | // split into chunks 304 | $chunks = (array) explode(':', trim($property), 2); 305 | 306 | // validate 307 | if(!isset($chunks[1])) continue; 308 | 309 | // loop chunks 310 | $properties[$chunks[0]] = trim($chunks[1]); 311 | } 312 | } 313 | 314 | // add new properties into the list 315 | foreach ($rule['properties'] as $key => $value) { 316 | $properties[$key] = $value; 317 | } 318 | 319 | // build string 320 | $propertyChunks = array(); 321 | 322 | // build chunks 323 | foreach ($properties as $key => $values) { 324 | foreach ((array) $values as $value) { 325 | $propertyChunks[] = $key . ': ' . $value . ';'; 326 | } 327 | } 328 | 329 | // build properties string 330 | $propertiesString = implode(' ', $propertyChunks); 331 | 332 | // set attribute 333 | if ($propertiesString != '') { 334 | $element->setAttribute('style', $propertiesString); 335 | } 336 | } 337 | } 338 | 339 | // reapply original styles 340 | $query = $this->buildXPathQuery( 341 | '*[@data-css-to-inline-styles-original-styles]' 342 | ); 343 | 344 | // validate query 345 | if($query === false) return; 346 | 347 | // search elements 348 | $elements = $xPath->query($query); 349 | 350 | // loop found elements 351 | foreach ($elements as $element) { 352 | // get the original styles 353 | $originalStyle = $element->attributes->getNamedItem( 354 | 'data-css-to-inline-styles-original-styles' 355 | )->value; 356 | 357 | if ($originalStyle != '') { 358 | $originalProperties = array(); 359 | $originalStyles = (array) explode(';', $originalStyle); 360 | 361 | foreach ($originalStyles as $property) { 362 | // validate property 363 | if($property == '') continue; 364 | 365 | // split into chunks 366 | $chunks = (array) explode(':', trim($property), 2); 367 | 368 | // validate 369 | if(!isset($chunks[1])) continue; 370 | 371 | // loop chunks 372 | $originalProperties[$chunks[0]] = trim($chunks[1]); 373 | } 374 | 375 | // get current styles 376 | $stylesAttribute = $element->attributes->getNamedItem('style'); 377 | $properties = array(); 378 | 379 | // any styles defined before? 380 | if ($stylesAttribute !== null) { 381 | // get value for the styles attribute 382 | $definedStyles = (string) $stylesAttribute->value; 383 | 384 | // split into properties 385 | $definedProperties = (array) explode(';', $definedStyles); 386 | 387 | // loop properties 388 | foreach ($definedProperties as $property) { 389 | // validate property 390 | if($property == '') continue; 391 | 392 | // split into chunks 393 | $chunks = (array) explode(':', trim($property), 2); 394 | 395 | // validate 396 | if(!isset($chunks[1])) continue; 397 | 398 | // loop chunks 399 | $properties[$chunks[0]] = trim($chunks[1]); 400 | } 401 | } 402 | 403 | // add new properties into the list 404 | foreach ($originalProperties as $key => $value) { 405 | $properties[$key] = $value; 406 | } 407 | 408 | // build string 409 | $propertyChunks = array(); 410 | 411 | // build chunks 412 | foreach ($properties as $key => $values) { 413 | foreach ((array) $values as $value) { 414 | $propertyChunks[] = $key . ': ' . $value . ';'; 415 | } 416 | } 417 | 418 | // build properties string 419 | $propertiesString = implode(' ', $propertyChunks); 420 | 421 | // set attribute 422 | if($propertiesString != '') $element->setAttribute( 423 | 'style', $propertiesString 424 | ); 425 | } 426 | 427 | // remove placeholder 428 | $element->removeAttribute( 429 | 'data-css-to-inline-styles-original-styles' 430 | ); 431 | } 432 | } 433 | 434 | // should we output XHTML? 435 | if ($outputXHTML) { 436 | // set formating 437 | $document->formatOutput = true; 438 | 439 | // get the HTML as XML 440 | $html = $document->saveXML(null, LIBXML_NOEMPTYTAG); 441 | 442 | // get start of the XML-declaration 443 | $startPosition = strpos($html, '', $startPosition); 449 | 450 | // remove the XML-header 451 | $html = ltrim(substr($html, $endPosition + 1)); 452 | } 453 | } 454 | 455 | // just regular HTML 4.01 as it should be used in newsletters 456 | else { 457 | // get the HTML 458 | $html = $document->saveHTML(); 459 | } 460 | 461 | // cleanup the HTML if we need to 462 | if($this->cleanup) $html = $this->cleanupHTML($html); 463 | 464 | // strip original style tags if we need to 465 | if ($this->stripOriginalStyleTags) { 466 | $html = $this->stripOriginalStyleTags($html); 467 | } 468 | 469 | // return 470 | return $html; 471 | } 472 | 473 | 474 | /** 475 | * Get the encoding to use 476 | * 477 | * @return string 478 | */ 479 | private function getEncoding() 480 | { 481 | return $this->encoding; 482 | } 483 | 484 | 485 | /** 486 | * Process the loaded CSS 487 | * 488 | * @return void 489 | */ 490 | private function processCSS() 491 | { 492 | // init vars 493 | $css = (string) $this->css; 494 | 495 | // remove newlines 496 | $css = str_replace(array("\r", "\n"), '', $css); 497 | 498 | // replace double quotes by single quotes 499 | $css = str_replace('"', '\'', $css); 500 | 501 | // remove comments 502 | $css = preg_replace('|/\*.*?\*/|', '', $css); 503 | 504 | // remove spaces 505 | $css = preg_replace('/\s\s+/', ' ', $css); 506 | 507 | if ($this->excludeMediaQueries) { 508 | $css = preg_replace('/@media [^{]*{([^{}]|{[^{}]*})*}/', '', $css); 509 | } 510 | 511 | // rules are splitted by } 512 | $rules = (array) explode('}', $css); 513 | 514 | // init var 515 | $i = 1; 516 | 517 | // loop rules 518 | foreach ($rules as $rule) { 519 | // split into chunks 520 | $chunks = explode('{', $rule); 521 | 522 | // invalid rule? 523 | if(!isset($chunks[1])) continue; 524 | 525 | // set the selectors 526 | $selectors = trim($chunks[0]); 527 | 528 | // get cssProperties 529 | $cssProperties = trim($chunks[1]); 530 | 531 | // split multiple selectors 532 | $selectors = (array) explode(',', $selectors); 533 | 534 | // loop selectors 535 | foreach ($selectors as $selector) { 536 | // cleanup 537 | $selector = trim($selector); 538 | 539 | // build an array for each selector 540 | $ruleSet = array(); 541 | 542 | // store selector 543 | $ruleSet['selector'] = $selector; 544 | 545 | // process the properties 546 | $ruleSet['properties'] = $this->processCSSProperties( 547 | $cssProperties 548 | ); 549 | 550 | // calculate specifity 551 | $ruleSet['specifity'] = $this->calculateCSSSpecifity( 552 | $selector 553 | ) + $i; 554 | 555 | // add into global rules 556 | $this->cssRules[] = $ruleSet; 557 | } 558 | 559 | // increment 560 | $i++; 561 | } 562 | 563 | // sort based on specifity 564 | if (!empty($this->cssRules)) { 565 | usort($this->cssRules, array(__CLASS__, 'sortOnSpecifity')); 566 | } 567 | } 568 | 569 | /** 570 | * Process the CSS-properties 571 | * 572 | * @return array 573 | * @param string $propertyString The CSS-properties. 574 | */ 575 | private function processCSSProperties($propertyString) 576 | { 577 | // split into chunks 578 | $properties = (array) explode(';', $propertyString); 579 | 580 | // init var 581 | $pairs = array(); 582 | 583 | // loop properties 584 | foreach ($properties as $property) { 585 | // split into chunks 586 | $chunks = (array) explode(':', $property, 2); 587 | 588 | // validate 589 | if(!isset($chunks[1])) continue; 590 | 591 | // cleanup 592 | $chunks[0] = trim($chunks[0]); 593 | $chunks[1] = trim($chunks[1]); 594 | 595 | // add to pairs array 596 | if(!isset($pairs[$chunks[0]]) || 597 | !in_array($chunks[1], $pairs[$chunks[0]])) { 598 | $pairs[$chunks[0]][] = $chunks[1]; 599 | } 600 | } 601 | 602 | // sort the pairs 603 | ksort($pairs); 604 | 605 | // return 606 | return $pairs; 607 | } 608 | 609 | /** 610 | * Should the IDs and classes be removed? 611 | * 612 | * @return void 613 | * @param bool[optional] $on Should we enable cleanup? 614 | */ 615 | public function setCleanup($on = true) 616 | { 617 | $this->cleanup = (bool) $on; 618 | } 619 | 620 | /** 621 | * Set CSS to use 622 | * 623 | * @return void 624 | * @param string $css The CSS to use. 625 | */ 626 | public function setCSS($css) 627 | { 628 | $this->css = (string) $css; 629 | } 630 | 631 | /** 632 | * Set the encoding to use with the DOMDocument 633 | * 634 | * @return void 635 | * @param string $encoding The encoding to use. 636 | */ 637 | public function setEncoding($encoding) 638 | { 639 | $this->encoding = (string) $encoding; 640 | } 641 | 642 | /** 643 | * Set HTML to process 644 | * 645 | * @return void 646 | * @param string $html The HTML to process. 647 | */ 648 | public function setHTML($html) 649 | { 650 | $this->html = (string) $html; 651 | } 652 | 653 | /** 654 | * Set use of inline styles block 655 | * If this is enabled the class will use the style-block in the HTML. 656 | * 657 | * @return void 658 | * @param bool[optional] $on Should we process inline styles? 659 | */ 660 | public function setUseInlineStylesBlock($on = true) 661 | { 662 | $this->useInlineStylesBlock = (bool) $on; 663 | } 664 | 665 | /** 666 | * Set strip original style tags 667 | * If this is enabled the class will remove all style tags in the HTML. 668 | * 669 | * @return void 670 | * @param bool[optional] $on Should we process inline styles? 671 | */ 672 | public function setStripOriginalStyleTags($on = true) 673 | { 674 | $this->stripOriginalStyleTags = (bool) $on; 675 | } 676 | 677 | /** 678 | * Set exclude media queries 679 | * 680 | * If this is enabled the media queries will be removed before inlining the rules 681 | * 682 | * @return void 683 | * @param bool[optional] $on 684 | */ 685 | public function setExcludeMediaQueries($on = true) 686 | { 687 | $this->excludeMediaQueries = (bool) $on; 688 | } 689 | 690 | /** 691 | * Strip style tags into the generated HTML 692 | * 693 | * @return string 694 | * @param string $html The HTML to strip style tags. 695 | */ 696 | private function stripOriginalStyleTags($html) 697 | { 698 | return preg_replace('|(.*)|isU', '', $html); 699 | } 700 | 701 | /** 702 | * Sort an array on the specifity element 703 | * 704 | * @return int 705 | * @param array $e1 The first element. 706 | * @param array $e2 The second element. 707 | */ 708 | private static function sortOnSpecifity($e1, $e2) 709 | { 710 | // validate 711 | if(!isset($e1['specifity']) || !isset($e2['specifity'])) return 0; 712 | 713 | // lower 714 | if($e1['specifity'] < $e2['specifity']) return -1; 715 | 716 | // higher 717 | if($e1['specifity'] > $e2['specifity']) return 1; 718 | 719 | // fallback 720 | return 0; 721 | } 722 | } 723 | -------------------------------------------------------------------------------- /htmlemail.php: -------------------------------------------------------------------------------- 1 | location = 'plugins'; 118 | $this->plugin_dir = plugin_dir_path( __FILE__ ); 119 | $this->plugin_url = plugins_url( '', __FILE__ ) . '/'; 120 | } else if ( defined( 'WPMU_PLUGIN_URL' ) && defined( 'WPMU_PLUGIN_DIR' ) && file_exists( WPMU_PLUGIN_DIR . '/' . basename( __FILE__ ) ) ) { 121 | $this->location = 'mu-plugins'; 122 | $this->plugin_dir = WPMU_PLUGIN_DIR . '/'; 123 | $this->plugin_url = WPMU_PLUGIN_URL . '/'; 124 | } else { 125 | wp_die( __( 'There was an issue determining where HTML Email is installed. Please reinstall.', 'htmlemail' ) ); 126 | } 127 | //Template Directory 128 | $this->template_directory = $this->plugin_dir . 'lib/templates/'; 129 | $this->template_url = $this->plugin_url . 'lib/templates/'; 130 | 131 | //Assets Directory 132 | $this->assets_path = $this->plugin_url . 'assets/'; 133 | 134 | //localize 135 | add_action( 'plugins_loaded', array( &$this, 'localization' ) ); 136 | 137 | //Actions 138 | add_action( 'admin_menu', array( &$this, 'admin_menu_link' ) ); 139 | add_action( 'network_admin_menu', array( &$this, 'admin_menu_link' ) ); 140 | add_action( 'phpmailer_init', array( &$this, 'convert_plain_text' ) ); 141 | 142 | //Filters 143 | add_filter( 'wp_mail', array( &$this, 'wp_mail' ) ); 144 | add_filter( 'retrieve_password_message', array( &$this, 'fix_pass_msg' ) ); 145 | 146 | //Templates 147 | add_filter( 'htmlemail_templates', array( $this, 'htmlemail_templates_list' ) ); 148 | 149 | //Enqueue files 150 | add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); 151 | 152 | //Return template data 153 | add_action( 'wp_ajax_htmlemail_get_template_data', array( $this, 'htmlemail_template_data' ) ); 154 | add_action( 'wp_ajax_get_preview_data', array( $this, 'get_preview_data' ) ); 155 | 156 | //Handle preview email ajax request 157 | add_action( 'wp_ajax_preview_email', array( $this, 'preview_email' ) ); 158 | 159 | // Set Content type HTML 160 | add_filter( 'wp_mail_content_type', array( $this, 'set_content_type' ), 11 ); 161 | add_filter( 'woocommerce_email_headers', array( $this, 'set_woocommerce_content_type' ) ); 162 | 163 | } 164 | 165 | function localization() { 166 | // Load up the localization file if we're using WordPress in a different language 167 | // Place it in this plugin's "languages" folder and name it "html_email-[value in wp-config].mo" 168 | if ( $this->location == 'plugins' ) { 169 | load_plugin_textdomain( 'htmlemail', false, $this->plugin_dir . 'languages/' ); 170 | } else if ( $this->location == 'mu-plugins' ) { 171 | load_muplugin_textdomain( 'htmlemail', $this->plugin_dir . 'languages/' ); 172 | } 173 | } 174 | 175 | /** 176 | * Removes the <> from password reset link sent in new user emails 177 | * @return mixed 178 | */ 179 | function clean_links( $message ) { 180 | return preg_replace( '#<(https?://[^*]+)>#', '$1', $message ); 181 | } 182 | 183 | /** 184 | * Filter the Content, add the template to actual email and then send it 185 | * 186 | * @param $args 187 | * 188 | * @return array 189 | */ 190 | function wp_mail( $args ) { 191 | extract( $args ); 192 | 193 | if ( ! is_multisite() || is_network_admin() ) { 194 | $modify_html_email = get_site_option( 'modify_html_email' ); 195 | } else { 196 | $modify_html_email = get_option( 'modify_html_email' ); 197 | } 198 | $modify_html_email = isset( $modify_html_email ) ? $modify_html_email : 1; 199 | /** 200 | * Check if the current mail is a html mail and template adding is allowed or not 201 | */ 202 | if ( ! empty( $this->is_html ) ) { 203 | if ( $this->is_html && ! $modify_html_email ) { 204 | return $args; 205 | } 206 | } elseif ( ! empty( $headers ) ) { 207 | //check headers 208 | if ( is_array( $headers ) ) { 209 | if ( in_array( 'text/html', $headers ) && ! $modify_html_email ) { 210 | return $args; 211 | } 212 | } elseif ( strpos( $headers, 'text/html' ) !== false && ! $modify_html_email ) { 213 | return $args; 214 | } 215 | } 216 | 217 | $html_template = $htmlemail_settings = ''; 218 | 219 | $this->plain_text_message = $message; 220 | 221 | // Clean Links 222 | $message = $this->clean_links( $message ); 223 | 224 | /** 225 | * Allows to enable or disable Next Line to br tag conversion 226 | */ 227 | $nl2br = apply_filters( 'wp_htmlemail_nl2br', false ); 228 | 229 | $message = $nl2br ? nl2br( $message ) : $message; 230 | 231 | //Force WP to add

tags to the message content 232 | if ( $message == strip_tags( $message ) ) { 233 | // No HTML, do wpautop 234 | $message = wpautop( $message ); 235 | } 236 | 237 | //Fetch HTML email settings 238 | $htmlemail_settings = get_site_option( 'htmlemail_settings' ); 239 | 240 | $current_template_name = isset( $htmlemail_settings['template_name'] ) ? ucfirst( strtolower( $htmlemail_settings['template_name'] ) ) : false; 241 | 242 | if( !$current_template_name ){ 243 | return compact( 'to', 'subject', 'message', 'headers', 'attachments' ); 244 | } 245 | 246 | $template_directory = $this->plugin_dir . 'lib/templates/'; 247 | $theme_path = $template_directory . $current_template_name; 248 | 249 | $this->template_url = $this->plugin_url . 'lib/templates/'; 250 | $this->theme_url = $this->template_url . $current_template_name; 251 | 252 | //Get Default Variables 253 | require_once( $theme_path . '/index.php' ); 254 | 255 | //Check if site is allowed to use its own template 256 | $site_override = isset( $htmlemail_settings['site_override'] ) ? $htmlemail_settings['site_override'] : ''; 257 | //As the network has site id 1, it loads the template for blog with id 1 but for preview we need to show network template 258 | if ( isset( $_POST['preview_html_email'] ) && 'Send' == $_POST['preview_html_email'] && is_network_admin() ) { 259 | $html_template = get_site_option( 'html_template' ); 260 | } 261 | 262 | if ( empty( $html_template ) && $site_override && is_multisite() ) { 263 | $html_template = get_option( 'html_template' ); 264 | } 265 | 266 | if ( empty( $html_template ) ) { 267 | $html_template = get_site_option( 'html_template' ); 268 | } 269 | 270 | if ( ! empty ( $html_template ) ) { 271 | if ( strpos( $html_template, '{MESSAGE}' ) !== false ) { 272 | //Replace {MESSAGE} in template with actual email content 273 | $key = '{MESSAGE}'; 274 | } else { 275 | //Compatibilty with previous version of the plugin, as it used MESSAGE instead of {MESSAGE} 276 | $key = 'MESSAGE'; 277 | } 278 | $message = str_replace( $key, $message, $html_template ); 279 | 280 | //Replace User name 281 | $user = get_user_by( 'email', $to ); 282 | if ( $user ) { 283 | $message = preg_replace( '~\{USER_NAME}~', $user->data->display_name, $message ); 284 | } else { 285 | $message = preg_replace( '~\{USER_NAME}~', '', $message ); 286 | } 287 | $message = preg_replace( '~\{USER_EMAIL}~', $to, $message ); 288 | 289 | $message = $this->replace_placeholders( $message, $args, false ); 290 | } 291 | 292 | //Compact & return all the vars 293 | return compact( 'to', 'subject', 'message', 'headers', 'attachments' ); 294 | } 295 | 296 | //removes the <> symbols from the reset password link so it's not hidden in html mode emails 297 | function fix_pass_msg( $msg ) { 298 | $msg = str_replace( '<', '', $msg ); 299 | $msg = str_replace( '>', '', $msg ); 300 | 301 | return $msg; 302 | } 303 | 304 | function convert_plain_text( $phpmailer ) { 305 | // Create plain text version of email if it doesn't exist 306 | if ( $phpmailer->AltBody == '' ) { 307 | $phpmailer->AltBody = $this->plain_text_message; 308 | } 309 | } 310 | 311 | /** 312 | * @desc Adds the options subpanel 313 | */ 314 | function admin_menu_link() { 315 | global $html_template, $html_template_network, $html_template_site; 316 | //If you change this from add_options_page, MAKE SURE you change the filter_plugin_actions function (below) to 317 | //reflect the page filename (ie - options-general.php) of the page your plugin is under! 318 | if ( is_multisite() ) { 319 | $html_template_network = add_submenu_page( 'settings.php', __( 'HTML Email Template', 'htmlemail' ), __( 'HTML Email Template', 'htmlemail' ), 'manage_network_options', 'html-template', array( 320 | &$this, 321 | 'admin_options_page' 322 | ) ); 323 | 324 | $htmlemail_settings = get_site_option( 'htmlemail_settings' ); 325 | 326 | $site_override = isset( $htmlemail_settings['site_override'] ) ? $htmlemail_settings ['site_override'] : ''; 327 | 328 | if ( $site_override ) { 329 | $html_template_site = add_options_page( __( 'HTML Email Template', 'htmlemail' ), __( 'HTML Email Template', 'htmlemail' ), 'manage_options', 'html-template', array( 330 | $this, 331 | 'admin_options_page' 332 | ) ); 333 | } 334 | //register scripts for site 335 | add_action( "load-{$html_template_site}", array( &$this, 'register_scripts' ) ); 336 | } else if ( ! is_multisite() ) { 337 | $html_template = add_submenu_page( 'options-general.php', __( 'HTML Email Template', 'htmlemail' ), __( 'HTML Email Template', 'htmlemail' ), 'manage_options', 'html-template', array( 338 | &$this, 339 | 'admin_options_page' 340 | ) ); 341 | } 342 | add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( 343 | &$this, 344 | 'filter_plugin_actions' 345 | ), 10, 2 ); 346 | add_action( "load-{$html_template}", array( &$this, 'register_scripts' ) ); 347 | add_action( "load-{$html_template_network}", array( &$this, 'register_scripts' ) ); 348 | } 349 | 350 | /** 351 | * @desc Adds the Settings link to the plugin activate/deactivate page 352 | */ 353 | function filter_plugin_actions( $links, $file ) { 354 | if ( is_multisite() ) { 355 | $settings_link = '' . __( 'Settings', 'htmlemail' ) . ''; 356 | } else { 357 | $settings_link = '' . __( 'Settings', 'htmlemail' ) . ''; 358 | } 359 | 360 | array_unshift( $links, $settings_link ); // before other links 361 | 362 | return $links; 363 | } 364 | 365 | /** 366 | * Adds settings/options page 367 | */ 368 | function admin_options_page() { 369 | global $current_user; 370 | 371 | //Process $_POST 372 | $this->save_settings(); 373 | 374 | //Fetch HTML email settings 375 | if ( ! is_multisite() || is_network_admin() ) { 376 | 377 | $htmlemail_settings = get_site_option( 'htmlemail_settings' ); 378 | $html_template = get_site_option( 'html_template' ); 379 | $modify_html_email = get_site_option( 'modify_html_email' ); 380 | 381 | } else { 382 | $htmlemail_settings = get_option( 'htmlemail_settings' ); 383 | $html_template = get_option( 'html_template' ); 384 | $modify_html_email = get_option( 'modify_html_email' ); 385 | 386 | } 387 | 388 | $current_template_name = isset( $htmlemail_settings['template_name'] ) ? $htmlemail_settings['template_name'] : ''; 389 | 390 | $modify_html_email = isset( $modify_html_email ) ? $modify_html_email : 1; 391 | 392 | //Whether to allow subsites to specify their own html template 393 | $site_override = isset( $htmlemail_settings['site_override'] ) ? $htmlemail_settings ['site_override'] : ''; 394 | 395 | ?> 396 |

397 |
398 | 399 |

400 | 401 |

402 | 403 |
404 |

405 | below by clicking over a template and then click over the load template button or type/paste your own HTML into the textarea.', 'htmlemail' ), 408 | __( 'Click "Preview" to quickly see what your emails will look like in a popup.', 'htmlemail' ), 409 | __( 'Send a "Test Email" to preview your template in actual email clients. You can specify an email address for this to be sent to.', 'htmlemail' ), 410 | __( 'Select "Save" and the HTML you have below will be used as your HTML Email Template for all transactional emails from your site.', 'htmlemail' ) 411 | ); ?> 412 |
    416 |
  • 417 | "; ?> 419 |
  • 422 |
423 |
424 | 425 | 426 |
427 | 428 | [+] 429 |
430 | 431 |
436 | 454 |
list_placeholders( '', true ); 456 | echo $this->template_images(); ?> 457 |
458 | 460 | 461 | 462 | 465 | 466 | 467 | 469 |
470 | 471 |
472 | 473 | 474 | 475 |
476 |
477 |
478 | 479 |
480 |
481 | 482 | 485 | 490 | 491 | 492 | 493 |
494 |
495 | html_theme = $html_theme; 501 | if ( is_network_admin() || ! is_multisite() ) { 502 | update_site_option( 'html_theme', $html_theme ); 503 | }else{ 504 | update_option( 'html_theme', $html_theme ); 505 | } 506 | } 507 | 508 | function get_html_theme(){ 509 | if ( $this->html_theme != "" ){ 510 | return $this->html_theme; 511 | }else{ 512 | if ( is_network_admin() || is_multisite() ) { 513 | return get_site_option( 'html_theme' ); 514 | }else{ 515 | return get_option( 'html_theme' ); 516 | } 517 | } 518 | return false; 519 | } 520 | 521 | function get_html_theme_path($html_theme = ""){ 522 | $html_theme = ( $html_theme == "" ) ? $this->get_html_theme() : ""; 523 | if ( $this->theme_path == "") { 524 | $this->theme_path = $this->template_directory . $html_theme; 525 | } 526 | return $this->theme_path; 527 | } 528 | 529 | function get_html_theme_url($html_theme = ""){ 530 | if ($html_theme=="") $html_theme = $this->get_html_theme(); 531 | if ( $this->theme_url == "") { 532 | $this->theme_url = $this->template_url . $html_theme; 533 | } 534 | return $this->theme_url ; 535 | } 536 | 537 | function register_scripts() { 538 | wp_register_style( 'slick_style', $this->assets_path . 'slick/slick.css' ); 539 | wp_register_script( 'slick_js', $this->assets_path . 'slick/slick.min.js', array( 'jquery' ), '', true ); 540 | wp_register_style( 'htmlemail_css', $this->assets_path . 'css/htmlemail.css' ); 541 | wp_register_script( 'htmlemail_js', $this->assets_path . 'js/htmlemail.js', array( 542 | 'jquery', 543 | 'slick_js', 544 | 'thickbox' 545 | ), '', true ); 546 | //Lolcalize string to js, to make them translatable 547 | $template_load_warning = __( "Your custom template changes will be lost, are you sure you want to continue?", 'htmlemail' ); 548 | $message_missing = __( "You need to place {MESSAGE} somewhere in the template, preferably a main content section.", 'htmlemail' ); 549 | $htmlemail_help_text = array( 550 | 'load_template' => $template_load_warning, 551 | 'message_missing' => $message_missing 552 | ); 553 | wp_localize_script( 'htmlemail_js', 'htmlemail_text', $htmlemail_help_text ); 554 | } 555 | 556 | function enqueue_scripts() { 557 | if ( ! $this->is_htmlemail_setting_page() ) { 558 | return; 559 | } 560 | wp_enqueue_style( 'slick_style' ); 561 | wp_enqueue_script( 'slick_js' ); 562 | wp_enqueue_style( 'htmlemail_css' ); 563 | wp_enqueue_script( 'htmlemail_js' ); 564 | wp_enqueue_style( 'thickbox' ); 565 | wp_enqueue_media(); 566 | } 567 | 568 | /** 569 | * Returns template list for Emails 570 | * @return type 571 | */ 572 | function htmlemail_templates_list() { 573 | $templates = array(); 574 | //get all template folders inside template directory 575 | foreach ( glob( $this->template_directory . '*', GLOB_ONLYDIR ) as $template_path ) { 576 | $template_url = $this->template_url . basename( $template_path ); 577 | if ( $template_path ) { 578 | $template_html = $template_path . '/template.html'; 579 | $template_screenshot = glob( $template_path . '/screenshot.*' ); 580 | //Check if it contains template.html and a screenshot 581 | if ( ! file_exists( $template_html ) || ! file_exists( $template_screenshot[0] ) ) { 582 | continue; 583 | } 584 | $theme_name = get_file_data( $template_path . '/style.css', array( 'Name' => 'Theme Name' ) ); 585 | $templates[] = array( 586 | 'name' => $theme_name['Name'], 587 | 'screenshot' => $template_url . '/' . basename( $template_screenshot[0] ) 588 | ); 589 | } 590 | } 591 | 592 | return $templates; 593 | } 594 | 595 | /** 596 | * Returns HTML for a selected template 597 | */ 598 | function htmlemail_template_data() { 599 | if ( empty( $_GET['theme'] ) ) { 600 | wp_send_json_error( 'no theme specified' ); 601 | } 602 | $this->html_theme = $_GET['theme']; 603 | $this->update_html_theme( ucfirst( strtolower( $_GET['theme'] ) ) ); 604 | $content = $this->get_contents_elements( $_GET['theme'] ); 605 | wp_send_json_success( $content ); 606 | } 607 | 608 | /** 609 | * Fetches content from template files and returns content with inline styling 610 | * 611 | * @param type $theme_name 612 | * 613 | * @return boolean 614 | */ 615 | function get_contents_elements( $theme_name = '' ) { 616 | if ( ! $theme_name ) { 617 | return false; 618 | } 619 | $this->html_theme = $theme_name; 620 | 621 | $html_theme = $this->get_html_theme(); 622 | if ( ! $html_theme ){ 623 | $this->update_html_theme( $theme_name ); 624 | } 625 | 626 | $contents = array(); 627 | $theme_name = explode( ' ', $theme_name ); 628 | $theme_name = implode( '', $theme_name ); 629 | $theme_name = ucfirst( strtolower( $theme_name ) ); 630 | $this->theme_path = $this->template_directory . $theme_name; 631 | $this->theme_url = $this->template_url . $theme_name; 632 | 633 | //Get Default Variables 634 | require_once( $this->theme_path . '/index.php' ); 635 | 636 | //Template Files 637 | $build_htmls['header'][] = $this->theme_path . "/header.html"; 638 | $build_htmls['content'][] = $this->theme_path . "/template.html"; 639 | $build_htmls['footer'][] = $this->theme_path . "/footer.html"; 640 | 641 | if ( defined( 'BUILDER_SETTING_USE_DEFAULT_HEADER_FOOTER' ) ) { 642 | $build_htmls['header'][] = $this->template_directory . "default_header.html"; 643 | $build_htmls['footer'][] = $this->template_directory . "default_footer.html"; 644 | } 645 | 646 | $build_styles['style'][] = $this->theme_path . "/style.css"; 647 | $build_styles['style_header'][] = $this->theme_path . "/style_header.css"; 648 | 649 | if ( defined( 'BUILDER_SETTING_USE_DEFAULT_STYLES' ) ) { 650 | $build_styles['default_style'][] = $this->template_directory . "default_style.css"; 651 | } 652 | 653 | $build_theme = array_merge( $build_htmls, $build_styles ); 654 | foreach ( $build_theme as $type => $possible_files ) { 655 | foreach ( $possible_files as $possible_file ) { 656 | if ( isset( $contents_parts[ $type ] ) && ! empty( $contents_parts[ $type ] ) ) { 657 | continue; 658 | } 659 | if ( file_exists( $possible_file ) ) { 660 | $handle = fopen( $possible_file, "r" ); 661 | $contents_parts[ $type ] = fread( $handle, filesize( $possible_file ) ); 662 | fclose( $handle ); 663 | 664 | if ( strpos( $type, 'style' ) !== false ) { 665 | $contents_parts[ $type ] = preg_replace( "/^\s*\/\*[^(\*\/)]*\*\//m", "", $contents_parts[ $type ] ); 666 | } 667 | } 668 | if ( ! isset( $contents_parts[ $type ] ) ) { 669 | $contents_parts[ $type ] = ''; 670 | } 671 | } 672 | } 673 | //if head missing - fix it! 674 | if ( strpos( $contents_parts['header'] . $contents_parts['content'], '' ) === false ) { 675 | if ( strpos( $contents_parts['header'] . $contents_parts['content'], '' ) === false ) { 676 | $body_header = ''; 677 | $body_footer = ''; 678 | } else { 679 | $body_header = $body_footer = ''; 680 | } 681 | 682 | $contents_parts['header'] = ' 683 | 684 | 685 | 686 | {EMAIL_TITLE} 687 | 691 | 692 | {HEADER} 693 | ' . $body_header . $contents_parts['header']; 694 | 695 | $contents_parts['footer'] = $contents_parts['footer'] . $body_footer . ' 696 | '; 697 | } 698 | //Merge header, content and footer 699 | $content = $contents_parts['header'] . $contents_parts['content'] . $contents_parts['footer']; 700 | $blog_url = get_option( 'siteurl' ); 701 | 702 | //Replace BLOG_URL with actual URL as DOM compatibility escapes img src 703 | $content = preg_replace( "/{BLOG_URL}/", $blog_url . '/', $content ); 704 | $style = isset( $contents_parts['default_style'] ) ? $contents_parts['default_style'] . $contents_parts['style'] . $contents_parts['style_header'] : $contents_parts['style'] . $contents_parts['style_header']; 705 | //Do the inline styling 706 | $content = $this->do_inline_styles( $content, $style ); 707 | 708 | //Check for DOM compatibilty from E-Newsletter 709 | $content = $this->dom_compatibility( $content ); 710 | 711 | //Replace CSS Variabls 712 | $possible_settings = array( 713 | 'BG_COLOR', 714 | //'BG_IMAGE', //Now it's controlled by uploader 715 | 'LINK_COLOR', 716 | 'BODY_COLOR', 717 | 'ALTERNATIVE_COLOR', 718 | 'TITLE_COLOR', 719 | 'EMAIL_TITLE' 720 | ); 721 | foreach ( $possible_settings as $possible_setting ) { 722 | if ( defined( 'BUILDER_DEFAULT_' . $possible_setting ) ) { 723 | $this->settings[] = $possible_setting; 724 | } 725 | } 726 | 727 | foreach ( $this->settings as $setting ) { 728 | if ( defined( 'BUILDER_DEFAULT_' . $setting ) ) { 729 | /* 730 | // Since BG_IMAGE removed from $possible_settings 731 | // It was causing issues when 732 | // wp-content/plugins/htmlemail/lib/templates/sometheme/template.php file includes the BG_IMAGE placeholder, 733 | // in the editor it will show as empty {} 734 | if ( $setting == 'BG_IMAGE' ) { 735 | //full path for image 736 | $value = defined( constant( 'BUILDER_DEFAULT_' . $setting ) ) ? $this->theme_url . constant( 'BUILDER_DEFAULT_' . $setting ) : ''; 737 | 738 | } else { 739 | $value = constant( 'BUILDER_DEFAULT_' . $setting ); 740 | } 741 | */ 742 | $value = constant( 'BUILDER_DEFAULT_' . $setting ); 743 | } 744 | if ( stripos( $setting, 'color' ) ) { 745 | $value = preg_replace( '/[^A-Za-z0-9\-]/', '', $value ); 746 | } 747 | if ( $setting != 'EMAIL_TITLE' ) { 748 | $content = preg_replace( "/\b($setting)\b/i", $value, $content ); 749 | } 750 | } 751 | 752 | return $content; 753 | } 754 | 755 | /** 756 | * Prepare inline styles 757 | **/ 758 | function do_inline_styles( $contents = '', $styles ) { 759 | if ( $contents && $styles ) { 760 | if ( ! class_exists( 'CssToInlineStyles' ) ) { 761 | require_once( $this->plugin_dir . 'lib/builder/css-inline.php' ); 762 | } 763 | 764 | $css_inline = new CssToInlineStyles( $contents, $styles ); 765 | $contents = $css_inline->convert(); 766 | } 767 | 768 | return $contents; 769 | } 770 | 771 | /** 772 | * DOM Walker to ensure compatibility 773 | * 774 | * @param type $contents 775 | * 776 | * @return type 777 | */ 778 | function dom_compatibility( $contents ) { 779 | 780 | if ( ! class_exists( 'DOMDocument' ) ) { 781 | return $contents; 782 | } 783 | 784 | $dom = new DOMDocument(); 785 | 786 | libxml_use_internal_errors( true ); 787 | @$dom->loadHTML( $contents ); 788 | libxml_clear_errors(); 789 | 790 | $imgs = $dom->getElementsByTagName( 'img' ); 791 | $ps = $dom->getElementsByTagName( 'p' ); 792 | foreach ( $ps as $p ) { 793 | $p_style = $p->getAttribute( 'style' ); 794 | if ( ! empty( $p_style ) ) { 795 | break; 796 | } 797 | } 798 | foreach ( $imgs as $img ) { 799 | $classes_to_aligns = array( 'left', 'right' ); 800 | foreach ( $classes_to_aligns as $class_to_align ) { 801 | if ( $img->hasAttribute( 'class' ) && strstr( $img->getAttribute( 'class' ), 'align' . $class_to_align ) ) { 802 | $img->setAttribute( 'align', $class_to_align ); 803 | } 804 | } 805 | 806 | if ( $img->hasAttribute( 'class' ) && strstr( $img->getAttribute( 'class' ), 'aligncenter' ) ) { 807 | $img_style = $img->getAttribute( 'style' ); 808 | $img_style = preg_replace( '#display:(.*?);#', '', $img_style ); 809 | $img->setAttribute( 'style', $img_style ); 810 | 811 | $parent = $img->parentNode; 812 | if ( $parent->nodeName == 'a' ) { 813 | $parent = $parent->parentNode; 814 | } 815 | 816 | if ( $parent->nodeName != 'div' ) { 817 | $parent->setAttribute( 'style', 'text-align:center;' . $parent->getAttribute( 'style' ) ); 818 | } else { 819 | $element = $dom->createElement( 'p' ); 820 | $element->setAttribute( 'style', 'text-align:center;' . $p_style ); 821 | 822 | $img->parentNode->replaceChild( $element, $img ); 823 | $element->appendChild( $img ); 824 | } 825 | } 826 | 827 | $style = $img->getAttribute( 'style' ); 828 | preg_match( '#margin:(.*?);#', $style, $matches ); 829 | if ( $matches ) { 830 | $space_px = explode( 'px', $matches[1] ); 831 | $space_procent = explode( '%', $matches[1] ); 832 | $space = ( $space_procent > $space_px ) ? $space_procent : $space_px; 833 | $space_unit = ( $space_procent > $space_px ) ? '%' : ''; 834 | if ( $space ) { 835 | $hspace = trim( $space[0] ); 836 | $vspace = ( isset( $space[1] ) ) ? $hspace : trim( $space[0] ); 837 | 838 | $img->setAttribute( 'hspace', $hspace . $space_unit ); 839 | $img->setAttribute( 'vspace', $vspace . $space_unit ); 840 | } 841 | $style = preg_replace( '#margin:(.*?);#', '', $style ); 842 | if ( $style ) { 843 | $img->setAttribute( 'style', $style ); 844 | } else { 845 | $img->removeAttribute( 'style' ); 846 | } 847 | } 848 | } 849 | $contents = $dom->saveHTML(); 850 | 851 | return $contents; 852 | } 853 | 854 | /** 855 | * Returns the list of placeholders in template content 856 | */ 857 | function list_placeholders( $content, $desc = false ) { 858 | if ( $desc ) { 859 | //Return Placeholder desc table 860 | $placeholder_desc = array( 861 | '{MESSAGE}' => __( 'Email content (required)', 'htmlemail' ), 862 | '{SIDEBAR_TITLE}' => __( "Title for the sidebar in email e.g. What's trending", 'htmlemail' ), 863 | '{FROM_NAME}' => __( "Sender's name if sender's email is associated with a user account", 'htmlemail' ), 864 | '{FROM_EMAIL}' => __( "Sender's email, email specified in site settings", 'htmlemail' ), 865 | '{BLOG_URL}' => __( 'Blog / Site URL', 'htmlemail' ), 866 | '{BLOG_NAME}' => __( 'Blog / Site name', 'htmlemail' ), 867 | '{ADMIN_EMAIL}' => __( 'Email address of the support or contact person. Same as {FROM_EMAIL}', 'htmlemail' ), 868 | '{USER_NAME}' => __( 'The display name of the recipient', 'htmlemail' ), 869 | '{USER_EMAIL}' => __( 'The display email of the recipient', 'htmlemail' ), 870 | '{EMAIL_TITLE}' => __( 'By default displays the Blog / Site name. It can be extended with the wpmudev_htmlemail/email_title filter. For example in order to return the subject instead of the Blog / Site name: 871 | add_filter( \'wpmudev_htmlemail/email_title\', function( $blog_url, $subject, $mail_args ){ 872 | return $subject; 873 | }, 10, 3 ); 874 | ', 'htmlemail' ), 875 | '{BG_IMAGE}' => __( 'A background image of the email template. You can upload background image from the "Images that can be used in template" section', 'htmlemail' ), 876 | '{HEADER_IMAGE}' => __( 'An image that appears in the email header. You can upload header image from the "Images that can be used in template" section', 'htmlemail' ), 877 | '{BLOG_DESCRIPTION}' => __( 'Blog Description', 'htmlemail' ), 878 | '{DATE}' => __( 'Current date', 'htmlemail' ), 879 | '{TIME}' => __( 'Current time', 'htmlemail' ), 880 | ); 881 | 882 | $output = '

' . __( 'List of variables that can be used in template', 'htmlemail' ) . 883 | '[+]

' 884 | . '
' 885 | . ''; 886 | $output .= ''; 887 | $output .= ''; 888 | 889 | //Get list of common variables 890 | foreach ( $placeholder_desc as $p_name => $p_desc ) { 891 | $output .= ''; 892 | $output .= ''; 893 | $output .= ''; 894 | $output .= ''; 895 | } 896 | $output .= '
Variable nameDefault value
' . $p_name . '' . $p_desc . '
' 897 | . '
'; 898 | 899 | return $output; 900 | } 901 | $placeholders = $links = ''; 902 | preg_match_all( "/\{.+\}/U", $content, $placeholders ); 903 | //Jugaad, need to find a fix for this 904 | preg_match_all( "/\%7B.+\%7D/U", $content, $links ); 905 | 906 | $placeholders = ! empty( $placeholders ) ? $placeholders[0] : ''; 907 | $links = ! empty( $links ) ? $links[0] : ''; 908 | $placeholders = array_merge( $placeholders, $links ); 909 | 910 | return $placeholders; 911 | } 912 | 913 | function template_images(){ 914 | 915 | //Fetch the images if set 916 | $html_images = array(); 917 | if ( ! is_multisite() || is_network_admin() ) { 918 | $html_images = get_site_option( 'html_template_images' ); 919 | } else { 920 | $html_images = get_option( 'html_template_images' ); 921 | } 922 | 923 | $bg_image = $header_image = ''; 924 | if( is_array( $html_images ) ){ 925 | 926 | $bg_image = isset( $html_images['bg'] ) ? esc_url( $html_images['bg'] ) : ''; 927 | $header_image = isset( $html_images['header'] ) ? esc_url( $html_images['header'] ) : ''; 928 | 929 | } 930 | 931 | $output = '

' . __( 'Images that can be used in template', 'htmlemail' ) . 932 | '[+]

'; 933 | 934 | $output .= '
'; 935 | 936 | $output .= '
'; 937 | 938 | $output .= '
'; 939 | $output .= ''; 940 | $output .= ''; 941 | $output .= ''; 942 | $output .= '
'; 943 | 944 | $output .= '
'; 945 | $output .= ''; 946 | $output .= ''; 947 | $output .= ''; 948 | $output .= '
'; 949 | 950 | $output .= '
'; 951 | $output .= '
'; 952 | 953 | return $output; 954 | } 955 | 956 | /** 957 | * Replaces placeholder text in email templates 958 | */ 959 | function replace_placeholders( $content, $mail_args = array(), $demo_message = true ) { 960 | $html_theme = $this->get_html_theme(); 961 | $html_theme = ( $html_theme ) ? $html_theme : $this->html_theme; 962 | 963 | $this->theme_path = $this->get_html_theme_path($html_theme); 964 | $this->theme_url = $this->get_html_theme_url($html_theme); 965 | require_once( $this->theme_path . '/index.php' ); 966 | 967 | $placeholders = $this->list_placeholders( $content ); 968 | $current_blog_id = get_current_blog_id(); 969 | $blog_url = get_option( 'siteurl' ); 970 | $admin_email = get_option( 'admin_email' ); 971 | $blog_name = get_option( 'blogname' ); 972 | $blog_description = get_option( 'blogdescription' ); 973 | $date = date_i18n( get_option( 'date_format' ) ); 974 | $time = date_i18n( get_option( 'time_format' ) ); 975 | 976 | $message = "This is a test message I want to try out to see if it works. This will be replaced with wordpress email content. 977 | Is it working well?"; 978 | 979 | $from_email = get_option( 'admin_email' ); 980 | $user_info = get_userdata( $from_email ); 981 | if ( $user_info ) { 982 | $display_name = $user_info->display_name; 983 | } else { 984 | $display_name = ''; 985 | } 986 | 987 | $html_images = array(); 988 | if ( ! is_multisite() || is_network_admin() ) { 989 | $html_images = get_site_option( 'html_template_images' ); 990 | } else { 991 | $html_images = get_option( 'html_template_images' ); 992 | } 993 | 994 | $bg_image = $header_image = false; 995 | if( is_array( $html_images ) ){ 996 | 997 | $bg_image = isset( $html_images['bg'] ) && $html_images['bg'] != '' ? esc_url( $html_images['bg'] ) : false; 998 | $header_image = isset( $html_images['header'] ) && $html_images['header'] != '' ? $this->get_image_by_url( $html_images['header'] ) : false; 999 | 1000 | } 1001 | 1002 | if( ! $bg_image ){ 1003 | $bg_image = defined( 'BUILDER_DEFAULT_BG_IMAGE' ) ? $this->theme_url . '/' . constant( 'BUILDER_DEFAULT_BG_IMAGE' ) : ''; 1004 | } 1005 | 1006 | if( ! $header_image ){ 1007 | $header_image = defined( 'BUILDER_DEFAULT_HEADER_IMAGE' ) ? '' : ''; 1008 | } 1009 | 1010 | if ( ! $header_image ){ 1011 | if ( defined( 'BUILDER_DEFAULT_HEADER_IMAGE') && ! defined('HEADER_IMAGE') ){ 1012 | $header_image = defined( 'BUILDER_DEFAULT_HEADER_IMAGE' ) ? '' : ''; 1013 | } 1014 | elseif ( defined('HEADER_IMAGE') ){ 1015 | $host = parse_url( constant('HEADER_IMAGE'), PHP_URL_HOST); 1016 | if ( $host == "" ) { 1017 | $header_image = ''; 1018 | } 1019 | else{ 1020 | $header_image = ''; 1021 | } 1022 | } 1023 | } 1024 | 1025 | //Sidebar 1026 | $posts_list = $this->htmlemail_recent_posts(); 1027 | /** 1028 | * Filter the post list displayed in email sidebar 1029 | * 1030 | * @since 2.0 1031 | * 1032 | * @param array $posts_list , An array of posts, containing ID and post_title for each post 1033 | */ 1034 | $posts_list = apply_filters( 'htmlemail_sidebar_posts', $posts_list ); 1035 | /** 1036 | * Filter the sidebar title in email template 1037 | * 1038 | * @since 2.0 1039 | * 1040 | * @param string $title , Title to be displayed in email 1041 | */ 1042 | $sidebar_title = apply_filters( 'htmlemail_sidebar_title', $title = "What's new" ); 1043 | 1044 | //Placeholder for posts 1045 | $count = 1; 1046 | $placeholder_posts = array(); 1047 | foreach ( $posts_list as $post ) { 1048 | if ( $count > 4 ) { 1049 | break; 1050 | } 1051 | $placeholder_posts["{POST_$count}"] = $this->short_str( $post['post_title'], '...', 10 ); 1052 | //Jugaad, to keep the template styling and links 1053 | $placeholder_posts[ "%7BPOST_" . $count . "_LINK%7D" ] = esc_url( get_permalink( $post['ID'] ) ); 1054 | $count ++; 1055 | } 1056 | //Show for preview only 1057 | if ( $demo_message ) { 1058 | //Removed as it conflicts 1059 | // $content = preg_replace( "/({MESSAGE})/", $message, $content ); 1060 | // $content = preg_replace( "/(MESSAGE)/", $message, $content ); 1061 | 1062 | if ( strpos( $content, '{MESSAGE}' ) !== false ) { 1063 | //Replace {MESSAGE} in template with actual email content 1064 | $key = '{MESSAGE}'; 1065 | } else { 1066 | //Compatibility with previous version of the plugin, as it used MESSAGE instead of {MESSAGE} 1067 | $key = 'MESSAGE'; 1068 | } 1069 | $content = str_replace( array( $key, '{USER_NAME}', '{USER_EMAIL}' ), array( $message, 'Jon', 'example@domain.com' ), $content ); 1070 | } 1071 | 1072 | $subject = isset( $mail_args['subject'] ) ? $mail_args['subject'] : ''; 1073 | $email_title = apply_filters( 'wpmudev_htmlemail/email_title', $blog_name, $subject, $mail_args ); 1074 | 1075 | $placeholders_list = array( 1076 | '{}' => '', 1077 | '{SIDEBAR_TITLE}' => $sidebar_title, 1078 | '{CONTENT_HEADER}' => '', 1079 | '{CONTENT_FOOTER}' => '', 1080 | '{FOOTER}' => '', 1081 | '{FROM_NAME}' => $display_name, 1082 | '{FROM_EMAIL}' => $from_email, 1083 | '{BLOG_URL}' => $blog_url, 1084 | '{BLOG_NAME}' => $blog_name, 1085 | '{EMAIL_TITLE}' => $email_title, 1086 | '{ADMIN_EMAIL}' => $admin_email, 1087 | '{BG_IMAGE}' => $bg_image, 1088 | '{HEADER_IMAGE}' => $header_image, 1089 | '{BLOG_DESCRIPTION}' => $blog_description, 1090 | '{DATE}' => $date, 1091 | '{TIME}' => $time 1092 | ); 1093 | $placeholders_list = $placeholders_list + $placeholder_posts; 1094 | foreach ( $placeholders as $placeholder ) { 1095 | if ( ! isset( $placeholders_list [ $placeholder ] ) ) { 1096 | continue; 1097 | } 1098 | $content = preg_replace( "/($placeholder)/", $placeholders_list[ $placeholder ], $content ); 1099 | } 1100 | //Replace admin email, left out due to escaped html 1101 | $content = preg_replace( "/(%7BADMIN_EMAIL%7D)/", $admin_email, $content ); 1102 | 1103 | return $content; 1104 | } 1105 | 1106 | /** 1107 | * Returns the whole img by url 1108 | * @param string $url, the url of the image we want to retrieve 1109 | * @param string $size, the size of the image 1110 | * @return string 1111 | */ 1112 | function get_image_by_url( $url, $size = 'full' ){ 1113 | global $wpdb; 1114 | if( $url == '' ){ 1115 | return false; 1116 | } 1117 | $attachment = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE guid='%s';", $url )); 1118 | return wp_get_attachment_image( $attachment[0], $size ); 1119 | } 1120 | 1121 | /** 1122 | * Checks if on setting page for HTML Email Template 1123 | * @global type $html_template 1124 | * @global type $hook_suffix 1125 | * @return boolean 1126 | */ 1127 | function is_htmlemail_setting_page() { 1128 | global $html_template, $html_template_network, $html_template_site, $hook_suffix; 1129 | if ( $GLOBALS['hook_suffix'] == $GLOBALS['html_template'] 1130 | || $GLOBALS['hook_suffix'] == $GLOBALS['html_template_site'] 1131 | || $GLOBALS['hook_suffix'] == $GLOBALS['html_template_network'] 1132 | ) { 1133 | return true; 1134 | } 1135 | 1136 | return false; 1137 | } 1138 | 1139 | /** 1140 | * Returns data for preview 1141 | */ 1142 | function get_preview_data() { 1143 | if ( ! current_user_can( 'unfiltered_html' ) ) { 1144 | wp_send_json_error( __( "Whoops, you don't have permissions to preview html.", 'htmlemail' ) ); 1145 | } 1146 | if ( empty( $_POST ) ) { 1147 | wp_send_json_error( __( 'Whoops, you need to enter some html to preview it!', 'htmlemail' ) ); 1148 | } 1149 | $content = trim( $_POST['content'] ); 1150 | $content = stripslashes( $content ); 1151 | $content = $this->replace_placeholders( $content ); 1152 | 1153 | if ( empty( $content ) ) { 1154 | wp_send_json_error( __( 'Whoops, you need to enter some html to preview it!', 'htmlemail' ) ); 1155 | } 1156 | 1157 | wp_send_json_success( $content ); 1158 | } 1159 | 1160 | /** 1161 | * Shortens string 1162 | * 1163 | * @param type $after 1164 | * @param type $length 1165 | * 1166 | * @return type 1167 | */ 1168 | function short_str( $str, $after = '', $length ) { 1169 | if ( empty( $str ) ) { 1170 | $str = explode( ' ', get_the_title(), $length ); 1171 | } else { 1172 | $str = explode( ' ', $str, $length ); 1173 | } 1174 | 1175 | if ( count( $str ) >= $length ) { 1176 | array_pop( $str ); 1177 | $str = implode( " ", $str ) . $after; 1178 | } else { 1179 | $str = implode( " ", $str ); 1180 | } 1181 | 1182 | return $str; 1183 | } 1184 | 1185 | /** 1186 | * Returns an array for recent posts 1187 | * @return boolean 1188 | */ 1189 | function htmlemail_recent_posts() { 1190 | //Recent Posts with their links 1191 | $args = array( 1192 | 'numberposts' => '4', 1193 | 'post_type' => 'post', 1194 | 'post_status' => 'publish' 1195 | ); 1196 | $recent_posts = wp_get_recent_posts( $args ); 1197 | 1198 | return $recent_posts; 1199 | } 1200 | 1201 | /** 1202 | * Send a preview email 1203 | */ 1204 | function preview_email() { 1205 | global $current_user; 1206 | 1207 | //Check for empty email and nonce 1208 | if ( empty( $_POST['preview_html_email_address'] ) || empty( $_POST['_ajax_nonce'] ) ) { 1209 | wp_send_json_error( __( 'Missing Parameters', 'htmlemail' ) ); 1210 | } 1211 | 1212 | //Verify nonce 1213 | if ( ! wp_verify_nonce( $_POST['_ajax_nonce'], 'preview_email' ) ) { 1214 | wp_send_json_error( __( 'Nonce verification failed', 'htmlemail' ) ); 1215 | } 1216 | 1217 | $email = ( isset( $_POST['preview_html_email_address'] ) && is_email( $_POST['preview_html_email_address'] ) ) ? $_POST['preview_html_email_address'] : $current_user->user_email; 1218 | $sent = wp_mail( $email, 'Test HTML Email Subject', "This is a test message I want to try out to see if it works\n\nIs it working well?" ); 1219 | 1220 | //Success 1221 | if ( $sent ) { 1222 | wp_send_json_success( sprintf( __( 'Preview email was mailed to %s!', 'htmlemail' ), $email ) ); 1223 | } 1224 | //Unable to send email 1225 | wp_send_json_error( __( 'Unable to send test email', 'htmlemail' ) ); 1226 | } 1227 | 1228 | /** 1229 | * Return Content type as HTML for plain text email 1230 | * 1231 | * @param $content_type 1232 | * 1233 | * @return string, Content type 1234 | */ 1235 | 1236 | function set_content_type( $content_type ) { 1237 | if ( $content_type == 'text/plain' ) { 1238 | $this->is_html = false; 1239 | 1240 | return 'text/html'; 1241 | } 1242 | $this->is_html = true; 1243 | 1244 | return $content_type; 1245 | } 1246 | 1247 | /** 1248 | * Set Content type for Woocommerce emails 1249 | */ 1250 | function set_woocommerce_content_type( $content_type ) { 1251 | return "Content-Type: " . 'text/html' . "\r\n"; 1252 | } 1253 | 1254 | /** 1255 | * Save settings for Network or Subsite 1256 | */ 1257 | function save_settings() { 1258 | //Save template content and other settings 1259 | if ( isset( $_POST['save_html_email_options'] ) ) { 1260 | if ( ! wp_verify_nonce( $_POST['_wpnonce'], 'html_email-update-options' ) ) { 1261 | die( __( 'Whoops! There was a problem with the data you posted. Please go back and try again.', 'htmlemail' ) ); 1262 | } 1263 | 1264 | $template = stripslashes( $_POST['template'] ); 1265 | $modify_html_email = ! empty( $_POST['modify_html_email'] ) ? $_POST['modify_html_email'] : 0; 1266 | $html_template_images = array( 1267 | 'bg' => '', 1268 | 'header' => '' 1269 | ); 1270 | if( is_array( $_POST['html_template_images'] ) ){ 1271 | $html_template_images = array_map( "esc_url_raw", $_POST['html_template_images'] ); 1272 | } 1273 | 1274 | //Update settings for network or blog 1275 | if ( is_network_admin() || ! is_multisite() ) { 1276 | 1277 | $htmlemail_settings = isset( $_POST['htmlemail_settings'] ) ? $_POST['htmlemail_settings'] : ''; 1278 | 1279 | update_site_option( 'htmlemail_settings', $htmlemail_settings ); 1280 | update_site_option( 'html_template', $template ); 1281 | update_site_option( 'modify_html_email', $modify_html_email ); 1282 | update_site_option( 'html_template_images', $html_template_images ); 1283 | } else { 1284 | update_option( 'html_template', $template ); 1285 | update_option( 'modify_html_email', $modify_html_email ); 1286 | update_option( 'html_template_images', $html_template_images ); 1287 | } 1288 | $this->update_html_theme( ucfirst( strtolower( $_POST['html_theme'] ) ) ); 1289 | echo '

' . esc_html__( 'Success! Your changes were sucessfully saved!', 'htmlemail' ) . '

'; 1290 | } 1291 | } 1292 | } //End Class 1293 | 1294 | //instantiate the class 1295 | $html_email_var = new HTML_emailer(); 1296 | 1297 | //Dash Notification Class 1298 | include_once( dirname( __FILE__ ) . '/includes/dash-notice/wpmudev-dash-notification.php' ); 1299 | //Load WPMU DEV Dashboard Notices 1300 | global $wpmudev_notices; 1301 | 1302 | $wpmudev_notices[] = array( 1303 | 'id' => 142, 1304 | 'name' => 'HTML Email Templates', 1305 | 'screens' => array( 'settings_page_html-template', 'settings_page_html-template-network' ) 1306 | ); 1307 | --------------------------------------------------------------------------------