├── .editorconfig ├── .gitignore ├── LICENSE.md ├── README.md ├── composer.json ├── src ├── NextCloudAdapter.php └── NextCloudServiceProvider.php └── tests └── ServiceProviderTest.php /.editorconfig: -------------------------------------------------------------------------------- 1 | ; This file is for unifying the coding style for different editors and IDEs. 2 | ; More information at http://editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | indent_size = 4 9 | indent_style = space 10 | end_of_line = lf 11 | insert_final_newline = true 12 | trim_trailing_whitespace = true 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | composer.lock 3 | docs 4 | vendor -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Jakub Jedlikowski 4 | 5 | > Permission is hereby granted, free of charge, to any person obtaining a copy 6 | > of this software and associated documentation files (the "Software"), to deal 7 | > in the Software without restriction, including without limitation the rights 8 | > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | > copies of the Software, and to permit persons to whom the Software is 10 | > furnished to do so, subject to the following conditions: 11 | > 12 | > The above copyright notice and this permission notice shall be included in 13 | > all copies or substantial portions of the Software. 14 | > 15 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | > THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # laravel-nextcloud 2 | 3 | Based on https://github.com/pascalbaljetmedia/laravel-webdav 4 | 5 | ## Install 6 | 7 | Via Composer 8 | 9 | ```bash 10 | $ composer require jedlikowski/laravel-nextcloud 11 | ``` 12 | 13 | ## Usage 14 | 15 | Register the service provider in your app.php config file: 16 | 17 | ```php 18 | // config/app.php 19 | 20 | 'providers' => [ 21 | ... 22 | Jedlikowski\NextCloudStorage\NextCloudServiceProvider::class 23 | ... 24 | ]; 25 | ``` 26 | 27 | Create a NextCloud filesystem disk: 28 | 29 | ```php 30 | // config/filesystems.php 31 | 32 | 'disks' => [ 33 | ... 34 | 'nextcloud' => [ 35 | 'driver' => 'nextcloud', 36 | 'baseUri' => 'https://mywebdavstorage.com', 37 | 'userName' => 'johndoe', 38 | 'password' => 'secret', 39 | 'pathPrefix' => '', // provide a subfolder name if your NextCloud instance isn't running directly on a domain, e.g. https://example.com/drive 40 | ], 41 | ... 42 | ]; 43 | ``` 44 | 45 | ## Security 46 | 47 | If you discover any security related issues, please email jakub.jedlikowski@gmail.com instead of using the issue tracker. 48 | 49 | ## Credits 50 | 51 | - [Jakub Jedlikowski][link-author] 52 | - [Pascal Baljet][link-author-2] 53 | 54 | ## License 55 | 56 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 57 | 58 | [link-author]: https://github.com/jedlikowski 59 | [link-author-2]: https://github.com/pascalbaljet 60 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jedlikowski/laravel-nextcloud", 3 | "type": "library", 4 | "version": "1.0.0", 5 | "description": "Laravel 5 NextCloud Filesystem", 6 | "keywords": [ 7 | "jedlikowski", 8 | "laravel-nextcloud" 9 | ], 10 | "homepage": "https://github.com/jedlikowski/laravel-nextcloud", 11 | "license": "MIT", 12 | "authors": [ 13 | { 14 | "name": "Jakub Jedlikowski", 15 | "role": "Developer" 16 | } 17 | ], 18 | "require": { 19 | "php": "~5.6|^7.0", 20 | "illuminate/filesystem": "5.0.* || 5.1.* || 5.2.* || 5.3.* || 5.4.* || 5.5.* || 5.6.* || 5.7.* || 5.8.*", 21 | "league/flysystem-webdav": "^1.0.8", 22 | "jakeasmith/http_build_url": "^1" 23 | }, 24 | "require-dev": { 25 | "orchestra/testbench": "^3.0", 26 | "phpunit/phpunit": "~5.0|~6.0|~7.0|~8.0" 27 | }, 28 | "autoload": { 29 | "psr-4": { 30 | "Jedlikowski\\NextCloudStorage\\": "src" 31 | } 32 | }, 33 | "autoload-dev": { 34 | "psr-4": { 35 | "Jedlikowski\\NextCloudStorage\\Tests\\": "tests" 36 | } 37 | }, 38 | "scripts": { 39 | "test": "vendor/bin/phpunit" 40 | }, 41 | "extra": { 42 | "laravel": { 43 | "providers": [ 44 | "Jedlikowski\\NextCloudStorage\\NextCloudServiceProvider" 45 | ] 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/NextCloudAdapter.php: -------------------------------------------------------------------------------- 1 | 'size', 25 | '{DAV:}getcontenttype' => 'mimetype', 26 | 'content-length' => 'size', 27 | 'content-type' => 'mimetype', 28 | '{http://owncloud.org/ns}size' => 'size', 29 | ]; 30 | 31 | protected $config; 32 | 33 | public function __construct(Client $client, string $pathPrefix, array $config) 34 | { 35 | $this->config = $config; 36 | parent::__construct($client, $pathPrefix); 37 | } 38 | 39 | protected function isDirectory(array $object) 40 | { 41 | if (isset($object['{DAV:}resourcetype']) && $object['{DAV:}resourcetype'] instanceof ResourceType && $object['{DAV:}resourcetype']->is('{DAV:}collection')) { 42 | return true; 43 | } 44 | 45 | return parent::isDirectory($object); 46 | } 47 | 48 | public function getUrl($path) 49 | { 50 | $location = $this->applyPathPrefix($this->encodePath($path)); 51 | $urlParts = parse_url($this->client->getAbsoluteUrl($location)); 52 | $urlParts['user'] = $this->config['userName']; 53 | $urlParts['pass'] = $this->config['password']; 54 | return http_build_url($urlParts); 55 | } 56 | } -------------------------------------------------------------------------------- /src/NextCloudServiceProvider.php: -------------------------------------------------------------------------------- 1 | set('filesystems.disks.nextcloud', [ 19 | 'driver' => 'nextcloud', 20 | 'baseUri' => 'https://mywebdavstorage.com', 21 | 'userName' => 'jedlikowski', 22 | 'password' => 'supersecretpassword', 23 | ]); 24 | } 25 | 26 | /** @test */ 27 | public function it_registers_a_webdav_driver() 28 | { 29 | $filesystem = Storage::disk('nextcloud'); 30 | $driver = $filesystem->getDriver(); 31 | $adapter = $driver->getAdapter(); 32 | 33 | $this->assertInstanceOf(NextCloudAdapter::class, $adapter); 34 | } 35 | 36 | /** @test */ 37 | public function it_can_have_an_optional_path_prefix() 38 | { 39 | $this->app['config']->set('filesystems.disks.nextcloud.pathPrefix', 'prefix'); 40 | $userName = $this->app['config']->get('filesystems.disks.nextcloud.userName'); 41 | 42 | $filesystem = Storage::disk('nextcloud'); 43 | $driver = $filesystem->getDriver(); 44 | $adapter = $driver->getAdapter(); 45 | 46 | $this->assertInstanceOf(NextCloudAdapter::class, $adapter); 47 | $this->assertEquals('prefix/remote.php/dav/files/' . $userName . '/', $adapter->getPathPrefix()); 48 | } 49 | 50 | /** @test */ 51 | public function it_can_generate_direct_url_to_file() 52 | { 53 | $userName = $this->app['config']->get('filesystems.disks.nextcloud.userName'); 54 | $filesystem = Storage::disk('nextcloud'); 55 | $driver = $filesystem->getDriver(); 56 | $adapter = $driver->getAdapter(); 57 | 58 | $filename = 'backup-2019-09-25-21-00-00.zip'; 59 | $targetUrl = 'https://jedlikowski:supersecretpassword@mywebdavstorage.com/remote.php/dav/files/' . $userName . '/' . $filename; 60 | 61 | $this->assertInstanceOf(NextCloudAdapter::class, $adapter); 62 | $this->assertEquals($targetUrl, $filesystem->url($filename)); 63 | } 64 | } --------------------------------------------------------------------------------