Completed
Push — develop ( 09456b...2094a2 )
by Mathias
14s queued 10s
created

OrganizationContext::iHaveOrganization()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 24
Code Lines 18

Duplication

Lines 7
Ratio 29.17 %

Importance

Changes 0
Metric Value
dl 7
loc 24
rs 8.9713
c 0
b 0
f 0
cc 2
eloc 18
nc 2
nop 1
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 Behat\Behat\Context\Context;
13
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
14
use Behat\Gherkin\Node\TableNode;
15
use Core\Entity\Permissions;
16
use Doctrine\Common\Util\Inflector;
17
use Organizations\Entity\Organization;
18
use Organizations\Entity\OrganizationName;
19
use Organizations\Entity\OrganizationReference;
20
use Yawik\Behat\Exception\FailedExpectationException;
21
use Organizations\Repository\Organization as OrganizationRepository;
22
use Jobs\Repository\Job as JobRepository;
23
24
/**
25
 * Class OrganizationContext
26
 *
27
 * @author  Anthonius Munthi <[email protected]>
28
 * @since   0.29
29
 * @package Yawik\Behat
30
 */
31
class OrganizationContext implements Context
32
{
33
	use CommonContextTrait;
34
35
    /**
36
     * @var JobContext
37
     */
38
	private $jobContext;
39
40
    /**
41
     * @BeforeScenario
42
     *
43
     * @param BeforeScenarioScope $scope
44
     */
45
    public function setupContext(BeforeScenarioScope $scope)
46
    {
47
        $this->jobContext = $scope->getEnvironment()->getContext(JobContext::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...
48
    }
49
50
	/**
51
	 * @Given I go to my organization page
52
	 */
53
	public function iGoToMyOrganizationPage()
54
	{
55
        $url = $this->buildUrl('lang/my-organization');
56
		$this->visit($url);
57
	}
58
	
59
	/**
60
	 * @When I hover over name form
61
	 */
62
	public function iMouseOverOrganizationNameForm()
63
	{
64
		$locator = '#sf-nameForm .sf-summary';
65
		$this->coreContext->iHoverOverTheElement($locator);
66
	}
67
	
68
	/**
69
	 * @Given I go to create new organization page
70
	 */
71
	public function iGoToCreateNewOrganizationPage()
72
	{
73
		//$this->visit('/organizations/edit');
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...
74
        $url = $this->buildUrl('lang/organizations/edit');
75
        $this->visit($url);
76
	}
77
	
78
	/**
79
	 * @Given I go to organization overview page
80
	 */
81
	public function iGoToOrganizationOverviewPage()
82
	{
83
		//$this->visit('/organizations');
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...
84
		$url = $this->buildUrl('lang/organizations');
85
		$this->visit($url);
86
	}
87
88
    /**
89
     * @Given I want to see list organization profiles
90
     */
91
	public function iWantToSeeListOrganizationProfiles()
92
    {
93
       $url = $this->buildUrl('lang/organizations/profile');
94
       $this->visit($url);
95
    }
96
97
    /**
98
     * @Given I have organization :name
99
     *
100
     * @internal param string $name
101
     * @internal param TableNode|null $table
102
     */
103
	public function iHaveOrganization($name)
104
    {
105
        $user = $this->getUserContext()->getCurrentUser();
106
        $organization = $this->findOrganizationByName($name,false);
107
        $repo = $this->getRepository('Organizations/Organization');
108 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...
109
110
            $organization = new Organization();
111
            $organizationName = new OrganizationName($name);
112
            $organization->setOrganizationName($organizationName);
113
            $organization->setIsDraft(false);
114
        }
115
        /* @var OrganizationReference $orgReference */
116
        $orgReference = $user->getOrganization();
117
        $parent = $orgReference->getOrganization();
118
        $organization->setParent($parent);
0 ignored issues
show
Bug introduced by
It seems like $parent defined by $orgReference->getOrganization() on line 117 can be null; however, Organizations\Entity\Organization::setParent() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
119
        $organization->setProfileSetting(Organization::PROFILE_ALWAYS_ENABLE);
120
        $permissions = $organization->getPermissions();
121
        $permissions->grant($user,Permissions::PERMISSION_ALL);
122
123
        $repo->store($organization);
124
        $repo->getDocumentManager()->refresh($organization);
125
        $repo->getDocumentManager()->refresh($user);
126
    }
127
128
    /**
129
     * @Given organization :name have jobs:
130
     */
131
    public function organizationHavePublishedJob($name,TableNode $table)
132
    {
133
        $user = $this->getUserContext()->getCurrentUser();
134
        if(is_null($user)){
135
            throw new FailedExpectationException('Need to login first');
136
        }
137
138
        $organization = $this->findOrganizationByName($name);
139
        foreach($table->getColumnsHash() as $index=>$definitions){
140
            $definitions['user'] = $user->getLogin();
141
            $status = isset($definitions['status']) ? $definitions['status']:'draft';
142
            unset($definitions['status']);
143
            $this->jobContext->buildJob($status,$definitions,$organization);
144
        }
145
    }
146
147
    /**
148
     * @Given profile setting for :name is :setting
149
     * @param $name
150
     * @param $setting
151
     */
152
    public function profileSetting($name,$setting)
153
    {
154
        $repo = $this->getRepository('Organizations/Organization');
155
        $organization = $this->findOrganizationByName($name);
156
157
        $organization->setProfileSetting($setting);
158
        $repo->store($organization);
159
        $repo->getDocumentManager()->refresh($organization);
160
    }
161
162
    /**
163
     * @Given I define contact for :organization organization with:
164
     * @param TableNode $table
165
     */
166
    public function iDefineContactWith($name, TableNode $table)
167
    {
168
        $organization = $this->findOrganizationByName($name);
169
        $contact = $organization->getContact();
170
171
        $definitions = $table->getRowsHash();
172
        foreach($definitions as $name=>$value){
173
            $field = Inflector::camelize($name);
174
            $method = 'set'.$field;
175
            $callback = array($contact,$method);
176
            if(is_callable($callback)){
177
                call_user_func_array($callback,[$value]);
178
            }
179
        }
180
        $this->getRepository('Organizations/Organization')->store($organization);
181
    }
182
183
    /**
184
     * @Given I go to profile page for organization :name
185
     * @Given I go to profile page for my organization
186
     * @param string $name
0 ignored issues
show
Documentation introduced by
Should the type for parameter $name not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
187
     * @throws FailedExpectationException
188
     */
189
    public function iGoToOrganizationProfilePage($name=null)
190
    {
191
        if(is_null($name)){
192
            $organization = $this->getUserContext()->getCurrentUser()->getOrganization()->getOrganization();
193
        }else{
194
            $organization = $this->findOrganizationByName($name);
195
        }
196
        $url = $this->buildUrl('lang/organizations/profileDetail',[
197
            'id' => $organization->getId()
198
        ]);
199
200
        $this->visit($url);
201
    }
202
203
    /**
204
     * @param string $name
205
     * @return Organization
206
     * @throws FailedExpectationException
207
     */
208
    public function findOrganizationByName($name, $throwException = true)
209
    {
210
        /* @var OrganizationRepository $repo */
211
        $repo = $this->getRepository('Organizations/Organization');
212
        $result = $repo->findByName($name);
213
        $organization = count($result) > 0 ? $result[0]:null;
214
        if(!$organization instanceof Organization && $throwException){
215
            throw new FailedExpectationException(
216
                sprintf('Organization %s is not found.',$name)
217
            );
218
        }
219
        return $organization;
220
    }
221
222
    /**
223
     * @Given organization :name have no job
224
     *
225
     * @param string $name
226
     */
227
    public function organizationHaveNoJob($name)
228
    {
229
        $org = $this->findOrganizationByName($name);
230
231
        /* @var JobRepository $jobRepo */
232
        $jobRepo = $this->getRepository('Jobs/Job');
233
        $result = $jobRepo->findByOrganization($org->getId());
234
235
        foreach($result as $job){
236
            $jobRepo->remove($job,true);
237
        }
238
    }
239
240
    /**
241
     * @Given I want to edit my organization
242
     */
243
    public function iWantToEditMyOrganization()
244
    {
245
        $user = $this->getUserContext()->getCurrentUser();
246
        $organization = $user->getOrganization()->getOrganization();
247
        $url = $this->buildUrl('lang/organizations/edit',['id' => $organization->getId()]);
248
        $this->visit($url);
249
    }
250
251
    /**
252
     * @Given I attach logo from file :file
253
     * @param $file
254
     */
255
    public function iAttachLogoFromFile($file)
256
    {
257
        $elementId = 'organizationLogo-original';
258
        $this->minkContext->attachFileToField($elementId,$file);
259
    }
260
261
    /**
262
     * @Given I remove logo from organization
263
     */
264
    public function iRemoveLogoFromOrganization()
265
    {
266
        $elementId = '#organizationLogo-original-delete';
267
        $element = $this->minkContext->getSession()->getPage()->find('css',$elementId);
268
        $element->click();
269
    }
270
}
271