Job   C
last analyzed

Complexity

Total Complexity 66

Size/Duplication

Total Lines 848
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 8

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 66
lcom 2
cbo 8
dl 0
loc 848
ccs 207
cts 207
cp 1
rs 5
c 0
b 0
f 0

53 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A getCity() 0 7 1
A getCompanyDescription() 0 6 1
A getCompanyEmail() 0 6 1
A getCompanyLogo() 0 6 1
A getCompanyName() 0 6 1
A getCompanyUrl() 0 6 1
A getCoreSchemaTypes() 0 4 1
A getCountry() 0 7 1
A getHiringOrganization() 0 8 2
A getJobLocation() 0 8 2
A getLatitude() 0 4 1
A getLinkedDataSchemaTypes() 0 4 1
A getLocation() 0 4 1
A getLongitude() 0 4 1
A getMinimumSalary() 0 4 1
A getPostalCode() 0 7 1
A getQuery() 0 4 1
A getSource() 0 4 1
A getSourceId() 0 4 1
A getState() 0 7 1
A getStreetAddress() 0 7 1
A getTelephone() 0 6 1
A jsonSerialize() 0 4 1
A setBaseSalary() 0 10 2
A setCity() 0 4 1
A setCompany() 0 6 1
A setCompanyDescription() 0 8 1
A setCompanyEmail() 0 8 1
A setCompanyLogo() 0 8 1
A setCompanyName() 0 8 1
A setCompanyUrl() 0 8 1
A setCountry() 0 4 1
A setDatePostedAsString() 0 12 2
A setLatitude() 0 10 1
A setLocation() 0 6 1
A setLongitude() 0 10 1
A setMinimumSalary() 0 6 1
A setOccupationalCategoryWithCodeAndTitle() 0 8 3
A setPostalCode() 0 4 1
A setQuery() 0 6 1
A setSource() 0 6 1
A setSourceId() 0 6 1
A setState() 0 4 1
A setStreetAddress() 0 8 2
A setTelephone() 0 10 1
A toJson() 0 4 1
A convertCurrency() 0 10 2
A getOrCreateHiringOrganization() 0 10 2
A getOrCreateJobLocation() 0 12 2
A getOrCreatePostalAddress() 0 10 2
A updateAddressAttribute() 0 20 2
A __get() 0 12 2

How to fix   Complexity   

Complex Class

Complex classes like Job 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 Job, and based on these observations, apply Extract Interface, too.

