mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
8c2d211661
@ -7,6 +7,7 @@ charset = utf-8
|
||||
end_of_line = LF
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
indent_size = 4
|
||||
|
||||
[*.{php,html,twig}]
|
||||
indent_style = space
|
||||
|
@ -22,6 +22,7 @@
|
||||
"league/csv": "^9.7.1",
|
||||
"nyholm/psr7": "^1.4",
|
||||
"phpoffice/phpspreadsheet": "^1.16",
|
||||
"ramsey/uuid-doctrine": "^1.7",
|
||||
"sensio/framework-extra-bundle": "^5.5",
|
||||
"symfony/asset": "4.*",
|
||||
"symfony/browser-kit": "^5.2",
|
||||
@ -29,6 +30,7 @@
|
||||
"symfony/expression-language": "4.*",
|
||||
"symfony/form": "4.*",
|
||||
"symfony/intl": "4.*",
|
||||
"symfony/mime": "^4 || ^5",
|
||||
"symfony/monolog-bundle": "^3.5",
|
||||
"symfony/security-bundle": "4.*",
|
||||
"symfony/serializer": "^5.2",
|
||||
|
@ -7,7 +7,9 @@ namespace Chill\DocStoreBundle\Entity;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use ChampsLibres\AsyncUploaderBundle\Model\AsyncFileInterface;
|
||||
use ChampsLibres\AsyncUploaderBundle\Validator\Constraints\AsyncFileExists;
|
||||
use ChampsLibres\WopiLib\Contract\Entity\Document;
|
||||
use DateTimeInterface;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
@ -19,7 +21,7 @@ use Symfony\Component\Serializer\Annotation as Serializer;
|
||||
* message="The file is not stored properly"
|
||||
* )
|
||||
*/
|
||||
class StoredObject implements AsyncFileInterface
|
||||
class StoredObject implements AsyncFileInterface, Document
|
||||
{
|
||||
/**
|
||||
* @ORM\Id()
|
||||
@ -47,6 +49,11 @@ class StoredObject implements AsyncFileInterface
|
||||
*/
|
||||
private array $iv = [];
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="uuid", unique=true)
|
||||
*/
|
||||
private Uuid $uuid;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime", name="creation_date")
|
||||
* @Serializer\Groups({"read"})
|
||||
@ -68,6 +75,7 @@ class StoredObject implements AsyncFileInterface
|
||||
public function __construct()
|
||||
{
|
||||
$this->creationDate = new \DateTime();
|
||||
$this->uuid = Uuid::uuid4();
|
||||
}
|
||||
|
||||
public function getId()
|
||||
@ -155,5 +163,13 @@ class StoredObject implements AsyncFileInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUuid(): Uuid
|
||||
{
|
||||
return $this->uuid;
|
||||
}
|
||||
|
||||
public function getWopiDocId(): string
|
||||
{
|
||||
return (string) $this->uuid;
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,12 @@
|
||||
"description": "A Chill bundle to store documents",
|
||||
"type": "symfony-bundle",
|
||||
"autoload": {
|
||||
"psr-4": { "Chill\\DocStoreBundle\\" : "" }
|
||||
"psr-4": {
|
||||
"Chill\\DocStoreBundle\\": ""
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"symfony/mime": "^4 || ^5"
|
||||
},
|
||||
"license": "AGPL-3.0"
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\DocStore;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
final class Version20210928182542 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Create UUID column on StoredObject table.';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE chill_doc.stored_object ADD uuid UUID NOT NULL');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_49604E36D17F50A6 ON chill_doc.stored_object (uuid)');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('DROP INDEX UNIQ_49604E36D17F50A6');
|
||||
$this->addSql('ALTER TABLE chill_doc.stored_object DROP uuid');
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@
|
||||
"php": ">= 7.4",
|
||||
"champs-libres/wopi-bundle": "dev-master",
|
||||
"nyholm/psr7": "^1.4",
|
||||
"php-opencloud/openstack": "^3.2.1"
|
||||
"symfony/mime": "^4 || ^5"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
@ -9,9 +9,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\WopiBundle\Controller;
|
||||
|
||||
use ChampsLibres\WopiLib\Configuration\WopiConfigurationInterface;
|
||||
use ChampsLibres\WopiLib\Discovery\WopiDiscoveryInterface;
|
||||
use Chill\DocStoreBundle\Repository\StoredObjectRepository;
|
||||
use ChampsLibres\WopiLib\Contract\Service\Configuration\ConfigurationInterface;
|
||||
use ChampsLibres\WopiLib\Contract\Service\Discovery\DiscoveryInterface;
|
||||
use ChampsLibres\WopiLib\Contract\Service\DocumentManagerInterface;
|
||||
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||
use Chill\WopiBundle\Service\Controller\ResponderInterface;
|
||||
use Exception;
|
||||
use loophp\psr17\Psr17Interface;
|
||||
@ -23,11 +24,11 @@ use Symfony\Component\Security\Core\Security;
|
||||
|
||||
final class Test
|
||||
{
|
||||
private StoredObjectRepository $storedObjectRepository;
|
||||
private DiscoveryInterface $wopiDiscovery;
|
||||
|
||||
private WopiDiscoveryInterface $wopiDiscovery;
|
||||
private DocumentManagerInterface $documentManager;
|
||||
|
||||
private WopiConfigurationInterface $wopiConfiguration;
|
||||
private ConfigurationInterface $wopiConfiguration;
|
||||
|
||||
private ResponderInterface $responder;
|
||||
|
||||
@ -38,15 +39,15 @@ final class Test
|
||||
private RouterInterface $router;
|
||||
|
||||
public function __construct(
|
||||
StoredObjectRepository $storedObjectRepository,
|
||||
WopiConfigurationInterface $wopiConfiguration,
|
||||
WopiDiscoveryInterface $wopiDiscovery,
|
||||
ConfigurationInterface $wopiConfiguration,
|
||||
DiscoveryInterface $wopiDiscovery,
|
||||
DocumentManagerInterface $documentManager,
|
||||
ResponderInterface $responder,
|
||||
Security $security,
|
||||
Psr17Interface $psr17,
|
||||
RouterInterface $router
|
||||
) {
|
||||
$this->storedObjectRepository = $storedObjectRepository;
|
||||
$this->documentManager = $documentManager;
|
||||
$this->wopiConfiguration = $wopiConfiguration;
|
||||
$this->wopiDiscovery = $wopiDiscovery;
|
||||
$this->responder = $responder;
|
||||
@ -58,11 +59,11 @@ final class Test
|
||||
public function __invoke(string $fileId): Response
|
||||
{
|
||||
$configuration = $this->wopiConfiguration->jsonSerialize();
|
||||
|
||||
$storedObject = $this->storedObjectRepository->findOneBy(['filename' => $fileId]);
|
||||
/** @var StoredObject $storedObject */
|
||||
$storedObject = $this->documentManager->findByDocumentId($fileId);
|
||||
|
||||
if (null === $storedObject) {
|
||||
throw new NotFoundHttpException(sprintf('Unable to find object named %s', $fileId));
|
||||
throw new NotFoundHttpException(sprintf('Unable to find object %s', $fileId));
|
||||
}
|
||||
|
||||
if ([] === $discoverExtension = $this->wopiDiscovery->discoverMimeType($storedObject->getType())) {
|
||||
@ -83,7 +84,7 @@ final class Test
|
||||
->generate(
|
||||
'checkFileInfo',
|
||||
[
|
||||
'fileId' => $storedObject->getFilename(),
|
||||
'fileId' => $this->documentManager->getDocumentId($storedObject),
|
||||
],
|
||||
UrlGeneratorInterface::ABSOLUTE_URL
|
||||
),
|
||||
|
@ -10,8 +10,10 @@ declare(strict_types=1);
|
||||
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
||||
|
||||
use ChampsLibres\AsyncUploaderBundle\TempUrl\TempUrlGeneratorInterface;
|
||||
use ChampsLibres\WopiLib\Service\Contract\WopiInterface;
|
||||
use Chill\WopiBundle\Service\Wopi\ChillWopi;
|
||||
use ChampsLibres\WopiBundle\Service\Wopi as CLWopi;
|
||||
use ChampsLibres\WopiLib\Contract\Service\DocumentManagerInterface;
|
||||
use Chill\WopiBundle\Service\Wopi\ChillDocumentManager;
|
||||
|
||||
return static function (ContainerConfigurator $container) {
|
||||
$services = $container
|
||||
@ -30,8 +32,14 @@ return static function (ContainerConfigurator $container) {
|
||||
->tag('controller.service_arguments');
|
||||
|
||||
$services
|
||||
->alias(WopiInterface::class, ChillWopi::class);
|
||||
->set(ChillWopi::class)
|
||||
->decorate(CLWopi::class)
|
||||
->arg('$wopi', service('.inner'));
|
||||
|
||||
$services
|
||||
->alias(DocumentManagerInterface::class, ChillDocumentManager::class);
|
||||
|
||||
// TODO: Move this into the async bundle (low priority)
|
||||
$services
|
||||
->alias(TempUrlGeneratorInterface::class, 'async_uploader.temp_url_generator');
|
||||
};
|
||||
|
@ -0,0 +1,243 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\WopiBundle\Service\Wopi;
|
||||
|
||||
use ChampsLibres\AsyncUploaderBundle\TempUrl\TempUrlGeneratorInterface;
|
||||
use ChampsLibres\WopiLib\Contract\Entity\Document;
|
||||
use ChampsLibres\WopiLib\Contract\Service\DocumentLockManagerInterface;
|
||||
use ChampsLibres\WopiLib\Contract\Service\DocumentManagerInterface;
|
||||
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||
use Chill\DocStoreBundle\Repository\StoredObjectRepository;
|
||||
use DateTimeInterface;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Error;
|
||||
use loophp\psr17\Psr17Interface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\Mime\MimeTypes;
|
||||
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
use Throwable;
|
||||
|
||||
final class ChillDocumentManager implements DocumentManagerInterface
|
||||
{
|
||||
private DocumentLockManagerInterface $documentLockManager;
|
||||
|
||||
private EntityManagerInterface $entityManager;
|
||||
|
||||
private HttpClientInterface $httpClient;
|
||||
|
||||
private Psr17Interface $psr17;
|
||||
|
||||
private RequestInterface $request;
|
||||
|
||||
private StoredObjectRepository $storedObjectRepository;
|
||||
|
||||
private TempUrlGeneratorInterface $tempUrlGenerator;
|
||||
|
||||
public function __construct(
|
||||
DocumentLockManagerInterface $documentLockManager,
|
||||
EntityManagerInterface $entityManager,
|
||||
HttpClientInterface $httpClient,
|
||||
Psr17Interface $psr17,
|
||||
StoredObjectRepository $storedObjectRepository,
|
||||
TempUrlGeneratorInterface $tempUrlGenerator,
|
||||
HttpMessageFactoryInterface $httpMessageFactory,
|
||||
RequestStack $requestStack
|
||||
) {
|
||||
$this->entityManager = $entityManager;
|
||||
$this->psr17 = $psr17;
|
||||
$this->storedObjectRepository = $storedObjectRepository;
|
||||
$this->documentLockManager = $documentLockManager;
|
||||
$this->tempUrlGenerator = $tempUrlGenerator;
|
||||
$this->httpClient = $httpClient;
|
||||
$this->request = $httpMessageFactory->createRequest($requestStack->getCurrentRequest());
|
||||
}
|
||||
|
||||
public function create(array $data): Document
|
||||
{
|
||||
/** @var StoredObject $document */
|
||||
$document = (new ObjectNormalizer())->denormalize([], StoredObject::class);
|
||||
|
||||
// Mime types / extension handling.
|
||||
$mimeTypes = new MimeTypes();
|
||||
$mimeTypes->getMimeTypes($data['extension']);
|
||||
$document->setType(reset($mimeTypes));
|
||||
|
||||
$document->setFilename($data['name']);
|
||||
|
||||
$this->entityManager->persist($document);
|
||||
$this->entityManager->flush($document);
|
||||
|
||||
// TODO : Ask proper mapping.
|
||||
// Available: basename, name, extension, content, size
|
||||
$this->setContent($document, $data['content']);
|
||||
|
||||
return $document;
|
||||
}
|
||||
|
||||
public function deleteLock(Document $document): void {
|
||||
$this->documentLockManager->deleteLock($document, $this->request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $documentFilename without extension !
|
||||
*/
|
||||
public function findByDocumentFilename(string $documentFilename): ?Document {
|
||||
return $this->storedObjectRepository->findOneBy(
|
||||
[
|
||||
'filename' => $documentFilename,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function findByDocumentId(string $documentId): ?Document {
|
||||
return $this->storedObjectRepository->findOneBy(
|
||||
[
|
||||
'uuid' => $documentId,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StoredObject $document
|
||||
*/
|
||||
public function getCreationDate(Document $document): DateTimeInterface
|
||||
{
|
||||
return $document->getCreationDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StoredObject $document
|
||||
*/
|
||||
public function getLastModifiedDate(Document $document): DateTimeInterface
|
||||
{
|
||||
// TODO: Add column 'LastModifiedDate' in StoredObject entity
|
||||
return $document->getCreationDate();
|
||||
}
|
||||
|
||||
public function getLock(Document $document): string {
|
||||
return $this->documentLockManager->getLock($document, $this->request);
|
||||
}
|
||||
|
||||
public function getVersion(Document $document): string {
|
||||
// TODO ?
|
||||
return '0';
|
||||
}
|
||||
|
||||
public function hasLock(Document $document): bool {
|
||||
return $this->documentLockManager->hasLock($document, $this->request);
|
||||
}
|
||||
|
||||
public function lock(Document $document, string $lock): void {
|
||||
$this->documentLockManager->setLock($document, $lock, $this->request);
|
||||
}
|
||||
|
||||
public function remove(Document $document): void {
|
||||
$entityIsDeleted = false;
|
||||
|
||||
try {
|
||||
$this->entityManager->remove($document);
|
||||
$entityIsDeleted = true;
|
||||
} catch (Throwable $e) {
|
||||
$entityIsDeleted = false;
|
||||
}
|
||||
|
||||
if ($entityIsDeleted === true) {
|
||||
$this->deleteContent($document);
|
||||
}
|
||||
}
|
||||
|
||||
public function write(Document $document, array $properties = []): void
|
||||
{
|
||||
$this->setContent($document, $properties['content']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StoredObject $document
|
||||
*
|
||||
* @return string The document filename with its extension.
|
||||
*/
|
||||
public function getBasename(Document $document): string {
|
||||
$exts = (new MimeTypes())->getExtensions($document->getType());
|
||||
|
||||
if ([] === $exts) {
|
||||
throw new Error('Unknown mimetype for stored document.');
|
||||
}
|
||||
|
||||
return sprintf('%s.%s', $document->getFilename(), reset($exts));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StoredObject $document
|
||||
*/
|
||||
public function getDocumentId(Document $document): string {
|
||||
return (string) $document->getUuid();
|
||||
}
|
||||
|
||||
public function getSha256(Document $document): string {
|
||||
return base64_encode(hash('sha256', $this->getContent($document)));
|
||||
}
|
||||
|
||||
public function getSize(Document $document): int {
|
||||
return strlen(stream_get_contents($this->read($document)));
|
||||
}
|
||||
|
||||
public function read(Document $document): StreamInterface {
|
||||
return $this
|
||||
->psr17
|
||||
->createStream($this->getContent($document));
|
||||
}
|
||||
|
||||
private function deleteContent(StoredObject $storedObject): string
|
||||
{
|
||||
/** @var StdClass $object */
|
||||
$object = $this->tempUrlGenerator->generate('DELETE', $storedObject->getFilename());
|
||||
|
||||
$response = $this->httpClient->request('DELETE', $object->url);
|
||||
|
||||
if (200 !== $response->getStatusCode())
|
||||
{
|
||||
throw new Error('Unable to delete stored object.');
|
||||
}
|
||||
}
|
||||
|
||||
private function getContent(StoredObject $storedObject): string
|
||||
{
|
||||
/** @var StdClass $object */
|
||||
$object = $this->tempUrlGenerator->generate('GET', $storedObject->getFilename());
|
||||
|
||||
$response = $this->httpClient->request('GET', $object->url);
|
||||
|
||||
if (200 !== $response->getStatusCode())
|
||||
{
|
||||
throw new Error('Unable to retrieve stored object.');
|
||||
}
|
||||
|
||||
return $response->getContent();
|
||||
}
|
||||
|
||||
private function setContent(StoredObject $storedObject, string $content): void
|
||||
{
|
||||
// TODO: Add strict typing in champs-libres/async-uploader-bundle
|
||||
/** @var StdClass $object */
|
||||
$object = $this->tempUrlGenerator->generate('PUT', $storedObject->getFilename());
|
||||
|
||||
$response = $this->httpClient->request('PUT', $object->url, ['body' => $content]);
|
||||
|
||||
if (200 !== $response->getStatusCode())
|
||||
{
|
||||
throw new Error('Unable to save stored object.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -9,46 +9,28 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\WopiBundle\Service\Wopi;
|
||||
|
||||
use ChampsLibres\AsyncUploaderBundle\TempUrl\TempUrlGeneratorInterface;
|
||||
use ChampsLibres\WopiLib\Discovery\WopiDiscoveryInterface;
|
||||
use ChampsLibres\WopiLib\Service\Contract\WopiInterface;
|
||||
use Chill\DocStoreBundle\Repository\StoredObjectRepository;
|
||||
use Exception;
|
||||
use ChampsLibres\WopiLib\Contract\Service\DocumentManagerInterface;
|
||||
use ChampsLibres\WopiLib\Contract\Service\WopiInterface;
|
||||
use loophp\psr17\Psr17Interface;
|
||||
use Psr\Http\Client\ClientInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
|
||||
final class ChillWopi implements WopiInterface
|
||||
{
|
||||
private DocumentManagerInterface $documentManager;
|
||||
|
||||
private Psr17Interface $psr17;
|
||||
|
||||
private WopiDiscoveryInterface $wopiDiscovery;
|
||||
|
||||
private StoredObjectRepository $storedObjectRepository;
|
||||
|
||||
private ClientInterface $httpClient;
|
||||
|
||||
private TempUrlGeneratorInterface $tempUrlGenerator;
|
||||
|
||||
private UserProviderInterface $userProvider;
|
||||
private WopiInterface $wopi;
|
||||
|
||||
public function __construct(
|
||||
DocumentManagerInterface $documentManager,
|
||||
Psr17Interface $psr17,
|
||||
WopiDiscoveryInterface $wopiDiscovery,
|
||||
StoredObjectRepository $storedObjectRepository,
|
||||
ClientInterface $httpClient,
|
||||
TempUrlGeneratorInterface $tempUrlGenerator,
|
||||
UserProviderInterface $userProvider
|
||||
WopiInterface $wopi
|
||||
) {
|
||||
$this->documentManager = $documentManager;
|
||||
$this->psr17 = $psr17;
|
||||
$this->wopiDiscovery = $wopiDiscovery;
|
||||
$this->storedObjectRepository = $storedObjectRepository;
|
||||
$this->httpClient = $httpClient;
|
||||
$this->tempUrlGenerator = $tempUrlGenerator;
|
||||
$this->userProvider = $userProvider;
|
||||
$this->wopi = $wopi;
|
||||
}
|
||||
|
||||
public function checkFileInfo(
|
||||
@ -56,59 +38,31 @@ final class ChillWopi implements WopiInterface
|
||||
?string $accessToken,
|
||||
RequestInterface $request
|
||||
): ResponseInterface {
|
||||
try {
|
||||
$user = $this->userProvider->loadUserByUsername($accessToken);
|
||||
} catch (UsernameNotFoundException $e) {
|
||||
return $this
|
||||
->psr17
|
||||
->createResponse(401);
|
||||
}
|
||||
$response = $this->wopi->checkFileInfo($fileId, $accessToken, $request);
|
||||
$document = $this->documentManager->findByDocumentId($fileId);
|
||||
|
||||
$storedObject = $this->storedObjectRepository->findOneBy(['filename' => $fileId]);
|
||||
$body = json_decode((string) $response->getBody(), true);
|
||||
|
||||
if (null === $storedObject) {
|
||||
throw new Exception(sprintf('Unable to find object named %s', $fileId));
|
||||
}
|
||||
|
||||
$mimeType = $storedObject->getType();
|
||||
|
||||
if ([] === $this->wopiDiscovery->discoverMimeType($mimeType)) {
|
||||
throw new Exception(sprintf('Unable to find mime type %s', $mimeType));
|
||||
}
|
||||
|
||||
return $this
|
||||
->psr17
|
||||
->createResponse()
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withBody($this->psr17->createStream((string) json_encode(
|
||||
[
|
||||
'BaseFileName' => $storedObject->getFilename(),
|
||||
'OwnerId' => uniqid(),
|
||||
'Size' => 0,
|
||||
'UserId' => uniqid(),
|
||||
// 'Version' => 'v' . uniqid(),
|
||||
'ReadOnly' => false,
|
||||
'UserCanWrite' => true,
|
||||
'UserCanNotWriteRelative' => true,
|
||||
'SupportsLocks' => false,
|
||||
'UserFriendlyName' => sprintf('User %s', $user->getUsername()),
|
||||
'UserExtraInfo' => [],
|
||||
'LastModifiedTime' => date('Y-m-d\TH:i:s.u\Z', $storedObject->getCreationDate()->getTimestamp()),
|
||||
'CloseButtonClosesWindow' => true,
|
||||
'EnableInsertRemoteImage' => true,
|
||||
'EnableShare' => false,
|
||||
'SupportsUpdate' => true,
|
||||
'SupportsRename' => false,
|
||||
'DisablePrint' => false,
|
||||
'DisableExport' => false,
|
||||
'DisableCopy' => false,
|
||||
]
|
||||
)));
|
||||
return $response
|
||||
->withBody(
|
||||
$this
|
||||
->psr17
|
||||
->createStream(
|
||||
(string) json_encode(
|
||||
$body +
|
||||
[
|
||||
'Version' => sprintf('v%s', $this->documentManager->getVersion($document)),
|
||||
// TODO: Add column 'LastModifiedDate' in StoredObject entity
|
||||
'LastModifiedTime' => $this->documentManager->getLastModifiedDate($document)->format('Y-m-d\TH:i:s.uP'),
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function deleteFile(string $fileId, ?string $accessToken, RequestInterface $request): ResponseInterface
|
||||
{
|
||||
return $this->getDebugResponse(__FUNCTION__, $request);
|
||||
return $this->wopi->deleteFile($fileId, $accessToken, $request);
|
||||
}
|
||||
|
||||
public function enumerateAncestors(
|
||||
@ -116,57 +70,17 @@ final class ChillWopi implements WopiInterface
|
||||
?string $accessToken,
|
||||
RequestInterface $request
|
||||
): ResponseInterface {
|
||||
return $this->getDebugResponse(__FUNCTION__, $request);
|
||||
return $this->wopi->enumerateAncestors($fileId, $accessToken, $request);
|
||||
}
|
||||
|
||||
public function getFile(string $fileId, ?string $accessToken, RequestInterface $request): ResponseInterface
|
||||
{
|
||||
try {
|
||||
$user = $this->userProvider->loadUserByUsername($accessToken);
|
||||
} catch (UsernameNotFoundException $e) {
|
||||
return $this
|
||||
->psr17
|
||||
->createResponse(401);
|
||||
}
|
||||
|
||||
$storedObject = $this->storedObjectRepository->findOneBy(['filename' => $fileId]);
|
||||
|
||||
if (null === $storedObject) {
|
||||
return $this
|
||||
->psr17
|
||||
->createResponse(404);
|
||||
}
|
||||
|
||||
// TODO: Add strict typing in champs-libres/async-uploader-bundle
|
||||
/** @var StdClass $object */
|
||||
$object = $this->tempUrlGenerator->generate('GET', $storedObject->getFilename());
|
||||
|
||||
$response = $this->httpClient->sendRequest($this->psr17->createRequest('GET', $object->url));
|
||||
|
||||
if (200 !== $response->getStatusCode())
|
||||
{
|
||||
return $this
|
||||
->psr17
|
||||
->createResponse(500);
|
||||
}
|
||||
|
||||
return $this
|
||||
->psr17
|
||||
->createResponse()
|
||||
->withHeader(
|
||||
'Content-Type',
|
||||
'application/octet-stream',
|
||||
)
|
||||
->withHeader(
|
||||
'Content-Disposition',
|
||||
sprintf('attachment; filename=%s', $storedObject->getFilename())
|
||||
)
|
||||
->withBody($response->getBody());
|
||||
return $this->wopi->getFile($fileId, $accessToken, $request);
|
||||
}
|
||||
|
||||
public function getLock(string $fileId, ?string $accessToken, RequestInterface $request): ResponseInterface
|
||||
{
|
||||
return $this->getDebugResponse(__FUNCTION__, $request);
|
||||
return $this->wopi->getLock($fileId, $accessToken, $request);
|
||||
}
|
||||
|
||||
public function getShareUrl(
|
||||
@ -174,7 +88,7 @@ final class ChillWopi implements WopiInterface
|
||||
?string $accessToken,
|
||||
RequestInterface $request
|
||||
): ResponseInterface {
|
||||
return $this->getDebugResponse(__FUNCTION__, $request);
|
||||
return $this->wopi->getShareUrl($fileId, $accessToken, $request);
|
||||
}
|
||||
|
||||
public function lock(
|
||||
@ -183,7 +97,7 @@ final class ChillWopi implements WopiInterface
|
||||
string $xWopiLock,
|
||||
RequestInterface $request
|
||||
): ResponseInterface {
|
||||
return $this->getDebugResponse(__FUNCTION__, $request);
|
||||
return $this->wopi->lock($fileId, $accessToken, $xWopiLock, $request);
|
||||
}
|
||||
|
||||
public function putFile(
|
||||
@ -193,49 +107,17 @@ final class ChillWopi implements WopiInterface
|
||||
string $xWopiEditors,
|
||||
RequestInterface $request
|
||||
): ResponseInterface {
|
||||
try {
|
||||
$user = $this->userProvider->loadUserByUsername($accessToken);
|
||||
} catch (UsernameNotFoundException $e) {
|
||||
return $this
|
||||
->psr17
|
||||
->createResponse(401);
|
||||
}
|
||||
|
||||
$storedObject = $this->storedObjectRepository->findOneBy(['filename' => $fileId]);
|
||||
|
||||
if (null === $storedObject) {
|
||||
throw new Exception(sprintf('Unable to find object named %s', $fileId));
|
||||
}
|
||||
|
||||
// TODO: Add strict typing in champs-libres/async-uploader-bundle
|
||||
/** @var StdClass $object */
|
||||
$object = $this->tempUrlGenerator->generate('PUT', $storedObject->getFilename());
|
||||
|
||||
$response = $this->httpClient->sendRequest($this->psr17->createRequest('PUT', $object->url)->withBody($request->getBody()));
|
||||
|
||||
if (201 !== $response->getStatusCode())
|
||||
{
|
||||
return $this
|
||||
->psr17
|
||||
->createResponse(500);
|
||||
}
|
||||
|
||||
return $this
|
||||
->psr17
|
||||
->createResponse()
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withAddedHeader('X-WOPI-Lock', $xWopiLock)
|
||||
->withBody($this->psr17->createStream((string) json_encode([])));
|
||||
return $this->wopi->putFile($fileId, $accessToken, $xWopiLock, $xWopiEditors, $request);
|
||||
}
|
||||
|
||||
public function putRelativeFile(string $fileId, string $accessToken, ?string $suggestedTarget, ?string $relativeTarget, bool $overwriteRelativeTarget, int $size, RequestInterface $request): ResponseInterface
|
||||
{
|
||||
return $this->getDebugResponse(__FUNCTION__, $request);
|
||||
return $this->wopi->putRelativeFile($fileId, $accessToken, $suggestedTarget, $relativeTarget, $overwriteRelativeTarget, $size, $request);
|
||||
}
|
||||
|
||||
public function putUserInfo(string $fileId, ?string $accessToken, RequestInterface $request): ResponseInterface
|
||||
{
|
||||
return $this->getDebugResponse(__FUNCTION__, $request);
|
||||
return $this->wopi->putUserInfo($fileId, $accessToken, $request);
|
||||
}
|
||||
|
||||
public function refreshLock(
|
||||
@ -244,7 +126,7 @@ final class ChillWopi implements WopiInterface
|
||||
string $xWopiLock,
|
||||
RequestInterface $request
|
||||
): ResponseInterface {
|
||||
return $this->getDebugResponse(__FUNCTION__, $request);
|
||||
return $this->wopi->refreshLock($fileId, $accessToken, $xWopiLock, $request);
|
||||
}
|
||||
|
||||
public function renameFile(
|
||||
@ -254,7 +136,7 @@ final class ChillWopi implements WopiInterface
|
||||
string $xWopiRequestedName,
|
||||
RequestInterface $request
|
||||
): ResponseInterface {
|
||||
return $this->getDebugResponse(__FUNCTION__, $request);
|
||||
return $this->wopi->renameFile($fileId, $accessToken, $xWopiLock, $xWopiRequestedName, $request);
|
||||
}
|
||||
|
||||
public function unlock(
|
||||
@ -263,7 +145,7 @@ final class ChillWopi implements WopiInterface
|
||||
string $xWopiLock,
|
||||
RequestInterface $request
|
||||
): ResponseInterface {
|
||||
return $this->getDebugResponse(__FUNCTION__, $request);
|
||||
return $this->wopi->unlock($fileId, $accessToken, $xWopiLock, $request);
|
||||
}
|
||||
|
||||
public function unlockAndRelock(
|
||||
@ -273,33 +155,6 @@ final class ChillWopi implements WopiInterface
|
||||
string $xWopiOldLock,
|
||||
RequestInterface $request
|
||||
): ResponseInterface {
|
||||
return $this->getDebugResponse(__FUNCTION__, $request);
|
||||
}
|
||||
|
||||
private function getDebugResponse(string $method, RequestInterface $request): ResponseInterface
|
||||
{
|
||||
$params = [];
|
||||
parse_str($request->getUri()->getQuery(), $params);
|
||||
|
||||
$data = (string) json_encode(array_merge(
|
||||
['method' => $method],
|
||||
$params,
|
||||
$request->getHeaders()
|
||||
));
|
||||
|
||||
return $this
|
||||
->psr17
|
||||
->createResponse()
|
||||
->withHeader('content', 'application/json')
|
||||
->withBody($this->psr17->createStream($data));
|
||||
}
|
||||
|
||||
private function getLockFilepath(string $fileId): string
|
||||
{
|
||||
return sprintf(
|
||||
'%s/%s.lock',
|
||||
$this->filesRepository,
|
||||
$fileId
|
||||
);
|
||||
return $this->wopi->unlockAndRelock($fileId, $accessToken, $xWopiLock, $xWopiOldLock, $request);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user