PluginProbe ʕ •ᴥ•ʔ
MailPoet – Newsletters, Email Marketing, and Automation / 5.34.2
MailPoet – Newsletters, Email Marketing, and Automation v5.34.2
5.34.2 5.34.1 5.34.0 5.33.1 5.33.0 5.32.0 5.31.0 5.30.0 5.29.0 5.28.1 5.28.0 5.27.0 5.26.0 5.26.1 5.25.0 5.24.0 4.43.0 4.43.1 4.44.0 4.44.1 4.45.0 4.46.0 4.47.0 4.48.0 4.48.1 4.48.2 4.49.0 4.49.1 4.5.0 4.5.1 4.5.2 4.50.0 4.50.1 4.51.0 4.51.1 4.51.2 4.52.0 4.53.0 4.54.0 4.55.0 4.56.0 4.57.0 4.58.0 4.58.1 4.58.2 4.6.0 4.6.1 4.6.2 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 5.0.0 5.0.1 5.0.2 5.1.0 5.1.1 5.10.0 5.10.1 5.11.0 5.12.0 5.12.1 5.12.10 5.12.11 5.12.12 5.12.13 5.12.2 5.12.3 5.12.4 5.12.5 5.12.6 5.12.7 5.12.8 5.12.9 5.13.0 5.13.1 5.13.2 5.14.0 5.14.1 5.14.2 5.14.3 5.15.0 5.15.1 5.16.0 5.16.1 5.16.2 5.16.3 5.16.4 5.17.0 5.17.1 5.17.2 5.17.3 5.17.4 5.17.5 5.17.6 5.18.0 5.19.0 5.2.0 5.2.1 5.2.2 5.2.3 5.20.0 5.21.0 5.21.1 5.21.2 5.21.3 5.22.0 5.22.1 5.22.2 5.22.3 5.22.4 5.23.0 5.23.1 5.23.2 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.4.0 5.4.1 5.4.2 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.6.3 5.6.4 5.7.0 5.7.1 5.8.0 5.8.1 5.9.0 3.0.0-beta.15 3.7.1 3.0.0-beta.16 3.7.2 3.0.0-beta.17 3.7.3 3.0.0-beta.18 3.7.4 3.0.0-beta.19 3.7.5 3.0.0-beta.2 3.7.6 3.0.0-beta.20 3.7.8 3.0.0-beta.21 3.70.0 3.0.0-beta.22 3.71.0 3.0.0-beta.23 3.71.1 3.0.0-beta.23.1 3.71.2 3.0.0-beta.23.2 3.71.3 3.0.0-beta.24 3.72.0 3.0.0-beta.25 3.73.0 3.0.0-beta.26 3.73.1 3.0.0-beta.27 3.73.2 3.0.0-beta.28 3.74.0 3.0.0-beta.29 3.74.1 3.0.0-beta.3 3.74.2 3.0.0-beta.30 3.74.3 3.0.0-beta.31 3.75.0 3.0.0-beta.32 3.75.1 3.0.0-beta.33 3.76.0 3.0.0-beta.33.1 3.77.0 3.0.0-beta.34.0.0 3.77.1 3.0.0-beta.36.0.0 3.78.0 3.0.0-beta.36.0.1 3.79.0 3.0.0-beta.36.2.0 3.8 3.0.0-beta.36.3.0 3.8.1 3.0.0-beta.36.3.1 3.8.2 3.0.0-beta.37.0.0 3.8.3 3.0.0-beta.4 3.8.4 3.0.0-beta.5 3.8.5 3.0.0-beta.6 3.8.6 3.0.0-beta.7 3.80.0 3.0.0-beta.7.1 3.81.0 3.0.0-beta.8 3.82.0 3.0.0-beta.9 3.83.0 3.0.0-rc.1.0.0 3.84.0 3.0.0-rc.1.0.1 3.84.1 3.0.0-rc.1.0.2 3.85.0 3.0.0-rc.1.0.3 3.85.1 3.0.0-rc.1.0.4 3.86.0 3.0.0-rc.2.0.0 3.87.0 3.0.0-rc.2.0.1 3.87.1 3.0.0-rc.2.0.2 3.87.2 3.0.0-rc.2.0.3 3.88.0 3.0.1 3.88.1 3.0.2 3.88.2 3.0.3 3.89.0 3.0.4 3.89.1 3.0.5 3.89.2 3.0.6 3.89.3 3.0.7 3.89.4 3.0.8 3.9.0 3.0.9 3.9.1 3.1.0 3.90.0 3.10 3.90.1 3.10.1 3.90.2 3.100.0 3.91.0 3.100.1 3.91.1 3.100.2 3.92.0 3.101.0 3.92.1 3.101.1 3.93.0 3.102.0 3.93.1 3.102.1 3.94.0 3.103.0 3.95.0 3.103.1 3.95.1 3.11.0 3.96.0 3.11.1 3.96.1 3.11.2 3.97.0 3.11.3 3.98.0 3.11.4 3.98.1 3.11.5 3.99.0 3.12.0 3.99.1 3.12.1 4.0.0 3.13.0 4.0.1 3.14.0 4.1.0 3.14.1 4.1.1 3.15.0 4.10.0 3.16.0 4.11.0 3.16.1 4.11.1 3.16.2 4.12.0 3.16.3 4.12.1 3.17.0 4.12.2 3.17.1 4.13.0 3.17.2 4.14.0 3.18.0 4.15.0 3.18.1 4.16.0 3.18.2 4.17.0 3.19.0 4.17.1 3.19.1 4.18.0 3.19.2 4.18.1 3.19.3 4.19.0 3.2.0 4.2.0 3.2.1 4.20.0 3.2.2 4.20.1 3.2.3 4.20.2 3.2.4 4.21.0 3.2.5 4.22.0 3.20.0 4.22.1 3.21.0 4.22.2 3.21.1 4.23.0 3.22.0 4.24.0 3.23.0 4.25.0 3.23.1 4.26.0 3.23.2 4.26.1 3.24.0 4.27.0 3.25.0 4.28.0 3.25.1 4.29.0 3.26.0 4.3.0 3.26.1 4.3.1 3.27.0 4.30.0 3.28.0 4.31.0 3.29.0 4.31.1 3.3.0 4.32.0 3.3.1 4.33.0 3.3.2 4.34.0 3.3.3 4.35.0 3.3.4 4.35.1 3.3.5 4.36.0 3.3.6 4.37.0 3.30.0 4.38.0 3.31.0 4.39.0 3.31.1 4.4.0 3.32.0 4.40.0 3.32.1 4.41.0 3.32.2 4.41.1 3.33.0 4.41.2 3.34.0 4.41.3 3.34.1 4.42.0 3.34.2 4.42.1 3.34.3 3.34.4 3.35.0 3.35.1 3.35.3 3.35.4 3.36.0 3.37.0 3.37.1 3.37.2 3.37.3 3.38.0 3.38.1 3.39.0 3.39.1 3.39.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.40.0 3.40.1 3.41.0 3.41.1 3.41.2 3.42.0 3.42.1 3.42.2 3.42.3 3.43.0 3.43.1 3.44.0 3.45.0 3.45.1 3.46.0 3.46.1 3.46.10 3.46.11 3.46.12 3.46.13 3.46.14 3.46.2 3.46.3 3.46.4 3.46.5 3.46.6 3.46.7 3.46.8 3.46.9 3.47.0 3.47.1 3.47.10 3.47.11 3.47.2 3.47.3 3.47.5 3.47.6 3.47.7 3.47.9 3.48.0 3.48.1 3.49.0 3.49.1 3.5.0 3.5.1 3.50.0 3.51.0 3.51.1 3.51.2 3.52.0 3.53.0 3.54.0 3.54.1 3.54.2 3.54.3 3.55.0 3.55.1 3.56.0 3.56.1 3.56.2 3.57.0 3.57.1 3.58.0 3.59.0 3.59.1 3.59.2 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.60.0 3.60.1 3.60.10 3.60.11 3.60.12 3.60.2 3.60.3 3.60.4 3.60.6 3.60.7 3.60.8 3.60.9 3.61.0 3.62.0 3.62.1 3.63.0 3.64.0 3.64.1 3.64.2 3.64.3 3.65.0 trunk 3.65.1 3.0.0 3.66.0 3.0.0-beta.1 3.67.0 3.0.0-beta.10 3.67.1 3.0.0-beta.11 3.68.0 3.0.0-beta.12 3.69.0 3.0.0-beta.13 3.69.1 3.0.0-beta.14 3.7.0
mailpoet / lib / Newsletter / Editor / PostContentManager.php
mailpoet / lib / Newsletter / Editor Last commit date
LayoutHelper.php 3 years ago MetaInformationManager.php 2 months ago PostContentManager.php 11 months ago PostListTransformer.php 3 years ago PostTransformer.php 1 year ago PostTransformerContentsExtractor.php 2 months ago StructureTransformer.php 3 years ago TitleListTransformer.php 1 year ago Transformer.php 3 years ago index.php 3 years ago
PostContentManager.php
207 lines
1 <?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
2
3 namespace MailPoet\Newsletter\Editor;
4
5 if (!defined('ABSPATH')) exit;
6
7
8 use MailPoet\Util\pQuery\pQuery;
9 use MailPoet\WooCommerce\Helper as WooCommerceHelper;
10 use MailPoet\WP\Functions as WPFunctions;
11
12 class PostContentManager {
13 const WP_POST_CLASS = 'mailpoet_wp_post';
14
15 public $maxExcerptLength = 60;
16
17 /** @var WooCommerceHelper */
18 private $woocommerceHelper;
19
20 /** @var WPFunctions */
21 private $wp;
22
23 public function __construct(
24 ?WooCommerceHelper $woocommerceHelper = null,
25 ?WPFunctions $wp = null
26 ) {
27 $this->wp = $wp ?: new WPFunctions;
28 $this->maxExcerptLength = $this->wp->applyFilters('mailpoet_newsletter_post_excerpt_length', $this->maxExcerptLength);
29 $this->woocommerceHelper = $woocommerceHelper ?: new WooCommerceHelper($this->wp);
30 }
31
32 public function getContent($post, $displayType) {
33 if ($displayType === 'titleOnly') {
34 return '';
35 }
36
37
38
39 if ($this->woocommerceHelper->isWooCommerceActive()) {
40 if ($this->isWcProduct($post)) {
41 return $this->getContentForProduct($post, $displayType);
42 }
43 if ($this->wp->getPostType($post) === 'product') {
44 $product = $this->woocommerceHelper->wcGetProduct($post->ID);
45 if ($product) {
46 return $this->getContentForProduct($product, $displayType);
47 }
48 }
49 }
50
51 if ($displayType === 'excerpt') {
52 if ($this->wp->hasExcerpt($post)) {
53 $content = self::stripShortCodes($this->wp->getTheExcerpt($post));
54 return $this->fixAnchorLinks($content, $post);
55 }
56 $content = self::stripShortCodes(
57 $this->wp->applyFilters(
58 'get_the_excerpt',
59 $this->generateExcerpt($post->post_content), // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
60 $post
61 )
62 );
63 return $this->fixAnchorLinks($content, $post);
64 }
65 $content = self::stripShortCodes($post->post_content); // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
66 return $this->fixAnchorLinks($content, $post);
67 }
68
69 public function filterContent($content, $displayType, $withPostClass = true) {
70 $content = self::convertEmbeddedContent($content);
71
72 // convert h4 h5 h6 to h3
73 $content = preg_replace('/<([\/])?h[456](.*?)>/', '<$1h3$2>', $content);
74
75 // convert currency signs
76 $content = str_replace(
77 ['$', '', '£', '¥'],
78 ['&#36;', '&euro;', '&pound;', '&#165;'],
79 $content
80 );
81
82 // strip useless tags
83 $tagsNotBeingStripped = [
84 '<p>', '<em>', '<span>', '<b>', '<strong>', '<i>',
85 '<a>', '<ul>', '<ol>', '<li>', '<br>', '<blockquote>',
86 ];
87 if ($displayType === 'full') {
88 $tagsNotBeingStripped = array_merge($tagsNotBeingStripped, ['<figure>', '<img>', '<h1>', '<h2>', '<h3>', '<hr>']);
89 }
90
91 if (is_array($content)) {
92 $content = implode(' ', $content);
93 }
94
95 $content = strip_tags($content, implode('', $tagsNotBeingStripped));
96 if ($withPostClass) {
97 $dOMParser = new pQuery();
98 $DOM = $dOMParser->parseStr(WPFunctions::get()->wpautop($content));
99 $paragraphs = $DOM->query('p');
100 foreach ($paragraphs as $paragraph) {
101 // We replace the class attribute to avoid conflicts in the newsletter editor
102 $paragraph->removeAttr('class');
103 $paragraph->addClass(self::WP_POST_CLASS);
104 }
105 $content = $DOM->__toString();
106 } else {
107 $content = WPFunctions::get()->wpautop($content);
108 }
109 $content = trim($content);
110
111 return $content;
112 }
113
114 private function getContentForProduct($product, $displayType) {
115 if ($displayType === 'excerpt') {
116 return $product->get_short_description();
117 }
118 return $product->get_description();
119 }
120
121 private function generateExcerpt($content) {
122 // remove image captions in gutenberg
123 $content = preg_replace(
124 "/<figcaption.*?>.*?<\/figcaption>/",
125 '',
126 $content
127 );
128 // remove image captions in classic posts
129 $content = preg_replace(
130 "/\[caption.*?\](.*?)\[\/caption\]/",
131 '',
132 $content
133 );
134
135 $content = self::stripShortCodes($content);
136
137 // if excerpt is empty then try to find the "more" tag
138 $excerpts = explode('<!--more-->', $content);
139 if (count($excerpts) > 1) {
140 // <!--more--> separator was present
141 return $excerpts[0];
142 } else {
143 // Separator not present, try to shorten long posts
144 return WPFunctions::get()->wpTrimWords($content, $this->maxExcerptLength, ' &hellip;');
145 }
146 }
147
148 private function stripShortCodes($content) {
149 // remove captions
150 $content = preg_replace(
151 "/\[caption.*?\](.*<\/a>)(.*?)\[\/caption\]/",
152 '$1',
153 $content
154 );
155
156 // remove other shortcodes
157 $content = preg_replace('/\[[^\[\]]*\]/', '', $content);
158
159 return $content;
160 }
161
162 private function convertEmbeddedContent($content = '') {
163 // remove embedded video and replace with links
164 $content = preg_replace(
165 '#<iframe.*?src=\"(.+?)\".*><\/iframe>#',
166 '<a href="$1">' . __('Click here to view media.', 'mailpoet') . '</a>',
167 $content
168 );
169
170 // replace youtube links
171 $content = preg_replace(
172 '#http://www.youtube.com/embed/([a-zA-Z0-9_-]*)#Ui',
173 'http://www.youtube.com/watch?v=$1',
174 $content
175 );
176
177 return $content;
178 }
179
180 private function isWcProduct($post) {
181 return class_exists('\WC_Product') && $post instanceof \WC_Product;
182 }
183
184 private function fixAnchorLinks($content, $post) {
185 if (empty($content) || !$post) {
186 return $content;
187 }
188
189 // Get the post's permalink to use as base URL
190 $postUrl = $this->wp->getPermalink($post);
191 if (!$postUrl) {
192 return $content;
193 }
194
195 // Find and replace anchor-only links (href="#...") with full URLs
196 $content = preg_replace_callback(
197 '/(<a[^>]+href=["\'])#([^"\']*)(["\'])/i',
198 function($matches) use ($postUrl) {
199 return $matches[1] . $postUrl . '#' . $matches[2] . $matches[3];
200 },
201 $content
202 );
203
204 return $content;
205 }
206 }
207