Completed
Push — develop ( e649e8...88dc2a )
by
unknown
15:53 queued 08:30
created

Organization::getHiringOrganizations()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
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
     * Event name of post construct event.
38
     *
39
     * @var string
40
     */
41
    const postConstruct = 'postRepositoryConstruct';
0 ignored issues
show
Coding Style introduced by
This class constant is not uppercase (expected POSTCONSTRUCT).
Loading history...
42
43
    /**
44
     * externalId. Allows external applications to reference their primary key.
45
     *
46
     * @var string
47
     * @ODM\Field(type="string")
48
     * @ODM\Index
49
     */
50
    protected $externalId;
51
    
52
    /**
53
     * The actual name of the organization.
54
     *
55
     * @var \Organizations\Entity\OrganizationName
56
     * @ODM\ReferenceOne(targetDocument="\Organizations\Entity\OrganizationName", simple=true, cascade="persist")
57
     */
58
    protected $organizationName;
59
60
    /**
61
     * Assigned permissions.
62
     *
63
     * @var PermissionsInterface
64
     * @ODM\EmbedOne(targetDocument="\Core\Entity\Permissions")
65
     */
66
    protected $permissions;
67
    
68
    /**
69
     * primary logo of an organization
70
     *
71
     * @var \Organizations\Entity\OrganizationImage
72
     * @ODM\ReferenceOne(targetDocument="\Organizations\Entity\OrganizationImage", inversedBy="organization", simple=true, nullable="true", cascade={"all"})
73
     */
74
    protected $image;
75
76
    /**
77
     * Flag indicating draft state of this job.
78
     *
79
     * @var bool
80
     * @ODM\Boolean
81
     */
82
    protected $isDraft = false;
83
    
84
    /**
85
     * Organization contact data.
86
     *
87
     * @ODM\EmbedOne(targetDocument="\Organizations\Entity\OrganizationContact") */
88
    protected $contact;
89
90
    /**
91
     * The organizations' description.
92
     *
93
     * @var string
94
     * @ODM\Field(type="string")
95
     */
96
    protected $description;
97
98
    /**
99
     * The parent of this organization.
100
     *
101
     * @see setParent()
102
     * @var OrganizationInterface | null
103
     * @ODM\ReferenceOne(targetDocument="\Organizations\Entity\Organization", simple=true, nullable=true)
104
     * @since 0.18
105
     */
106
    protected $parent;
107
108
    /**
109
     * The hiring organizations of this organization.
110
     *
111
     * @var Collection
112
     * @ODM\ReferenceMany(
113
     *      targetDocument="Organizations\Entity\Organization",
114
     *      repositoryMethod="getHiringOrganizationsCursor"
115
     * )
116
     * @since 0.18
117
     */
118
    protected $hiringOrganizations;
119
120
    /**
121
     * The associated employees (users)
122
     *
123
     * @ODM\EmbedMany(targetDocument="\Organizations\Entity\Employee")
124
     * @var Collection
125
     */
126
    protected $employees;
127
128
    /**
129
     * Jobs of this organization.
130
     *
131
     * @var Collection
132
     * @ODM\ReferenceMany(targetDocument="\Jobs\Entity\Job", simple=true, mappedBy="organization")
133
     * @since 0.18
134
     */
135
    protected $jobs;
136
137
    /**
138
     * the owner of a Organization
139
     *
140
     * @var UserInterface $user
141
     * @ODM\ReferenceOne(targetDocument="\Auth\Entity\User", simple=true)
142
     * @ODM\Index
143
     */
144
    protected $user;
145
146
    /**
147
     * Default values of an organizations job template
148
     *
149
     * @var TemplateInterface;
150
     * @ODM\EmbedOne(targetDocument="\Organizations\Entity\Template")
151
     */
152
    protected $template;
153
154
    /**
155
     * Default values Workflow
156
     *
157
     * @var WorkflowSettingsInterface $workflowSettings;
158
     * @ODM\EmbedOne(targetDocument="\Organizations\Entity\WorkflowSettings")
159
     */
160
    protected $workflowSettings;
161
162
    /**
163
     * Sets the parent of an organization
164
     *
165
     * @param OrganizationInterface $parent
166
     *
167
     * @return $this
168
     */
169
    public function setParent(OrganizationInterface $parent)
170
    {
171
        $this->parent = $parent;
172
173
        return $this;
174
    }
