Completed
Push — master ( b5c2a9...ab10ed )
by Atymic
06:11
created

src/SocialiteWasCalled.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace SocialiteProviders\Manager;
4
5
use Illuminate\Contracts\Container\Container as Application;
6
use Laravel\Socialite\Contracts\Factory as SocialiteFactory;
7
use Laravel\Socialite\One\AbstractProvider as SocialiteOAuth1AbstractProvider;
8
use Laravel\Socialite\SocialiteManager;
9
use Laravel\Socialite\Two\AbstractProvider as SocialiteOAuth2AbstractProvider;
10
use League\OAuth1\Client\Server\Server as OAuth1Server;
11
use SocialiteProviders\Manager\Contracts\Helpers\ConfigRetrieverInterface;
12
use SocialiteProviders\Manager\Exception\InvalidArgumentException;
13
14
class SocialiteWasCalled
15
{
16
    const SERVICE_CONTAINER_PREFIX = 'SocialiteProviders.config.';
17
18
    /**
19
     * @var \Illuminate\Contracts\Container\Container
20
     */
21
    protected $app;
22
23
    /**
24
     * @var \SocialiteProviders\Manager\Contracts\Helpers\ConfigRetrieverInterface
25
     */
26
    private $configRetriever;
27
28
    /**
29 10
     * @var array
30
     */
31 10
    private $spoofedConfig = [
32 10
        'client_id' => 'spoofed_client_id',
33 10
        'client_secret' => 'spoofed_client_secret',
34
        'redirect' => 'spoofed_redirect',
35
    ];
36
37
    /**
38
     * @param \Illuminate\Contracts\Container\Container $app
39
     * @param \SocialiteProviders\Manager\Contracts\Helpers\ConfigRetrieverInterface $configRetriever
40
     */
41
    public function __construct(Application $app, ConfigRetrieverInterface $configRetriever)
42
    {
43
        $this->app = $app;
44 10
        $this->configRetriever = $configRetriever;
45
    }
46
47 10
    /**
48 10
     * @param string $providerName  'meetup'
49 4
     * @param string $providerClass 'Your\Name\Space\ClassNameProvider' must extend
50 4
     *                              either Laravel\Socialite\Two\AbstractProvider or
51 4
     *                              Laravel\Socialite\One\AbstractProvider
52 4
     * @param string $oauth1Server  'Your\Name\Space\ClassNameServer' must extend League\OAuth1\Client\Server\Server
53
     *
54 4
     * @return void
55 4
     *
56
     * @throws \SocialiteProviders\Manager\Exception\InvalidArgumentException
57
     */
58
    public function extendSocialite($providerName, $providerClass, $oauth1Server = null)
59
    {
60
        /** @var SocialiteManager $socialite */
61
        $socialite = $this->app->make(SocialiteFactory::class);
62
63
        $this->classExists($providerClass);
64
        if ($this->isOAuth1($oauth1Server)) {
65 10
            $this->classExists($oauth1Server);
66
            $this->classExtends($providerClass, SocialiteOAuth1AbstractProvider::class);
67 10
        }
68
69 7
        $socialite->extend(
70 3
            $providerName,
71 2
            function () use ($socialite, $providerName, $providerClass, $oauth1Server) {
72 2
                $provider = $this->buildProvider($socialite, $providerName, $providerClass, $oauth1Server);
73
                if (defined('SOCIALITEPROVIDERS_STATELESS') && SOCIALITEPROVIDERS_STATELESS) {
74
                    return $provider->stateless();
0 ignored issues
show
The method stateless does only exist in Laravel\Socialite\Two\AbstractProvider, but not in Laravel\Socialite\One\AbstractProvider.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
75 4
                }
76 3
77
                return $provider;
78
            }
79
        );
80
    }
81
82
    /**
83
     * @param \Laravel\Socialite\SocialiteManager $socialite
84
     * @param string                              $providerName
85
     * @param string                              $providerClass
86
     * @param null|string                         $oauth1Server
87
     *
88 2
     * @return \Laravel\Socialite\One\AbstractProvider|\Laravel\Socialite\Two\AbstractProvider
89
     *
90 2
     * @throws \SocialiteProviders\Manager\Exception\MissingConfigException
91 1
     */
92
    protected function buildProvider(SocialiteManager $socialite, $providerName, $providerClass, $oauth1Server)
93 1
    {
94 1
        if ($this->isOAuth1($oauth1Server)) {
95 1
            return $this->buildOAuth1Provider($socialite, $providerClass, $providerName, $oauth1Server);
96
        }
97
98
        return $this->buildOAuth2Provider($socialite, $providerClass, $providerName);
99
    }
100
101
    /**
102
     * Build an OAuth 1 provider instance.
103
     *
104
     * @param \Laravel\Socialite\SocialiteManager $socialite
105
     * @param string $providerClass must extend Laravel\Socialite\One\AbstractProvider
106
     * @param string $providerName
107 3
     * @param string $oauth1Server  must extend League\OAuth1\Client\Server\Server
108
     *
109 3
     * @return \Laravel\Socialite\One\AbstractProvider
110
     *
111 3
     * @throws \SocialiteProviders\Manager\Exception\MissingConfigException
112
     */
113
    protected function buildOAuth1Provider(SocialiteManager $socialite, $providerClass, $providerName, $oauth1Server)
114
    {
115
        $this->classExtends($oauth1Server, OAuth1Server::class);
116
117
        $config = $this->getConfig($providerClass, $providerName);
118
119
        $configServer = $socialite->formatConfig($config->get());
120
121 6
        $provider = new $providerClass(
122
            $this->app->offsetGet('request'), new $oauth1Server($configServer)
0 ignored issues
show
The method offsetGet() does not seem to exist on object<Illuminate\Contracts\Container\Container>.

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...
123 6
        );
124 6
125 6
        $provider->setConfig($config);
126
127 6
        return $provider;
128 4
    }
129 2
130 2
    /**
131
     * Build an OAuth 2 provider instance.
132
     *
133 2
     * @param SocialiteManager $socialite
134
     * @param string           $providerClass must extend Laravel\Socialite\Two\AbstractProvider
135 2
     * @param string           $providerName
136 1
     *
137 1
     * @return \Laravel\Socialite\Two\AbstractProvider
138 1
     *
139
     * @throws \SocialiteProviders\Manager\Exception\MissingConfigException
140
     */
141 1
    protected function buildOAuth2Provider(SocialiteManager $socialite, $providerClass, $providerName)
142
    {
143
        $this->classExtends($providerClass, SocialiteOAuth2AbstractProvider::class);
144
145
        $config = $this->getConfig($providerClass, $providerName);
146
147
        $provider = $socialite->buildProvider($providerClass, $config->get());
148
149
        $provider->setConfig($config);
150
151 7
        return $provider;
152
    }
153 7
154
    /**
155
     * @param string $providerClass
156
     * @param string $providerName
157
     *
158
     * @return \SocialiteProviders\Manager\Contracts\ConfigInterface
159
     *
160
     * @throws \SocialiteProviders\Manager\Exception\MissingConfigException
161
     */
162 5
    protected function getConfig($providerClass, $providerName)
163
    {
164 5
        return $this->configRetriever->fromServices(
165 1
            $providerName, $providerClass::additionalConfigKeys()
166 1
        );
167
    }
168 4
169
    /**
170 10
     * Check if a server is given, which indicates that OAuth1 is used.
171
     *
172 10
     * @param string $oauth1Server
173 4
     *
174
     * @return bool
175 7
     */
176
    private function isOAuth1($oauth1Server)
177
    {
178
        return !empty($oauth1Server);
179
    }
180
181
    /**
182
     * @param string $class
183
     * @param string $baseClass
184
     *
185
     * @return void
186
     *
187
     * @throws \SocialiteProviders\Manager\Exception\InvalidArgumentException
188
     */
189
    private function classExtends($class, $baseClass)
190
    {
191
        if (false === is_subclass_of($class, $baseClass)) {
0 ignored issues
show
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if $baseClass can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
192
            throw new InvalidArgumentException("{$class} does not extend {$baseClass}");
193
        }
194
    }
195
196
    /**
197
     * @param string $providerClass
198
     *
199
     * @return void
200
     *
201
     * @throws \SocialiteProviders\Manager\Exception\InvalidArgumentException
202
     */
203
    private function classExists($providerClass)
204
    {
205
        if (!class_exists($providerClass)) {
206
            throw new InvalidArgumentException("{$providerClass} doesn't exist");
207
        }
208
    }
209
}
210