Completed
Push — develop ( a3bac5...6cab8d )
by
unknown
07:34
created

Organization::setUser()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 9
Ratio 100 %
Metric Value
dl 9
loc 9
rs 9.6666
cc 2
eloc 6
nc 2
nop 1
1
<?php
2
/**
3
 * YAWIK
4
 *
5
 * @copyright (c) 2013 - 2016 Cross Solution (http://cross-solution.de)
6
 * @license   MIT
7
 */
8
9
namespace Organizations\Entity;
10
11
use Auth\Entity\UserInterface;
12
use Core\Entity\AbstractIdentifiableModificationDateAwareEntity as BaseEntity;
13
use Core\Entity\Collection\ArrayCollection;
14
use Doctrine\Common\Collections\Collection;
15
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
16
use Core\Repository\DoctrineMongoODM\Annotation as Cam;
17
use Core\Entity\Permissions;
18
use Core\Entity\PermissionsInterface;
19
use Core\Entity\EntityInterface;
20
use Zend\Hydrator\HydratorInterface;
21
use Core\Entity\Hydrator\EntityHydrator;
22
use Core\Entity\DraftableEntityInterface;
23
24
/**
25
 * The organization.
26
 *
27
 * @ODM\Document(collection="organizations", repositoryClass="Organizations\Repository\Organization")
28
 * @ODM\HasLifecycleCallbacks
29
 *
30
 * @todo write test
31
 * @author Mathias Weitz <[email protected]>
32
 * @author Mathias Gelhausen <[email protected]>
33
 */