175
176
    /**
177
     * Gets the parent of an organization
178
     *
179
     * @return null|OrganizationInterface
180
     */
181
    public function getParent()
182
    {
183
        return $this->parent;
184
    }
185
186
    /**
187
     * Gets linked organizations
188
     *
189
     * @return Collection
190
     */
191
    public function getHiringOrganizations()
192
    {
193
        return $this->hiringOrganizations;
194
    }
195
196
    /**
197
     * @return bool
198
     */
199
    public function isHiringOrganization()
200
    {
201
        return null !== $this->parent;
202
    }
203
204
    /**
205
     * Sets the external id.
206
     *
207
     * @param $externalId
208
     *
209
     * @return self
210
     */
211
    public function setExternalId($externalId)
212
    {
213
        $this->externalId = $externalId;
214
        return $this;
215
    }
216
217
    /**
218
     * Gets the internal id.
219
     *
220
     * @return string
221
     */
222
    public function getExternalId()
223
    {
224
        return $this->externalId;
225
    }
226
227
    /**
228
     * @todo review this
229
     * @param HydratorInterface $hydrator
230
     *
231
     * @return $this
232
     */
233
    public function setHydrator(HydratorInterface $hydrator)
234
    {
235
        return $this;
236
    }
237
238
    /**
239
     * * @todo review this
240
     * @return EntityHydrator
241
     */
242
    public function getHydrator()
243
    {
244
        return new EntityHydrator();
245
    }
246
247
    /**
248
     * Sets the name of an organization
249
     *
250
     * @param OrganizationName $organizationName
251
     *
252
     * @return $this
253
     */
254
    public function setOrganizationName(OrganizationName $organizationName)
255
    {
256
        if (isset($this->organizationName)) {
257
            $this->organizationName->refCounterDec()->refCompanyCounterDec();
258
        }
259
        $this->organizationName = $organizationName;
260
        $this->organizationName->refCounterInc()->refCompanyCounterInc();
261
        return $this;
262
    }
263
264
    /**
265
     * Gets the organization name entity of an organisation
266
     *
267
     * @return OrganizationName
268
     */
269
    public function getOrganizationName()
270
    {
271
        return $this->organizationName;
272
    }
273
274
275
    /**
276
     * Gets the organization name
277
     *
278
     * @return string
279
     */
280
    public function getName()
281
    {
282
        if (empty($this->organizationName)) {
283
            return '';
284
        }
285
        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...
286
    }
287
288
    /**
289
     * @deprecated
290
     * @return array
291
     */
292
    public function getSearchableProperties()
293
    {
294
        return array();
295
    }
296
297
    /**
298
     * Gets the Permissions of an organization
299
     *
300
     * @return PermissionsInterface
301
     */
302
    public function getPermissions()
303
    {
304
        if (!$this->permissions) {
305
            $permissions = new Permissions();
306
            if ($this->user) {
307
                $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...
308
            }
309
            $this->setPermissions($permissions);
310
        }
311
        return $this->permissions;
312
    }
313
314
    /**
315
     * Sets the Permissions of an Organization
316
     *
317
     * @param PermissionsInterface $permissions
318
     *
319
     * @return $this
320
     */
321 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...
322
    {
323
        // Assure the user has always all rights.
324
        if ($this->user) {
325
            $permissions->grant($this->user, Permissions::PERMISSION_ALL);
326
        }
327
        $this->permissions = $permissions;
328
        return $this;
329
    }
330
331
    /**
332
     * Gets the Permissions Resource ID
333
     *
334
     * @return string
335
     */
336
    public function getPermissionsResourceId()
337
    {
338
        return 'organization:' . $this->getId();
339
    }
340
341
    /**
342
     * @param null $type
343
     *
344
     * @return array
345
     */
346
    public function getPermissionsUserIds($type = null)
