Skip to content

Instantly share code, notes, and snippets.

@roxblnfk
Last active July 16, 2019 23:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save roxblnfk/591c944a71e32cc39349a37f64b8d2ed to your computer and use it in GitHub Desktop.
Save roxblnfk/591c944a71e32cc39349a37f64b8d2ed to your computer and use it in GitHub Desktop.
FlySystem/WebDAV wrapper (fix ->readStream() for v1.0.5 https://github.com/thephpleague/flysystem-webdav/tree/1.0.5)
<?php
use League\Flysystem\Filesystem;
use WebDAVAdapterWrapper;
use WebDAVClientWrapper;
$client = new WebDAVClientWrapper($settings);
$adapter = new WebDAVAdapterWrapper($client);
$flysystem = new Filesystem($adapter);
<?php
use League\Flysystem\Util;
use League\Flysystem\WebDAV\WebDAVAdapter;
class WebDAVAdapterWrapper extends WebDAVAdapter
{
/**
* @var WebDAVClientWrapper
*/
protected $client;
/**
* {@inheritdoc}
*/
public function readStream($path)
{
$location = $this->applyPathPrefix($this->encodePath($path));
try {
$response = $this->client->request('GET', $location);
if ($response['statusCode'] !== 200) {
return false;
}
return array_merge([
'stream' => $response['response']->getBodyAsStream(),
'timestamp' => strtotime(is_array($response['headers']['last-modified'])
? current($response['headers']['last-modified'])
: $response['headers']['last-modified']),
'path' => $path,
], Util::map($response['headers'], static::$resultMap));
} catch (\Exception $e) {
return false;
}
}
/**
* {@inheritdoc}
*/
public function read($path)
{
$location = $this->applyPathPrefix($this->encodePath($path));
try {
$response = $this->client->request('GET', $location);
if ($response['statusCode'] !== 200) {
return false;
}
return array_merge([
'contents' => isset($response['body']) ? $response['body'] : $response['response']->getBodyAsString(),
'timestamp' => strtotime(is_array($response['headers']['last-modified'])
? current($response['headers']['last-modified'])
: $response['headers']['last-modified']),
'path' => $path,
], Util::map($response['headers'], static::$resultMap));
} catch (\Exception $e) {
return false;
}
}
}
<?php
use Sabre\DAV\Client;
use Sabre\HTTP\ClientException;
use Sabre\HTTP\ClientHttpException;
use Sabre\HTTP\Request;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\Response;
use Sabre\HTTP\ResponseInterface;
class WebDAVClientWrapper extends Client
{
/**
* Cached curl handle.
* @var resource
*/
protected $curlHandle;
/**
* Performs an actual HTTP request, and returns the result.
*
* If the specified url is relative, it will be expanded based on the base
* url.
*
* The returned array contains 3 keys:
* * response - the response instance
* * httpCode - a HTTP code (200, 404, etc)
* * headers - a list of response http headers. The header names have
* been lowercased.
*
* For large uploads, it's highly recommended to specify body as a stream
* resource. You can easily do this by simply passing the result of
* fopen(..., 'r').
*
* This method will throw an exception if an HTTP error was received. Any
* HTTP status code above 399 is considered an error.
*
* Note that it is no longer recommended to use this method, use the send()
* method instead.
*
* @param string $method
* @param string $url
* @param string|resource|null $body
* @param array $headers
* @return ResponseInterface[]|array
* @throws ClientHttpException
* @throws ClientException, in case a curl error occurred.
*/
function request($method, $url = '', $body = null, array $headers = [])
{
$url = $this->getAbsoluteUrl($url);
$response = $this->send(new Request($method, $url, $headers, $body));
return [
'response' => $response,
// 'body' => $response->getBodyAsString(),
'statusCode' => (int)$response->getStatus(),
'headers' => array_change_key_case($response->getHeaders()),
];
}
/**
* This method is responsible for performing a single request.
*
* @param RequestInterface $request
* @return ResponseInterface
* @throws ClientException
*/
protected function doRequest(RequestInterface $request)
{
$settings = $this->createCurlSettingsArray($request);
$settings[CURLOPT_RETURNTRANSFER] = false;
$settings[CURLOPT_HEADER] = false;
$headers = '';
$settings[CURLOPT_HEADERFUNCTION] = function ($curl, $str) use (&$headers) {
$headers .= $str;
return strlen($str);
};
$body = '';
if (!key_exists(CURLOPT_NOBODY, $settings) || !$settings[CURLOPT_NOBODY]) {
$settings[CURLOPT_FILE] = $body = tmpfile();
}
if (!$this->curlHandle) {
$this->curlHandle = curl_init();
}
curl_setopt_array($this->curlHandle, $settings);
$this->curlExec($this->curlHandle);
if ($body)
rewind($body);
$response = $this->parseCurlSeparatedResult($headers, $body, $this->curlHandle);
if ($response['status'] === self::STATUS_CURLERROR) {
throw new ClientException($response['curl_errmsg'], $response['curl_errno']);
}
return $response['response'];
}
/**
* @param string $headers
* @param resource|string $body
* @param resource $curlHandle
* @return array
*/
protected function parseCurlSeparatedResult($headers, $body, $curlHandle)
{
list($curlInfo, $curlErrNo, $curlErrMsg) = $this->curlStuff($curlHandle);
if ($curlErrNo) {
return [
'status' => self::STATUS_CURLERROR,
'curl_errno' => $curlErrNo,
'curl_errmsg' => $curlErrMsg,
];
}
$response = new Response($curlInfo['http_code'], null, $body);
$headerBlob = explode("\r\n\r\n", trim($headers, "\r\n"));
# We only care about the last set of headers
$headerBlob = end($headerBlob);
# Splitting headers
$headerBlob = explode("\r\n", $headerBlob);
foreach ($headerBlob as $header) {
$parts = explode(':', $header, 2);
if (count($parts) == 2) {
$response->addHeader(trim($parts[0]), trim($parts[1]));
}
}
$httpCode = intval($response->getStatus());
return [
'status' => $httpCode >= 400 ? self::STATUS_HTTPERROR : self::STATUS_SUCCESS,
'response' => $response,
'http_code' => $httpCode,
];
}
}
@roxblnfk
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment