lib/private/Files/Meta/MetaFileVersionNode.php
<?php
/**
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @copyright Copyright (c) 2022, ownCloud GmbH
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Files\Meta;
use OC\Files\Filesystem;
use OC\Files\Node\AbstractFile;
use OC\Files\Node\File;
use OCP\Files\ForbiddenException;
use OCP\Files\IProvidesAdditionalHeaders;
use OC\Preview;
use OCA\Files_Sharing\SharedStorage;
use OCP\Files\IProvidesVersionAuthor;
use OCP\Files\IProvidesVersionTag;
use OCP\Files\IRootFolder;
use OCP\Files\IPreviewNode;
use OCP\Files\Storage\IVersionedStorage;
use OCP\Files\Storage\IStorage;
use OCP\IImage;
/**
* Noncurrent version of the file node. This class represents a version of a file in the meta endpoint
*
* @package OC\Files\Meta
*/
class MetaFileVersionNode extends AbstractFile implements IPreviewNode, IProvidesAdditionalHeaders, IProvidesVersionAuthor, IProvidesVersionTag {
/** @var string */
private $versionId;
/** @var MetaVersionCollection */
private $parent;
/** @var IStorage|IVersionedStorage|SharedStorage */
private $storage;
/** @var string */
private $internalPath;
/** @var IRootFolder */
private $root;
/** @var array */
private $versionInfo;
/**
* MetaFileVersionNode constructor.
*
* @param MetaVersionCollection $parent
* @param IRootFolder $root
* @param array $version
* @param IStorage|IVersionedStorage|SharedStorage $storage
* @param string $internalPath
*/
public function __construct(
MetaVersionCollection $parent,
IRootFolder $root,
array $version,
IStorage $storage,
$internalPath
) {
$this->parent = $parent;
$this->versionId = $version['version'];
$this->versionInfo = $version;
$this->storage = $storage;
$this->internalPath = $internalPath;
$this->root = $root;
}
/**
* @inheritdoc
*/
public function getName() {
return $this->versionId;
}
public function getPath() {
return $this->parent->getPath() . '/' . $this->getName();
}
/**
* @inheritdoc
*/
public function getEditedBy() : string {
return $this->versionInfo['edited_by'] ?? '';
}
/**
* @inheritdoc
*/
public function getVersionTag() : string {
return $this->versionInfo['version_tag'] ?? '';
}
/**
* @inheritdoc
*/
public function getSize() {
return isset($this->versionInfo['size']) ? $this->versionInfo['size'] : null;
}
/**
* @inheritdoc
*/
public function getContent() {
$handle = $this->fopen('r+');
$data = \stream_get_contents($handle);
\fclose($handle);
return $data;
}
/**
* @inheritdoc
*/
public function copy($targetPath) {
$target = $this->root->get($targetPath);
if ($target instanceof File && $target->getId() === $this->parent->getId()) {
if (!$target->isUpdateable()) {
throw new ForbiddenException("Cannot write to $targetPath", false);
}
return $this->storage->restoreVersion($this->internalPath, $this->versionId);
}
// for now we only allow restoring of a version
return false;
}
public function getMTime() {
return isset($this->versionInfo['timestamp']) ? $this->versionInfo['timestamp'] : null;
}
public function getMimetype() {
return isset($this->versionInfo['mimetype']) ? $this->versionInfo['mimetype'] : 'application/octet-stream';
}
public function getEtag() {
return isset($this->versionInfo['etag']) ? $this->versionInfo['etag'] : null;
}
public function fopen($mode) {
return $this->storage->getContentOfVersion($this->internalPath, $this->versionId);
}
/**
* @return array
*/
public function getHeaders() {
return [];
}
/**
* @inheritdoc
*/
public function getContentDispositionFileName() {
// internalPath is empty for the share receiver if a single file was shared.
// We need to retrieve the file name via the mount point then.
if ($this->storage->instanceOfStorage(SharedStorage::class) && $this->internalPath === '') {
$mountPoint = $this->storage->getMountPoint();
return \basename($mountPoint);
}
return \basename($this->internalPath);
}
public function getId() {
return $this->parent->getId();
}
public function getMountPoint() {
return Filesystem::getMountManager()->find($this->versionInfo['path']);
}
/**
* @param array $options
* @return IImage
* @since 10.1.0
*/
public function getThumbnail($options) {
$maxX = \array_key_exists('x', $options) ? (int)$options['x'] : 32;
$maxY = \array_key_exists('y', $options) ? (int)$options['y'] : 32;
$scalingUp = \array_key_exists('scalingup', $options) ? (bool)$options['scalingup'] : true;
$keepAspect = \array_key_exists('a', $options) ? true : false;
$mode = \array_key_exists('mode', $options) ? $options['mode'] : 'fill';
$preview = new Preview();
$preview->setFile($this, $this->versionId);
$preview->setMaxX($maxX);
$preview->setMaxY($maxY);
$preview->setScalingUp($scalingUp);
$preview->setMode($mode);
$preview->setKeepAspect($keepAspect);
return $preview->getPreview();
}
public function getStorage() {
return $this->storage;
}
public function isUpdateable() {
// Versions are not updateable
return false;
}
}