Passed
Push — develop ( 28c299...928e2a )
by Mathias
12:40
created

JobContext   B

Complexity

Total Complexity 49

Size/Duplication

Total Lines 333
Duplicated Lines 6.01 %

Coupling/Cohesion

Components 1
Dependencies 12

Importance

Changes 0
Metric Value
wmc 49
lcom 1
cbo 12
dl 20
loc 333
rs 8.48
c 0
b 0
f 0

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like JobContext often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use JobContext, and based on these observations, apply Extract Interface, too.

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\Status;
13
use Auth\Entity\User;
14
use Behat\Behat\Context\Context;
15
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
16
use Behat\Gherkin\Node\TableNode;
17
use Core\Entity\Permissions;
18
use Doctrine\Common\Util\Inflector;
19
use Documents\UserRepository;
20
use Geo\Service\Photon;
21
use Jobs\Entity\Classifications;
22
use Jobs\Entity\Job;
23
use Jobs\Entity\Location;
24
use Jobs\Entity\StatusInterface;
25
use Jobs\Repository\Categories as CategoriesRepo;
26
use Jobs\Repository\Job as JobRepository;
27
use Zend\Json\Json;
28
29
/**
30
 * Class JobContext
31
 *
32
 * @author Anthonius Munthi <[email protected]>
33
 * @package Yawik\Behat
34
 */
