Completed
Push — master ( 82ed2a...577910 )
by Aimeos
14:13
created

LaravelTest::testSaveUpdateDeleteItem()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 59

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 59
rs 8.8945
c 0
b 0
f 0
cc 2
nc 2
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2021
6
 */
7
8
9
 namespace Aimeos\MShop\Customer\Manager\Lists;
10
11
12
class LaravelTest extends \PHPUnit\Framework\TestCase
13
{
14
	private $object;
15
	private $context;
16
	private $editor = 'ai-laravel:lib/custom';
17
18
19
	protected function setUp() : void
20
	{
21
		$this->context = \TestHelper::getContext();
22
		$this->editor = $this->context->getEditor();
23
		$manager = \Aimeos\MShop\Customer\Manager\Factory::create( $this->context, 'Laravel' );
24
		$this->object = $manager->getSubManager( 'lists', 'Laravel' );
25
	}
26
27
28
	protected function tearDown() : void
29
	{
30
		unset( $this->object, $this->context );
31
	}
32
33
34
	public function testClear()
35
	{
36
		$this->assertInstanceOf( \Aimeos\MShop\Common\Manager\Iface::class, $this->object->clear( array( -1 ) ) );
0 ignored issues
show
Documentation introduced by
array(-1) is of type array<integer,integer,{"0":"integer"}>, but the function expects a object<Aimeos\MShop\Common\Manager\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
37
	}
38
39
40
	public function testAggregate()
41
	{
42
		$search = $this->object->filter( true );
43
		$expr = array(
44
			$search->getConditions(),
45
			$search->compare( '==', 'customer.lists.editor', 'ai-laravel:lib/custom' ),
46
		);
47
		$search->setConditions( $search->and( $expr ) );
0 ignored issues
show
Documentation introduced by
$expr is of type array<integer,object<Aim...ion\\Compare\\Iface>"}>, but the function expects a array<integer,object<Aim...ression\Compare\Iface>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
48
49
		$result = $this->object->aggregate( $search, 'customer.lists.domain' )->toArray();
0 ignored issues
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 aggregate() does only exist in the following implementations of said interface: Aimeos\MShop\Attribute\Manager\Lists\Standard, Aimeos\MShop\Catalog\Manager\Lists\Standard, Aimeos\MShop\Customer\Manager\Laravel, Aimeos\MShop\Customer\Manager\Lists\Laravel, Aimeos\MShop\Customer\Manager\Lists\Standard, Aimeos\MShop\Index\Manager\Attribute\MySQL, Aimeos\MShop\Index\Manager\Attribute\PgSQL, Aimeos\MShop\Index\Manager\Attribute\SQLSrv, Aimeos\MShop\Index\Manager\Attribute\Standard, Aimeos\MShop\Index\Manager\Catalog\MySQL, Aimeos\MShop\Index\Manager\Catalog\PgSQL, Aimeos\MShop\Index\Manager\Catalog\SQLSrv, Aimeos\MShop\Index\Manager\Catalog\Standard, Aimeos\MShop\Index\Manager\MySQL, Aimeos\MShop\Index\Manager\PgSQL, Aimeos\MShop\Index\Manager\Price\MySQL, Aimeos\MShop\Index\Manager\Price\PgSQL, Aimeos\MShop\Index\Manager\Price\SQLSrv, Aimeos\MShop\Index\Manager\Price\Standard, Aimeos\MShop\Index\Manager\SQLSrv, Aimeos\MShop\Index\Manager\Standard, Aimeos\MShop\Index\Manager\Supplier\MySQL, Aimeos\MShop\Index\Manager\Supplier\PgSQL, Aimeos\MShop\Index\Manager\Supplier\SQLSrv, Aimeos\MShop\Index\Manager\Supplier\Standard, Aimeos\MShop\Index\Manager\Text\MySQL, Aimeos\MShop\Index\Manager\Text\PgSQL, Aimeos\MShop\Index\Manager\Text\SQLSrv, Aimeos\MShop\Index\Manager\Text\Standard, Aimeos\MShop\Media\Manager\Lists\Standard, Aimeos\MShop\Order\Manager\Base\Address\Standard, Aimeos\MShop\Order\Manager\Base\Coupon\Standard, Aimeos\MShop\Order\Manag...duct\Attribute\Standard, Aimeos\MShop\Order\Manager\Base\Product\Standard, Aimeos\MShop\Order\Manag...vice\Attribute\Standard, Aimeos\MShop\Order\Manager\Base\Service\Standard, Aimeos\MShop\Order\Manager\Base\Standard, Aimeos\MShop\Order\Manager\Standard, Aimeos\MShop\Order\Manager\Status\Standard, Aimeos\MShop\Price\Manager\Lists\Standard, Aimeos\MShop\Product\Manager\Lists\Standard, Aimeos\MShop\Review\Manager\Standard, Aimeos\MShop\Service\Manager\Lists\Standard, Aimeos\MShop\Subscription\Manager\Standard, Aimeos\MShop\Supplier\Manager\Lists\Standard, Aimeos\MShop\Text\Manager\Lists\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...
50
51
		$this->assertEquals( 2, count( $result ) );
52
		$this->assertArrayHasKey( 'text', $result );
53
		$this->assertEquals( 4, $result['text'] );
54
	}
55
56
57
	public function testCreateItem()
58
	{
59
		$this->assertInstanceOf( '\\Aimeos\\MShop\\Common\\Item\\Lists\\Iface', $this->object->create() );
60
	}
61
62
63
	public function testGetItem()
64
	{
65
		$search = $this->object->filter()->slice( 0, 1 );
66
67
		if( ( $item = $this->object->search( $search )->first() ) === null ) {
68
			throw new \RuntimeException( 'No item found' );
69
		}
70
71
		$this->assertEquals( $item, $this->object->get( $item->getId() ) );
72
	}
73
74
75
	public function testSaveUpdateDeleteItem()
76
	{
77
		$search = $this->object->filter()->slice( 0, 1 );
78
79
		if( ( $item = $this->object->search( $search )->first() ) === null ) {
80
			throw new \RuntimeException( 'No item found' );
81
		}
82
83
		$item->setId( null );
84
		$item->setDomain( 'unittest' );
85
		$resultSaved = $this->object->save( $item );
86
		$itemSaved = $this->object->get( $item->getId() );
87
88
		$itemExp = clone $itemSaved;
89
		$itemExp->setDomain( 'unittest2' );
90
		$resultUpd = $this->object->save( $itemExp );
91
		$itemUpd = $this->object->get( $itemExp->getId() );
92
93
		$this->object->delete( $itemSaved->getId() );
94
95
96
		$this->assertTrue( $item->getId() !== null );
97
		$this->assertEquals( $item->getId(), $itemSaved->getId() );
98
		$this->assertEquals( $item->getSiteId(), $itemSaved->getSiteId() );
99
		$this->assertEquals( $item->getParentId(), $itemSaved->getParentId() );
100
		$this->assertEquals( $item->getType(), $itemSaved->getType() );
101
		$this->assertEquals( $item->getRefId(), $itemSaved->getRefId() );
102
		$this->assertEquals( $item->getDomain(), $itemSaved->getDomain() );
103
		$this->assertEquals( $item->getDateStart(), $itemSaved->getDateStart() );
104
		$this->assertEquals( $item->getDateEnd(), $itemSaved->getDateEnd() );
105
		$this->assertEquals( $item->getPosition(), $itemSaved->getPosition() );
106
		$this->assertEquals( $this->editor, $itemSaved->getEditor() );
107
		$this->assertStringStartsWith( date( 'Y-m-d', time() ), $itemSaved->getTimeCreated() );
108
		$this->assertStringStartsWith( date( 'Y-m-d', time() ), $itemSaved->getTimeModified() );
109
110
		$this->assertEquals( $this->editor, $itemSaved->getEditor() );
111
		$this->assertRegExp( '/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/', $itemSaved->getTimeCreated() );
112
		$this->assertRegExp( '/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/', $itemSaved->getTimeModified() );
113
114
		$this->assertEquals( $itemExp->getId(), $itemUpd->getId() );
115
		$this->assertEquals( $itemExp->getSiteId(), $itemUpd->getSiteId() );
116
		$this->assertEquals( $itemExp->getParentId(), $itemUpd->getParentId() );
117
		$this->assertEquals( $itemExp->getType(), $itemUpd->getType() );
118
		$this->assertEquals( $itemExp->getRefId(), $itemUpd->getRefId() );
119
		$this->assertEquals( $itemExp->getDomain(), $itemUpd->getDomain() );
120
		$this->assertEquals( $itemExp->getDateStart(), $itemUpd->getDateStart() );
121
		$this->assertEquals( $itemExp->getDateEnd(), $itemUpd->getDateEnd() );
122
		$this->assertEquals( $itemExp->getPosition(), $itemUpd->getPosition() );
123
124
		$this->assertEquals( $this->editor, $itemUpd->getEditor() );
125
		$this->assertEquals( $itemExp->getTimeCreated(), $itemUpd->getTimeCreated() );
126
		$this->assertRegExp( '/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/', $itemUpd->getTimeModified() );
127
128
		$this->assertInstanceOf( \Aimeos\MShop\Common\Item\Iface::class, $resultSaved );
129
		$this->assertInstanceOf( \Aimeos\MShop\Common\Item\Iface::class, $resultUpd );
130
131
		$this->expectException( '\\Aimeos\\MShop\\Exception' );
132
		$this->object->get( $itemSaved->getId() );
133
	}
134
135
136
	public function testSearchItems()
137
	{
138
		$total = 0;
139
		$search = $this->object->filter();
140
141
		$expr = [];
142
		$expr[] = $search->compare( '!=', 'customer.lists.id', null );
143
		$expr[] = $search->compare( '!=', 'customer.lists.siteid', null );
144
		$expr[] = $search->compare( '!=', 'customer.lists.parentid', null );
145
		$expr[] = $search->compare( '!=', 'customer.lists.key', null );
146
		$expr[] = $search->compare( '==', 'customer.lists.domain', 'text' );
147
		$expr[] = $search->compare( '==', 'customer.lists.type', 'default' );
148
		$expr[] = $search->compare( '>', 'customer.lists.refid', 0 );
149
		$expr[] = $search->compare( '==', 'customer.lists.datestart', '2010-01-01 00:00:00' );
150
		$expr[] = $search->compare( '==', 'customer.lists.dateend', '2098-01-01 00:00:00' );
151
		$expr[] = $search->compare( '!=', 'customer.lists.config', null );
152
		$expr[] = $search->compare( '>', 'customer.lists.position', 0 );
153
		$expr[] = $search->compare( '==', 'customer.lists.status', 1 );
154
		$expr[] = $search->compare( '>=', 'customer.lists.mtime', '1970-01-01 00:00:00' );
155
		$expr[] = $search->compare( '>=', 'customer.lists.ctime', '1970-01-01 00:00:00' );
156
		$expr[] = $search->compare( '==', 'customer.lists.editor', $this->editor );
157
158
		$search->setConditions( $search->and( $expr ) );
159
		$search->slice( 0, 2 );
160
		$results = $this->object->search( $search, [], $total );
161
		$this->assertEquals( 2, count( $results ) );
162
		$this->assertEquals( 3, $total );
163
164
		foreach( $results as $itemId => $item ) {
165
			$this->assertEquals( $itemId, $item->getId() );
166
		}
167
	}
168
169
170
	public function testSearchItemsAll()
171
	{
172
		//search without base criteria
173
		$search = $this->object->filter();
174
		$search->setConditions( $search->compare( '==', 'customer.lists.editor', $this->editor ) );
175
		$result = $this->object->search( $search );
176
		$this->assertEquals( 5, count( $result ) );
177
	}
178
179
180
	public function testSearchItemsBase()
181
	{
182
		//search with base criteria
183
		$search = $this->object->filter( true );
184
		$conditions = array(
185
			$search->compare( '==', 'customer.lists.editor', $this->editor ),
186
			$search->getConditions()
187
		);
188
		$search->setConditions( $search->and( $conditions ) );
0 ignored issues
show
Documentation introduced by
$conditions is of type array<integer,object<Aim...ression\\Iface>|null"}>, but the function expects a array<integer,object<Aim...ression\Compare\Iface>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
189
		$this->assertEquals( 5, count( $this->object->search( $search ) ) );
190
	}
191
192
193
	public function testGetSubManager()
194
	{
195
		$this->assertInstanceOf( '\\Aimeos\\MShop\\Common\\Manager\\Iface', $this->object->getSubManager( 'type' ) );
196
		$this->assertInstanceOf( '\\Aimeos\\MShop\\Common\\Manager\\Iface', $this->object->getSubManager( 'type', 'Standard' ) );
197
198
		$this->expectException( '\\Aimeos\\MShop\\Exception' );
199
		$this->object->getSubManager( 'unknown' );
200
	}
201
}
202