* @copyright Since 2013 Ovidiu Cimpean * @license Do not edit, modify or copy this file * * @version Release: 4 */ class NewsletterProTemplateContent { public $html; private $variables = []; private $variables_chimp = []; /** * @var NewsletterProTemplate */ private $template; const CONTENT_TITLE = 100; const CONTENT_HEADER = 101; const CONTENT_BODY = 102; const CONTENT_FOOTER = 103; const CONTENT_HTML = 104; const CONTENT_FULL = 105; const CONTENT_MESSAGE = 106; const CONTENT_CSS = 107; const CONTENT_CSS_LINK = 108; const CONTENT_CSS_FILE = 109; const CONTENT_CSS_GLOBAL_FILE = 110; const COMPARE_TYPE_FUNCTION = 100; const COMPARE_TYPE_OPERATION = 101; const COMPARE_RIGHT_TYPE_STRING = 100; const COMPARE_RIGHT_TYPE_INTEGER = 101; const COMPARE_RIGHT_TYPE_VARIABLE = 102; private $compare_type_functions = [ 'isset', ]; private $compare_type_operations = [ '==', '!=', '<=', '>=', '===', ]; public static function newInstance() { return new self(); } public function setTemplate($template) { $this->template = $template; return $this; } public static function getContentNames() { return [ self::CONTENT_TITLE => 'title', self::CONTENT_HEADER => 'header', self::CONTENT_BODY => 'body', self::CONTENT_FOOTER => 'footer', self::CONTENT_HTML => 'html', self::CONTENT_FULL => 'full', self::CONTENT_MESSAGE => 'message', self::CONTENT_CSS => 'css', self::CONTENT_CSS_LINK => 'css_link', self::CONTENT_CSS_FILE => 'css_file', self::CONTENT_CSS_GLOBAL_FILE => 'css_global_file', ]; } public function setVariables($variables) { $this->variables = array_merge($this->variables, $variables); return $this; } public function setChimpVariables($variables) { $this->variables_chimp = array_merge($this->variables_chimp, $variables); return $this; } public function variables() { return $this->variables; } public function variablesChimp() { return $this->variables_chimp; } public function setContent($html) { $this->html = $html; return $this; } public function setContentByIdLang($id_lang, $html) { $this->html[$id_lang] = $html; return $this; } public function getTitle($html) { if (preg_match('/<\s*?(title)\s*?.*?>(?P.*?)<\s*?\/\s*?\1\s*?>/', $html, $match)) { return $match['content']; } return false; } public function getHeader($html) { if (preg_match('/(?P^[\s\S]*?<\s*?body\s*?.*?>)/i', $html, $match)) { return $match['content']; } return false; } public function getBody($html) { if (preg_match('/<\s*?(body)\s*.*?>(?P[\s\S]*)/i', $html, $match)) { return $match['content']; } return false; } public function getFooter($html) { if (preg_match('/(?P<\s*?\/\s*?\s*?body\s*?>[\s\S]*)/i', $html, $match)) { return $match['content']; } return false; } public function getCSS($html) { $style = ''; $css_content_array = $this->getFilesCSS(); if (!empty($css_content_array)) { $style .= join("\n\n", $css_content_array); } $header = $this->getHeader($html); if (preg_match_all('/<(?:\s*?)style[^>]*>(?P[\s\S]*?)(<(?:\s*?)\/(?:\s*?)style(?:\s*?)>)/', $header, $match)) { $style .= implode("\n\n", $match['content']); } return $style; } public function getConditions() { $conditions = []; foreach ($this->html as $id_lang => $value) { preg_match_all('/\{(?:\s+)?if\s[\s\S]*?(\{(?:\s+)?\/(?:\s+)?if(?:\s+)?\})/', $value, $matches); $conditions[$id_lang] = $matches[0]; } return $conditions; } public function getRenderConditions() { if (!isset($this->variables)) { throw new NewsletterProTemplateContentException('You must set the variables first.'); } $module = NewsletterPro::getInstance(); $conditions = $this->getConditions(); $conditions_render = []; foreach ($conditions as $id_lang => $conditions_array) { foreach ($conditions_array as $key => $condition) { preg_match('/\{if[^}]+}(.*)\{\/if\}/', $condition, $condition_content); $condition_content = explode('{else}', $condition_content[1]); preg_match('/\{(?:\s+)?if\s(?:\s+)?(?P[^}]+)\}/i', $condition, $compare); $compare = trim($compare['content']); $match_compare_functions = '/('.join('|', $this->compare_type_functions).')\((\w+)\)/'; $match_compare_operations = '/(\w+)(?:\s+)?('.join('|', $this->compare_type_operations).')(?:\s+)?(.*)/'; $compare_type = null; $compare_left = null; $compare_function = null; $compare_operation = null; $compare_rigt = null; $compare_rigt_type = null; if (preg_match($match_compare_functions, $compare, $compare_type_match)) { $compare_type = self::COMPARE_TYPE_FUNCTION; $compare_function = $compare_type_match[1]; $compare_rigt = $compare_type_match[2]; } elseif (preg_match($match_compare_operations, $compare, $compare_type_match)) { $compare_type = self::COMPARE_TYPE_OPERATION; $compare_left = $compare_type_match[1]; $compare_operation = $compare_type_match[2]; $compare_rigt = $compare_type_match[3]; if (preg_match('/^("|\')(.*)\1$/', $compare_rigt)) { $compare_rigt_type = self::COMPARE_RIGHT_TYPE_STRING; $compare_rigt = trim($compare_rigt, '\'"'); } elseif (preg_match('/^[A-Za-z]+\w+$/', $compare_rigt)) { $compare_rigt_type = self::COMPARE_RIGHT_TYPE_VARIABLE; } else { $compare_rigt_type = self::COMPARE_RIGHT_TYPE_INTEGER; } } else { throw new NewsletterProTemplateContentException(sprintf($module->l('The condition "%s" is not valid.'), $compare)); } if (self::COMPARE_TYPE_FUNCTION == $compare_type) { if (!in_array($compare_function, $this->compare_type_functions)) { throw new NewsletterProTemplateContentException(sprintf($module->l('The condition function "%" is not valid.'), $compare_function)); } switch ($compare_function) { case 'isset': if (isset($this->variables[$compare_rigt]) && Tools::strlen($this->variables[$compare_rigt]) > 0) { $conditions_render[$id_lang][$condition] = $condition_content[0]; } else { if (isset($condition_content[1])) { $conditions_render[$id_lang][$condition] = $condition_content[1]; } else { $conditions_render[$id_lang][$condition] = ''; } } break; default: throw new NewsletterProTemplateContentException(sprintf($module->l('The condition function "%" is not defined'), $compare_function)); break; } } else { if (!in_array($compare_operation, $this->compare_type_operations)) { throw new NewsletterProTemplateContentException(sprintf($module->l('The condition operator "%" is not valid.'), $compare_operation)); } if (self::COMPARE_RIGHT_TYPE_STRING == $compare_rigt_type) { $compare_rigt = (string) $compare_rigt; } elseif (self::COMPARE_RIGHT_TYPE_VARIABLE == $compare_rigt_type) { if (isset($this->variables[$compare_rigt])) { $compare_rigt = $this->variables[$compare_rigt]; } else { $compare_rigt = null; } } else { $compare_rigt = (int) $compare_rigt; } $variable_exists = (isset($this->variables[$compare_left])); if ($variable_exists) { $compare_left_value = $this->variables[$compare_left]; switch ($compare_operation) { case '==': if ($compare_left_value == $compare_rigt) { $conditions_render[$id_lang][$condition] = $condition_content[0]; } else { if (isset($condition_content[1])) { $conditions_render[$id_lang][$condition] = $condition_content[1]; } else { $conditions_render[$id_lang][$condition] = ''; } } break; case '!=': if ($compare_left_value != $compare_rigt) { $conditions_render[$id_lang][$condition] = $condition_content[0]; } else { if (isset($condition_content[1])) { $conditions_render[$id_lang][$condition] = $condition_content[1]; } else { $conditions_render[$id_lang][$condition] = ''; } } break; case '<=': if ($compare_left_value <= $compare_rigt) { $conditions_render[$id_lang][$condition] = $condition_content[0]; } else { if (isset($condition_content[1])) { $conditions_render[$id_lang][$condition] = $condition_content[1]; } else { $conditions_render[$id_lang][$condition] = ''; } } break; case '>=': if ($compare_left_value >= $compare_rigt) { $conditions_render[$id_lang][$condition] = $condition_content[0]; } else { if (isset($condition_content[1])) { $conditions_render[$id_lang][$condition] = $condition_content[1]; } else { $conditions_render[$id_lang][$condition] = ''; } } break; case '===': if ($compare_left_value === $compare_rigt) { $conditions_render[$id_lang][$condition] = $condition_content[0]; } else { if (isset($condition_content[1])) { $conditions_render[$id_lang][$condition] = $condition_content[1]; } else { $conditions_render[$id_lang][$condition] = ''; } } break; default: throw new NewsletterProTemplateContentException(sprintf($module->l('The condition operator "%" is not defined'), $compare_operation)); break; } } else { if (isset($condition_content[1])) { $conditions_render[$id_lang][$condition] = $condition_content[1]; } else { $conditions_render[$id_lang][$condition] = ''; } } } } } return $conditions_render; } public function html($content_type = NewsletterProTemplateContent::CONTENT_FULL, $add_css = false) { $content_lang = $this->html; if ($add_css) { foreach ($content_lang as $id_lang => $content) { $content_lang[$id_lang] = $this->addDefaultCSS($content); } } return $this->content($content_lang, $content_type); } public function render($content_type = NewsletterProTemplateContent::CONTENT_FULL) { if (!isset($this->template)) { throw new NewsletterProTemplateContentException(sprintf('The variable "%s" is not set.', 'template')); } $render_condition = $this->getRenderConditions(); $render = $this->html; foreach ($render as $id_lang => $content) { // execute condtions if (isset($render_condition[$id_lang])) { $content = str_replace(array_keys($render_condition[$id_lang]), array_values($render_condition[$id_lang]), $content); } // render variables, I've made this for mailchimp foreach ($this->variables as $variable_name => $value) { $this->variables[$variable_name] = preg_replace_callback('/\{(\w+)\}/', [$this, 'replaceVariables'], $value); } // render chimp variables, I've made this for mailchimp foreach ($this->variables_chimp as $variable_name => $value) { $this->variables_chimp[$variable_name] = preg_replace_callback('/\{(\w+)\}/', [$this, 'replaceVariables'], $value); } // replace variables $content = preg_replace_callback('/\{(\w+)\}/', [$this, 'replaceVariables'], $content); // replace chimp variables $content = preg_replace_callback('/\*\|(\w+)\|\*/', [$this, 'replaceChimpVariables'], $content); $content = $this->replaceTemplateVariables($content); $content = $this->addDefaultCSS($content); $render[$id_lang] = $content; } // replace dynamic variables $render = NewsletterProTemplateDynamicVariables::newInstance($render, $this->template->user)->render(); $header_lang = []; foreach ($render as $id_lang => $render_value) { $header = []; // die($render_value); if (preg_match('/[\s\S]*?[\s\S]*?/', $render_value, $match)) { $match = explode(';', $match[1]); foreach ($match as $value) { $value = trim($value); if (Tools::strlen($value) > 0) { $exp = explode('=', $value); $result = trim($exp[1]); $header[trim($exp[0])] = $result; } } } $header_lang[$id_lang] = $header; } foreach ($render as $id_lang => $render_value) { // place the convert css to inline style afther the dynamic variables to prevent a template error if (isset($header_lang[$id_lang]['convertInlineCss'])) { if ('true' == $header_lang[$id_lang]['convertInlineCss']) { $render[$id_lang] = NewsletterProCSStoInlineStyle::convert($render_value); } else { // make sure the eomticons are displayed $render[$id_lang] = $this->encodeEmoticons($render[$id_lang]); } } elseif ((bool) pqnp_config('CONVERT_CSS_TO_INLINE_STYLE')) { $render[$id_lang] = NewsletterProCSStoInlineStyle::convert($render_value); } else { // make sure the eomticons are displayed $render[$id_lang] = $this->encodeEmoticons($render[$id_lang]); } if (isset($header_lang[$id_lang]['unsubscribe']) && 'true' === $header_lang[$id_lang]['unsubscribe']) { NewsletterProSubscriptionManager::newInstance()->unsubscribe($this->variables['email']); } } return $this->content($render, $content_type); } private function encodeEmoticons($data) { $current_encode = mb_detect_encoding($data, 'UTF-8, ISO-8859-1, ISO-8859-15, HTML-ENTITIES', true); $data = html_entity_decode($data, ENT_COMPAT | ENT_HTML401 | ENT_HTML5, $current_encode); return mb_convert_encoding($data, 'UTF-8', $current_encode); } public function getHeaders() { $content_lang = $this->html; $headers = []; foreach ($content_lang as $id_lang => $html) { $header = []; if (preg_match('/[\s\S]*?[\s\S]*?/', $html, $match)) { $match = explode(';', $match[1]); foreach ($match as $value) { $value = trim($value); if (Tools::strlen($value) > 0) { $exp = explode('=', $value); $result = trim($exp[1]); $header[trim($exp[0])] = $result; } } } $headers[$id_lang] = $header; } return $headers; } public function content($content_lang, $content_type) { $render_content = []; $content_names = $this->getContentNames(); switch ($content_type) { case self::CONTENT_TITLE: foreach ($content_lang as $id_lang => $content) { $render_content[$id_lang] = $this->getTitle($content); } break; case self::CONTENT_HEADER: foreach ($content_lang as $id_lang => $content) { $render_content[$id_lang] = $this->getHeader($content); } break; case self::CONTENT_BODY: foreach ($content_lang as $id_lang => $content) { $render_content[$id_lang] = $this->getBody($content); } break; case self::CONTENT_FOOTER: foreach ($content_lang as $id_lang => $content) { $render_content[$id_lang] = $this->getFooter($content); } break; case self::CONTENT_HTML: foreach ($content_lang as $id_lang => $content) { $render_content[$id_lang] = $content; } break; case self::CONTENT_FULL: foreach ($content_lang as $id_lang => $content) { $render_content[$id_lang][$content_names[self::CONTENT_TITLE]] = $this->getTitle($content); $render_content[$id_lang][$content_names[self::CONTENT_HEADER]] = $this->getHeader($content); $render_content[$id_lang][$content_names[self::CONTENT_BODY]] = $this->getBody($content); $render_content[$id_lang][$content_names[self::CONTENT_FOOTER]] = $this->getFooter($content); $render_content[$id_lang][$content_names[self::CONTENT_HTML]] = $content; $render_content[$id_lang][$content_names[self::CONTENT_CSS]] = $this->getCSS($content); $render_content[$id_lang][$content_names[self::CONTENT_CSS_LINK]] = $this->cssLink($id_lang); $render_content[$id_lang][$content_names[self::CONTENT_CSS_FILE]] = $this->template->css; $render_content[$id_lang][$content_names[self::CONTENT_CSS_GLOBAL_FILE]] = $this->template->getCSSGlobalFileContent(); } break; case self::CONTENT_MESSAGE: foreach ($content_lang as $id_lang => $content) { $render_content[$id_lang][$content_names[self::CONTENT_TITLE]] = $this->getTitle($content); $render_content[$id_lang][$content_names[self::CONTENT_BODY]] = $content; } break; case self::CONTENT_CSS: foreach ($content_lang as $id_lang => $content) { $render_content[$id_lang] = $this->getCSS($content); } break; case self::CONTENT_CSS_LINK: foreach (array_keys($content_lang) as $id_lang) { $render_content[$id_lang] = $this->cssLink($id_lang); } // no break case self::CONTENT_CSS_FILE: foreach (array_keys($content_lang) as $id_lang) { $render_content[$id_lang] = $this->template->css; } // no break case self::CONTENT_CSS_GLOBAL_FILE: foreach (array_keys($content_lang) as $id_lang) { $render_content[$id_lang] = $this->template->getCSSGlobalFileContent(); } break; default: throw new NewsletterProTemplateContentException('Invalid content type.'); break; } return $render_content; } private function replaceVariables($match) { $variable_name = $match[1]; return isset($this->variables[$variable_name]) ? $this->variables[$variable_name] : '{'.$variable_name.'}'; } private function replaceChimpVariables($match) { $variable_name = $match[1]; return isset($this->variables_chimp[$variable_name]) ? $this->variables_chimp[$variable_name] : '*|'.$variable_name.'|*'; } private function replaceTemplateVariables($content) { $title = $this->getTitle($content); if ($title) { $content = str_replace('{newsletter_title}', urlencode($title), $content); if (Tools::isSubmit('testCampaign')) { ddd($content); } } if ($this->template instanceof NewsletterProTemplateHistory) { $module = NewsletterPro::getInstance(); $content = str_replace('{id_newsletter_pro_tpl_history}', $this->template->id_history, $content); // viewInBrowser will remove the opened email tracking if the browser is viewed by admin if (!Tools::isSubmit('viewInBrowser')) { $tracking_link = NewsletterProApi::getLink('openedEmail', [ 'token' => $module->getTokenByIdHistory((int) $this->template->id_history), 'email' => (string) $this->variables['email'], ], false, true, null, (int) $this->template->user->id_lang, (int) $this->template->user->id_shop); $tracking_img = ''.$module->l('open email').''; if ($body_end = $this->getEndBodyStrpos($content)) { $content = substr_replace($content, $tracking_img, $body_end, 0); } else { $content .= $tracking_img; } } } else { $content = str_replace('&id_newsletter={id_newsletter_pro_tpl_history}', '', $content); } return $content; } private function getEndBodyStrpos($content) { if (preg_match('/(?P\<\s*?\/\s*?body\s*?\>)/', $content, $match)) { return (int) strpos($content, $match['body']); } return false; } public function cssLink($id_lang = null) { $links = []; // $link = _MODULE_DIR_.'newsletterpro/css.php?getNewsletterTemplateCSS&name='.$this->template->name.'&id_lang=%d&uid='.uniqid(); $link = NewsletterProApi::getLink('css', [ 'getNewsletterTemplateCSS' => true, 'name' => $this->template->name, 'id_lang' => '%d', 'uid' => uniqid(), ], false, true); foreach (array_keys($this->template->dir_template_lang_file) as $id_l) { $links[$id_l] = sprintf($link, $id_l); } if (isset($this->template->load_id_lang)) { return $links[$this->template->load_id_lang]; } if (isset($id_lang)) { return $links[$id_lang]; } return $links; } private function addDefaultCSS($content) { $open_head_tag = ''; $head_pos = strpos($content, $open_head_tag); if (false === $head_pos) { return $content; } $after_head_post = $head_pos + Tools::strlen($open_head_tag); $css_content_array = $this->getFilesCSS(); if (!empty($css_content_array)) { $content = substr_replace($content, "\n".''."\n", $after_head_post, 0); } return $content; } private function getFilesCSS() { $css_content_array = []; $css_global = $this->template->getCSSGlobalFileContent(); if ($css_global) { $css_content_array[] = $css_global; } if ($this->template->css) { $css_content_array[] = $this->template->css; } return $css_content_array; } }