Can't create multiple instances of connected account provider type XenForo

Kirby

Well-known member
Affected version
2.3.0 Beta 4
Kinda. There’s only one pre-installed but you can add multiple entries of type XF:Provider\XenForo to the provider table in the database if that’s needed.
This does not work as the providerId is hardcoded in XF\ConnectedAccount\ProviderData

PHP:
public function getDefaultEndpoint(): string
{
    /** @var \XF\Entity\ConnectedAccountProvider $provider */
    $provider = \XF::app()->em()->find(ConnectedAccountProvider::class, 'xenforo');

    return $provider->options['board_url'] . '/api/me';
}

So even if another entry (xenforo2) is created manually it would not work as the provider data class would always try to access the API of instance xenforo.

Suggested Fix
Code:
--- src/XF/ConnectedAccount/ProviderData/XenForo.php    Sun Apr 14 23:07:34 2024
+++ src/XF/ConnectedAccount/ProviderData/XenForo.php    Sun Apr 14 23:07:46 2024
@@ -11,3 +11,3 @@
         /** @var \XF\Entity\ConnectedAccountProvider $provider */
-        $provider = \XF::app()->em()->find(ConnectedAccountProvider::class, 'xenforo');
+        $provider = \XF::app()->em()->find(ConnectedAccountProvider::class, $this->providerId);

But this change alone is not sufficient:
The service class XF\ConnectedAccount\Service\XenForo also can't handle multiple instances and will return the hardcoded provider instance xenforo:
PHP:
protected function getProvider(): \XF\Entity\ConnectedAccountProvider
{
    return \XF::app()->em()->find(\XF\Entity\ConnectedAccountProvider::class, 'xenforo');
}

Changing this so the service class can handle multiple instances as well is more complicated as the service class (unlike the provider data class) currently does not know for which instance if is called.

Possible Fix
Code:
--- src/XF/ConnectedAccount/Provider/AbstractProvider.php    Tue Mar 19 22:31:32 2024
+++ src/XF/ConnectedAccount/Provider/AbstractProvider.php    Mon Apr 15 00:39:53 2024
@@ -171,3 +171,3 @@
 
-        $provider = \XF::app()->oAuth()->provider($this->getOAuthServiceName(), $config);
+        $provider = \XF::app()->oAuth()->provider($this->getOAuthServiceName(), $config, $this->providerId);
         if (!$provider)

--- src/XF/ConnectedAccount/Service/XenForo.php    Tue Mar 19 22:31:32 2024
+++ src/XF/ConnectedAccount/Service/XenForo.php    Mon Apr 15 00:41:15 2024
@@ -14,2 +14,4 @@
 {
+    protected $providerId;
+
     protected function getAuthorizationMethod(): int
@@ -66,3 +68,3 @@
     {
-        return \XF::app()->em()->find(\XF\Entity\ConnectedAccountProvider::class, 'xenforo');
+        return \XF::app()->em()->find(\XF\Entity\ConnectedAccountProvider::class, $this->providerId);
     }
@@ -74,2 +76,7 @@
         return true;
+    }
+
+    public function setProviderId(string $providerId): void
+    {
+        $this->providerId = $providerId;
     }

--- src/XF/SubContainer/OAuth.php    Tue Mar 19 22:31:32 2024
+++ src/XF/SubContainer/OAuth.php    Mon Apr 15 00:51:02 2024
@@ -44,4 +44,16 @@
 
-        $container->factory('provider', function($serviceName, array $config, Container $c)
+        $container->factory('provider', function($serviceName, array $params, Container $c)
         {
+            // optional: keep backwards compatibility for $config
+            if (isset($params['key']))
+            {
+                $config = $params;
+                $providerId = '';
+            }
+            else
+            {
+                $config = $params[0];
+                $providerId = $params[1];
+            }
+
             /** @var \OAuth\Common\Consumer\Credentials $credentials */
@@ -76,3 +88,10 @@
 
-            return $serviceFactory->createService($serviceName, $credentials, $storage, $config['scopes']);
+            $service = $serviceFactory->createService($serviceName, $credentials, $storage, $config['scopes']);
+
+            if (method_exists($service, 'setProviderId'))
+            {
+                $service->setProviderId($providerId);
+            }
+
+            return $service;
         });
@@ -100,2 +119,3 @@
      * @param array $config
+     * @param string $providerId
      *
@@ -103,5 +123,5 @@
      */
-    public function provider($serviceName, array $config = [])
+    public function provider($serviceName, array $config = [], string $providerId = '')
     {
-        return $this->container->create('provider', $serviceName, $config);
+        return $this->container->create('provider', $serviceName, [$config, $providerId]);
     }
 
Last edited:
Top Bottom