TenantManager::getDefaultTenant()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
namespace Vivait\AuthBundle\EventListener;
3
4
use Doctrine\ORM\EntityRepository;
5
use Symfony\Bridge\Monolog\Logger;
6
use Symfony\Component\HttpFoundation\Request;
7
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
8
use Symfony\Component\HttpKernel\KernelEvents;
9
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
10
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
11
use Symfony\Component\Security\Core\SecurityContext;
12
use Vivait\AuthBundle\Entity\Tenant;
13
use Vivait\AuthBundle\Entity\TenantRepository;
14
use Vivait\AuthBundle\Entity\User;
15
16
class TenantManager implements EventSubscriberInterface
17
{
18
	const SESSION_VAR = 'vivait_auth_tenant';
19
20
	/**
21
	 * @var SecurityContext
22
	 */
23
	protected $security_context;
24
25
	/**
26
	 * @var Tenant
27
	 */
28
	protected $tenant;
29
30
	/**
31
	 * @var TenantRepository
32
	 */
33
	protected $tenant_repository;
34
35
	/**
36
	 * @var Logger
37
	 */
38
	protected $logger;
39
40
	function __construct(SecurityContext $security_context, Logger $logger, EntityRepository $tenant_repository) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
41
		$this->security_context  = $security_context;
42
		$this->logger            = $logger;
43
		$this->tenant_repository = $tenant_repository;
0 ignored issues
show
Documentation Bug introduced by
$tenant_repository is of type object<Doctrine\ORM\EntityRepository>, but the property $tenant_repository was declared to be of type object<Vivait\AuthBundle\Entity\TenantRepository>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
44
	}
45
46
47
	public function onKernelRequest(GetResponseEvent $event)
48
	{
49
		$request   = $event->getRequest();
50
		$token     = $this->security_context->getToken();
0 ignored issues
show
Deprecated Code introduced by
The method Symfony\Component\Securi...rityContext::getToken() has been deprecated with message: since version 2.6, to be removed in 3.0. Use TokenStorageInterface::getToken() instead. {@inheritdoc}

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
51
		if (!$token || !is_object($token)) {
52
			return;
53
		}
54
55
		/* @var $user User */
56
		$user      = $token->getUser();
57
		$is_object = $user instanceOf User;
58
59
		// Try the request first
60
		$tenant = $this->getRequestTenant($request);
61
62
		// Then look at the user's highest priority setting
63
		if ($is_object && !$tenant) {
64
			$tenant = $this->getUserTenant();
65
		}
66
67
		// Now just pick the global highest priority
68
		if (!$tenant) {
69
			$tenant = $this->getDefaultTenant();
70
		}
71
72
		// Did we find a tenant?
73
		if ($tenant) {
74
			// Store them against the request
75
			$this->setTenant($tenant);
76
77
			// Store it against the user
78
			if ($is_object) {
79
				$user->setCurrentTenant($tenant);
80
			}
81
		}
82
		else {
83
			// TODO: Throw a big fat warning
84
			$this->logger->warning('No default tenant could be found');
85
		}
86
	}
87
88
	protected function getDefaultTenant() {
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
89
		return $this->tenant_repository->findOneBy(array(), array(
90
			'priority' => 'ASC'
91
		));
92
	}
93
94
	protected function getRequestTenant(Request $request) {
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
95
		$session   = $request->getSession();
96
		$tenant_id = $request->get('_tenant');
97
98
		if (!$tenant_id) {
99
			$tenant_id = $session->get(self::SESSION_VAR);
100
		}
101
102
		if ($tenant_id) {
103
			$tenant = $this->tenant_repository->find($tenant_id);
104
105
			// Tenant not in database
106
			if (!$tenant) {
107
				$this->logger->warning(sprintf('Tenant ID "%s" could not be loaded by repository', $tenant_id));
108
			}
109
110
111
			$session->set(self::SESSION_VAR, $tenant_id);
112
113
			return $tenant;
114
		}
115
		return null;
116
	}
117
118
	protected function getUserTenant() {
119
		$token = $this->security_context->getToken();
0 ignored issues
show
Deprecated Code introduced by
The method Symfony\Component\Securi...rityContext::getToken() has been deprecated with message: since version 2.6, to be removed in 3.0. Use TokenStorageInterface::getToken() instead. {@inheritdoc}

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
120
		/* @var $user User */
121
		$user = $token->getUser();
122
123
		if ($user instanceOf User) {
124
			if($user->getCurrentTenant()) {
125
				return $user->getCurrentTenant();
126
			}
127
128
			return $user->getTenants()->first();
129
		}
130
		return null;
131
	}
132
133
	public static function getSubscribedEvents()
134
	{
135
		return array(
136
			// must be registered before the default Locale listener
137
			KernelEvents::REQUEST => array(array('onKernelRequest', 1)),
138
		);
139
	}
140
141
	/**
142
	 * Sets tenant
143
	 * @param mixed $tenant
144
	 * @return $this
145
	 */
146
	public function setTenant(Tenant $tenant) {
147
		$this->tenant = $tenant;
148
		return $this;
149
	}
150
151
	/**
152
	 * Gets tenant
153
	 * @return Tenant
154
	 */
155
	public function getTenant() {
156
		return $this->tenant;
157
	}
158
}