Skip to content
Permalink
Browse files Browse the repository at this point in the history
SW-26866 - Add test for marketing core class
  • Loading branch information
mitelg committed Jul 14, 2022
1 parent f81db00 commit 7875855
Show file tree
Hide file tree
Showing 10 changed files with 121 additions and 39 deletions.
10 changes: 0 additions & 10 deletions .phpstan-baseline.neon
Expand Up @@ -31345,16 +31345,6 @@ parameters:
count: 1
path: engine/Shopware/Core/sMarketing.php

-
message: "#^Method sMarketing\\:\\:sMailCampaignsGetDetail\\(\\) has no return type specified\\.$#"
count: 1
path: engine/Shopware/Core/sMarketing.php

-
message: "#^Method sMarketing\\:\\:sMailCampaignsGetDetail\\(\\) has parameter \\$id with no type specified\\.$#"
count: 1
path: engine/Shopware/Core/sMarketing.php

-
message: "#^Parameter \\#3 \\$subject of function preg_replace expects array\\|string, string\\|null given\\.$#"
count: 2
Expand Down
8 changes: 5 additions & 3 deletions .phpstan.neon
Expand Up @@ -179,6 +179,8 @@ parameters:
# This is a bleeding edge feature and not working well since now. See https://github.com/phpstan/phpstan-doctrine/issues/332
- '#Parameter .* of method Doctrine\\ORM\\.*::.*\(\) expects .*literal-string.* given#'

- # Doctrine type is integer. PHPStan allows only specific values
message: '#Property Shopware\\Models\\Dispatch\\Dispatch::\$.* type mapping mismatch: database can contain int but property expects 0\|1\|2\|3#'
path: engine/Shopware/Models/Dispatch/Dispatch.php
- # Doctrine type is integer|string. PHPStan allows only specific values
message: '#Property Shopware\\Models\\.*\\.*::\$.* type mapping mismatch: database can contain (int|string) but property expects .*#'
paths:
- engine/Shopware/Models/Dispatch/Dispatch.php
- engine/Shopware/Models/Newsletter/Container.php
12 changes: 8 additions & 4 deletions engine/Shopware/Controllers/Backend/Newsletter.php
Expand Up @@ -29,6 +29,7 @@
use Shopware\Components\Routing\RouterInterface;
use Shopware\Components\ShopRegistrationServiceInterface;
use Shopware\Components\Validator\EmailValidator;
use Shopware\Models\Newsletter\Container;
use Shopware\Models\Plugin\Plugin;
use Shopware\Models\Shop\Shop;
use Symfony\Component\HttpFoundation\Response;
Expand Down Expand Up @@ -508,15 +509,18 @@ public function getMailingDetails($id)
trigger_error(sprintf('%s:%s is deprecated since Shopware 5.6 and will be private with 5.8.', __CLASS__, __METHOD__), E_USER_DEPRECATED);

$details = Shopware()->Modules()->Marketing()->sMailCampaignsGetDetail((int) $id);
if (!\is_array($details)) {
return [];
}

