Passed
Push — master ( efd2b3...249e4d )
by Marcel
02:26
created

SaasClientService::getCurrentClient()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 30
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 7
eloc 17
nc 6
nop 1
dl 0
loc 30
rs 8.8333
c 2
b 1
f 0
1
<?php
2
3
/*
4
 * This file is part of the SaasProviderBundle package.
5
 * (c) Fluxter <http://fluxter.net/>
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace Fluxter\SaasProviderBundle\Service;
11
12
use Doctrine\ORM\EntityManagerInterface;
13
use Fluxter\SaasProviderBundle\Model\Exception\ClientCouldNotBeDiscoveredException;
14
use Fluxter\SaasProviderBundle\Model\SaasClientInterface;
15
use Fluxter\SaasProviderBundle\Model\SaasParameterInterface;
16
use Symfony\Component\DependencyInjection\ContainerInterface;
17
use Symfony\Component\HttpFoundation\RequestStack;
18
use Symfony\Component\HttpFoundation\Session\SessionInterface;
19
20
class SaasClientService
21
{
22
    private const SaasClientSessionIndex = 'SAASCLIENT';
23
24
    /** @var EntityManagerInterface */
25
    private $em;
26
27
    /** @var SessionInterface */
28
    private $session;
29
30
    /** @var string */
31
    private $saasClientEntity;
32
33
    /** @var RequestStack */
34
    private $requestStack;
35
36
    public function __construct(ContainerInterface $container, EntityManagerInterface $em, SessionInterface $session, RequestStack $requestStack)
37
    {
38
        $this->em = $em;
39
        $this->session = $session;
40
        $this->saasClientEntity = $container->getParameter('saas_provider.client_entity');
41
        $this->requestStack = $requestStack;
42
    }
43
44
    public function __call($name, $arguments)
45
    {
46
        $client = $this->getCurrentClient();
47
48
        $method = "get$name";
49
        if (method_exists($client, $method)) {
50
            return $client->$method();
51
        }
52
        $method = "is$name";
53
        if (method_exists($client, $method)) {
54
            return $client->$method();
55
        }
56
57
        throw new \Exception("Unknown SaaS-Client function / variable: {$name}!");
58
    }
59
60
    public function createClient(array $parameters)
61
    {
62
        /** @var SaasClientInterface $client */
63
        $client = new $this->saasClientEntity();
64
65
        /** @var SaasParameterInterface $parameter */
66
        foreach ($parameters as $parameter) {
67
            $client->addParameter($parameter);
68
        }
69
70
        $this->em->persist($client);
71
        $this->em->flush($client);
0 ignored issues
show
Unused Code introduced by
The call to Doctrine\Persistence\ObjectManager::flush() has too many arguments starting with $client. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

71
        $this->em->/** @scrutinizer ignore-call */ 
72
                   flush($client);

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. Please note the @ignore annotation hint above.

Loading history...
72
73
        return $client;
74
    }
75
76
    /**
77
     * Returns the current http host in lower case.
78
     * For example: "http://localhost:8000" returns "localhost"
79
     * https://test.test.de would return "test.test.de"
80
     *
81
     * @return string
82
     */
83
    private function getCurrentHttpHost() : string
84
    {
85
        $url = $this->requestStack->getCurrentRequest()->getHttpHost();
86
        $url = strtolower($url);
87
        if (strpos($url, ':') !== false) {
88
            $url = preg_replace('/:(.*)/', '', $url);
89
        }
90
91
        return strtolower($url);
92
    }
93
94
    private function discoverClient() : ?SaasClientInterface
95
    {
96
        $url = $this->getCurrentHttpHost();
97
        $repo = $this->em->getRepository($this->saasClientEntity);
98
        $client = $repo->findOneBy(['url' => $url]);
99
        if ($client == null) {
100
            return null;
101
        }
102
        
103
        $this->saveSaasClientSession($client);
104
        return $client;
105
    }
106
107
    private function resetSaasClientSession() {
108
        $this->session->set(self::SaasClientSessionIndex, null);
109
    }
110
111
    private function saveSaasClientSession(SaasClientInterface $client) {
112
        $this->session->set(self::SaasClientSessionIndex, $client->getId());
113
    }
114
115
    /**
116
     * Returns the current client, recognized by the url and the client entity
117
     *
118
     * @param boolean $autodiscover
119
     * @return SaasClientInterface|null
120
     */
121
    public function getCurrentClient(bool $autodiscover = true) : SaasClientInterface
122
    {
123
        if (!$this->session->has(self::SaasClientSessionIndex) || $this->session->get(self::SaasClientSessionIndex) == null) {
124
            if ($autodiscover) {
125
                $this->discoverClient();
126
                return $this->getCurrentClient(false);
127
            }
128
129
            return null;
0 ignored issues
show
Bug Best Practice introduced by
The expression return null returns the type null which is incompatible with the type-hinted return Fluxter\SaasProviderBund...del\SaasClientInterface.
Loading history...
130
        }
131
132
        $repo = $this->em->getRepository($this->saasClientEntity);
133
        /** @var SaasClientInterface $client */
134
        $client = $repo->findOneById($this->session->get(self::SaasClientSessionIndex));
0 ignored issues
show
Bug introduced by
The method findOneById() does not exist on Doctrine\Persistence\ObjectRepository. Did you maybe mean findOneBy()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

134
        /** @scrutinizer ignore-call */ 
135
        $client = $repo->findOneById($this->session->get(self::SaasClientSessionIndex));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
135
        if (null == $client) {
136
            throw new ClientCouldNotBeDiscoveredException();
137
        }
138
        
139
        // Validate
140
        $url = $this->getCurrentHttpHost();
141
        if (strtolower($client->getUrl()) != strtolower($url)) {
142
            $this->resetSaasClientSession();
143
            $this->discoverClient();
144
            return $this->getCurrentClient(false);
145
        }
146
147
        if ($client == null) {
148
            throw new ClientCouldNotBeDiscoveredException();
149
        }
150
        return $client;
151
    }
152
}
153