347
    {
348
        // if we have a user, grant him full access to all associated permissions.
349
        $user = $this->getUser();
350
        $spec = $user
351
              ? $spec = array(PermissionsInterface::PERMISSION_ALL => array($this->getUser()->getId()))
352
              : array();
353
354
        if (null === $type || ('Job/Permissions' != $type && 'Application' != $type)) {
355
            return $spec;
356
        }
357
358
        if ('Job/Permissions' == $type) {
359
            $change = EmployeePermissionsInterface::JOBS_CHANGE;
360
            $view = EmployeePermissionsInterface::JOBS_VIEW;
361
        } else {
362
            $change = EmployeePermissionsInterface::APPLICATIONS_CHANGE;
363
            $view = EmployeePermissionsInterface::APPLICATIONS_VIEW;
364
        }
365
366
        $employees = $this->getEmployees();
367
368
        foreach ($employees as $emp) {
369
            /* @var $emp EmployeeInterface */
370
            if ($emp->isUnassigned()) {
371
                continue;
372
            }
373
374
            $perm = $emp->getPermissions();
375
            if ($perm->isAllowed($change)) {
376
                $spec[PermissionsInterface::PERMISSION_CHANGE][] = $emp->getUser()->getId();
377
            } elseif ($perm->isAllowed($view)) {
378
                $spec[PermissionsInterface::PERMISSION_VIEW][] = $emp->getUser()->getId();
379
            }
380
        }
381
382
        return $spec;
383
    }
384
385
    /**
386
     * Sets the logo of an organization
387
     *
388
     * @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...
389
     *
390
     * @return self
391
     */
392
    public function setImage(OrganizationImage $image = null)
393
    {
394
        $this->image = $image;
395
        return $this;
396
    }
397
398
    /**
399
     * Gets the Logo of an organization
400
     *
401
     * @return OrganizationImage
402
     */
403
    public function getImage()
404
    {
405
        return $this->image;
406
    }
407
408
    /**
409
     * Sets the Contact Data of an organization
410
     *
411
     * @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...
412
     *
413
     * @return $this
414
     */
415
    public function setContact(EntityInterface $contact = null)
416
    {
417
        if (!$contact instanceof OrganizationContact) {
418
            $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...
419
        }
420
        $this->contact = $contact;
421
        return $this;
422
    }
423
424
    /**
425
     * Gets the contact Data of an organization
426
     *
427
     * @return OrganizationContact
428
     */
429
    public function getContact()
430
    {
431
        if (!$this->contact instanceof OrganizationContact) {
432
            $this->contact = new OrganizationContact();
433
        }
434
        return $this->contact;
435
    }
436
437
    /**
438
     * Gets the Draft flag
439
     *
440
     * @return bool
441
     */
442
    public function isDraft()
443
    {
444
        return $this->isDraft;
445
    }
446
447
    /**
448
     * Sets the draft flag
449
     *
450
     * @param bool $flag
451
     *
452
     * @return $this
453
     */
454
    public function setIsDraft($flag)
455
    {
456
        $this->isDraft = (bool) $flag;
457
        return $this;
458
    }
459
460
    /**
461
     * Gets the default description of an organization.
462
     *
463
     * This description is used as the default of the company_description
464
     * used in a job template
465
     *
466
     * @return string
467
     */
468
    public function getDescription()
469
    {
470
        return $this->description;
471
    }
472
473
    /**
474
     * Set the default description af an organization
475
     *
476
     * @param string $description
477
     *
478
     * @return $this
479
     */
480
    public function setDescription($description)
481
    {
482
        $this->description = $description;
483
484
        return $this;
485
    }
486
487
    /**
488
     * Sets the the list of employees
489
     *
490
     * @param Collection $employees
491
     *
492
     * @return $this
493
     */
494
    public function setEmployees(Collection $employees)
495
    {
496
        /* todo: Throw exception or at least log incidents, where employees are added to "hiring orgs" */
497
        if (!$this->isHiringOrganization()) {
498
            $this->employees = $employees;
499
        }
500
501
        return $this;
502
    }
503
504
    /**
505
     * Gets the list of employees
506
     *
507
     * @return ArrayCollection|Collection
508
     */
509
    public function getEmployees()
510
    {
511
        if ($this->isHiringOrganization()) {
512
            // Always return empty list, as we never have employees in this case.
513
            return new ArrayCollection();
514
        }
515
516
        if (!$this->employees) {
517
            $this->setEmployees(new ArrayCollection());
518
        }
519
520
        return $this->employees;
521
    }
522
523
    /**
524
     * Gets an employee by User or ID.
525
     *
526
     * @param UserInterface|string $userOrId
527
     *
528
     * @return mixed|null
529
     */
530
    public function getEmployee($userOrId)
531
    {
532
        $employees = $this->getEmployees();
533
        $userId    = $userOrId instanceof \Auth\Entity\UserInterface ? $userOrId->getId() : $userOrId;
534
535
        foreach ($employees as $employee) {
536
            if ($employee->getUser()->getId() == $userId) {
537
                return $employee;
538
            }
539
        }
540
541
        return null;
542
    }