34
class Organization extends BaseEntity implements OrganizationInterface, DraftableEntityInterface
35
{
36
37
    /**
38
     * Event name of post construct event.
39
     *
40
     * @var string
41
     */
42
    const postConstruct = 'postRepositoryConstruct';
0 ignored issues
show
Coding Style introduced by
This class constant is not uppercase (expected POSTCONSTRUCT).
Loading history...
43
44
    /**
45
     * externalId. Allows external applications to reference their primary key.
46
     *
47
     * @var string
48
     * @ODM\String
49
     * @ODM\Index
50
     */
51
    protected $externalId;
52
    
53
    /**
54
     * The actual name of the organization.
55
     *
56
     * @var \Organizations\Entity\OrganizationName
57
     * @ODM\ReferenceOne(targetDocument="\Organizations\Entity\OrganizationName", simple=true, cascade="persist")
58
     */
59
    protected $organizationName;
60
61
    /**
62
     * Assigned permissions.
63
     *
64
     * @var PermissionsInterface
65
     * @ODM\EmbedOne(targetDocument="\Core\Entity\Permissions")
66
     */
67
    protected $permissions;
68
    
69
    /**
70
     * primary logo of an organization
71
     *
72
     * @var \Organizations\Entity\OrganizationImage
73
     * @ODM\ReferenceOne(targetDocument="\Organizations\Entity\OrganizationImage", inversedBy="organization", simple=true, nullable="true", cascade={"all"})
74
     */
75
    protected $image;
76
77
    /**
78
     * Flag indicating draft state of this job.
79
     *
80
     * @var bool
81
     * @ODM\Boolean
82
     */
83
    protected $isDraft = false;
84
    
85
    /**
86
     * Organization contact data.
87
     *
88
     * @ODM\EmbedOne(targetDocument="\Organizations\Entity\OrganizationContact") */
89
    protected $contact;
90
91
    /**
92
     * The organizations' description.
93
     *
94
     * @var string
95
     * @ODM\String
96
     */
97
    protected $description;
98
99
    /**
100
     * The parent of this organization.
101
     *
102
     * @see setParent()
103
     * @var OrganizationInterface | null
104
     * @ODM\ReferenceOne(targetDocument="\Organizations\Entity\Organization", simple=true, nullable=true)
105
     * @since 0.18
106
     */
107
    protected $parent;
108
109
    /**
110
     * The hiring organizations of this organization.
111
     *
112
     * @var Collection
113
     * @ODM\ReferenceMany(
114
     *      targetDocument="Organizations\Entity\Organization",
115
     *      repositoryMethod="getHiringOrganizationsCursor"
116
     * )
117
     * @since 0.18
118
     */
119
    protected $hiringOrganizations;
120
121
    /**
122
     * The associated employees (users)
123
     *
124
     * @ODM\EmbedMany(targetDocument="\Organizations\Entity\Employee")
125
     * @var Collection
126
     */
127
    protected $employees;
128
129
    /**
130
     * Jobs of this organization.
131
     *
132
     * @var Collection
133
     * @ODM\ReferenceMany(targetDocument="\Jobs\Entity\Job", simple=true, mappedBy="organization")
134
     * @since 0.18
135
     */
136
    protected $jobs;
137
138
    /**
139
     * the owner of a Organization
140
     *
141
     * @var UserInterface $user
142
     * @ODM\ReferenceOne(targetDocument="\Auth\Entity\User", simple=true)
143
     * @ODM\Index
144
     */
145
    protected $user;
146
147
    /**
148
     * Default values of an organizations job template
149
     *
150
     * @var TemplateInterface;
151
     * @ODM\EmbedOne(targetDocument="\Organizations\Entity\Template")
152
     */
153
    protected $template;
154
155
    /**
156
     * Sets the parent of an organization
157
     *
158
     * @param OrganizationInterface $parent
159
     *
160
     * @return $this
161
     */
162
    public function setParent(OrganizationInterface $parent)
163
    {
164
        $this->parent = $parent;
165
166
        return $this;
167
    }
168
169
    /**
170
     * Gets the parent of an organization
171
     *
172
     * @return null|OrganizationInterface
173
     */
174
    public function getParent()
175
    {
176
        return $this->parent;
177
    }
178
179
    /**
180
     * Gets linked organizations
181
     *
182
     * @return Collection
183
     */
184
    public function getHiringOrganizations()
185
    {
186
        return $this->hiringOrganizations;
187
    }
188
189
    /**
190
     * @return bool
191
     */
192
    public function isHiringOrganization()
193
    {
194
        return null !== $this->parent;
195
    }
196
197
    /**
198
     * Sets the external id.
199
     *
200
     * @param $externalId
201
     *
202
     * @return self
203
     */
204
    public function setExternalId($externalId)
205
    {
206
        $this->externalId = $externalId;
207
        return $this;
208
    }
209
210
    /**
211
     * Gets the internal id.
212
     *
213
     * @return string
214
     */
215
    public function getExternalId()
216
    {
217
        return $this->externalId;
218
    }
219
220
    /**
221
     * @todo review this
222
     * @param HydratorInterface $hydrator
223
     *
224
     * @return $this
225
     */
226
    public function setHydrator(HydratorInterface $hydrator)
227
    {
228
        return $this;
229
    }
230
231
    /**
232
     * * @todo review this
233
     * @return EntityHydrator
234
     */
235
    public function getHydrator()
236
    {
237
        return new EntityHydrator();
238
    }
239
240
    /**
241
     * Sets the name of an organization
242
     *
243
     * @param OrganizationName $organizationName
244
     *
245
     * @return $this
246
     */
247
    public function setOrganizationName(OrganizationName $organizationName)
248
    {
249
        if (isset($this->organizationName)) {
250
            $this->organizationName->refCounterDec()->refCompanyCounterDec();
251
        }
252
        $this->organizationName = $organizationName;
253
        $this->organizationName->refCounterInc()->refCompanyCounterInc();
254
        return $this;
255
    }
256
257
    /**
258
     * Gets the organization name entity of an organisation
259
     *
260
     * @return OrganizationName
261
     */
262
    public function getOrganizationName()
263
    {
264
        return $this->organizationName;
265
    }
266
267
268
    /**
269
     * Gets the organization name
270
     *
271
     * @return string
272
     */
273
    public function getName()
274
    {
275
        if (empty($this->organizationName)) {
276
            return '';
277
        }
278
        return $this->organizationName->name;
0 ignored issues
show
Documentation introduced by
The property $name is declared protected in Organizations\Entity\OrganizationName. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
279
    }
280
281
    /**
282
     * @deprecated
283
     * @return array
284
     */
285
    public function getSearchableProperties()
286
    {
287
        return array();
288
    }
289
290
    /**
291
     * @deprecated
292
     * @param array $keywords
293
     */
294
    public function setKeywords(array $keywords)
295
    {
296
    }
297
298
    /**
299
     * @deprecated
300
     */
301
    public function clearKeywords()
302
    {
303
    }
304
305
    /**
306
     * @deprecated
307
     */
308
    public function getKeywords()
309
    {
310
    }
311
312
    /**
313
     * Gets the Permissions of an organization
314
     *
315
     * @return PermissionsInterface
316
     */
317
    public function getPermissions()
318
    {
319
        if (!$this->permissions) {
320
            $permissions = new Permissions();
321
            if ($this->user) {
322
                $permissions->grant($this->user, Permissions::PERMISSION_ALL);
0 ignored issues
show
Documentation introduced by
$this->user is of type object<Auth\Entity\UserInterface>, but the function expects a string|object<Core\Entit...sionsResourceInterface>.

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...
323
            }
324
            $this->setPermissions($permissions);
325
        }
326
        return $this->permissions;
327
    }
328
329
    /**
330
     * Sets the Permissions of an Organization
331
     *
332
     * @param PermissionsInterface $permissions
333
     *
334
     * @return $this
335
     */
336 View Code Duplication
    public function setPermissions(PermissionsInterface $permissions)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
337
    {
338
        // Assure the user has always all rights.
339
        if ($this->user) {
340
            $permissions->grant($this->user, Permissions::PERMISSION_ALL);
341
        }
342
        $this->permissions = $permissions;
343
        return $this;
344
    }
345
346
    /**
347
     * Gets the Permissions Resource ID
348
     *
349
     * @return string
350
     */
351
    public function getPermissionsResourceId()
352
    {
353
        return 'organization:' . $this->getId();
354
    }
355
356
    /**
357
     * @param null $type
358
     *
359
     * @return array
360
     */
361
    public function getPermissionsUserIds($type = null)
362
    {
363
        // if we have a user, grant him full access to all associated permissions.
364
        $user = $this->getUser();
365
        $spec = $user
366
              ? $spec = array(PermissionsInterface::PERMISSION_ALL => array($this->getUser()->getId()))
367
              : array();
368
369
        if (null === $type || ('Job/Permissions' != $type && 'Application' != $type)) {
370
            return $spec;
371
        }
372
373
        if ('Job/Permissions' == $type) {
374
            $change = EmployeePermissionsInterface::JOBS_CHANGE;
375
            $view = EmployeePermissionsInterface::JOBS_VIEW;
376
        } else {
377
            $change = EmployeePermissionsInterface::APPLICATIONS_CHANGE;
378
            $view = EmployeePermissionsInterface::APPLICATIONS_VIEW;
379
        }
380
381
        $employees = $this->getEmployees();
382
383
        foreach ($employees as $emp) {
384
            /* @var $emp EmployeeInterface */
385
            if ($emp->isUnassigned()) {
386
                continue;
387
            }
388
389
            $perm = $emp->getPermissions();
390
            if ($perm->isAllowed($change)) {
391
                $spec[PermissionsInterface::PERMISSION_CHANGE][] = $emp->getUser()->getId();
392
            } elseif ($perm->isAllowed($view)) {
393
                $spec[PermissionsInterface::PERMISSION_VIEW][] = $emp->getUser()->getId();
394
            }
395
        }
396
397
        return $spec;
398
    }
399
400
    /**
401
     * Sets the logo of an organization
402
     *
403
     * @param OrganizationImage $image
0 ignored issues
show
Documentation introduced by
Should the type for parameter $image not be null|OrganizationImage?

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...
404
     *
405
     * @return self
406
     */
407
    public function setImage(OrganizationImage $image = null)
408
    {
409
        $this->image = $image;
410
        return $this;
411
    }
412
413
    /**
414
     * Gets the Logo of an organization
415
     *
416
     * @return OrganizationImage
417
     */
418
    public function getImage()
419
    {
420
        return $this->image;
421
    }
422
423
    /**
424
     * Sets the Contact Data of an organization
425
     *
426
     * @param EntityInterface $contact
0 ignored issues
show
Documentation introduced by
Should the type for parameter $contact not be null|EntityInterface?

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...
427
     *
428
     * @return $this
429
     */
430
    public function setContact(EntityInterface $contact = null)
431
    {
432
        if (!$contact instanceof OrganizationContact) {
433
            $contact = new OrganizationContact($contact);
0 ignored issues
show
Unused Code introduced by
The call to OrganizationContact::__construct() has too many arguments starting with $contact.

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...
434
        }
435
        $this->contact = $contact;
436
        return $this;
437
    }
438
439
    /**
440
     * Gets the contact Data of an organization
441
     *
442
     * @return OrganizationContact
443
     */
444
    public function getContact()
445
    {
446
        if (!$this->contact instanceof OrganizationContact) {
447
            $this->contact = new OrganizationContact();
448
        }
449
        return $this->contact;
450
    }
451
452
    /**
453
     * Gets the Draft flag
454
     *
455
     * @return bool
456
     */
457
    public function isDraft()
458
    {
459
        return $this->isDraft;
460
    }
461
462
    /**
463
     * Sets the draft flag
464
     *
465
     * @param bool $flag
466
     *
467
     * @return $this
468
     */
469
    public function setIsDraft($flag)
470
    {
471
        $this->isDraft = (bool) $flag;
472
        return $this;
473
    }
474
475
    /**
476
     * Gets the default description of an organization.
477
     *
478
     * This description is used as the default of the company_description
479
     * used in a job template
480
     *
481
     * @return string
482
     */
483
    public function getDescription()
484
    {
485
        return $this->description;
486
    }
487
488
    /**
489
     * Set the default description af an organization
490
     *
491
     * @param string $description
492
     *
493
     * @return $this
494
     */
495
    public function setDescription($description)
496
    {
497
        $this->description = $description;
498
499
        return $this;
500
    }
501
502
    /**
503
     * Sets the the list of employees
504
     *
505
     * @param Collection $employees
506
     *
507
     * @return $this
508
     */
509
    public function setEmployees(Collection $employees)
510
    {
511
        /* todo: Throw exception or at least log incidents, where employees are added to "hiring orgs" */
512
        if (!$this->isHiringOrganization()) {
513
            $this->employees = $employees;
514
        }
515
516
        return $this;
517
    }
518
519
    /**
520
     * Gets the list of employees
521
     *
522
     * @return ArrayCollection|Collection
523
     */
524
    public function getEmployees()
525
    {
526
        if ($this->isHiringOrganization()) {
527
            // Always return empty list, as we never have employees in this case.
528
            return new ArrayCollection();
529
        }
530
531
        if (!$this->employees) {
532
            $this->setEmployees(new ArrayCollection());
533
        }
534
535
        return $this->employees;
536
    }
537
538
    /**
539
     * Gets an employee by User or ID.
540
     *
541
     * @param UserInterface|string $userOrId
542
     *
543
     * @return mixed|null
544
     */
545
    public function getEmployee($userOrId)
546
    {
547
        $employees = $this->getEmployees();
548
        $userId    = $userOrId instanceof \Auth\Entity\UserInterface ? $userOrId->getId() : $userOrId;
549
550
        foreach ($employees as $employee) {
551
            if ($employee->getUser()->getId() == $userId) {
552
                return $employee;
553
            }
554
        }
555
556
        return null;
557
    }
558
559
    /**
560
     * Gets a list of Employees by a user role
561
     *
562
     * @param string $role
563
     * @return ArrayCollection
564
     */
565
    public function getEmployeesByRole($role){
566
        $employees = new ArrayCollection();
567
568
        /* @var \Organizations\Entity\Employee $employee */
569
        foreach ($this->getEmployees() as $employee) {
570
            if ($role === $employee->getRole()) {
571
                $employees->add($employee);
572
            }
573
        }
574
        return $employees;
575
    }
576
577
    /**
578
     * Checks, if a User is the owner of an organization
579
     *
580
     * @param UserInterface $user
581
     *
582
     * @return bool
583
     */
584
    public function isOwner(UserInterface $user)
585
    {
586
        return $this->getUser()->getId() == $user->getId();
587
    }
588
589
    /**
590
     * Returns true, if a User is an employee of the organization
591
     *
592
     * @param UserInterface $user
593
     *
594
     * @return bool
595
     */
596
    public function isEmployee(UserInterface $user)
597
    {
598
        return $this->refs && in_array($user->getId(), $this->refs->getEmployeeIds());
0 ignored issues
show
Documentation introduced by
The property refs does not exist on object<Organizations\Entity\Organization>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
599
    }
600
601
    /**
602
     * Returns true, if the user belongs to the organization.
603
     *
604
     * @param UserInterface $user
605
     *
606
     * @return bool
607
     */
608
    public function isAssociated(UserInterface $user)
609
    {
610
        return $this->isOwner($user) || $this->isEmployee($user);
611
    }
612
613
    /**
614
     * Updates the organizationsPermissions to allow all employees to view this organization.
615
     *
616
     * In case of a HiringOrganization Permissions are granted to all employees of the parent
617
     * organization.
618
     *
619
     * @ODM\PreUpdate
620
     * @ODM\PrePersist
621
     * @since 0.18
622
     */
623
    public function updatePermissions()
624
    {
625
        if ($this->isHiringOrganization()) {
626
            $organization = $this->getParent();
627
            $owner        = $organization->getUser();
628
629
            $this->setUser($owner);
630
        } else {
631
            $organization = $this;
632
        }
633
634
        /* @var $employees null | ArrayCollection | \Doctrine\ODM\MongoDB\PersistentCollection */
635
        $employees = $organization->getEmployees();
636
637
        $perms = $this->getPermissions();
638
639
        foreach ($employees as $emp) {
0 ignored issues
show
Bug introduced by
The expression $employees of type null is not traversable.
Loading history...
640
            /* @var $emp \Organizations\Entity\Employee */
641
            $perms->grant($emp->getUser(), PermissionsInterface::PERMISSION_CHANGE, false);
0 ignored issues
show
Unused Code introduced by
The call to PermissionsInterface::grant() has too many arguments starting with false.

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...
642
        }
643
        $perms->build();
644
    }
645
646 View Code Duplication
    public function setUser(UserInterface $user)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
647
    {
648
        if ($this->user) {
649
            $this->getPermissions()->revoke($this->user, Permissions::PERMISSION_ALL, false);
0 ignored issues
show
Unused Code introduced by
The call to PermissionsInterface::revoke() has too many arguments starting with false.

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...
650
        }
651
        $this->user = $user;
652
        $this->getPermissions()->grant($user, Permissions::PERMISSION_ALL);
653
        return $this;
654
    }
655
656
    /**
657
     * Gets the owner of the organization
658
     *
659
     * @return UserInterface
660
     */
661
    public function getUser()
662
    {
663
        return $this->user;
664
    }
665
666
    /**
667
     * Gets the Jobs of an organization
668
     *
669
     * @return Collection
670
     */
671
    public function getJobs()
672
    {
673
        return $this->jobs;
674
    }
675
676
    /**
677
     * Gets default values of an organizations job template
678
     *
679
     * @return TemplateInterface
680
     */
681
    public function getTemplate()
682
    {
683
        if (null === $this->template){
684
            $this->template = new Template();
685
        }
686
        return $this->template;
687
    }
688
689
    /**
690
     * Sets default values of an organizations job template
691
     *
692
     * @return self
0 ignored issues
show
Documentation introduced by
Should the return type not be Organization|null?

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...
693
     */
694
    public function setTemplate(TemplateInterface $template)
695
    {
696
        // TODO: Implement setTemplate() method.
697
    }
698
}