Completed
Push — master ( 4ffab1...137f58 )
by Aimeos
07:59
created

StandardTest::testEditProductAttributes()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 43
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 43
rs 8.8571
cc 2
eloc 27
nc 2
nop 0
1
<?php
2
3
namespace Aimeos\Controller\Frontend\Basket;
4
5
6
/**
7
 * @copyright Metaways Infosystems GmbH, 2012
8
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
9
 * @copyright Aimeos (aimeos.org), 2015
10
 */
11
class StandardTest extends \PHPUnit_Framework_TestCase
12
{
13
	private $object;
14
	private $context;
15
	private $testItem;
16
17
18
	protected function setUp()
19
	{
20
		$this->context = \TestHelperFrontend::getContext();
21
		$this->testItem = \Aimeos\MShop\Factory::createManager( $this->context, 'product' )->findItem( 'U:TESTP' );
1 ignored issue
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Aimeos\MShop\Common\Manager\Iface as the method findItem() does only exist in the following implementations of said interface: Aimeos\MShop\Attribute\Manager\Lists\Type\Standard, Aimeos\MShop\Attribute\Manager\Standard, Aimeos\MShop\Attribute\Manager\Type\Standard, Aimeos\MShop\Catalog\Manager\Decorator\Base, Aimeos\MShop\Catalog\Manager\Decorator\Sitecheck, Aimeos\MShop\Catalog\Manager\Lists\Type\Standard, Aimeos\MShop\Catalog\Manager\Standard, Aimeos\MShop\Common\Manager\Decorator\Base, Aimeos\MShop\Common\Manager\Decorator\Changelog, Aimeos\MShop\Common\Manager\Decorator\Sitecheck, Aimeos\MShop\Common\Manager\Type\Base, Aimeos\MShop\Coupon\Manager\Code\Standard, Aimeos\MShop\Customer\Manager\Base, Aimeos\MShop\Customer\Manager\Group\Standard, Aimeos\MShop\Customer\Manager\Lists\Type\Standard, Aimeos\MShop\Customer\Manager\Standard, Aimeos\MShop\Locale\Manager\Site\Standard, Aimeos\MShop\Media\Manager\Lists\Type\Standard, Aimeos\MShop\Media\Manager\Type\Standard, Aimeos\MShop\Plugin\Manager\Type\Standard, Aimeos\MShop\Price\Manager\Lists\Type\Standard, Aimeos\MShop\Price\Manager\Type\Standard, Aimeos\MShop\Product\Manager\Lists\Type\Standard, Aimeos\MShop\Product\Man...\Property\Type\Standard, Aimeos\MShop\Product\Manager\Standard, Aimeos\MShop\Product\Man...tock\Warehouse\Standard, Aimeos\MShop\Product\Manager\Type\Standard, Aimeos\MShop\Service\Manager\Lists\Type\Standard, Aimeos\MShop\Service\Manager\Standard, Aimeos\MShop\Service\Manager\Type\Standard, Aimeos\MShop\Supplier\Manager\Lists\Type\Standard, Aimeos\MShop\Supplier\Manager\Standard, Aimeos\MShop\Tag\Manager\Type\Standard, Aimeos\MShop\Text\Manager\Lists\Type\Standard, Aimeos\MShop\Text\Manager\Type\Standard.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
22
23
		$this->object = new \Aimeos\Controller\Frontend\Basket\Standard( $this->context );
24
	}
25
26
27
	protected function tearDown()
28
	{
29
		$this->object->clear();
30
		$this->context->getSession()->set( 'aimeos', array() );
31
32
		unset( $this->object, $this->testItem );
33
	}
34
35
36
	public function testAddDeleteProduct()
37
	{
38
		$basket = $this->object->get();
39
40
41
		$this->object->addProduct( $this->testItem->getId(), 2 );
42
43
		$this->assertEquals( 1, count( $basket->getProducts() ) );
44
		$this->assertEquals( 2, $basket->getProduct( 0 )->getQuantity() );
45
		$this->assertEquals( 'U:TESTPSUB01', $basket->getProduct( 0 )->getProductCode() );
46
47
48
		$item = \Aimeos\MShop\Factory::createManager( $this->context, 'product' )->findItem( 'CNC' );
1 ignored issue
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Aimeos\MShop\Common\Manager\Iface as the method findItem() does only exist in the following implementations of said interface: Aimeos\MShop\Attribute\Manager\Lists\Type\Standard, Aimeos\MShop\Attribute\Manager\Standard, Aimeos\MShop\Attribute\Manager\Type\Standard, Aimeos\MShop\Catalog\Manager\Decorator\Base, Aimeos\MShop\Catalog\Manager\Decorator\Sitecheck, Aimeos\MShop\Catalog\Manager\Lists\Type\Standard, Aimeos\MShop\Catalog\Manager\Standard, Aimeos\MShop\Common\Manager\Decorator\Base, Aimeos\MShop\Common\Manager\Decorator\Changelog, Aimeos\MShop\Common\Manager\Decorator\Sitecheck, Aimeos\MShop\Common\Manager\Type\Base, Aimeos\MShop\Coupon\Manager\Code\Standard, Aimeos\MShop\Customer\Manager\Base, Aimeos\MShop\Customer\Manager\Group\Standard, Aimeos\MShop\Customer\Manager\Lists\Type\Standard, Aimeos\MShop\Customer\Manager\Standard, Aimeos\MShop\Locale\Manager\Site\Standard, Aimeos\MShop\Media\Manager\Lists\Type\Standard, Aimeos\MShop\Media\Manager\Type\Standard, Aimeos\MShop\Plugin\Manager\Type\Standard, Aimeos\MShop\Price\Manager\Lists\Type\Standard, Aimeos\MShop\Price\Manager\Type\Standard, Aimeos\MShop\Product\Manager\Lists\Type\Standard, Aimeos\MShop\Product\Man...\Property\Type\Standard, Aimeos\MShop\Product\Manager\Standard, Aimeos\MShop\Product\Man...tock\Warehouse\Standard, Aimeos\MShop\Product\Manager\Type\Standard, Aimeos\MShop\Service\Manager\Lists\Type\Standard, Aimeos\MShop\Service\Manager\Standard, Aimeos\MShop\Service\Manager\Type\Standard, Aimeos\MShop\Supplier\Manager\Lists\Type\Standard, Aimeos\MShop\Supplier\Manager\Standard, Aimeos\MShop\Tag\Manager\Type\Standard, Aimeos\MShop\Text\Manager\Lists\Type\Standard, Aimeos\MShop\Text\Manager\Type\Standard.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
49
50
		$this->object->addProduct( $item->getId(), 2, array(), array(), array(), array(), array(), 'default' );
51
		$item2 = $this->object->get()->getProduct( 1 );
52
		$this->object->deleteProduct( 0 );
53
54
		$this->assertEquals( 1, count( $basket->getProducts() ) );
55
		$this->assertEquals( $item2, $basket->getProduct( 1 ) );
56
		$this->assertEquals( 'CNC', $basket->getProduct( 1 )->getProductCode() );
57
	}
58
59
60
	public function testAddProductBundle()
61
	{
62
		$item = \Aimeos\MShop\Factory::createManager( $this->context, 'product' )->findItem( 'U:BUNDLE' );
1 ignored issue
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Aimeos\MShop\Common\Manager\Iface as the method findItem() does only exist in the following implementations of said interface: Aimeos\MShop\Attribute\Manager\Lists\Type\Standard, Aimeos\MShop\Attribute\Manager\Standard, Aimeos\MShop\Attribute\Manager\Type\Standard, Aimeos\MShop\Catalog\Manager\Decorator\Base, Aimeos\MShop\Catalog\Manager\Decorator\Sitecheck, Aimeos\MShop\Catalog\Manager\Lists\Type\Standard, Aimeos\MShop\Catalog\Manager\Standard, Aimeos\MShop\Common\Manager\Decorator\Base, Aimeos\MShop\Common\Manager\Decorator\Changelog, Aimeos\MShop\Common\Manager\Decorator\Sitecheck, Aimeos\MShop\Common\Manager\Type\Base, Aimeos\MShop\Coupon\Manager\Code\Standard, Aimeos\MShop\Customer\Manager\Base, Aimeos\MShop\Customer\Manager\Group\Standard, Aimeos\MShop\Customer\Manager\Lists\Type\Standard, Aimeos\MShop\Customer\Manager\Standard, Aimeos\MShop\Locale\Manager\Site\Standard, Aimeos\MShop\Media\Manager\Lists\Type\Standard, Aimeos\MShop\Media\Manager\Type\Standard, Aimeos\MShop\Plugin\Manager\Type\Standard, Aimeos\MShop\Price\Manager\Lists\Type\Standard, Aimeos\MShop\Price\Manager\Type\Standard, Aimeos\MShop\Product\Manager\Lists\Type\Standard, Aimeos\MShop\Product\Man...\Property\Type\Standard, Aimeos\MShop\Product\Manager\Standard, Aimeos\MShop\Product\Man...tock\Warehouse\Standard, Aimeos\MShop\Product\Manager\Type\Standard, Aimeos\MShop\Service\Manager\Lists\Type\Standard, Aimeos\MShop\Service\Manager\Standard, Aimeos\MShop\Service\Manager\Type\Standard, Aimeos\MShop\Supplier\Manager\Lists\Type\Standard, Aimeos\MShop\Supplier\Manager\Standard, Aimeos\MShop\Tag\Manager\Type\Standard, Aimeos\MShop\Text\Manager\Lists\Type\Standard, Aimeos\MShop\Text\Manager\Type\Standard.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
63
64
		$this->object->addProduct( $item->getId(), 1 );
65
66
		$this->assertEquals( 1, count( $this->object->get()->getProducts() ) );
67
		$this->assertEquals( 'U:BUNDLE', $this->object->get()->getProduct( 0 )->getProductCode() );
68
		$this->assertEquals( 2, count( $this->object->get()->getProduct( 0 )->getProducts() ) );
69
	}
70
71
72
	public function testAddProductVariant()
73
	{
74
		$attributeManager = \Aimeos\MShop\Attribute\Manager\Factory::createManager( \TestHelperFrontend::getContext() );
75
76
		$search = $attributeManager->createSearch();
77
		$search->setConditions( $search->compare( '==', 'attribute.code', array( 'xs', 'white' ) ) );
78
79
		$attributes = $attributeManager->searchItems( $search );
80
81
		if( count( $attributes ) === 0 ) {
82
			throw new \Exception( 'Attributes not found' );
83
		}
84
85
86
		$item = \Aimeos\MShop\Factory::createManager( $this->context, 'product' )->findItem( 'CNC' );
1 ignored issue
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Aimeos\MShop\Common\Manager\Iface as the method findItem() does only exist in the following implementations of said interface: Aimeos\MShop\Attribute\Manager\Lists\Type\Standard, Aimeos\MShop\Attribute\Manager\Standard, Aimeos\MShop\Attribute\Manager\Type\Standard, Aimeos\MShop\Catalog\Manager\Decorator\Base, Aimeos\MShop\Catalog\Manager\Decorator\Sitecheck, Aimeos\MShop\Catalog\Manager\Lists\Type\Standard, Aimeos\MShop\Catalog\Manager\Standard, Aimeos\MShop\Common\Manager\Decorator\Base, Aimeos\MShop\Common\Manager\Decorator\Changelog, Aimeos\MShop\Common\Manager\Decorator\Sitecheck, Aimeos\MShop\Common\Manager\Type\Base, Aimeos\MShop\Coupon\Manager\Code\Standard, Aimeos\MShop\Customer\Manager\Base, Aimeos\MShop\Customer\Manager\Group\Standard, Aimeos\MShop\Customer\Manager\Lists\Type\Standard, Aimeos\MShop\Customer\Manager\Standard, Aimeos\MShop\Locale\Manager\Site\Standard, Aimeos\MShop\Media\Manager\Lists\Type\Standard, Aimeos\MShop\Media\Manager\Type\Standard, Aimeos\MShop\Plugin\Manager\Type\Standard, Aimeos\MShop\Price\Manager\Lists\Type\Standard, Aimeos\MShop\Price\Manager\Type\Standard, Aimeos\MShop\Product\Manager\Lists\Type\Standard, Aimeos\MShop\Product\Man...\Property\Type\Standard, Aimeos\MShop\Product\Manager\Standard, Aimeos\MShop\Product\Man...tock\Warehouse\Standard, Aimeos\MShop\Product\Manager\Type\Standard, Aimeos\MShop\Service\Manager\Lists\Type\Standard, Aimeos\MShop\Service\Manager\Standard, Aimeos\MShop\Service\Manager\Type\Standard, Aimeos\MShop\Supplier\Manager\Lists\Type\Standard, Aimeos\MShop\Supplier\Manager\Standard, Aimeos\MShop\Tag\Manager\Type\Standard, Aimeos\MShop\Text\Manager\Lists\Type\Standard, Aimeos\MShop\Text\Manager\Type\Standard.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
87
88
		$this->object->addProduct( $item->getId(), 1, array(), array_keys( $attributes ), array(), array(), array(), 'default' );
89
90
		$this->assertEquals( 1, count( $this->object->get()->getProducts() ) );
91
		$this->assertEquals( 'CNC', $this->object->get()->getProduct( 0 )->getProductCode() );
92
	}
93
94
95
	public function testAddProductVariantIncomplete()
96
	{
97
		$attributeManager = \Aimeos\MShop\Factory::createManager( $this->context, 'attribute' );
98
99
		$search = $attributeManager->createSearch();
100
		$expr = array(
101
			$search->compare( '==', 'attribute.domain', 'product' ),
102
			$search->compare( '==', 'attribute.code', '30' ),
103
			$search->compare( '==', 'attribute.type.code', 'length' ),
104
		);
105
		$search->setConditions( $search->combine( '&&', $expr ) );
106
107
		$attributes = $attributeManager->searchItems( $search );
108
109
		if( count( $attributes ) === 0 ) {
110
			throw new \Exception( 'Attributes not found' );
111
		}
112
113
114
		$item = \Aimeos\MShop\Factory::createManager( $this->context, 'product' )->findItem( 'U:TEST' );
1 ignored issue
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Aimeos\MShop\Common\Manager\Iface as the method findItem() does only exist in the following implementations of said interface: Aimeos\MShop\Attribute\Manager\Lists\Type\Standard, Aimeos\MShop\Attribute\Manager\Standard, Aimeos\MShop\Attribute\Manager\Type\Standard, Aimeos\MShop\Catalog\Manager\Decorator\Base, Aimeos\MShop\Catalog\Manager\Decorator\Sitecheck, Aimeos\MShop\Catalog\Manager\Lists\Type\Standard, Aimeos\MShop\Catalog\Manager\Standard, Aimeos\MShop\Common\Manager\Decorator\Base, Aimeos\MShop\Common\Manager\Decorator\Changelog, Aimeos\MShop\Common\Manager\Decorator\Sitecheck, Aimeos\MShop\Common\Manager\Type\Base, Aimeos\MShop\Coupon\Manager\Code\Standard, Aimeos\MShop\Customer\Manager\Base, Aimeos\MShop\Customer\Manager\Group\Standard, Aimeos\MShop\Customer\Manager\Lists\Type\Standard, Aimeos\MShop\Customer\Manager\Standard, Aimeos\MShop\Locale\Manager\Site\Standard, Aimeos\MShop\Media\Manager\Lists\Type\Standard, Aimeos\MShop\Media\Manager\Type\Standard, Aimeos\MShop\Plugin\Manager\Type\Standard, Aimeos\MShop\Price\Manager\Lists\Type\Standard, Aimeos\MShop\Price\Manager\Type\Standard, Aimeos\MShop\Product\Manager\Lists\Type\Standard, Aimeos\MShop\Product\Man...\Property\Type\Standard, Aimeos\MShop\Product\Manager\Standard, Aimeos\MShop\Product\Man...tock\Warehouse\Standard, Aimeos\MShop\Product\Manager\Type\Standard, Aimeos\MShop\Service\Manager\Lists\Type\Standard, Aimeos\MShop\Service\Manager\Standard, Aimeos\MShop\Service\Manager\Type\Standard, Aimeos\MShop\Supplier\Manager\Lists\Type\Standard, Aimeos\MShop\Supplier\Manager\Standard, Aimeos\MShop\Tag\Manager\Type\Standard, Aimeos\MShop\Text\Manager\Lists\Type\Standard, Aimeos\MShop\Text\Manager\Type\Standard.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
115
116
		$this->object->addProduct( $item->getId(), 1, array(), array_keys( $attributes ) );
117
118
		$this->assertEquals( 1, count( $this->object->get()->getProducts() ) );
119
		$this->assertEquals( 'U:TESTSUB02', $this->object->get()->getProduct( 0 )->getProductCode() );
120
		$this->assertEquals( 2, count( $this->object->get()->getProduct( 0 )->getAttributes() ) );
121
	}
122
123
124
	public function testAddProductVariantNonUnique()
125
	{
126
		$attributeManager = \Aimeos\MShop\Factory::createManager( $this->context, 'attribute' );
127
128
		$search = $attributeManager->createSearch();
129
		$expr = array(
130
			$search->compare( '==', 'attribute.domain', 'product' ),
131
			$search->compare( '==', 'attribute.code', '30' ),
132
			$search->compare( '==', 'attribute.type.code', 'width' ),
133
		);
134
		$search->setConditions( $search->combine( '&&', $expr ) );
135
136
		$attributes = $attributeManager->searchItems( $search );
137
138
		if( count( $attributes ) === 0 ) {
139
			throw new \Exception( 'Attributes not found' );
140
		}
141
142
143
		$item = \Aimeos\MShop\Factory::createManager( $this->context, 'product' )->findItem( 'U:TEST' );
1 ignored issue
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Aimeos\MShop\Common\Manager\Iface as the method findItem() does only exist in the following implementations of said interface: Aimeos\MShop\Attribute\Manager\Lists\Type\Standard, Aimeos\MShop\Attribute\Manager\Standard, Aimeos\MShop\Attribute\Manager\Type\Standard, Aimeos\MShop\Catalog\Manager\Decorator\Base, Aimeos\MShop\Catalog\Manager\Decorator\Sitecheck, Aimeos\MShop\Catalog\Manager\Lists\Type\Standard, Aimeos\MShop\Catalog\Manager\Standard, Aimeos\MShop\Common\Manager\Decorator\Base, Aimeos\MShop\Common\Manager\Decorator\Changelog, Aimeos\MShop\Common\Manager\Decorator\Sitecheck, Aimeos\MShop\Common\Manager\Type\Base, Aimeos\MShop\Coupon\Manager\Code\Standard, Aimeos\MShop\Customer\Manager\Base, Aimeos\MShop\Customer\Manager\Group\Standard, Aimeos\MShop\Customer\Manager\Lists\Type\Standard, Aimeos\MShop\Customer\Manager\Standard, Aimeos\MShop\Locale\Manager\Site\Standard, Aimeos\MShop\Media\Manager\Lists\Type\Standard, Aimeos\MShop\Media\Manager\Type\Standard, Aimeos\MShop\Plugin\Manager\Type\Standard, Aimeos\MShop\Price\Manager\Lists\Type\Standard, Aimeos\MShop\Price\Manager\Type\Standard, Aimeos\MShop\Product\Manager\Lists\Type\Standard, Aimeos\MShop\Product\Man...\Property\Type\Standard, Aimeos\MShop\Product\Manager\Standard, Aimeos\MShop\Product\Man...tock\Warehouse\Standard, Aimeos\MShop\Product\Manager\Type\Standard, Aimeos\MShop\Service\Manager\Lists\Type\Standard, Aimeos\MShop\Service\Manager\Standard, Aimeos\MShop\Service\Manager\Type\Standard, Aimeos\MShop\Supplier\Manager\Lists\Type\Standard, Aimeos\MShop\Supplier\Manager\Standard, Aimeos\MShop\Tag\Manager\Type\Standard, Aimeos\MShop\Text\Manager\Lists\Type\Standard, Aimeos\MShop\Text\Manager\Type\Standard.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
144
145
		$this->setExpectedException( '\\Aimeos\\Controller\\Frontend\\Basket\\Exception' );
146
		$this->object->addProduct( $item->getId(), 1, array(), array_keys( $attributes ) );
147
	}
148
149
150
	public function testAddProductVariantNotRequired()
151
	{
152
		$attributeManager = \Aimeos\MShop\Factory::createManager( $this->context, 'attribute' );
153
154
		$search = $attributeManager->createSearch();
155
		$search->setConditions( $search->compare( '==', 'attribute.code', 'xs' ) );
156
157
		$attributes = $attributeManager->searchItems( $search );
158
159
		if( count( $attributes ) === 0 ) {
160
			throw new \Exception( 'Attribute not found' );
161
		}
162
163
		$options = array( 'variant' => false );
164
165
		$this->object->addProduct( $this->testItem->getId(), 1, $options, array_keys( $attributes ) );
166
167
		$this->assertEquals( 1, count( $this->object->get()->getProducts() ) );
168
		$this->assertEquals( 'U:TESTP', $this->object->get()->getProduct( 0 )->getProductCode() );
169
	}
170
171
172
	public function testAddProductConfigAttribute()
173
	{
174
		$attributeManager = \Aimeos\MShop\Factory::createManager( $this->context, 'attribute' );
175
176
		$search = $attributeManager->createSearch();
177
		$search->setConditions( $search->compare( '==', 'attribute.code', 'xs' ) );
178
179
		$attributes = $attributeManager->searchItems( $search );
180
181
		if( empty( $attributes ) ) {
182
			throw new \Exception( 'Attribute not found' );
183
		}
184
185
		$this->object->addProduct( $this->testItem->getId(), 1, array(), array(), array_keys( $attributes ) );
186
		$basket = $this->object->get();
187
188
		$this->assertEquals( 1, count( $basket->getProducts() ) );
189
		$this->assertEquals( 'U:TESTPSUB01', $basket->getProduct( 0 )->getProductCode() );
190
		$this->assertEquals( 'xs', $basket->getProduct( 0 )->getAttribute( 'size', 'config' ) );
191
	}
192
193
194
	public function testAddProductHiddenAttribute()
195
	{
196
		$attributeManager = \Aimeos\MShop\Factory::createManager( $this->context, 'attribute' );
197
198
		$search = $attributeManager->createSearch();
199
		$expr = array(
200
			$search->compare( '==', 'attribute.code', '29' ),
201
			$search->compare( '==', 'attribute.type.code', 'width' ),
202
		);
203
		$search->setConditions( $search->combine( '&&', $expr ) );
204
205
		$attributes = $attributeManager->searchItems( $search );
206
207
		if( empty( $attributes ) ) {
208
			throw new \Exception( 'Attribute not found' );
209
		}
210
211
		$this->object->addProduct( $this->testItem->getId(), 1, array(), array(), array(), array_keys( $attributes ) );
212
213
		$basket = $this->object->get();
214
		$this->assertEquals( 1, count( $basket->getProducts() ) );
215
216
		$product = $basket->getProduct( 0 );
217
		$this->assertEquals( 'U:TESTPSUB01', $product->getProductCode() );
218
219
		$attributes = $product->getAttributes();
220
		$this->assertEquals( 1, count( $attributes ) );
221
222
		if( ( $attribute = reset( $attributes ) ) === false ) {
223
			throw new \Exception( 'No attribute' );
224
		}
225
226
		$this->assertEquals( 'hidden', $attribute->getType() );
227
		$this->assertEquals( '29', $product->getAttribute( 'width', 'hidden' ) );
228
	}
229
230
231
	public function testAddProductCustomAttribute()
232
	{
233
		$attributeManager = \Aimeos\MShop\Factory::createManager( $this->context, 'attribute' );
234
235
		$search = $attributeManager->createSearch();
236
		$expr = array(
237
			$search->compare( '==', 'attribute.code', 'custom' ),
238
			$search->compare( '==', 'attribute.type.code', 'date' ),
239
		);
240
		$search->setConditions( $search->combine( '&&', $expr ) );
241
242
		$attributes = $attributeManager->searchItems( $search );
243
244
		if( ( $attrItem = reset( $attributes ) ) === false ) {
245
			throw new \Exception( 'Attribute not found' );
246
		}
247
248
		$attrValues = array( $attrItem->getId() => '2000-01-01' );
249
250
		$this->object->addProduct( $this->testItem->getId(), 1, array(), array(), array(), array(), $attrValues );
251
		$basket = $this->object->get();
252
253
		$this->assertEquals( 1, count( $basket->getProducts() ) );
254
		$this->assertEquals( '2000-01-01', $basket->getProduct( 0 )->getAttribute( 'date', 'custom' ) );
255
	}
256
257
258
	public function testAddProductAttributeNotAssigned()
259
	{
260
		$attributeManager = \Aimeos\MShop\Factory::createManager( $this->context, 'attribute' );
261
262
		$search = $attributeManager->createSearch();
263
		$expr = array(
264
			$search->compare( '==', 'attribute.code', '30' ),
265
			$search->compare( '==', 'attribute.type.code', 'width' ),
266
		);
267
		$search->setConditions( $search->combine( '&&', $expr ) );
268
269
		$attribute = $attributeManager->searchItems( $search );
270
271
		if( empty( $attribute ) ) {
272
			throw new \Exception( 'Attribute not found' );
273
		}
274
275
		$hiddenAttrIds = array_keys( $attribute );
276
		$configAttrIds = array_keys( $attribute );
277
278
		$this->setExpectedException( '\\Aimeos\\Controller\\Frontend\\Basket\\Exception' );
279
		$this->object->addProduct( $this->testItem->getId(), 1, array(), array(), $configAttrIds, $hiddenAttrIds );
280
	}
281
282
283
	public function testAddProductNegativeQuantityException()
284
	{
285
		$this->setExpectedException( '\\Aimeos\\MShop\\Order\\Exception' );
286
		$this->object->addProduct( $this->testItem->getId(), -1 );
287
	}
288
289
290
	public function testAddProductNoPriceException()
291
	{
292
		$item = \Aimeos\MShop\Factory::createManager( $this->context, 'product' )->findItem( 'MNOP' );
1 ignored issue
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Aimeos\MShop\Common\Manager\Iface as the method findItem() does only exist in the following implementations of said interface: Aimeos\MShop\Attribute\Manager\Lists\Type\Standard, Aimeos\MShop\Attribute\Manager\Standard, Aimeos\MShop\Attribute\Manager\Type\Standard, Aimeos\MShop\Catalog\Manager\Decorator\Base, Aimeos\MShop\Catalog\Manager\Decorator\Sitecheck, Aimeos\MShop\Catalog\Manager\Lists\Type\Standard, Aimeos\MShop\Catalog\Manager\Standard, Aimeos\MShop\Common\Manager\Decorator\Base, Aimeos\MShop\Common\Manager\Decorator\Changelog, Aimeos\MShop\Common\Manager\Decorator\Sitecheck, Aimeos\MShop\Common\Manager\Type\Base, Aimeos\MShop\Coupon\Manager\Code\Standard, Aimeos\MShop\Customer\Manager\Base, Aimeos\MShop\Customer\Manager\Group\Standard, Aimeos\MShop\Customer\Manager\Lists\Type\Standard, Aimeos\MShop\Customer\Manager\Standard, Aimeos\MShop\Locale\Manager\Site\Standard, Aimeos\MShop\Media\Manager\Lists\Type\Standard, Aimeos\MShop\Media\Manager\Type\Standard, Aimeos\MShop\Plugin\Manager\Type\Standard, Aimeos\MShop\Price\Manager\Lists\Type\Standard, Aimeos\MShop\Price\Manager\Type\Standard, Aimeos\MShop\Product\Manager\Lists\Type\Standard, Aimeos\MShop\Product\Man...\Property\Type\Standard, Aimeos\MShop\Product\Manager\Standard, Aimeos\MShop\Product\Man...tock\Warehouse\Standard, Aimeos\MShop\Product\Manager\Type\Standard, Aimeos\MShop\Service\Manager\Lists\Type\Standard, Aimeos\MShop\Service\Manager\Standard, Aimeos\MShop\Service\Manager\Type\Standard, Aimeos\MShop\Supplier\Manager\Lists\Type\Standard, Aimeos\MShop\Supplier\Manager\Standard, Aimeos\MShop\Tag\Manager\Type\Standard, Aimeos\MShop\Text\Manager\Lists\Type\Standard, Aimeos\MShop\Text\Manager\Type\Standard.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
293
294
		$this->setExpectedException( '\\Aimeos\\MShop\\Price\\Exception' );
295
		$this->object->addProduct( $item->getId(), 1 );
296
	}
297
298
299
	public function testAddProductConfigAttributeException()
300
	{
301
		$this->setExpectedException( '\\Aimeos\\Controller\\Frontend\\Basket\\Exception' );
302
		$this->object->addProduct( $this->testItem->getId(), 1, array(), array(), array( -1 ) );
303
	}
304
305
306
	public function testAddProductEmptySelectionException()
307
	{
308
		$item = \Aimeos\MShop\Factory::createManager( $this->context, 'product' )->findItem( 'U:noSel' );
1 ignored issue
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Aimeos\MShop\Common\Manager\Iface as the method findItem() does only exist in the following implementations of said interface: Aimeos\MShop\Attribute\Manager\Lists\Type\Standard, Aimeos\MShop\Attribute\Manager\Standard, Aimeos\MShop\Attribute\Manager\Type\Standard, Aimeos\MShop\Catalog\Manager\Decorator\Base, Aimeos\MShop\Catalog\Manager\Decorator\Sitecheck, Aimeos\MShop\Catalog\Manager\Lists\Type\Standard, Aimeos\MShop\Catalog\Manager\Standard, Aimeos\MShop\Common\Manager\Decorator\Base, Aimeos\MShop\Common\Manager\Decorator\Changelog, Aimeos\MShop\Common\Manager\Decorator\Sitecheck, Aimeos\MShop\Common\Manager\Type\Base, Aimeos\MShop\Coupon\Manager\Code\Standard, Aimeos\MShop\Customer\Manager\Base, Aimeos\MShop\Customer\Manager\Group\Standard, Aimeos\MShop\Customer\Manager\Lists\Type\Standard, Aimeos\MShop\Customer\Manager\Standard, Aimeos\MShop\Locale\Manager\Site\Standard, Aimeos\MShop\Media\Manager\Lists\Type\Standard, Aimeos\MShop\Media\Manager\Type\Standard, Aimeos\MShop\Plugin\Manager\Type\Standard, Aimeos\MShop\Price\Manager\Lists\Type\Standard, Aimeos\MShop\Price\Manager\Type\Standard, Aimeos\MShop\Product\Manager\Lists\Type\Standard, Aimeos\MShop\Product\Man...\Property\Type\Standard, Aimeos\MShop\Product\Manager\Standard, Aimeos\MShop\Product\Man...tock\Warehouse\Standard, Aimeos\MShop\Product\Manager\Type\Standard, Aimeos\MShop\Service\Manager\Lists\Type\Standard, Aimeos\MShop\Service\Manager\Standard, Aimeos\MShop\Service\Manager\Type\Standard, Aimeos\MShop\Supplier\Manager\Lists\Type\Standard, Aimeos\MShop\Supplier\Manager\Standard, Aimeos\MShop\Tag\Manager\Type\Standard, Aimeos\MShop\Text\Manager\Lists\Type\Standard, Aimeos\MShop\Text\Manager\Type\Standard.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
309
310
		$this->setExpectedException( '\\Aimeos\\Controller\\Frontend\\Basket\\Exception' );
311
		$this->object->addProduct( $item->getId(), 1 );
312
	}
313
314
315
	public function testAddProductSelectionWithPricelessItem()
316
	{
317
		$item = \Aimeos\MShop\Factory::createManager( $this->context, 'product' )->findItem( 'U:TESTPSUB01' );
1 ignored issue
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Aimeos\MShop\Common\Manager\Iface as the method findItem() does only exist in the following implementations of said interface: Aimeos\MShop\Attribute\Manager\Lists\Type\Standard, Aimeos\MShop\Attribute\Manager\Standard, Aimeos\MShop\Attribute\Manager\Type\Standard, Aimeos\MShop\Catalog\Manager\Decorator\Base, Aimeos\MShop\Catalog\Manager\Decorator\Sitecheck, Aimeos\MShop\Catalog\Manager\Lists\Type\Standard, Aimeos\MShop\Catalog\Manager\Standard, Aimeos\MShop\Common\Manager\Decorator\Base, Aimeos\MShop\Common\Manager\Decorator\Changelog, Aimeos\MShop\Common\Manager\Decorator\Sitecheck, Aimeos\MShop\Common\Manager\Type\Base, Aimeos\MShop\Coupon\Manager\Code\Standard, Aimeos\MShop\Customer\Manager\Base, Aimeos\MShop\Customer\Manager\Group\Standard, Aimeos\MShop\Customer\Manager\Lists\Type\Standard, Aimeos\MShop\Customer\Manager\Standard, Aimeos\MShop\Locale\Manager\Site\Standard, Aimeos\MShop\Media\Manager\Lists\Type\Standard, Aimeos\MShop\Media\Manager\Type\Standard, Aimeos\MShop\Plugin\Manager\Type\Standard, Aimeos\MShop\Price\Manager\Lists\Type\Standard, Aimeos\MShop\Price\Manager\Type\Standard, Aimeos\MShop\Product\Manager\Lists\Type\Standard, Aimeos\MShop\Product\Man...\Property\Type\Standard, Aimeos\MShop\Product\Manager\Standard, Aimeos\MShop\Product\Man...tock\Warehouse\Standard, Aimeos\MShop\Product\Manager\Type\Standard, Aimeos\MShop\Service\Manager\Lists\Type\Standard, Aimeos\MShop\Service\Manager\Standard, Aimeos\MShop\Service\Manager\Type\Standard, Aimeos\MShop\Supplier\Manager\Lists\Type\Standard, Aimeos\MShop\Supplier\Manager\Standard, Aimeos\MShop\Tag\Manager\Type\Standard, Aimeos\MShop\Text\Manager\Lists\Type\Standard, Aimeos\MShop\Text\Manager\Type\Standard.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
Unused Code introduced by
$item is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
318
319
		$this->object->addProduct( $this->testItem->getId(), 1 );
320
321
		$this->assertEquals( 'U:TESTPSUB01', $this->object->get()->getProduct( 0 )->getProductCode() );
322
	}
323
324
325
	public function testAddProductLowQuantityPriceException()
326
	{
327
		$item = \Aimeos\MShop\Factory::createManager( $this->context, 'product' )->findItem( 'IJKL' );
1 ignored issue
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Aimeos\MShop\Common\Manager\Iface as the method findItem() does only exist in the following implementations of said interface: Aimeos\MShop\Attribute\Manager\Lists\Type\Standard, Aimeos\MShop\Attribute\Manager\Standard, Aimeos\MShop\Attribute\Manager\Type\Standard, Aimeos\MShop\Catalog\Manager\Decorator\Base, Aimeos\MShop\Catalog\Manager\Decorator\Sitecheck, Aimeos\MShop\Catalog\Manager\Lists\Type\Standard, Aimeos\MShop\Catalog\Manager\Standard, Aimeos\MShop\Common\Manager\Decorator\Base, Aimeos\MShop\Common\Manager\Decorator\Changelog, Aimeos\MShop\Common\Manager\Decorator\Sitecheck, Aimeos\MShop\Common\Manager\Type\Base, Aimeos\MShop\Coupon\Manager\Code\Standard, Aimeos\MShop\Customer\Manager\Base, Aimeos\MShop\Customer\Manager\Group\Standard, Aimeos\MShop\Customer\Manager\Lists\Type\Standard, Aimeos\MShop\Customer\Manager\Standard, Aimeos\MShop\Locale\Manager\Site\Standard, Aimeos\MShop\Media\Manager\Lists\Type\Standard, Aimeos\MShop\Media\Manager\Type\Standard, Aimeos\MShop\Plugin\Manager\Type\Standard, Aimeos\MShop\Price\Manager\Lists\Type\Standard, Aimeos\MShop\Price\Manager\Type\Standard, Aimeos\MShop\Product\Manager\Lists\Type\Standard, Aimeos\MShop\Product\Man...\Property\Type\Standard, Aimeos\MShop\Product\Manager\Standard, Aimeos\MShop\Product\Man...tock\Warehouse\Standard, Aimeos\MShop\Product\Manager\Type\Standard, Aimeos\MShop\Service\Manager\Lists\Type\Standard, Aimeos\MShop\Service\Manager\Standard, Aimeos\MShop\Service\Manager\Type\Standard, Aimeos\MShop\Supplier\Manager\Lists\Type\Standard, Aimeos\MShop\Supplier\Manager\Standard, Aimeos\MShop\Tag\Manager\Type\Standard, Aimeos\MShop\Text\Manager\Lists\Type\Standard, Aimeos\MShop\Text\Manager\Type\Standard.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
328
329
		$this->setExpectedException( '\\Aimeos\\MShop\\Price\\Exception' );
330
		$this->object->addProduct( $item->getId(), 1 );
331
	}
332
333
334
	public function testAddProductHigherQuantities()
335
	{
336
		$item = \Aimeos\MShop\Factory::createManager( $this->context, 'product' )->findItem( 'IJKL' );
1 ignored issue
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Aimeos\MShop\Common\Manager\Iface as the method findItem() does only exist in the following implementations of said interface: Aimeos\MShop\Attribute\Manager\Lists\Type\Standard, Aimeos\MShop\Attribute\Manager\Standard, Aimeos\MShop\Attribute\Manager\Type\Standard, Aimeos\MShop\Catalog\Manager\Decorator\Base, Aimeos\MShop\Catalog\Manager\Decorator\Sitecheck, Aimeos\MShop\Catalog\Manager\Lists\Type\Standard, Aimeos\MShop\Catalog\Manager\Standard, Aimeos\MShop\Common\Manager\Decorator\Base, Aimeos\MShop\Common\Manager\Decorator\Changelog, Aimeos\MShop\Common\Manager\Decorator\Sitecheck, Aimeos\MShop\Common\Manager\Type\Base, Aimeos\MShop\Coupon\Manager\Code\Standard, Aimeos\MShop\Customer\Manager\Base, Aimeos\MShop\Customer\Manager\Group\Standard, Aimeos\MShop\Customer\Manager\Lists\Type\Standard, Aimeos\MShop\Customer\Manager\Standard, Aimeos\MShop\Locale\Manager\Site\Standard, Aimeos\MShop\Media\Manager\Lists\Type\Standard, Aimeos\MShop\Media\Manager\Type\Standard, Aimeos\MShop\Plugin\Manager\Type\Standard, Aimeos\MShop\Price\Manager\Lists\Type\Standard, Aimeos\MShop\Price\Manager\Type\Standard, Aimeos\MShop\Product\Manager\Lists\Type\Standard, Aimeos\MShop\Product\Man...\Property\Type\Standard, Aimeos\MShop\Product\Manager\Standard, Aimeos\MShop\Product\Man...tock\Warehouse\Standard, Aimeos\MShop\Product\Manager\Type\Standard, Aimeos\MShop\Service\Manager\Lists\Type\Standard, Aimeos\MShop\Service\Manager\Standard, Aimeos\MShop\Service\Manager\Type\Standard, Aimeos\MShop\Supplier\Manager\Lists\Type\Standard, Aimeos\MShop\Supplier\Manager\Standard, Aimeos\MShop\Tag\Manager\Type\Standard, Aimeos\MShop\Text\Manager\Lists\Type\Standard, Aimeos\MShop\Text\Manager\Type\Standard.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
337
338
		$this->object->addProduct( $item->getId(), 2, array(), array(), array(), array(), array(), 'unit_warehouse3' );
339
340
		$this->assertEquals( 2, $this->object->get()->getProduct( 0 )->getQuantity() );
341
		$this->assertEquals( 'IJKL', $this->object->get()->getProduct( 0 )->getProductCode() );
342
	}
343
344
345
	public function testDeleteProductFlagError()
346
	{
347
		$this->object->addProduct( $this->testItem->getId(), 2 );
348
349
		$item = $this->object->get()->getProduct( 0 );
350
		$item->setFlags( \Aimeos\MShop\Order\Item\Base\Product\Base::FLAG_IMMUTABLE );
351
352
		$this->setExpectedException( '\\Aimeos\\Controller\\Frontend\\Basket\\Exception' );
353
		$this->object->deleteProduct( 0 );
354
	}
355
356
357
	public function testEditProduct()
358
	{
359
		$this->object->addProduct( $this->testItem->getId(), 1 );
360
361
		$item = $this->object->get()->getProduct( 0 );
362
		$this->assertEquals( 1, $item->getQuantity() );
363
364
		$this->object->editProduct( 0, 4 );
365
366
		$item = $this->object->get()->getProduct( 0 );
367
		$this->assertEquals( 4, $item->getQuantity() );
368
		$this->assertEquals( 'U:TESTPSUB01', $item->getProductCode() );
369
	}
370
371
372
	public function testEditProductAttributes()
373
	{
374
		$attributeManager = \Aimeos\MShop\Factory::createManager( $this->context, 'attribute' );
375
376
		$search = $attributeManager->createSearch();
377
		$conditions = array(
378
			$search->compare( '==', 'attribute.domain', 'product' ),
379
			$search->combine( '||', array(
380
				$search->combine( '&&', array(
381
					$search->compare( '==', 'attribute.code', 'xs' ),
382
					$search->compare( '==', 'attribute.type.code', 'size' ),
383
				) ),
384
				$search->combine( '&&', array(
385
					$search->compare( '==', 'attribute.code', 'white' ),
386
					$search->compare( '==', 'attribute.type.code', 'color' ),
387
				) ),
388
			) )
389
		);
390
		$search->setConditions( $search->combine( '&&', $conditions ) );
391
		$attributes = $attributeManager->searchItems( $search );
392
393
		if( ( $attribute = reset( $attributes ) ) === false ) {
394
			throw new \Exception( 'No attributes available' );
395
		}
396
397
398
		$item = \Aimeos\MShop\Factory::createManager( $this->context, 'product' )->findItem( 'U:TESTP' );
1 ignored issue
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Aimeos\MShop\Common\Manager\Iface as the method findItem() does only exist in the following implementations of said interface: Aimeos\MShop\Attribute\Manager\Lists\Type\Standard, Aimeos\MShop\Attribute\Manager\Standard, Aimeos\MShop\Attribute\Manager\Type\Standard, Aimeos\MShop\Catalog\Manager\Decorator\Base, Aimeos\MShop\Catalog\Manager\Decorator\Sitecheck, Aimeos\MShop\Catalog\Manager\Lists\Type\Standard, Aimeos\MShop\Catalog\Manager\Standard, Aimeos\MShop\Common\Manager\Decorator\Base, Aimeos\MShop\Common\Manager\Decorator\Changelog, Aimeos\MShop\Common\Manager\Decorator\Sitecheck, Aimeos\MShop\Common\Manager\Type\Base, Aimeos\MShop\Coupon\Manager\Code\Standard, Aimeos\MShop\Customer\Manager\Base, Aimeos\MShop\Customer\Manager\Group\Standard, Aimeos\MShop\Customer\Manager\Lists\Type\Standard, Aimeos\MShop\Customer\Manager\Standard, Aimeos\MShop\Locale\Manager\Site\Standard, Aimeos\MShop\Media\Manager\Lists\Type\Standard, Aimeos\MShop\Media\Manager\Type\Standard, Aimeos\MShop\Plugin\Manager\Type\Standard, Aimeos\MShop\Price\Manager\Lists\Type\Standard, Aimeos\MShop\Price\Manager\Type\Standard, Aimeos\MShop\Product\Manager\Lists\Type\Standard, Aimeos\MShop\Product\Man...\Property\Type\Standard, Aimeos\MShop\Product\Manager\Standard, Aimeos\MShop\Product\Man...tock\Warehouse\Standard, Aimeos\MShop\Product\Manager\Type\Standard, Aimeos\MShop\Service\Manager\Lists\Type\Standard, Aimeos\MShop\Service\Manager\Standard, Aimeos\MShop\Service\Manager\Type\Standard, Aimeos\MShop\Supplier\Manager\Lists\Type\Standard, Aimeos\MShop\Supplier\Manager\Standard, Aimeos\MShop\Tag\Manager\Type\Standard, Aimeos\MShop\Text\Manager\Lists\Type\Standard, Aimeos\MShop\Text\Manager\Type\Standard.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
399
400
		$this->object->addProduct( $item->getId(), 1, array(), array(), array_keys( $attributes ) );
401
		$this->object->editProduct( 0, 4 );
402
403
		$item = $this->object->get()->getProduct( 0 );
404
		$this->assertEquals( 2, count( $item->getAttributes() ) );
405
		$this->assertEquals( 4, $item->getQuantity() );
406
407
408
		$this->object->editProduct( 0, 3, array(), array( $attribute->getType() ) );
409
410
		$item = $this->object->get()->getProduct( 0 );
411
		$this->assertEquals( 3, $item->getQuantity() );
412
		$this->assertEquals( 1, count( $item->getAttributes() ) );
413
		$this->assertEquals( 'U:TESTPSUB01', $item->getProductCode() );
414
	}
415
416
417
	public function testEditProductFlagError()
418
	{
419
		$this->object->addProduct( $this->testItem->getId(), 2 );
420
421
		$item = $this->object->get()->getProduct( 0 );
422
		$item->setFlags( \Aimeos\MShop\Order\Item\Base\Product\Base::FLAG_IMMUTABLE );
423
424
		$this->setExpectedException( '\\Aimeos\\Controller\\Frontend\\Basket\\Exception' );
425
		$this->object->editProduct( 0, 4 );
426
	}
427
428
429
	public function testAddCoupon()
430
	{
431
		$this->object->addProduct( $this->testItem->getId(), 2 );
432
		$this->object->addCoupon( 'GHIJ' );
433
434
		$basket = $this->object->get();
435
436
		$this->assertEquals( 1, count( $basket->getCoupons() ) );
437
	}
438
439
440
	public function testAddCouponInvalidCode()
441
	{
442
		$this->setExpectedException( '\\Aimeos\\Controller\\Frontend\\Basket\\Exception' );
443
		$this->object->addCoupon( 'invalid' );
444
	}
445
446
447
	public function testAddCouponMissingRequirements()
448
	{
449
		$this->setExpectedException( '\\Aimeos\\Controller\\Frontend\\Basket\\Exception' );
450
		$this->object->addCoupon( 'OPQR' );
451
	}
452
453
454
	public function testDeleteCoupon()
455
	{
456
		$this->object->addProduct( $this->testItem->getId(), 2 );
457
		$this->object->addCoupon( '90AB' );
458
		$this->object->deleteCoupon( '90AB' );
459
460
		$basket = $this->object->get();
461
462
		$this->assertEquals( 0, count( $basket->getCoupons() ) );
463
	}
464
465
466
	public function testClear()
467
	{
468
		$this->object->addProduct( $this->testItem->getId(), 2 );
469
		$this->object->clear();
470
471
		$this->assertEquals( 0, count( $this->object->get()->getProducts() ) );
472
	}
473
474
475
	public function testSetAddressDelete()
476
	{
477
		$this->object->setAddress( \Aimeos\MShop\Order\Item\Base\Address\Base::TYPE_PAYMENT, null );
478
479
		$this->setExpectedException( '\Aimeos\MShop\Order\Exception' );
480
		$this->object->get()->getAddress( \Aimeos\MShop\Order\Item\Base\Address\Base::TYPE_PAYMENT );
481
	}
482
483
484
	public function testSetBillingAddressByItem()
485
	{
486
		$item = $this->getAddress( 'Example company' );
487
488
		$this->object->setAddress( \Aimeos\MShop\Order\Item\Base\Address\Base::TYPE_PAYMENT, $item );
489
490
		$address = $this->object->get()->getAddress( \Aimeos\MShop\Order\Item\Base\Address\Base::TYPE_PAYMENT );
491
		$this->assertEquals( 'Example company', $address->getCompany() );
492
	}
493
494
495
	public function testSetBillingAddressByArray()
496
	{
497
		$fixture = array(
498
			'order.base.address.company' => '<p onclick="javascript: alert(\'gotcha\');">Example company</p>',
499
			'order.base.address.vatid' => 'DE999999999',
500
			'order.base.address.title' => '<br/>Dr.',
501
			'order.base.address.salutation' => \Aimeos\MShop\Common\Item\Address\Base::SALUTATION_MR,
502
			'order.base.address.firstname' => 'firstunit',
503
			'order.base.address.lastname' => 'lastunit',
504
			'order.base.address.address1' => 'unit str.',
505
			'order.base.address.address2' => ' 166',
506
			'order.base.address.address3' => '4.OG',
507
			'order.base.address.postal' => '22769',
508
			'order.base.address.city' => 'Hamburg',
509
			'order.base.address.state' => 'Hamburg',
510
			'order.base.address.countryid' => 'de',
511
			'order.base.address.languageid' => 'de',
512
			'order.base.address.telephone' => '05554433221',
513
			'order.base.address.email' => '[email protected]',
514
			'order.base.address.telefax' => '05554433222',
515
			'order.base.address.website' => 'www.example.com',
516
			'order.base.address.flag' => 0,
517
		);
518
519
		$this->object->setAddress( \Aimeos\MShop\Order\Item\Base\Address\Base::TYPE_PAYMENT, $fixture );
520
521
		$address = $this->object->get()->getAddress( \Aimeos\MShop\Order\Item\Base\Address\Base::TYPE_PAYMENT );
522
		$this->assertEquals( 'Example company', $address->getCompany() );
523
		$this->assertEquals( 'Dr.', $address->getTitle() );
524
		$this->assertEquals( 'firstunit', $address->getFirstname() );
525
	}
526
527
528
	public function testSetBillingAddressByArrayError()
529
	{
530
		$this->setExpectedException( '\\Aimeos\\Controller\\Frontend\\Basket\\Exception' );
531
		$this->object->setAddress( \Aimeos\MShop\Order\Item\Base\Address\Base::TYPE_PAYMENT, array( 'error' => false ) );
532
	}
533
534
535
	public function testSetBillingAddressParameterError()
536
	{
537
		$this->setExpectedException( '\\Aimeos\\Controller\\Frontend\\Basket\\Exception' );
538
		$this->object->setAddress( \Aimeos\MShop\Order\Item\Base\Address\Base::TYPE_PAYMENT, 'error' );
539
	}
540
541
542
	public function testSetDeliveryAddressByItem()
543
	{
544
		$item = $this->getAddress( 'Example company' );
545
546
		$this->object->setAddress( \Aimeos\MShop\Order\Item\Base\Address\Base::TYPE_DELIVERY, $item );
547
548
		$address = $this->object->get()->getAddress( \Aimeos\MShop\Order\Item\Base\Address\Base::TYPE_DELIVERY );
549
		$this->assertEquals( 'Example company', $address->getCompany() );
550
	}
551
552
553
	public function testSetDeliveryAddressByArray()
554
	{
555
		$fixture = array(
556
			'order.base.address.company' => '<p onclick="javascript: alert(\'gotcha\');">Example company</p>',
557
			'order.base.address.vatid' => 'DE999999999',
558
			'order.base.address.title' => '<br/>Dr.',
559
			'order.base.address.salutation' => \Aimeos\MShop\Common\Item\Address\Base::SALUTATION_MR,
560
			'order.base.address.firstname' => 'firstunit',
561
			'order.base.address.lastname' => 'lastunit',
562
			'order.base.address.address1' => 'unit str.',
563
			'order.base.address.address2' => ' 166',
564
			'order.base.address.address3' => '4.OG',
565
			'order.base.address.postal' => '22769',
566
			'order.base.address.city' => 'Hamburg',
567
			'order.base.address.state' => 'Hamburg',
568
			'order.base.address.countryid' => 'de',
569
			'order.base.address.languageid' => 'de',
570
			'order.base.address.telephone' => '05554433221',
571
			'order.base.address.email' => '[email protected]',
572
			'order.base.address.telefax' => '05554433222',
573
			'order.base.address.website' => 'www.example.com',
574
			'order.base.address.flag' => 0,
575
		);
576
		$this->object->setAddress( \Aimeos\MShop\Order\Item\Base\Address\Base::TYPE_DELIVERY, $fixture );
577
578
		$address = $this->object->get()->getAddress( \Aimeos\MShop\Order\Item\Base\Address\Base::TYPE_DELIVERY );
579
		$this->assertEquals( 'Example company', $address->getCompany() );
580
		$this->assertEquals( 'Dr.', $address->getTitle() );
581
		$this->assertEquals( 'firstunit', $address->getFirstname() );
582
	}
583
584
585
	public function testSetDeliveryAddressByArrayError()
586
	{
587
		$this->setExpectedException( '\\Aimeos\\Controller\\Frontend\\Basket\\Exception' );
588
		$this->object->setAddress( \Aimeos\MShop\Order\Item\Base\Address\Base::TYPE_DELIVERY, array( 'error' => false ) );
589
	}
590
591
592
	public function testSetDeliveryAddressTypeError()
593
	{
594
		$this->setExpectedException( '\\Aimeos\\Controller\\Frontend\\Basket\\Exception' );
595
		$this->object->setAddress( \Aimeos\MShop\Order\Item\Base\Address\Base::TYPE_DELIVERY, 'error' );
596
	}
597
598
599
	public function testSetServicePayment()
600
	{
601
		$manager = \Aimeos\MShop\Factory::createManager( $this->context, 'service' );
602
		$service = $manager->findItem( 'unitpaymentcode', array(), 'service', 'payment' );
603
604
		$this->object->setService( 'payment', $service->getId(), array() );
605
		$this->assertEquals( 'unitpaymentcode', $this->object->get()->getService( 'payment' )->getCode() );
606
607
		$this->setExpectedException( '\\Aimeos\\Controller\\Frontend\\Basket\\Exception' );
608
		$this->object->setService( 'payment', $service->getId(), array( 'prepay' => true ) );
609
	}
610
611
612
	public function testSetDeliveryOption()
613
	{
614
		$manager = \Aimeos\MShop\Factory::createManager( $this->context, 'service' );
615
		$service = $manager->findItem( 'unitcode', array(), 'service', 'delivery' );
616
617
		$this->object->setService( 'delivery', $service->getId(), array() );
618
		$this->assertEquals( 'unitcode', $this->object->get()->getService( 'delivery' )->getCode() );
619
620
		$this->setExpectedException( '\\Aimeos\\Controller\\Frontend\\Basket\\Exception' );
621
		$this->object->setService( 'delivery', $service->getId(), array( 'fast shipping' => true, 'air shipping' => false ) );
622
	}
623
624
625
	public function testCheckLocale()
626
	{
627
		$manager = \Aimeos\MShop\Factory::createManager( $this->context, 'service' );
628
		$payment = $manager->findItem( 'unitpaymentcode', array(), 'service', 'payment' );
629
		$delivery = $manager->findItem( 'unitcode', array(), 'service', 'delivery' );
630
631
		$this->object->addProduct( $this->testItem->getId(), 2 );
632
		$this->object->addCoupon( 'OPQR' );
633
634
		$this->object->setService( 'payment', $payment->getId() );
635
		$this->object->setService( 'delivery', $delivery->getId() );
636
637
		$basket = $this->object->get();
638
		$price = $basket->getPrice();
639
640
		foreach( $basket->getProducts() as $product )
641
		{
642
			$this->assertEquals( 2, $product->getQuantity() );
643
			$product->getPrice()->setCurrencyId( 'CHF' );
644
		}
645
646
		$basket->getService( 'delivery' )->getPrice()->setCurrencyId( 'CHF' );
647
		$basket->getService( 'payment' )->getPrice()->setCurrencyId( 'CHF' );
648
		$basket->getLocale()->setCurrencyId( 'CHF' );
649
		$price->setCurrencyId( 'CHF' );
650
651
		$this->context->getLocale()->setCurrencyId( 'CHF' );
652
		$this->object->setAddress( \Aimeos\MShop\Order\Item\Base\Address\Base::TYPE_PAYMENT, $this->getAddress( 'Example company' ) );
653
654
		$this->context->getSession()->set( 'aimeos/basket/currency', 'CHF' );
655
		$this->context->getLocale()->setCurrencyId( 'EUR' );
656
657
		$this->context->getSession()->set( 'aimeos/basket/content-unittest-en-EUR-', null );
658
659
		$object = new \Aimeos\Controller\Frontend\Basket\Standard( $this->context );
660
		$basket = $object->get();
661
662
		foreach( $basket->getProducts() as $product )
663
		{
664
			$this->assertEquals( 'EUR', $product->getPrice()->getCurrencyId() );
665
			$this->assertEquals( 2, $product->getQuantity() );
666
		}
667
668
		$this->assertEquals( 'EUR', $basket->getService( 'payment' )->getPrice()->getCurrencyId() );
669
		$this->assertEquals( 'EUR', $basket->getService( 'delivery' )->getPrice()->getCurrencyId() );
670
		$this->assertEquals( 'EUR', $basket->getLocale()->getCurrencyId() );
671
		$this->assertEquals( 'EUR', $basket->getPrice()->getCurrencyId() );
672
	}
673
674
675
	/**
676
	 * @param string $company
677
	 */
678
	protected function getAddress( $company )
679
	{
680
		$customer = \Aimeos\MShop\Customer\Manager\Factory::createManager( \TestHelperFrontend::getContext(), 'Standard' );
681
		$addressManager = $customer->getSubManager( 'address', 'Standard' );
682
683
		$search = $addressManager->createSearch();
684
		$search->setConditions( $search->compare( '==', 'customer.address.company', $company ) );
685
		$items = $addressManager->searchItems( $search );
686
687
		if( ( $item = reset( $items ) ) === false ) {
688
			throw new \Exception( sprintf( 'No address item with company "%1$s" found', $company ) );
689
		}
690
691
		return $item;
692
	}
693
}
694