543
544
    /**
545
     * Gets a list of Employees by a user role
546
     *
547
     * @param string $role
548
     * @return ArrayCollection
549
     */
550
    public function getEmployeesByRole($role){
551
        $employees = new ArrayCollection();
552
553
        /* @var \Organizations\Entity\Employee $employee */
554
        foreach ($this->getEmployees() as $employee) {
555
            if ($role === $employee->getRole()) {
556
                $employees->add($employee);
557
            }
558
        }
559
        return $employees;
560
    }
561
562
    /**
563
     * Checks, if a User is the owner of an organization
564
     *
565
     * @param UserInterface $user
566
     *
567
     * @return bool
568
     */
569
    public function isOwner(UserInterface $user)
570
    {
571
        return $this->getUser()->getId() == $user->getId();
572
    }
573
574
    /**
575
     * Returns true, if a User is an employee of the organization
576
     *
577
     * @param UserInterface $user
578
     *
579
     * @return bool
580
     */
581
    public function isEmployee(UserInterface $user)
582
    {
583
        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...
584
    }
585
586
    /**
587
     * Returns true, if the user belongs to the organization.
588
     *
589
     * @param UserInterface $user
590
     *
591
     * @return bool
592
     */
593
    public function isAssociated(UserInterface $user)
594
    {
595
        return $this->isOwner($user) || $this->isEmployee($user);
596
    }
597
598
    /**
599
     * Updates the organizationsPermissions to allow all employees to view this organization.
600
     *
601
     * In case of a HiringOrganization Permissions are granted to all employees of the parent
602
     * organization.
603
     *
604
     * @ODM\PreUpdate
605
     * @ODM\PrePersist
606
     * @since 0.18
607
     */
608
    public function updatePermissions()
609
    {
610
        if ($this->isHiringOrganization()) {
611
            $organization = $this->getParent();
612
            $owner        = $organization->getUser();
613
614
            $this->setUser($owner);
615
        } else {
616
            $organization = $this;
617
        }
618
619
        /* @var $employees null | ArrayCollection | \Doctrine\ODM\MongoDB\PersistentCollection */
620
        $employees = $organization->getEmployees();
621
622
        $perms = $this->getPermissions();
623
624
        foreach ($employees as $emp) {
0 ignored issues
show
Bug introduced by
The expression $employees of type null is not traversable.
Loading history...
625
            /* @var $emp \Organizations\Entity\Employee */
626
            $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...
627
        }
628
        $perms->build();
629
    }
630
631 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...
632
    {
633
        if ($this->user) {
634
            $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...
635
        }
636
        $this->user = $user;
637
        $this->getPermissions()->grant($user, Permissions::PERMISSION_ALL);
638
        return $this;
639
    }
640
641
    /**
642
     * Gets the owner of the organization
643
     *
644
     * @return UserInterface
645
     */
646
    public function getUser()
647
    {
648
        return $this->user;
649
    }
650
651
    /**
652
     * Gets the Jobs of an organization
653
     *
654
     * @return Collection
655
     */
656
    public function getJobs()
657
    {
658
        return $this->jobs;
659
    }
660
661
    /**
662
     * Gets default values of an organizations job template
663
     *
664
     * @return TemplateInterface
665
     */
666
    public function getTemplate()
667
    {
668
        if (null === $this->template){
669
            $this->template = new Template();
670
        }
671
        return $this->template;
672
    }
673
674
    /**
675
     * Sets default values of an organizations job template
676
     *
677
     * @return self
678
     */
679
    public function setTemplate(TemplateInterface $template)
680
    {
681
        $this->template=$template;
682
        return $this;
683
    }
684
685
    /**
686
     * Gets Workflow Settings
687
     *
688
     * @return WorkflowSettings|WorkflowSettingsInterface
689
     */
690
    public function getWorkflowSettings(){
691
        if (null == $this->workflowSettings) {
692
            $this->workflowSettings = new WorkflowSettings();
693
        }
694
        return $this->workflowSettings;
695
    }
696
697
    /**
698
     * Sets Workflow Settings
699
     *
700
     * @param $workflowSettings
701
     *
702
     * @return self
703
     */
704
    public function setWorkflowSettings($workflowSettings){
705
        $this->workflowSettings=$workflowSettings;
706
        return $this;
707
    }
708
}