foreach ($details['containers'] as $key => $container) {
if ($container['type'] === 'ctVoucher') {
if ($container['type'] === Container::TYPE_VOUCHER) {
if (!empty($container['value'])) {
$details['voucher'] = $container['value'];
}
$details['containers'][$key]['type'] = 'ctText';
$details['containers'][$key]['type'] = Container::TYPE_TEXT;
}
if ($container['type'] === 'ctSuggest') {
if ($container['type'] === Container::TYPE_SUGGEST) {
$details['suggest'] = true;
}
}
Expand Down Expand Up @@ -551,7 +555,7 @@ public function getMailingVoucher($id)
trigger_error(sprintf('%s:%s is deprecated since Shopware 5.6 and will be private with 5.8.', __CLASS__, __METHOD__), E_USER_DEPRECATED);

$sql = 'SELECT value FROM s_campaigns_containers WHERE type=? AND promotionID=?';
$voucherID = Shopware()->Db()->fetchOne($sql, ['ctVoucher', $id]);
$voucherID = Shopware()->Db()->fetchOne($sql, [Container::TYPE_VOUCHER, $id]);
if (empty($voucherID)) {
return false;
}
Expand Down
18 changes: 12 additions & 6 deletions engine/Shopware/Core/sMarketing.php
Expand Up @@ -33,6 +33,7 @@
use Shopware\Components\Compatibility\LegacyStructConverter;
use Shopware\Models\Banner\Banner;
use Shopware\Models\Category\Category;
use Shopware\Models\Newsletter\Container;
use Shopware\Models\Tracking\Banner as TrackingBanner;

/**
Expand Down Expand Up @@ -631,6 +632,11 @@ public function sGetSimilarArticles($articleId = null, $limit = null)
return $similarProducts;
}

/**
* @param int $id
*
* @return array<string, mixed>|false
*/
public function sMailCampaignsGetDetail($id)
{
$sql = "
Expand Down Expand Up @@ -662,7 +668,7 @@ public function sMailCampaignsGetDetail($id)

foreach ($getCampaignContainers as $campaignKey => $campaignValue) {
switch ($campaignValue['type']) {
case 'ctBanner':
case Container::TYPE_BANNER:
// Query Banner
$getBanner = $this->db->fetchRow("
SELECT image, link, linkTarget, description FROM s_campaigns_banner
Expand All @@ -680,7 +686,7 @@ public function sMailCampaignsGetDetail($id)
$getCampaignContainers[$campaignKey]['description'] = $getBanner['description'];
$getCampaignContainers[$campaignKey]['data'] = $getBanner;
break;
case 'ctLinks':
case Container::TYPE_LINKS:
// Query links
$getLinks = $this->db->fetchAll("
SELECT description, link, target FROM s_campaigns_links
Expand All @@ -689,7 +695,7 @@ public function sMailCampaignsGetDetail($id)
");
$getCampaignContainers[$campaignKey]['data'] = $getLinks;
break;
case 'ctArticles':
case Container::TYPE_PRODUCTS:
$sql = "
SELECT articleordernumber, type FROM s_campaigns_articles
WHERE parentID={$campaignValue['id']}
Expand All @@ -699,8 +705,8 @@ public function sMailCampaignsGetDetail($id)
$getProducts = $this->db->fetchAll($sql);
$getCampaignContainers[$campaignKey]['data'] = $this->sGetMailCampaignsProducts($getProducts);
break;
case 'ctText':
case 'ctVoucher':
case Container::TYPE_TEXT:
case Container::TYPE_VOUCHER:
$getText = $this->db->fetchRow("
SELECT headline, html,image,alignment,link FROM s_campaigns_html
WHERE parentID={$campaignValue['id']}
Expand All @@ -711,7 +717,7 @@ public function sMailCampaignsGetDetail($id)
if (strpos($getText['link'], 'http') === false && $getText['link']) {
$getText['link'] = 'http://' . $getText['link'];
}
$getCampaignContainers[$campaignKey]['description'] = htmlspecialchars($getText['headline']);
$getCampaignContainers[$campaignKey]['description'] = htmlspecialchars($getText['headline'], ENT_COMPAT);
$getCampaignContainers[$campaignKey]['data'] = $getText;
break;
}
Expand Down
21 changes: 14 additions & 7 deletions engine/Shopware/Models/Newsletter/Container.php
Expand Up @@ -40,6 +40,13 @@
*/
class Container extends ModelEntity
{
public const TYPE_TEXT = 'ctText';
public const TYPE_PRODUCTS = 'ctArticles';
public const TYPE_BANNER = 'ctBanner';
public const TYPE_LINKS = 'ctLinks';
public const TYPE_VOUCHER = 'ctVoucher';
public const TYPE_SUGGEST = 'ctSuggest';

/**
* INVERSE SIDE
*
Expand Down Expand Up @@ -127,7 +134,7 @@ class Container extends ModelEntity
/**
* Type of the container (sText, sBanner etc)
*
* @var string
* @var self::TYPE_*
*
* @ORM\Column(name="type", type="string", length=255, nullable=false)
*/
Expand Down Expand Up @@ -190,15 +197,15 @@ public function getPosition()
}

/**
* @param string $type
* @param self::TYPE_* $type
*/
public function setType($type)
{
$this->type = $type;
}

/**
* @return string
* @return self::TYPE_*
*/
public function getType()
{
Expand Down Expand Up @@ -245,7 +252,7 @@ public function getValue()
public function setText($text)
{
$return = $this->setOneToOne($text, Text::class, 'text', 'container');
$this->setType('ctText');
$this->setType(self::TYPE_TEXT);

return $return;
}
Expand All @@ -266,7 +273,7 @@ public function getText()
public function setArticles($articles)
{
$return = $this->setOneToMany($articles, Article::class, 'articles', 'container');
$this->setType('ctArticles');
$this->setType(self::TYPE_PRODUCTS);

return $return;
}
Expand All @@ -287,7 +294,7 @@ public function getArticles()
public function setBanner($banner)
{
$return = $this->setOneToOne($banner, Banner::class, 'banner', 'container');
$this->setType('ctBanner');
$this->setType(self::TYPE_BANNER);

return $return;
}
Expand All @@ -308,7 +315,7 @@ public function getBanner()
public function setLinks($links)
{
$return = $this->setOneToMany($links, Link::class, 'links', 'container');
$this->setType('ctLinks');
$this->setType(self::TYPE_LINKS);

return $return;
}
Expand Down
Expand Up @@ -129,7 +129,7 @@ public function getId()
public function setContainer($container)
{
$this->container = $container;
$container->setType('ctArticles');
$container->setType(Container::TYPE_PRODUCTS);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion engine/Shopware/Models/Newsletter/ContainerType/Banner.php
Expand Up @@ -171,7 +171,7 @@ public function getTarget()
public function setContainer($container)
{
$this->container = $container;
$container->setType('ctBanner');
$container->setType(Container::TYPE_BANNER);
}

/**
Expand Down
9 changes: 5 additions & 4 deletions engine/Shopware/Models/Newsletter/ContainerType/Link.php
Expand Up @@ -26,6 +26,7 @@

use Doctrine\ORM\Mapping as ORM;
use Shopware\Components\Model\ModelEntity;
use Shopware\Models\Newsletter\Container;

/**
* Shopware text model represents a link container type.
Expand All @@ -39,7 +40,7 @@ class Link extends ModelEntity
* OWNING SIDE
* Owning side of relation between container type 'article' and parent container
*
* @var \Shopware\Models\Newsletter\Container|null
* @var Container|null
*
* @ORM\ManyToOne(targetEntity="Shopware\Models\Newsletter\Container", inversedBy="links")
* @ORM\JoinColumn(name="parentID", referencedColumnName="id")
Expand Down Expand Up @@ -165,16 +166,16 @@ public function getTarget()
}

/**
* @param \Shopware\Models\Newsletter\Container $container
* @param Container $container
*/
public function setContainer($container)
{
$this->container = $container;
$container->setType('ctLinks');
$container->setType(Container::TYPE_LINKS);
}

/**
* @return \Shopware\Models\Newsletter\Container|null
* @return Container|null
*/
public function getContainer()
{
Expand Down
6 changes: 3 additions & 3 deletions engine/Shopware/Models/Newsletter/ContainerType/Text.php
Expand Up @@ -123,10 +123,10 @@ public function getAlignment()
}

/**
* @param Container $container
* @param string $type
* @param Container $container
* @param Container::TYPE_* $type
*/
public function setContainer($container, $type = 'ctText')
public function setContainer($container, $type = Container::TYPE_TEXT)
{
$this->container = $container;
$container->setType($type);
Expand Down
72 changes: 72 additions & 0 deletions tests/Functional/Core/MarketingTest.php
@@ -0,0 +1,72 @@
<?php

declare(strict_types=1);
/**
* Shopware 5
* Copyright (c) shopware AG
*
* According to our dual licensing model, this program can be used either
* under the terms of the GNU Affero General Public License, version 3,
* or under a proprietary license.
*
* The texts of the GNU Affero General Public License with an additional
* permission and of our proprietary license can be found at and
* in the LICENSE file you have received along with this program.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* "Shopware" is a registered trademark of shopware AG.
* The licensing of the program under the AGPLv3 does not imply a
* trademark license. Therefore any rights, title and interest in
* our trademarks remain entirely with us.
*/

namespace Shopware\Tests\Functional\Core;

use Doctrine\DBAL\Connection;
use PHPUnit\Framework\TestCase;
use Shopware\Models\Newsletter\Container;
use Shopware\Tests\Functional\Traits\ContainerTrait;
use sMarketing;

class MarketingTest extends TestCase
{
use ContainerTrait;

public function testMailCampaignsGetDetail(): void
{
$newsletterId = $this->prepareNewsletter();

$marketingModule = $this->getContainer()->get('modules')->getModule('Marketing');
static::assertInstanceOf(sMarketing::class, $marketingModule);

$newsletter = $marketingModule->sMailCampaignsGetDetail($newsletterId);
static::assertIsArray($newsletter);

static::assertSame("&lt;script&gt;alert('XSS')&lt;/script&gt;", $newsletter['containers'][0]['description']);
}

private function prepareNewsletter(): int
{
$connection = $this->getContainer()->get(Connection::class);

$connection->insert('s_campaigns_mailings', []);
$newsletterId = (int) $connection->lastInsertId();

$connection->insert('s_campaigns_containers', [
'promotionID' => $newsletterId,
'type' => Container::TYPE_TEXT,
]);
$newsletterContainerId = (int) $connection->lastInsertId();

$connection->insert('s_campaigns_html', [
'parentID' => $newsletterContainerId,
'headline' => "<script>alert('XSS')</script>",
]);

return $newsletterId;
}
}

0 comments on commit 7875855

Please sign in to comment.