media_avportal-8.x-1.0-beta10/src/StreamWrapper/AvPortalStreamWrapper.php
src/StreamWrapper/AvPortalStreamWrapper.php
<?php
declare(strict_types=1);
namespace Drupal\media_avportal\StreamWrapper;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\StreamWrapper\ReadOnlyStream;
use Drupal\Core\Utility\Error;
use Drupal\Core\StreamWrapper\StreamWrapperInterface;
use Drupal\media_avportal\AvPortalClientInterface;
use Psr\Http\Message\StreamInterface;
/**
* AV Portal stream wrapper.
*
* @codingStandardsIgnoreStart PSR1.Methods.CamelCapsMethodName
*/
abstract class AvPortalStreamWrapper extends ReadOnlyStream implements AvPortalStreamWrapperInterface {
/**
* The AV Portal client.
*
* @var \Drupal\media_avportal\AvPortalClientInterface
*/
protected AvPortalClientInterface $avPortalClient;
/**
* The AV Portal configuration.
*
* @var \Drupal\Core\Config\ImmutableConfig
*/
protected ImmutableConfig $configuration;
/**
* The response stream.
*
* @var \Psr\Http\Message\StreamInterface
*/
protected StreamInterface $stream;
/**
* AvPortalStreamWrapper constructor.
*/
public function __construct() {
// Dependency injection does not work with stream wrappers.
$this->avPortalClient = \Drupal::service('media_avportal.client');
$this->configuration = \Drupal::configFactory()->get('media_avportal.settings');
}
/**
* {@inheritdoc}
*/
public function dir_closedir(): bool {
trigger_error('dir_closedir() not supported for AV portal stream wrappers', E_USER_WARNING);
return FALSE;
}
/**
* {@inheritdoc}
*/
public function dir_opendir($path, $options): bool {
trigger_error('dir_opendir() not supported for AV portal stream wrappers', E_USER_WARNING);
return FALSE;
}
/**
* {@inheritdoc}
*/
public function dir_readdir(): bool {
trigger_error('dir_readdir() not supported for AV portal stream wrappers', E_USER_WARNING);
return FALSE;
}
/**
* {@inheritdoc}
*/
public function dir_rewinddir(): bool {
trigger_error('dir_rewinddir() not supported for AV portal stream wrappers', E_USER_WARNING);
return FALSE;
}
/**
* {@inheritdoc}
*/
public function dirname($uri = NULL): string {
if (!isset($uri)) {
$uri = $this->uri;
}
[$scheme, $target] = explode('://', $uri, 2);
$dirname = dirname($target);
if ($dirname == '.') {
$dirname = '';
}
return $scheme . '://' . $dirname;
}
/**
* {@inheritdoc}
*/
public function stream_cast($cast_as): bool {
trigger_error('stream_cast() not supported for AV portal stream wrappers', E_USER_WARNING);
return FALSE;
}
/**
* {@inheritdoc}
*/
public function stream_close(): int {
return 0;
}
/**
* {@inheritdoc}
*/
public function stream_eof(): bool {
return $this->stream->eof();
}
/**
* {@inheritdoc}
*/
public function stream_open($path, $mode, $options, &$opened_path): bool {
if (!in_array($mode, ['r', 'rb'])) {
return FALSE;
}
try {
$this->setUri($path);
$response = $this->avPortalClient->resourceRequestByUri($this->uri);
$this->stream = $response->getBody();
}
catch (\Exception $exception) {
if ($options & STREAM_REPORT_ERRORS) {
Error::logException(\Drupal::logger('media_avportal'), $exception);
}
return FALSE;
}
if ($options & STREAM_USE_PATH) {
$opened_path = $path;
}
return TRUE;
}
/**
* {@inheritdoc}
*/
public function stream_read($count): string|false {
return $this->stream->read($count);
}
/**
* {@inheritdoc}
*/
public function stream_seek($offset, $whence = SEEK_SET): bool {
try {
$this->stream->seek($offset, $whence);
}
catch (\RuntimeException) {
return FALSE;
}
return TRUE;
}
/**
* Change stream options.
*/
public function stream_set_option($option, $arg1, $arg2): bool {
return FALSE;
}
/**
* {@inheritdoc}
*/
public function stream_stat(): array|false {
// This has been copied from
// https://github.com/guzzle/psr7/blob/2.7/src/StreamWrapper.php
// See also https://www.php.net/manual/en/function.stat.php
return [
'dev' => 0,
'ino' => 0,
'mode' => 0100000 | 0444, // regular file + read only
'nlink' => 0,
'uid' => 0,
'gid' => 0,
'rdev' => 0,
'size' => 0,
'atime' => 0,
'mtime' => 0,
'ctime' => 0,
'blksize' => 0,
'blocks' => 0,
];
}
/**
* {@inheritdoc}
*/
public function stream_tell(): int {
return $this->stream->tell();
}
/**
* {@inheritdoc}
*/
public function url_stat($path, $flags): array|false {
$this->setUri($path);
return ($flags & STREAM_URL_STAT_QUIET)
? @$this->stream_stat()
: $this->stream_stat();
}
/**
* {@inheritdoc}
*/
public static function getType(): int {
return StreamWrapperInterface::READ;
}
/**
* {@inheritdoc}
*/
public function realpath(): string {
return $this->getTarget();
}
/**
* Returns the local target of the resource within the stream.
*
* @param null $uri
* The URI.
*
* @return string
* The target.
*/
protected function getTarget($uri = NULL): string {
if (!isset($uri)) {
$uri = $this->uri;
}
[, $target] = explode('://', $uri, 2);
return trim($target, '\/');
}
/**
* Appends the scheme to the external URL retrieved by getExternalUrl().
*
* @param string $url
* The external URL.
*
* @return string
* The full external URL.
*/
protected function getFullExternalUrl(string $url): string {
$parsed = parse_url($url);
if (!isset($parsed['scheme'])) {
$url = 'https:' . $url;
}
return $url;
}
}
