From 6667c70e19000d0fb1fe9927b662d74b6839a0e3 Mon Sep 17 00:00:00 2001 From: wxa Date: Thu, 24 Oct 2019 21:07:01 +0300 Subject: [PATCH] Remove AspectMock usage from PostContentTransformerTest [MAILPOET-2454] --- lib/Newsletter/Editor/PostTransformer.php | 210 ++---------------- .../PostTransformerContentsExtractor.php | 199 +++++++++++++++++ .../Editor/PostContentTransformerTest.php | 69 ++++-- 3 files changed, 263 insertions(+), 215 deletions(-) create mode 100644 lib/Newsletter/Editor/PostTransformerContentsExtractor.php diff --git a/lib/Newsletter/Editor/PostTransformer.php b/lib/Newsletter/Editor/PostTransformer.php index cd8ee7075b..971730d62a 100644 --- a/lib/Newsletter/Editor/PostTransformer.php +++ b/lib/Newsletter/Editor/PostTransformer.php @@ -2,26 +2,22 @@ namespace MailPoet\Newsletter\Editor; -use MailPoet\Config\Env; -use MailPoet\WooCommerce\Helper as WooCommerceHelper; -use MailPoet\WP\Functions as WPFunctions; - class PostTransformer { + /** @var PostTransformerContentsExtractor */ + private $extractor; private $args; private $with_layout; private $image_position; - private $wp; - /** @var WooCommerceHelper */ - private $woocommerce_helper; - - function __construct($args) { + function __construct($args, PostTransformerContentsExtractor $extractor = null) { $this->args = $args; $this->with_layout = isset($args['withLayout']) ? (bool)filter_var($args['withLayout'], FILTER_VALIDATE_BOOLEAN) : false; $this->image_position = 'left'; - $this->wp = new WPFunctions(); - $this->woocommerce_helper = new WooCommerceHelper(); + if ($extractor === null) { + $extractor = new PostTransformerContentsExtractor($args); + } + $this->extractor = $extractor; } function getDivider() { @@ -41,9 +37,9 @@ class PostTransformer { } private function getStructure($post) { - $content = $this->getContent($post, true, $this->args['displayType']); - $title = $this->getTitle($post); - $featured_image = $this->getFeaturedImage($post); + $content = $this->extractor->getContent($post, true, $this->args['displayType']); + $title = $this->extractor->getTitle($post); + $featured_image = $this->extractor->getFeaturedImage($post); $featured_image_position = $this->args['featuredImagePosition']; if ( @@ -51,7 +47,7 @@ class PostTransformer { && $featured_image_position === 'belowTitle' && ( $this->args['displayType'] === 'excerpt' - || $this->isProduct($post) + || $this->extractor->isProduct($post) ) ) { array_unshift($content, $title, $featured_image); @@ -73,9 +69,9 @@ class PostTransformer { private function getStructureWithLayout($post) { $with_post_class = $this->args['displayType'] === 'full'; - $content = $this->getContent($post, $with_post_class, $this->args['displayType']); - $title = $this->getTitle($post); - $featured_image = $this->getFeaturedImage($post); + $content = $this->extractor->getContent($post, $with_post_class, $this->args['displayType']); + $title = $this->extractor->getTitle($post); + $featured_image = $this->extractor->getFeaturedImage($post); $featured_image_position = $this->args['featuredImagePosition']; @@ -84,7 +80,7 @@ class PostTransformer { || $featured_image_position === 'none' || ( $this->args['displayType'] !== 'excerpt' - && !$this->isProduct($post) + && !$this->extractor->isProduct($post) ) ) { array_unshift($content, $title); @@ -154,180 +150,4 @@ class PostTransformer { $this->image_position = ($this->image_position === 'left') ? 'right' : 'left'; return $this->image_position; } - - private function getContent($post, $with_post_class, $display_type) { - $content_manager = new PostContentManager(); - $meta_manager = new MetaInformationManager(); - - $content = $content_manager->getContent($post, $this->args['displayType']); - $content = $meta_manager->appendMetaInformation($content, $post, $this->args); - $content = $content_manager->filterContent($content, $display_type, $with_post_class); - - $structure_transformer = new StructureTransformer(); - $content = $structure_transformer->transform($content, $this->args['imageFullWidth'] === true); - - if ($this->isProduct($post)) { - $content = $this->addProductDataToContent($content, $post); - } - - $read_more_btn = $this->getReadMoreButton($post); - $blocks_count = count($content); - if ($read_more_btn['type'] === 'text' && $blocks_count > 0 && $content[$blocks_count - 1]['type'] === 'text') { - $content[$blocks_count - 1]['text'] .= $read_more_btn['text']; - } else { - $content[] = $read_more_btn; - } - return $content; - } - - private function getImageInfo($id) { - /* - * In some cases wp_get_attachment_image_src ignore the second parameter - * and use global variable $content_width value instead. - * By overriding it ourselves when ensure a constant behaviour regardless - * of the user setup. - * - * https://mailpoet.atlassian.net/browse/MAILPOET-1365 - */ - global $content_width; // default is NULL - - $content_width_copy = $content_width; - $content_width = Env::NEWSLETTER_CONTENT_WIDTH; - $image_info = $this->wp->wpGetAttachmentImageSrc($id, 'mailpoet_newsletter_max'); - $content_width = $content_width_copy; - - return $image_info; - } - - private function getFeaturedImage($post) { - $post_id = $post->ID; - $post_title = $this->sanitizeTitle($post->post_title); - $image_full_width = (bool)filter_var($this->args['imageFullWidth'], FILTER_VALIDATE_BOOLEAN); - - if (!has_post_thumbnail($post_id)) { - return false; - } - - $thumbnail_id = $this->wp->getPostThumbnailId($post_id); - $image_info = $this->getImageInfo($thumbnail_id); - - // get alt text - $alt_text = trim(strip_tags(get_post_meta( - $thumbnail_id, - '_wp_attachment_image_alt', - true - ))); - if (strlen($alt_text) === 0) { - // if the alt text is empty then use the post title - $alt_text = trim(strip_tags($post_title)); - } - - return [ - 'type' => 'image', - 'link' => $this->wp->getPermalink($post_id), - 'src' => $image_info[0], - 'alt' => $alt_text, - 'fullWidth' => $image_full_width, - 'width' => $image_info[1], - 'height' => $image_info[2], - 'styles' => [ - 'block' => [ - 'textAlign' => 'center', - ], - ], - ]; - } - - private function getReadMoreButton($post) { - if ($this->args['readMoreType'] === 'button') { - $button = $this->args['readMoreButton']; - $button['url'] = $this->wp->getPermalink($post->ID); - return $button; - } - - $read_more_text = sprintf( - '

%s

', - $this->wp->getPermalink($post->ID), - $this->args['readMoreText'] - ); - - return [ - 'type' => 'text', - 'text' => $read_more_text, - ]; - } - - private function getTitle($post) { - $title = $this->sanitizeTitle($post->post_title); - - if (filter_var($this->args['titleIsLink'], FILTER_VALIDATE_BOOLEAN)) { - $title = '' . $title . ''; - } - - if (in_array($this->args['titleFormat'], ['h1', 'h2', 'h3'])) { - $tag = $this->args['titleFormat']; - } elseif ($this->args['titleFormat'] === 'ul') { - $tag = 'li'; - } else { - $tag = 'h1'; - } - - $alignment = (in_array($this->args['titleAlignment'], ['left', 'right', 'center'])) ? $this->args['titleAlignment'] : 'left'; - - $title = '<' . $tag . ' data-post-id="' . $post->ID . '" style="text-align: ' . $alignment . ';">' . $title . ''; - return [ - 'type' => 'text', - 'text' => $title, - ]; - } - - private function getPrice($post) { - $price = null; - $product = null; - if ($this->woocommerce_helper->isWooCommerceActive()) { - $product = $this->woocommerce_helper->wcGetProduct($post->ID); - } - if ($product) { - $price = '

' . strip_tags($product->get_price_html(), '') . '

'; - } - return $price; - } - - private function addProductDataToContent($content, $post) { - if (!isset($this->args['pricePosition']) || $this->args['pricePosition'] === 'hidden') { - return $content; - } - $price = $this->getPrice($post); - $blocks_count = count($content); - if ($blocks_count > 0 && $content[$blocks_count - 1]['type'] === 'text') { - if ($this->args['pricePosition'] === 'below') { - $content[$blocks_count - 1]['text'] = $content[$blocks_count - 1]['text'] . $price; - } else { - $content[$blocks_count - 1]['text'] = $price . $content[$blocks_count - 1]['text']; - } - } else { - $content[] = [ - 'type' => 'text', - 'text' => $price, - ]; - } - return $content; - } - - private function isProduct($post) { - return $post->post_type === 'product'; - } - - /** - * Replaces double quote character with a unicode - * alternative to avoid problems when inlining CSS. - * [MAILPOET-1937] - * - * @param string $title - * @return string - */ - private function sanitizeTitle($title) { - return str_replace('"', '"', $title); - } - } diff --git a/lib/Newsletter/Editor/PostTransformerContentsExtractor.php b/lib/Newsletter/Editor/PostTransformerContentsExtractor.php new file mode 100644 index 0000000000..f50f558bc1 --- /dev/null +++ b/lib/Newsletter/Editor/PostTransformerContentsExtractor.php @@ -0,0 +1,199 @@ +args = $args; + $this->wp = new WPFunctions(); + $this->woocommerce_helper = new WooCommerceHelper(); + } + + function getContent($post, $with_post_class, $display_type) { + $content_manager = new PostContentManager(); + $meta_manager = new MetaInformationManager(); + + $content = $content_manager->getContent($post, $this->args['displayType']); + $content = $meta_manager->appendMetaInformation($content, $post, $this->args); + $content = $content_manager->filterContent($content, $display_type, $with_post_class); + + $structure_transformer = new StructureTransformer(); + $content = $structure_transformer->transform($content, $this->args['imageFullWidth'] === true); + + if ($this->isProduct($post)) { + $content = $this->addProductDataToContent($content, $post); + } + + $read_more_btn = $this->getReadMoreButton($post); + $blocks_count = count($content); + if ($read_more_btn['type'] === 'text' && $blocks_count > 0 && $content[$blocks_count - 1]['type'] === 'text') { + $content[$blocks_count - 1]['text'] .= $read_more_btn['text']; + } else { + $content[] = $read_more_btn; + } + return $content; + } + + private function getImageInfo($id) { + /* + * In some cases wp_get_attachment_image_src ignore the second parameter + * and use global variable $content_width value instead. + * By overriding it ourselves when ensure a constant behaviour regardless + * of the user setup. + * + * https://mailpoet.atlassian.net/browse/MAILPOET-1365 + */ + global $content_width; // default is NULL + + $content_width_copy = $content_width; + $content_width = Env::NEWSLETTER_CONTENT_WIDTH; + $image_info = $this->wp->wpGetAttachmentImageSrc($id, 'mailpoet_newsletter_max'); + $content_width = $content_width_copy; + + return $image_info; + } + + function getFeaturedImage($post) { + $post_id = $post->ID; + $post_title = $this->sanitizeTitle($post->post_title); + $image_full_width = (bool)filter_var($this->args['imageFullWidth'], FILTER_VALIDATE_BOOLEAN); + + if (!has_post_thumbnail($post_id)) { + return false; + } + + $thumbnail_id = $this->wp->getPostThumbnailId($post_id); + $image_info = $this->getImageInfo($thumbnail_id); + + // get alt text + $alt_text = trim(strip_tags(get_post_meta( + $thumbnail_id, + '_wp_attachment_image_alt', + true + ))); + if (strlen($alt_text) === 0) { + // if the alt text is empty then use the post title + $alt_text = trim(strip_tags($post_title)); + } + + return [ + 'type' => 'image', + 'link' => $this->wp->getPermalink($post_id), + 'src' => $image_info[0], + 'alt' => $alt_text, + 'fullWidth' => $image_full_width, + 'width' => $image_info[1], + 'height' => $image_info[2], + 'styles' => [ + 'block' => [ + 'textAlign' => 'center', + ], + ], + ]; + } + + private function getReadMoreButton($post) { + if ($this->args['readMoreType'] === 'button') { + $button = $this->args['readMoreButton']; + $button['url'] = $this->wp->getPermalink($post->ID); + return $button; + } + + $read_more_text = sprintf( + '

%s

', + $this->wp->getPermalink($post->ID), + $this->args['readMoreText'] + ); + + return [ + 'type' => 'text', + 'text' => $read_more_text, + ]; + } + + function getTitle($post) { + $title = $this->sanitizeTitle($post->post_title); + + if (filter_var($this->args['titleIsLink'], FILTER_VALIDATE_BOOLEAN)) { + $title = '' . $title . ''; + } + + if (in_array($this->args['titleFormat'], ['h1', 'h2', 'h3'])) { + $tag = $this->args['titleFormat']; + } elseif ($this->args['titleFormat'] === 'ul') { + $tag = 'li'; + } else { + $tag = 'h1'; + } + + $alignment = (in_array($this->args['titleAlignment'], ['left', 'right', 'center'])) ? $this->args['titleAlignment'] : 'left'; + + $title = '<' . $tag . ' data-post-id="' . $post->ID . '" style="text-align: ' . $alignment . ';">' . $title . ''; + return [ + 'type' => 'text', + 'text' => $title, + ]; + } + + private function getPrice($post) { + $price = null; + $product = null; + if ($this->woocommerce_helper->isWooCommerceActive()) { + $product = $this->woocommerce_helper->wcGetProduct($post->ID); + } + if ($product) { + $price = '

' . strip_tags($product->get_price_html(), '') . '

'; + } + return $price; + } + + private function addProductDataToContent($content, $post) { + if (!isset($this->args['pricePosition']) || $this->args['pricePosition'] === 'hidden') { + return $content; + } + $price = $this->getPrice($post); + $blocks_count = count($content); + if ($blocks_count > 0 && $content[$blocks_count - 1]['type'] === 'text') { + if ($this->args['pricePosition'] === 'below') { + $content[$blocks_count - 1]['text'] = $content[$blocks_count - 1]['text'] . $price; + } else { + $content[$blocks_count - 1]['text'] = $price . $content[$blocks_count - 1]['text']; + } + } else { + $content[] = [ + 'type' => 'text', + 'text' => $price, + ]; + } + return $content; + } + + function isProduct($post) { + return $post->post_type === 'product'; + } + + /** + * Replaces double quote character with a unicode + * alternative to avoid problems when inlining CSS. + * [MAILPOET-1937] + * + * @param string $title + * @return string + */ + private function sanitizeTitle($title) { + return str_replace('"', '"', $title); + } +} diff --git a/tests/integration/Newsletter/Editor/PostContentTransformerTest.php b/tests/integration/Newsletter/Editor/PostContentTransformerTest.php index 1febda5ba4..25e862afbd 100644 --- a/tests/integration/Newsletter/Editor/PostContentTransformerTest.php +++ b/tests/integration/Newsletter/Editor/PostContentTransformerTest.php @@ -2,8 +2,9 @@ namespace MailPoet\Test\Newsletter\Editor; -use AspectMock\Test as Mock; +use Codeception\Stub\Expected; use MailPoet\Newsletter\Editor\PostTransformer; +use MailPoet\Newsletter\Editor\PostTransformerContentsExtractor; class PostContentTransformerTest extends \MailPoetTest { /** @var array */ @@ -241,12 +242,25 @@ class PostContentTransformerTest extends \MailPoetTest { $post = []; $expected_with_post_class = true; - $transformer = new PostTransformer($args); - $mock_get_content = Mock::double($transformer, ['getContent' => $this->content_mock]); - Mock::double($transformer, ['getFeaturedImage' => null]); - Mock::double($transformer, ['getTitle' => 'Title']); + $extractor = $this->make( + PostTransformerContentsExtractor::class, + [ + 'getContent' => Expected::once($this->content_mock), + 'getFeaturedImage' => null, + 'getTitle' => 'Title', + ], + $this + ); + $extractor->expects($this->once()) + ->method('getContent') + ->with( + $this->equalTo($post), + $this->equalTo($expected_with_post_class), + $this->equalTo('full') + ); + + $transformer = new PostTransformer($args, $extractor); $transformer->transform($post); - $mock_get_content->verifyInvokedOnce('getContent', [$post, $expected_with_post_class, 'full']); } function testShouldNotAddClassToParagraphsInExcerptWithLayout() { @@ -259,27 +273,42 @@ class PostContentTransformerTest extends \MailPoetTest { $post = []; $expected_with_post_class = false; - $transformer = new PostTransformer($args); - $mock_get_content = Mock::double($transformer, ['getContent' => $this->content_mock]); - Mock::double($transformer, ['getFeaturedImage' => null]); - Mock::double($transformer, ['getTitle' => 'Title']); + $extractor = $this->make( + PostTransformerContentsExtractor::class, + [ + 'getContent' => Expected::once($this->content_mock), + 'getFeaturedImage' => null, + 'getTitle' => 'Title', + ], + $this + ); + $extractor->expects($this->once()) + ->method('getContent') + ->with( + $this->equalTo($post), + $this->equalTo($expected_with_post_class), + $this->equalTo('excerpt') + ); + + $transformer = new PostTransformer($args, $extractor); $transformer->transform($post); - $mock_get_content->verifyInvokedOnce('getContent', [$post, $expected_with_post_class, 'excerpt']); } /** * @return PostTransformer */ private function getTransformer(array $args, array $content, array $title, array $image = null) { - $transformer = new PostTransformer($args); - Mock::double($transformer, ['getContent' => $content]); - Mock::double($transformer, ['getFeaturedImage' => $image]); - Mock::double($transformer, ['getTitle' => $title]); - Mock::double($transformer, ['isProduct' => false]); + $extractor = $this->make( + PostTransformerContentsExtractor::class, + [ + 'getContent' => $content, + 'getFeaturedImage' => $image, + 'getTitle' => $title, + 'isProduct' => false, + ], + $this + ); + $transformer = new PostTransformer($args, $extractor); return $transformer; } - - function _after() { - Mock::clean(); - } }