thephpleague / flysystem-rackspace

Flysystem Adapter for Rackspace
37 stars 28 forks source link

Seems not to work with PHP8 - Guzzle issue? #29

Open edgreenberg-mri opened 1 year ago

edgreenberg-mri commented 1 year ago

Instantiating Flysystem/Rackspace fails with PHP8. I've had this working with PHP7.4 for at least a year or so.

On PHP8, we get:

Deprecated: Required parameter $archive follows optional parameter $path in /var/www/html/includes/vendor/rackspace/php-opencloud/lib/OpenCloud/ObjectStore/Service.php on line 167
PHP Fatal error:  Uncaught Guzzle\Common\Exception\InvalidArgumentException: Invalid handle provided in /var/www/html/includes/vendor/guzzle/guzzle/src/Guzzle/Http/Curl/CurlHandle.php:237
Stack trace:
#0 /var/www/html/includes/vendor/guzzle/guzzle/src/Guzzle/Http/Curl/CurlHandle.php(223): Guzzle\Http\Curl\CurlHandle->__construct()
... and so on

Any fix for this?

colethorsen commented 1 week ago

The dependency rackspace/php-opencloud (which itself has this old guzzle as a dependency) is no longer supported and they recommend switching to php-opencloud/openstack

There are several flysystem adapters for openstack such as: https://github.com/chrisnharvey/flysystem-openstack-swift https://github.com/webalternatif/flysystem-openstack-swift

Here's some code to help you get started, as authenticating Rackspace through OpenStack isn't exactly straightforward.

This uses php-opencloud/openstack v3.10.0

$authUrl = 'https://identity.api.rackspacecloud.com/v2.0/';

$httpClient = new \GuzzleHttp\Client([
    'base_uri' => \OpenStack\Common\Transport\Utils::normalizeUrl($authUrl),
    'handler'  => \GuzzleHttp\HandlerStack::create(),
]);

$openstack = new \OpenStack\OpenStack([
    'authUrl'         => $authUrl,
    'identityService' => RackspaceIdentityService::factory($httpClient),
    'region'          => '{{ ADD RACKSPACE REGION }}',
    'user'            => [
        'username' => '{{ ADD RACKSPACE USERNAME HERE }}',
        'apiKey'   => '{{ ADD RACKSPACE API KEY HERE }}',
    ],
]);

$container = $openstack->objectStoreV1([
    'catalogName' => 'cloudFiles',
])
    ->getContainer('{{ ADD CONTAINER NAME HERE }}');

$adapter = new \Nimbusoft\Flysystem\OpenStack\SwiftAdapter($container);
$filesystem = new \League\Flysystem\Filesystem($adapter);

You also need to create the identity service referenced in the code:

use OpenStack\Common\Auth\IdentityService;
use OpenStack\Identity\v2\Models\Catalog;
use OpenStack\Identity\v2\Models\Token;
use OpenStack\Identity\v2\Service as V2Service;

class RackspaceIdentityService extends V2Service implements IdentityService
{
    public function authenticate(array $options = []): array
    {
        $response = $this->execute([
            'method'   => 'POST',
            'path'     => 'tokens',
            'skipAuth' => true,
            'params'   => [
                'username'   => [
                    'type'     => 'string',
                    'required' => true,
                    'path'     => 'auth.RAX-KSKEY:apiKeyCredentials',
                ],
                'apiKey'   => [
                    'type'     => 'string',
                    'required' => true,
                    'path'     => 'auth.RAX-KSKEY:apiKeyCredentials',
                ],
            ],
        ], $options['user']);

        $token = $this->model(Token::class, $response);

        $serviceUrl = $this->model(Catalog::class, $response)->getServiceUrl(
            $options['catalogName'],
            $options['catalogType'],
            $options['region'],
            $options['urlType']
        );

        return [$token, $serviceUrl];
    }
}