35
class JobContext implements Context
36
{
37
	use CommonContextTrait;
38
	
39
	/**
40
	 * @var Select2Context
41
	 */
42
	private $select2Context;
43
	
44
	/**
45
	 * @var Job
46
	 */
47
	private $currentJob;
48
	
49
	/**
50
	 * @var JobRepository
51
	 */
52
	static private $jobRepo;
53
	
54
	/**
55
	 * @param User $user
56
	 */
57
	static public function removeJobByUser(User $user)
58
	{
59
		$repo = static::$jobRepo;
60
		$results = $repo->findBy(['user' => $user]);
61
		foreach($results as $result){
62
			$repo->remove($result,true);
63
		}
64
	}
65
	
66
	/**
67
	 * @BeforeScenario
68
	 *
69
	 * @param BeforeScenarioScope $scope
70
	 */
71
	public function beforeScenario(BeforeScenarioScope $scope)
72
	{
73
		$this->select2Context = $scope->getEnvironment()->getContext(Select2Context::class);
74
		if(is_null(static::$jobRepo)){
75
			$this->gatherContexts($scope);
76
			static::$jobRepo = $this->getJobRepository();
77
		}
78
	}
79
	
80
	/**
81
	 * @Given I go to job board page
82
	 */
83
	public function iGoToJobBoardPage()
84
	{
85
		$this->visit('/jobboard');
86
	}
87
	
88
	/**
89
	 * @Given I go to create job page
90
	 */
91
	public function iGoToCreateJob()
92
	{
93
	    $url = $this->buildUrl('lang/jobs/manage',['action' => 'edit']);
94
		$this->visit($url);
95
	}
96
	
97
	/**
98
	 * @Given I go to job overview page
99
	 */
100
	public function iGoToJobOverviewPage()
101
	{
102
		$this->visit('/jobs');
103
	}
104
	
105
	/**
106
	 * @Given I go to edit job draft with title :jobTitle
107
	 * @param $jobTitle
108
	 * @throws \Exception when job is not found
109
	 */
110
	public function iGoToEditJobWithTitle($jobTitle)
111
	{
112
		$job = $this->getJobRepository()->findOneBy(['title' => $jobTitle]);
113
		if(!$job instanceof Job){
114
			throw new \Exception(sprintf('Job with title "%s" is not found',$jobTitle));
115
		}
116
		$this->currentJob = $job;
117
		$url = $this->buildUrl('lang/jobs/manage',[
118
		    'id' => $job->getId()
119
        ]);
120
		$this->visit($url);
121
	}
122
	
123
	/**
124
	 * @Given I don't have any classification data
125
	 */
126
	public function iDonTHaveAnyClassificationData()
127
	{
128
		$this->currentJob->setClassifications(new Classifications());
129
		$this->getJobRepository()->store($this->currentJob);
130
	}
131
	
132
	/**
133
	 * @When I don't have any posted job
134
	 */
135
	public function iDonTHaveAnyPostedJob()
136
	{
137
		/* @var $jobRepository JobRepository */
138
		/* @var $job Job */
139
		$user = $this->getUserContext()->getCurrentUser();
140
141
		$jobRepository = $this->getJobRepository();
142
		$results = $jobRepository->getUserJobs($user->getId());
143
		foreach($results as $job){
144
			$jobRepository->remove($job,true);
145
		}
146
		$this->currentJob = null;
147
	}
148
	
149
	/**
150
	 * @When I fill job location search with :search and choose :choice
151
	 *
152
	 */
153
	public function iFillJobLocationAndChoose($search,$choice)
154
	{
155
		$select2 = $this->select2Context;
156
		$select2->iFillInSelect2FieldWith('jobBase[geoLocation]',$search,$choice);
157
	}
158
	
159
	/**
160
	 * @When I choose :value from :field
161
	 */
162
	public function iJobClassificationSelect($value,$field)
163
	{
164
		$field = Inflector::camelize($field);
165
		
166
		$mapSelect2 = [
167
			'professions' => '#classifications-professions-span .select2-container',
168
			'industries'  => '#classifications-industries-span .select2-container',
169
			'employmentTypes' => '#classifications-employmentTypes-span .select2-container',
170
		];
171
		
172
		$mapMultiple = [
173
			'professions'       => "select#classifications-professions",
174
			'industries'        => "select#classifications-industries",
175
			'employmentTypes'    => "select#classifications-employmentTypes",
176
		];
177
		
178
		if(!isset($mapSelect2[$field])){
179
			throw new \Exception('Undefined field selection value "'.$field.'"');
180
		}
181
		
182
		$multipleField = $mapMultiple[$field];
183
		$page = $this->minkContext->getSession()->getPage();
184
		$element = $page->find('css',$mapMultiple[$field]);
185
		if(!is_null($element) && $element->getAttribute('multiple')=='multiple'){
186
			$this->minkContext->selectOption($value,$multipleField);
187
		}else{
188
			$locator = $mapSelect2[$field];
189
			$this->select2Context->iFillInSelect2Field($locator,$value);
190
		}
191
	}
192
	
193
	/**
194
	 * @return JobRepository
195
	 */
196
	public function getJobRepository()
197
	{
198
		return $this->getRepository('Jobs/Job');
199
	}
200
	
201
	/**
202
	 * @return CategoriesRepo
203
	 */
204
	public function getCategoriesRepository()
205
	{
206
		return $this->getRepository('Jobs/Category');
207
	}
208
	
209
	/**
210
	 * @When I have a :status job with the following:
211
	 * @param TableNode $fields
212
	 */
213
	public function iHaveAJobWithTheFollowing($status,TableNode $fields)
214
	{
215
		$this->buildJob($status,$fields->getRowsHash());
216
	}
217
218
	public function buildJob($status, $definitions,$organization = null)
219
    {
220
        $normalizedField = [
221
            'template' => 'modern',
222
        ];
223
        foreach($definitions as $field => $value){
224
            $field = Inflector::camelize($field);
225
            if($field == 'professions' || $field == 'industries'){
226
                $value = explode(',',$value);
227
            }
228
            $normalizedField[$field] = $value;
229
        }
230
231
        $jobRepo = $this->getJobRepository();
232
        $job = $jobRepo->findOneBy([
233
            'title' => $normalizedField['title']
234
        ]);
235
        if(!$job instanceof Job){
236
            $job = new Job();
237
            $job->setTitle($normalizedField['title']);
238
        }
239
240
        if(isset($normalizedField['user'])){
241
            /* @var $userRepo UserRepository */
242
            $userRepo = $this->getRepository('Auth\Entity\User');
243
            $user = $userRepo->findOneBy(['login' => $normalizedField['user']]);
244
            if(is_null($organization)){
245
                $organization = $user->getOrganization()->getOrganization();
246
            }
247
            if($user instanceof User){
248
                $job->setUser($user);
249
                $job->setOrganization($organization);
250
            }else{
251
                throw new \Exception('There is no user with this login:"'.$normalizedField['user'.'"']);
252
            }
253
        }
254
255
        if($status == 'draft'){
256
            $job->setIsDraft(true);
257
        }elseif($status == 'published'){
258
            $job->setIsDraft(false);
259
            $job->setDatePublishStart(new \DateTime());
260
        }
261
        $job->setStatus(Status::ACTIVE);
262
263
        if(isset($normalizedField['location'])){
264
            $this->setLocation($job,$normalizedField['location']);
265
        }
266
        if(isset($normalizedField['professions'])){
267
            $this->addProfessions($job,$normalizedField['professions']);
268
        }
269
270
        if(isset($normalizedField['industries'])){
271
            $this->addIndustries($job,$normalizedField['industries']);
272
        }
273
        if(isset($normalizedField['employmentTypes'])){
274
            $types = $this->getCategories([$normalizedField['employmentTypes']]);
275
            $type = array_shift($types);
276
            $values = $job->getClassifications()->getEmploymentTypes()->getValues();
277
            if(!is_array($values) || !in_array($type,$values)){
278
                $job->getClassifications()->getEmploymentTypes()->getItems()->add($type);
279
            }
280
        }
281
282
        $jobRepo->store($job);
283
        $this->currentJob = $job;
284
    }
285
286
	
287
	private function setLocation(Job $job, $term)
288
	{
289
		/* @var $client Photon */
290
		$client = $this->coreContext->getServiceManager()->get('Geo/Client');
291
		$result = $client->queryOne($term);
292
		$location = new Location();
293
		$serialized = Json::encode($result);
294
		$location->fromString($serialized);
295
		
296
		$locations = $job->getLocations();
297
		if(count($locations)){
298
			$locations->clear();
299
		}
300
		$job->getLocations()->add($location);
301
	}
302
	
303
	private function addProfessions(Job &$job,$terms)
304
	{
305
		$professions = $this->getCategories($terms);
306
		foreach($professions as $profession){
307
			$values = $job->getClassifications()->getProfessions()->getValues();
308
			if(!is_array($values) || !in_array($profession,$values)){
309
				$job->getClassifications()->getProfessions()->getItems()->add($profession);
310
			}
311
		}
312
	}
313
	
314
	private function addIndustries(Job &$job, $terms)
315
	{
316
		$industries = $this->getCategories($terms);
317
		foreach($industries as $industry){
318
			$values = $job->getClassifications()->getIndustries()->getValues();
319
			if(!is_array($values) || !in_array($industry,$values)){
320
				$job->getClassifications()->getIndustries()->getItems()->add($industry);
321
			}
322
		}
323
	}
324
	
325
	/**
326
	 * @param array $categories
327
	 *
328
	 * @return mixed
329
	 */
330
	private function getCategories(array $categories)
331
	{
332
		$catRepo = $this->getCategoriesRepository();
333
		
334
		// get a professions
335
		$qb = $catRepo->createQueryBuilder()
336
		              ->field('name')->in($categories)
337
		              ->getQuery()
338
		;
339
		$results = $qb->execute();
340
		return $results->toArray();
341
	}
342
	
343
	
344
	/**
345
	 * @return Job
346
	 */
347
	private function getCurrentUserJobDraft($jobTitle)
348
	{
349
		$repo = $this->getJobRepository();
350
		$user = $this->getCurrentUser();
351
		
352
		$job = $repo->findDraft($user);
353
		
354
		if(is_null($job)){
355
			$job = new Job();
356
			$job
357
				->setUser($user)
358
				->setOrganization($user->getOrganization()->getOrganization())
359
				->setStatus(StatusInterface::CREATED)
360
			;
361
			$job->setIsDraft(true);
362
		}
363
		$job->setTitle($jobTitle);
364
		$repo->store($job);
365
		return $job;
366
	}
367
}
368