1
<?php namespace JobApis\Jobs\Client;
2
3
use \DateTime;
4
use \JsonSerializable;
5
use JobApis\Jobs\Client\Exceptions\InvalidFormatException;
6
use JobApis\Jobs\Client\Schema\Entity\GeoCoordinates;
7
use JobApis\Jobs\Client\Schema\Entity\JobPosting;
8
use JobApis\Jobs\Client\Schema\Entity\Organization;
9
use JobApis\Jobs\Client\Schema\Entity\Place;
10
use JobApis\Jobs\Client\Schema\Entity\PostalAddress;
11
12
class Job extends JobPosting implements JsonSerializable
13
{
14
    use AttributeTrait, JsonLinkedDataTrait;
15
16
    const SERIALIZE_STANDARD = "serialize-standard";
17
18
    const SERIALIZE_STANDARD_LD = "serialize-standard-ld";
19
20
    const SERIALIZE_CORE_SCHEMA_LD = "serialize-core-schema-ld";
21
22
    /**
23
     * Job Company
24
     *
25
     * @var string
26
     */
27
    protected $company;
28
29
    /**
30
     * Job End Date
31
     *
32
     * @var string
33
     */
34
    protected $endDate;
35
36
    /**
37
     * Job Industry
38
     *
39
     * @var string
40
     */
41
    protected $industry;
42
43
    /**
44
     * Javascript Action
45
     *
46
     * @var string
47
     */
48
    protected $javascriptAction;
49
50
    /**
51
     * Javascript Function
52
     *
53
     * @var string
54
     */
55
    protected $javascriptFunction;
56
57
    /**
58
     * Job Location
59
     *
60
     * @var string
61
     */
62
    protected $location;
63
64
    /**
65
     * Job Maximum Salary
66
     *
67
     * @var string
68
     */
69
    protected $maximumSalary;
70
71
    /**
72
     * Job Minimum Salary
73
     *
74
     * @var string
75
     */
76
    protected $minimumSalary;
77
78
    /**
79
     * Job Query
80
     *
81
     * @var string
82
     */
83
    protected $query;
84
85
    /**
86
     * Job Source
87
     *
88
     * @var string
89
     */
90
    protected $source;
91
92
    /**
93
     * Job Id
94
     *
95
     * @var string
96
     */
97
    protected $sourceId;
98
99
    /**
100
     * Job Start Date
101
     *
102
     * @var string
103
     */
104
    protected $startDate;
105
106
    /**
107
     * Create new job
108
     *
109
     * @param array $attributes
110
     */
111
    public function __construct($attributes = [])
112
    {
113 106
        array_walk($attributes, function ($value, $key) {
114 16
            $this->{$key} = $value;
115 106
        });
116 106
    }
117
118
    /**
119
     * Magic method to get protected property, if exists
120
     *
121
     * @param  string $name
122
     *
123
     * @return mixed
124
     * @throws \OutOfRangeException
125
     */
126 48
    public function __get($name)
127
    {
128 48
        if (!property_exists($this, $name)) {
129 2
            throw new \OutOfRangeException(sprintf(
130 2
                '%s does not contain a property by the name of "%s"',
131 2
                __CLASS__,
132
                $name
133 2
            ));
134
        }
135
136 46
        return $this->{$name};
137
    }
138
139
    // Getters
140
141
    /**
142
     * Get city
143
     *
144
     * @return string
145
     */
146 4
    public function getCity()
147
    {
148 4
        $location = $this->getOrCreateJobLocation();
149
150 4
        return $this->getOrCreatePostalAddress($location)
151 4
            ->getAddressLocality();
152
    }
153
154
    /**
155
     * Get hiring organization description
156
     *
157
     * @return string
158
     */
159 4
    public function getCompanyDescription()
160
    {
161 4
        $company = $this->getOrCreateHiringOrganization();
162
163 4
        return $company->getDescription();
164
    }
165
166
    /**
167
     * Get hiring organization email
168
     *
169
     * @return string
170
     */
171 4
    public function getCompanyEmail()
172
    {
173 4
        $company = $this->getOrCreateHiringOrganization();
174
175 4
        return $company->getEmail();
176
    }
177
178
    /**
179
     * Get hiring organization logo
180
     *
181
     * @return string
182
     */
183 4
    public function getCompanyLogo()
184
    {
185 4
        $company = $this->getOrCreateHiringOrganization();
186
187 4
        return $company->getLogo();
188
    }
189
190
    /**
191
     * Get hiring organization name
192
     *
193
     * @return string
194
     */
195 6
    public function getCompanyName()
196
    {
197 6
        $company = $this->getOrCreateHiringOrganization();
198
199 6
        return $company->getName();
200
    }
201
202
    /**
203
     * Get hiring organization url
204
     *
205
     * @return string
206
     */
207 4
    public function getCompanyUrl()
208
    {
209 4
        $company = $this->getOrCreateHiringOrganization();
210
211 4
        return $company->getUrl();
212
    }
213
214
    /**
215
     * Get core schema types
216
     *
217
     * @return array
218
     */
219 8
    public function getCoreSchemaTypes()
220
    {
221 8
        return [self::SERIALIZE_CORE_SCHEMA_LD];
222
    }
223
224
    /**
225
     * Get country
226
     *
227
     * @return string
228
     */
229 4
    public function getCountry()
230
    {
231 4
        $location = $this->getOrCreateJobLocation();
232
233 4
        return $this->getOrCreatePostalAddress($location)
234 4
            ->getAddressCountry();
235
    }
236
237
    /**
238
     * Gets hiringOrganization.
239
     *
240
     * @return Organization
241
     */
242 34
    public function getHiringOrganization($parent = false)
243
    {
244 34
        if ($parent) {
245 34
            return parent::getHiringOrganization();
246
        }
247
248 14
        return $this->getOrCreateHiringOrganization();
249
    }
250
251
    /**
252
     * Gets jobLocation.
253
     *
254
     * @return Place
255
     */
256 18
    public function getJobLocation($parent = false)
257
    {
258 18
        if ($parent) {
259 18
            return parent::getJobLocation();
260
        }
261
262 16
        return $this->getOrCreateJobLocation();
263
    }
264
265
    /**
266
     * Gets latitude.
267
     *
268
     * @return string
269
     */
270 2
    public function getLatitude()
271
    {
272 2
        return $this->getJobLocation()->getGeo()->getLatitude();
273
    }
274
275
    /**
276
     * Get linked data schema types
277
     *
278
     * @return array
279
     */
280 8
    public function getLinkedDataSchemaTypes()
281
    {
282 8
        return [self::SERIALIZE_STANDARD_LD, self::SERIALIZE_CORE_SCHEMA_LD];
283
    }
284
285
    /**
286
     * Get location
287
     *
288
     * @return string
289
     */
290 2
    public function getLocation()
291
    {
292 2
        return $this->location;
293
    }
294
295
    /**
296
     * Gets longitude.
297
     *
298
     * @return string
299
     */
300 2
    public function getLongitude()
301
    {
302 2
        return $this->getJobLocation()->getGeo()->getLongitude();
303
    }
304
305
    /**
306
     * Get minimum salary
307
     *
308
     * @return float
309
     */
310 2
    public function getMinimumSalary()
311
    {
312 2
        return $this->minimumSalary;
313
    }
314
315
    /**
316
     * Get postal code
317
     *
318
     * @return string
319
     */
320 4
    public function getPostalCode()
321
    {
322 4
        $location = $this->getOrCreateJobLocation();
323
324 4
        return $this->getOrCreatePostalAddress($location)
325 4
            ->getPostalCode();
326
    }
327
328
    /**
329
     * Gets query.
330
     *
331
     * @return string
332
     */
333 2
    public function getQuery()
334
    {
335 2
        return $this->query;
336
    }
337
338
    /**
339
     * Gets source.
340
     *
341
     * @return string
342
     */
343 2
    public function getSource()
344
    {
345 2
        return $this->source;
346
    }
347
348
    /**
349
     * Gets sourceId.
350
     *
351
     * @return string
352
     */
353 4
    public function getSourceId()
354
    {
355 4
        return $this->sourceId;
356
    }
357
358
    /**
359
     * Get state
360
     *
361
     * @return string
362
     */
363 4
    public function getState()
364
    {
365 4
        $location = $this->getOrCreateJobLocation();
366
367 4
        return $this->getOrCreatePostalAddress($location)
368 4
            ->getAddressRegion();
369
    }
370
371
    /**
372
     * Get street address
373
     *
374
     * @return string
375
     */
376 6
    public function getStreetAddress()
377
    {
378 6
        $location = $this->getOrCreateJobLocation();
379
380 6
        return $this->getOrCreatePostalAddress($location)
381 6
            ->getStreetAddress();
382
    }
383
384
    /**
385
     * Get telephone
386
     *
387
     * @return string
388
     */
389 4
    public function getTelephone()
390
    {
391 4
        $location = $this->getOrCreateJobLocation();
392
393 4
        return $location->getTelephone();
394
    }
395
396
    /**
397
     * Allow class to be serialized with json_encode
398
     *
399
     * @param  string $serializeSetting
400
     *
401
     * @return array
402
     */
403 8
    public function jsonSerialize($serializeSetting = self::SERIALIZE_STANDARD)
404
    {
405 8
        return $this->serialize($serializeSetting);
406
    }
407
408
    // Setters
409
410
    /**
411
     * Sets baseSalary.
412
     *
413
     * @param float $baseSalary
414
     *
415
     * @return $this
416
     */
417 14
    public function setBaseSalary($baseSalary)
418
    {
419 14
        $baseSalary = $this->convertCurrency($baseSalary);
420
421 14
        if ($baseSalary) {
422 12
            parent::setBaseSalary($baseSalary);
423 12
        }
424
425 14
        return $this;
426
    }
427
428
    /**
429
     * Set city
430
     *
431
     * @param string $city
432
     *
433
     * @return $this
434
     */
435 2
    public function setCity($city)
436
    {
437 2
        return $this->updateAddressAttribute('addressLocality', $city);
438
    }
439
440
    /**
441
     * Set company (simple)
442
     *
443
     * @param string $company
444
     *
445
     * @return $this
446
     */
447 6
    public function setCompany($company)
448
    {
449 6
        $this->company = $company;
450
451 6
        return $this->setCompanyName($company);
452
    }
453
454
    /**
455
     * Set hiring organization description
456
     *
457
     * @param string $description
458
     *
459
     * @return $this
460
     */
461 2
    public function setCompanyDescription($description)
462
    {
463 2
        $company = $this->getOrCreateHiringOrganization();
464
465 2
        $company->setDescription($description);
466
467 2
        return $this->setHiringOrganization($company);
468
    }
469
470
    /**
471
     * Set hiring organization email
472
     *
473
     * @param string $email
474
     *
475
     * @return $this
476
     */
477 2
    public function setCompanyEmail($email)
478
    {
479 2
        $company = $this->getOrCreateHiringOrganization();
480
481 2
        $company->setEmail($email);
482
483 2
        return $this->setHiringOrganization($company);
484
    }
485
486
    /**
487
     * Set hiring organization logo url
488
     *
489
     * @param string $logo (image url)
490
     *
491
     * @return $this
492
     */
493 2
    public function setCompanyLogo($logo)
494
    {
495 2
        $company = $this->getOrCreateHiringOrganization();
496
497 2
        $company->setLogo($logo);
498
499 2
        return $this->setHiringOrganization($company);
500
    }
501
502
    /**
503
     * Set hiring organization name
504
     *
505
     * @param string $companyName
506
     *
507
     * @return $this
508
     */
509 10
    public function setCompanyName($companyName)
510
    {
511 10
        $company = $this->getOrCreateHiringOrganization();
512
513 10
        $company->setName($companyName);
514
515 10
        return $this->setHiringOrganization($company);
516
    }
517
518
    /**
519
     * Set hiring organization url
520
     *
521
     * @param string $url
522
     *
523
     * @return $this
524
     */
525 2
    public function setCompanyUrl($url)
526
    {
527 2
        $company = $this->getOrCreateHiringOrganization();
528
529 2
        $company->setUrl($url);
530
531 2
        return $this->setHiringOrganization($company);
532
    }
533
534
    /**
535
     * Set country
536
     *
537
     * @param string $country
538
     *
539
     * @return $this
540
     */
541 2
    public function setCountry($country)
542
    {
543 2
        return $this->updateAddressAttribute('addressCountry', $country);
544
    }
545
546
    /**
547
     * Sets datePosted.
548
     *
549
     * @param string $datePosted
550
     *
551
     * @return $this
552
     */
553 8
    public function setDatePostedAsString($datePosted)
554
    {
555 8
        if (strtotime($datePosted) !== false) {
556 6
            $datePosted = new DateTime($datePosted);
557
558 6
            $this->setDatePosted($datePosted);
559 6
        } else {
560 2
            throw new InvalidFormatException;
561
        }
562
563 6
        return $this;
564
    }
565
566
    /**
567
     * Set latitude.
568
     *
569
     * @param string $latitude
570
     *
571
     * @return $this
572
     */
573 2
    public function setLatitude($latitude)
574
    {
575 2
        $location = $this->getOrCreateJobLocation();
576 2
        $geo = $location->getGeo();
577 2
        $geo->setLatitude($latitude);
578 2
        $location->setGeo($geo);
579 2
        $this->setJobLocation($location);
580
581 2
        return $this;
582
    }
583
584
    /**
585
     * Set location
586
     *
587
     * @param string $location
588
     *
589
     * @return $this
590
     */
591 2
    public function setLocation($location)
592
    {
593 2
        $this->location = $location;
594
595 2
        return $this;
596
    }
597
598
    /**
599
     * Set longitude.
600
     *
601
     * @param string $longitude
602
     *
603
     * @return $this
604
     */
605 2
    public function setLongitude($longitude)
606
    {
607 2
        $location = $this->getOrCreateJobLocation();
608 2
        $geo = $location->getGeo();
609 2
        $geo->setLongitude($longitude);
610 2
        $location->setGeo($geo);
611 2
        $this->setJobLocation($location);
612
613 2
        return $this;
614
    }
615
616
    /**
617
     * Set minimum salary
618
     *
619
     * @param mixed $salary
620
     *
621
     * @return $this
622
     */
623 2
    public function setMinimumSalary($salary)
624
    {
625 2
        $this->minimumSalary = $salary;
626
627 2
        return $this->setBaseSalary($salary);
628
    }
629
630
    /**
631
     * Sets occupationalCategory with code and title as input
632
     *
633
     * @param string $code
634
     * @param string $title
635
     *
636
     * @return $this
637
     */
638 2
    public function setOccupationalCategoryWithCodeAndTitle($code, $title)
639
    {
640 2
        if ($code && $title) {
641 2
            $this->setOccupationalCategory($code . ' - ' . $title);
642 2
        }
643
644 2
        return $this;
645
    }
646
647
    /**
648
     * Set postal code
649
     *
650
     * @param string $postalCode
651
     *
652
     * @return $this
653
     */
654 2
    public function setPostalCode($postalCode)
655
    {
656 2
        return $this->updateAddressAttribute('postalCode', $postalCode);
657
    }
658
659
    /**
660
     * Sets query.
661
     *
662
     * @param string $query
663
     *
664
     * @return $this
665
     */
666 6
    public function setQuery($query)
667
    {
668 6
        $this->query = $query;
669
670 6
        return $this;
671
    }
672
673
    /**
674
     * Sets source.
675
     *
676
     * @param string $source
677
     *
678
     * @return $this
679
     */
680 6
    public function setSource($source)
681
    {
682 6
        $this->source = $source;
683
684 6
        return $this;
685
    }
686
687
    /**
688
     * Sets sourceId.
689
     *
690
     * @param string $sourceId
691
     *
692
     * @return $this
693
     */
694 8
    public function setSourceId($sourceId)
695
    {
696 8
        $this->sourceId = $sourceId;
697
698 8
        return $this;
699
    }
700
701
    /**
702
     * Set state
703
     *
704
     * @param string $state
705
     *
706
     * @return $this
707
     */
708 2
    public function setState($state)
709
    {
710 2
        return $this->updateAddressAttribute('addressRegion', $state);
711
    }
712
713
    /**
714
     * Set street address
715
     *
716
     * @param string $streetAddress
717
     *
718
     * @return $this
719
     */
720 4
    public function setStreetAddress($streetAddress)
721
    {
722 4
        if (preg_match('/po box/', strtolower($streetAddress))) {
723 2
            $this->updateAddressAttribute('postOfficeBoxNumber', $streetAddress);
724 2
        }
725
726 4
        return $this->updateAddressAttribute('streetAddress', $streetAddress);
727
    }
728
729
    /**
730
     * Set telephone
731
     *
732
     * @param string $telephone
733
     *
734
     * @return $this
735
     */
736 2
    public function setTelephone($telephone)
737
    {
738 2
        $organization = $this->getOrCreateHiringOrganization()
739 2
            ->setTelephone($telephone);
740 2
        $location = $this->getOrCreateJobLocation()
741 2
            ->setTelephone($telephone);
742
743 2
        return $this->setHiringOrganization($organization)
744 2
            ->setJobLocation($location);
745
    }
746
747
    /**
748
     * Serialize class as json
749
     *
750
     * @param  string $serializeSetting
751
     *
752
     * @return string
753
     */
754 8
    public function toJson($serializeSetting = self::SERIALIZE_STANDARD)
755
    {
756 8
        return json_encode($this->jsonSerialize($serializeSetting));
757
    }
758
759
    // Private Methods
760
761
    /**
762
     * Attempt to convert currency to float
763
     *
764
     * @param  mixed $amount
765
     *
766
     * @return float|null
767
     */
768 14
    private function convertCurrency($amount)
769
    {
770 14
        $amount = preg_replace('/[^\\d.]+/', '', $amount);
771
772 14
        if (is_numeric($amount)) {
773 12
            return (float) $amount;
774
        }
775
776 2
        return null;
777
    }
778
779
    /**
780
     * Gets hiring org if it exists or creates if it doesn't
781
     *
782
     * @return Organization
783
     */
784 34
    private function getOrCreateHiringOrganization()
785
    {
786 34
        $company = $this->getHiringOrganization(true);
787
788 34
        if (!$company) {
789 34
            $company = new Organization;
790 34
        }
791
792 34
        return $company;
793
    }
794
795
    /**
796
     * Gets jobLocation if it exists or creates if it doesn't
797
     *
798
     * @return Place
799
     */
800 18
    private function getOrCreateJobLocation()
801
    {
802 18
        $location = $this->getJobLocation(true);
803
804 18
        if (!$location) {
805 18
            $location = new Place;
806 18
            $geo = new GeoCoordinates;
807 18
            $location->setGeo($geo);
808 18
        }
809
810 18
        return $location;
811
    }
812
813
    /**
814
     * Gets address from location if it exists or creates if it doesn't
815
     *
816
     * @param Place $location
817
     *
818
     * @return PostalAddress
819
     */
820 14
    private function getOrCreatePostalAddress(Place $location)
821
    {
822 14
        $address = $location->getAddress();
823
824 14
        if (!$address) {
825 14
            $address = new PostalAddress;
826 14
        }
827
828 14
        return $address;
829
    }
830
831
    /**
832
     * Attempt to update commonly shared address information
833
     *
834
     * @param  string $attribute
835
     * @param  string $value
836
     *
837
     * @return $this
838
     */
839 12
    private function updateAddressAttribute($attribute, $value)
840
    {
841 12
        $organization = $this->getOrCreateHiringOrganization();
842 12
        $location = $this->getOrCreateJobLocation();
843 12
        $address = $this->getOrCreatePostalAddress($location);
844
845 12
        $setMethod = 'set'.ucfirst($attribute);
846
847 12
        if (method_exists($address, $setMethod)) {
848 12
            $address->$setMethod($value);
849 12
        }
850
851 12
        $organization->setAddress($address);
852 12
        $location->setAddress($address);
853
854 12
        $this->setHiringOrganization($organization);
855 12
        $this->setJobLocation($location);
856
857 12
        return $this;
858
    }
859
}
860