Completed
Pull Request — develop (#462)
by ANTHONIUS
08:03
created

UserContext::tearDown()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 22
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 22
rs 9.2
c 1
b 0
f 0
cc 2
eloc 16
nc 2
nop 0
1
<?php
2
/**
3
 * YAWIK
4
 *
5
 * @filesource
6
 * @license MIT
7
 * @copyright  2013 - 2017 Cross Solution <http://cross-solution.de>
8
 */
9
10
namespace Yawik\Behat;
11
12
use Auth\Entity\User as User;
13
use Auth\Entity\UserInterface;
14
use Auth\Repository\User as UserRepository;
15
use Auth\Service\Register;
16
use Behat\Behat\Context\Context;
17
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
18
use Behat\Gherkin\Node\TableNode;
19
use Behat\MinkExtension\Context\MinkContext;
20
use Core\Entity\Permissions;
21
use Doctrine\Common\Util\Inflector;
22
use Doctrine\ODM\MongoDB\DocumentManager;
23
use Doctrine\ODM\MongoDB\Event\LifecycleEventArgs;
24
use Doctrine\ODM\MongoDB\Events;
25
use Organizations\Entity\Organization;
26
use Organizations\Entity\OrganizationName;
27
use Organizations\Repository\Organization as OrganizationRepository;
28
use Yawik\Behat\Exception\FailedExpectationException;
29
30
class UserContext implements Context
31
{
32
    use CommonContextTrait;
33
	
34
	/**
35
	 * @var User[]
36
	 */
37
	static private $users = [];
38
	
39
	/**
40
	 * @var UserRepository
41
	 */
42
	static private $userRepo;
43
	
44
	private $socialLoginInfo = [];
45
46
    /**
47
     * @var DocumentManager
48
     */
49
	static private $dm;
50
	
51
	/**
52
	 * @var UserInterface
53
	 */
54
	private $loggedInUser;
55
56
    /**
57
     * @var Organization
58
     */
59
	private $mainOrganization;
60
61
    /**
62
     * @var User
63
     */
64
    protected $currentUser;
65
	
66
	public function __construct($parameters=[])
67
	{
68
		$defaultLoginInfo = [
69
			'facebook' => [
70
				'email' => getenv('FACEBOOK_USER_EMAIL'),
71
				'pass' => getenv('FACEBOOK_USER_PASSWORD')
72
			],
73
			'linkedin' => [
74
				'session_key-login' => getenv('LINKEDIN_USER_EMAIL'),
75
				'session_password-login' => getenv('LINKEDIN_USER_PASSWORD')
76
			],
77
		];
78
		$socialLoginConfig = isset($parameters['social_login_info']) ? $parameters['social_login_info']:[];
79
		$this->socialLoginInfo = array_merge($defaultLoginInfo,$socialLoginConfig);
80
	}
81
82
    /**
83
     * Empty all data every each tests
84
     *
85
     * @AfterSuite
86
     */
87
	static public function tearDown()
0 ignored issues
show
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
88
    {
89
        $dm = static::$dm;
0 ignored issues
show
Bug introduced by
Since $dm is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $dm to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
90
91
        $documents = [
92
            'Applications\Entity\Application',
93
            'Cv\Entity\Cv',
94
            'Jobs\Entity\Job',
95
            'Organizations\Entity\Organization',
96
            'Auth\Entity\User',
97
            'Jobs\Entity\Category',
98
            'Auth\Entity\UserImage',
99
            'Organizations\Entity\OrganizationName',
100
        ];
101
        foreach($documents as $document){
102
            $dm->createQueryBuilder($document)
103
                ->remove()
104
                ->getQuery()
105
                ->execute()
106
            ;
107
        }
108
    }
109
110
	/**
111
	 * @BeforeScenario
112
	 * @param BeforeScenarioScope $scope
113
	 */
114
	public function beforeScenario(BeforeScenarioScope $scope)
115
	{
116
		$this->minkContext = $scope->getEnvironment()->getContext(MinkContext::class);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Behat\Testwork\Environment\Environment as the method getContext() does only exist in the following implementations of said interface: Behat\Behat\Context\Envi...lizedContextEnvironment, FriendsOfBehat\ContextSe...ntextServiceEnvironment.

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...
117
		$this->coreContext = $scope->getEnvironment()->getContext(CoreContext::class);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Behat\Testwork\Environment\Environment as the method getContext() does only exist in the following implementations of said interface: Behat\Behat\Context\Envi...lizedContextEnvironment, FriendsOfBehat\ContextSe...ntextServiceEnvironment.

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...
118
		static::$userRepo = $this->getUserRepository();
0 ignored issues
show
Bug introduced by
Since $userRepo is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $userRepo to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
119
		static::$dm = $this->getUserRepository()->getDocumentManager();
0 ignored issues
show
Bug introduced by
Since $dm is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $dm to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
120
	}
121
	
122
	/**
123
	 * @When I fill in login form with :provider user
124
	 */
125
	public function iSignInWithSocialUser($provider)
126
	{
127
		$provider = strtolower($provider);
128
		$mink = $this->minkContext;
129
		foreach($this->socialLoginInfo[$provider] as $field=>$value){
130
			$mink->fillField($field,$value);
131
		}
132
	}
133
	
134
	/**
135
	 * @Given I am logged in as a recruiter
136
	 * @Given I am logged in as a recruiter with :organization as organization
137
	 */
138
	public function iAmLoggedInAsARecruiter($organization=null)
139
	{
140
		$user = $this->thereIsAUserIdentifiedBy(
141
			'[email protected]',
142
			'test',User::ROLE_RECRUITER,
143
			'Test Recruiter',
144
			$organization
145
		);
146
		$this->startLogin($user,'test');
0 ignored issues
show
Bug introduced by
It seems like $user defined by $this->thereIsAUserIdent...ruiter', $organization) on line 140 can also be of type object<Core\Entity\EntityInterface>; however, Yawik\Behat\UserContext::startLogin() does only seem to accept object<Auth\Entity\UserInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
147
		if(!is_null($organization)){
148
            $this->iHaveMainOrganization($user,$organization);
0 ignored issues
show
Bug introduced by
It seems like $user defined by $this->thereIsAUserIdent...ruiter', $organization) on line 140 can also be of type object<Core\Entity\EntityInterface>; however, Yawik\Behat\UserContext::iHaveMainOrganization() does only seem to accept object<Auth\Entity\UserInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
149
        }
150
	}
151
	
152
	/**
153
	 * @Given I don't have :login user
154
	 * @param string $login
155
	 */
156
	public function iDonTHaveUser($login)
157
	{
158
		$repo = $this->getUserRepository();
159
		$user=$repo->findByLogin($login);
160
		if($user instanceof UserInterface){
161
			$repo->remove($user,true);
162
		}
163
	}
164
	
165
	/**
166
	 * @Given I have a :role with the following:
167
	 * @param $role
168
	 * @param TableNode $fields
169
	 */
170
	public function iHaveUserWithTheFollowing($role,TableNode $fields)
171
	{
172
		$normalizedFields = [
173
			'login' => '[email protected]',
174
			'fullname' => 'Test Login',
175
			'role' => User::ROLE_USER,
176
			'password' => 'test',
177
			'organization' => 'Cross Solution'
178
		];
179
		foreach($fields->getRowsHash() as $field=>$value){
180
			$field = Inflector::camelize($field);
181
			$normalizedFields[$field] = $value;
182
		}
183
		
184
		$this->thereIsAUserIdentifiedBy(
185
			$normalizedFields['login'],
186
			$normalizedFields['password'],
187
			$role,
188
			$normalizedFields['fullname'],
189
			$normalizedFields['organization']
190
		);
191
		
192
	}
193
	
194
	/**
195
	 * @Given I am logged in as an administrator
196
	 */
197
	public function iAmLoggedInAsAnAdmin()
198
	{
199
		$user = $this->thereIsAUserIdentifiedBy('[email protected]','test',User::ROLE_ADMIN);
200
		$this->startLogin($user,'test');
0 ignored issues
show
Bug introduced by
It seems like $user defined by $this->thereIsAUserIdent...ntity\User::ROLE_ADMIN) on line 199 can also be of type object<Core\Entity\EntityInterface>; however, Yawik\Behat\UserContext::startLogin() does only seem to accept object<Auth\Entity\UserInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
201
	}
202
	
203
	private function startLogin(UserInterface $user, $password)
204
	{
205
		$currentUser = $this->currentUser;
206
		if(!is_object($currentUser) || $user->getId()!=$currentUser->getId()){
207
			$this->iWantToLogIn();
208
			$this->iSpecifyTheUsernameAs($user->getLogin());
209
			$this->iSpecifyThePasswordAs($password);
210
			$this->iLogIn();
211
			$this->currentUser = $user;
0 ignored issues
show
Documentation Bug introduced by
$user is of type object<Auth\Entity\UserInterface>, but the property $currentUser was declared to be of type object<Auth\Entity\User>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
212
		}
213
	}
214
	
215
	/**
216
	 * @return UserRepository
217
	 */
218
	public function getUserRepository()
219
	{
220
		return $this->coreContext->getRepositories()->get('Auth\Entity\User');
221
	}
222
	
223
	/**
224
	 * @Given there is a user :email identified by :password
225
	 */
226
	public function thereIsAUserIdentifiedBy($email, $password,$role=User::ROLE_RECRUITER,$fullname="Test Recruiter",$organization=null)
227
	{
228
		$repo = $this->getUserRepository();
229
		if(!is_object($user=$repo->findByEmail($email))){
230
			$user = $this->createUser($email,$password,$role,$fullname,$organization);
0 ignored issues
show
Unused Code introduced by
The call to UserContext::createUser() has too many arguments starting with $organization.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
231
		}
232
		
233
		if(!is_null($organization)){
234
			$this->iHaveMainOrganization($user,$organization);
0 ignored issues
show
Bug introduced by
It seems like $user can also be of type object<Core\Entity\EntityInterface>; however, Yawik\Behat\UserContext::iHaveMainOrganization() does only seem to accept object<Auth\Entity\UserInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
235
		}
236
		$this->addCreatedUser($user);
0 ignored issues
show
Bug introduced by
It seems like $user can also be of type object<Core\Entity\EntityInterface>; however, Yawik\Behat\UserContext::addCreatedUser() does only seem to accept object<Auth\Entity\UserInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
237
		$repo->getDocumentManager()->refresh($user);
238
		return $user;
239
	}
240
	
241
	/**
242
	 * @param $email
243
	 * @param $password
244
	 * @param $username
245
	 * @param string $fullname
246
	 * @param string $role
247
	 *
248
	 * @return \Auth\Entity\UserInterface
0 ignored issues
show
Documentation introduced by
Should the return type not be \Core\Entity\EntityInterface?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
249
	 */
250
	public function createUser($email,$password,$role=User::ROLE_RECRUITER,$fullname="Test Recruiter")
251
	{
252
		/* @var Register $service */
253
		/* @var User $user */
254
		$repo = $this->getUserRepository();
255
		$user = $repo->create([]);
256
		$user->setLogin($email);
257
		$user->setPassword($password);
258
		$user->setRole($role);
259
		$settings = $user->getSettings('Applications');
0 ignored issues
show
Unused Code introduced by
$settings 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...
260
		
261
		$expFullName = explode(' ',$fullname);
262
		$info = $user->getInfo();
263
		$info->setFirstName(array_shift($expFullName));
264
		$info->setLastName(count($expFullName)>0 ? implode(' ',$expFullName):'');
265
		$info->setEmail($email);
266
		$info->setEmailVerified(true);
267
		$repo->store($user);
268
		$repo->getDocumentManager()->refresh($user);
269
		
270
		$eventArgs = new LifecycleEventArgs($user, $repo->getDocumentManager());
271
		$repo->getDocumentManager()->getEventManager()->dispatchEvent(
272
			Events::postLoad,
273
			$eventArgs
274
		);
275
		/* @var \Core\EventManager\EventManager $events */
276
		/* @var \Auth\Listener\Events\AuthEvent $event */
277
		//@TODO: [Behat] event not working in travis
278
		//$events = $this->coreContext->getEventManager();
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
279
		//$event  = $events->getEvent(AuthEvent::EVENT_USER_REGISTERED, $this);
0 ignored issues
show
Unused Code Comprehensibility introduced by
57% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
280
		//$event->setUser($user);
0 ignored issues
show
Unused Code Comprehensibility introduced by
86% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
281
		//$events->triggerEvent($event);
0 ignored issues
show
Unused Code Comprehensibility introduced by
86% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
282
		return $user;
283
	}
284
	
285
	/**
286
	 * @When I have :organization as my main organization
287
	 * @param $orgName
288
	 */
289
	public function iHaveMainOrganization(UserInterface $user,$orgName)
290
	{
291
		/* @var $repoOrganization OrganizationRepository */
292
		$repoOrganization = $this->coreContext->getRepositories()->get('Organizations/Organization');
293
		$result = $repoOrganization->findByName($orgName);
294
		$organization = count($result) > 0 ? $result[0]:null;
295 View Code Duplication
		if(!$organization instanceof Organization){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
296
			$organization = new Organization();
297
			$organizationName = new OrganizationName($orgName);
298
			$organization->setOrganizationName($organizationName);
299
		}
300
        $organization->setProfileSetting(Organization::PROFILE_ALWAYS_ENABLE);
301
        $permissions = $organization->getPermissions();
302
        $permissions->grant($user,Permissions::PERMISSION_ALL);
303
304
        $organization->setUser($user);
305
        $repoOrganization->store($organization);
306
        $repoOrganization->getDocumentManager()->refresh($organization);
307
308
        $this->mainOrganization = $organization;
309
	}
310
311
    /**
312
     * @return Organization
313
     */
314
    public function getMainOrganization()
315
    {
316
        return $this->mainOrganization;
317
    }
318
319
	
320
	/**
321
	 * @When I want to log in
322
	 */
323
	public function iWantToLogIn()
324
	{
325
		$session = $this->minkContext->getSession();
326
		$url = $this->buildUrl('lang/auth');
327
		$session->visit($url);
328
	}
329
	
330
	/**
331
	 * @When I specify the username as :username
332
	 */
333
	public function iSpecifyTheUsernameAs($username)
334
	{
335
		$this->minkContext->fillField('Login name',$username);
336
	}
337
	
338
	/**
339
	 * @When I specify the password as :password
340
	 */
341
	public function iSpecifyThePasswordAs($password)
342
	{
343
		$this->minkContext->fillField('Password',$password);
344
	}
345
	
346
	/**
347
	 * @Given I am logged in as :username identified by :password
348
	 */
349
	public function iAmLoggedInAsIdentifiedBy($username, $password)
350
	{
351
		$repo = $this->getUserRepository();
352
		$user = $repo->findByLogin($username);
353
		
354
		if(!$user instanceof User){
355
			throw new \Exception(sprintf('There is no user with this login: "%s"',$username));
356
		}
357
		$this->iWantToLogIn();
358
		$this->iSpecifyTheUsernameAs($username);
359
		$this->iSpecifyThePasswordAs($password);
360
		$this->iLogIn();
361
        $this->currentUser = $user;
362
	}
363
	
364
	/**
365
	 * @When I log in
366
	 */
367
	public function iLogIn()
368
	{
369
		$this->minkContext->pressButton('login');
370
	}
371
	
372
	/**
373
	 * @When I press logout link
374
	 */
375
	public function iPressLogoutLink()
376
	{
377
		$url = $this->buildUrl('auth-logout');
378
		$this->visit($url);
379
	}
380
	
381
	/**
382
	 * @Given I log in with username :username and password :password
383
	 */
384
	public function iLogInWith($username, $password)
385
	{
386
		$repo = $this->getUserRepository();
387
		$user = $repo->findByLogin($username);
388
		$this->iWantToLogIn();
389
		$this->iSpecifyTheUsernameAs($username);
390
		$this->iSpecifyThePasswordAs($password);
391
		$this->iLogIn();
392
		$this->loggedInUser = $user;
393
	}
394
	
395
	/**
396
	 * @When I go to profile page
397
	 */
398
	public function iGoToProfilePage()
399
	{
400
		$url = $this->buildUrl('lang/my');
401
		$this->visit($url);
402
	}
403
	
404
	/**
405
	 * @Given there is a user with the following:
406
	 */
407
	public function thereIsAUserWithTheFollowing(TableNode $table)
408
	{
409
		$repo = $this->getUserRepository();
410
		$data = $table->getRowsHash();
411
		$email = isset($data['email']) ? $data['email']:'[email protected]';
412
		$password = isset($data['password']) ? $data['password']:'test';
413
		$fullname = isset($data['fullname']) ? $data['fullname']:'Test User';
414
		$role = isset($data['role']) ? $data['role']:User::ROLE_RECRUITER;
415
		
416
		if(!is_object($user=$repo->findByLogin($email))){
417
			$user = $this->createUser($email,$password,$role,$fullname);
418
		}
419
		$this->currentUser = $user;
0 ignored issues
show
Documentation Bug introduced by
It seems like $user of type object<Core\Entity\EntityInterface> or object<Auth\Entity\UserInterface> is incompatible with the declared type object<Auth\Entity\User> of property $currentUser.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
420
		$this->addCreatedUser($user);
0 ignored issues
show
Bug introduced by
It seems like $user can also be of type object<Core\Entity\EntityInterface>; however, Yawik\Behat\UserContext::addCreatedUser() does only seem to accept object<Auth\Entity\UserInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
421
	}
422
	
423
	private function addCreatedUser(UserInterface $user)
424
	{
425
		if(!in_array($user,static::$users)){
0 ignored issues
show
Bug introduced by
Since $users is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $users to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
426
			static::$users[] = $user;
0 ignored issues
show
Bug introduced by
Since $users is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $users to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
427
		}
428
	}
429
	
430
	/**
431
	 * @When I want to change my password
432
	 */
433
	public function iWantToChangeMyPassword()
434
	{
435
		$url = $this->buildUrl('lang/my-password');
436
		$this->visit($url);
437
	}
438
439
    /**
440
     * @return User
441
     * @throws FailedExpectationException
442
     */
443
	public function getCurrentUser()
444
    {
445
        if(!$this->currentUser instanceof User){
446
            throw new FailedExpectationException('Need to login first before use this step');
447
        }
448
        return $this->currentUser;
449
    }
450
}
451
452