Merge pull request 'feature/php-laravel-sdk-integration' from feature/php-laravel-sdk-integration into develop

Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/document-server-integration/pulls/25
Reviewed-by: Stepan Mayorov <stepan.mayorov@onlyoffice.com>
Reviewed-by: Alexander Kondratev <aleksandr.kondratyev@onlyoffice.com>
This commit is contained in:
Sergey Linnik
2025-01-31 12:02:28 +00:00
48 changed files with 963 additions and 722 deletions

4
.gitmodules vendored
View File

@ -64,10 +64,6 @@
[submodule "web/documentserver-example/csharp/assets/document-formats"] [submodule "web/documentserver-example/csharp/assets/document-formats"]
path = web/documentserver-example/csharp/assets/document-formats path = web/documentserver-example/csharp/assets/document-formats
url = https://github.com/ONLYOFFICE/document-formats url = https://github.com/ONLYOFFICE/document-formats
[submodule "web/documentserver-example/php-laravel/public/assets/document-formats"]
path = web/documentserver-example/php-laravel/public/assets/document-formats
url = https://github.com/ONLYOFFICE/document-formats
branch = master
[submodule "web/documentserver-example/php-laravel/public/assets/document-templates"] [submodule "web/documentserver-example/php-laravel/public/assets/document-templates"]
path = web/documentserver-example/php-laravel/public/assets/document-templates path = web/documentserver-example/php-laravel/public/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates url = https://github.com/ONLYOFFICE/document-templates

View File

@ -15,6 +15,7 @@
- php-laravel: create, edit, and submit pdf forms - php-laravel: create, edit, and submit pdf forms
- php-laravel: show forgotten files on a seperate page - php-laravel: show forgotten files on a seperate page
- php-laravel: fetch files - php-laravel: fetch files
- php-laravel: integrate sdk
- restore by url - restore by url
- refresh config - refresh config
- on uploading xml convert to supported type only - on uploading xml convert to supported type only

View File

@ -1,3 +1,10 @@
# PHP SDK ENV VARIABLES
## COMMAND SERVICE
DOCS_INTEGRATION_SDK_COMMAND_SERVICE_URL=/command
DOCS_INTEGRATION_SDK_CONVERT_SERVICE_URL=/converter
## DOCUMENT STORAGE ENV VARIABLES ## DOCUMENT STORAGE ENV VARIABLES
DOCUMENT_STORAGE_PUBLIC_URL=http://localhost DOCUMENT_STORAGE_PUBLIC_URL=http://localhost

View File

@ -18,15 +18,15 @@
namespace App\Helpers\URL; namespace App\Helpers\URL;
use App\Services\StorageConfig; use App\OnlyOffice\Managers\SettingsManager;
class FileURL extends URL class FileURL extends URL
{ {
public static function download(string $filename, string $address = ''): string public static function download(string $filename, string $address = ''): string
{ {
$config = app(StorageConfig::class); $settings = app(SettingsManager::class);
return static::build($config->get('url.private'), 'files/download', [ return static::build($settings->getSetting('url.storage.private'), 'files/download', [
'fileName' => $filename, 'fileName' => $filename,
'userAddress' => $address, 'userAddress' => $address,
]); ]);
@ -34,9 +34,9 @@ class FileURL extends URL
public static function changes(string $filename, string $address, int $version): string public static function changes(string $filename, string $address, int $version): string
{ {
$config = app(StorageConfig::class); $settings = app(SettingsManager::class);
return static::build($config->get('url.private'), 'files/versions/changes', [ return static::build($settings->getSetting('url.storage.private'), 'files/versions/changes', [
'filename' => $filename, 'filename' => $filename,
'userAddress' => $address, 'userAddress' => $address,
'version' => $version, 'version' => $version,
@ -45,9 +45,9 @@ class FileURL extends URL
public static function previous(string $filename, string $address, int $version): string public static function previous(string $filename, string $address, int $version): string
{ {
$config = app(StorageConfig::class); $settings = app(SettingsManager::class);
return static::build($config->get('url.private'), 'files/versions/previous', [ return static::build($settings->getSetting('url.storage.private'), 'files/versions/previous', [
'filename' => $filename, 'filename' => $filename,
'userAddress' => $address, 'userAddress' => $address,
'version' => $version, 'version' => $version,
@ -56,9 +56,9 @@ class FileURL extends URL
public static function history(string $filename, string $address): string public static function history(string $filename, string $address): string
{ {
$config = app(StorageConfig::class); $settings = app(SettingsManager::class);
return static::build($config->get('url.private'), 'files/download', [ return static::build($settings->getSetting('url.storage.private'), 'files/download', [
'fileName' => $filename, 'fileName' => $filename,
'userAddress' => $address, 'userAddress' => $address,
]); ]);
@ -66,9 +66,9 @@ class FileURL extends URL
public static function create(string $extension, string $user): string public static function create(string $extension, string $user): string
{ {
$config = app(StorageConfig::class); $settings = app(SettingsManager::class);
return static::build($config->get('url.public'), 'editor', [ return static::build($settings->getSetting('url.storage.public'), 'editor', [
'fileExt' => $extension, 'fileExt' => $extension,
'user' => $user, 'user' => $user,
]); ]);
@ -76,9 +76,9 @@ class FileURL extends URL
public static function callback(string $filename, string $user): string public static function callback(string $filename, string $user): string
{ {
$config = app(StorageConfig::class); $settings = app(SettingsManager::class);
return static::build($config->get('url.private'), 'editor/track', [ return static::build($settings->getSetting('url.storage.private'), 'editor/track', [
'fileName' => $filename, 'fileName' => $filename,
'userAddress' => $user, 'userAddress' => $user,
]); ]);

View File

@ -18,13 +18,13 @@
namespace App\Helpers\URL; namespace App\Helpers\URL;
use App\Services\StorageConfig; use App\OnlyOffice\Managers\SettingsManager;
class TemplateURL extends URL class TemplateURL extends URL
{ {
public static function image(string $type) public static function image(string $type)
{ {
$config = app(StorageConfig::class); $settings = app(SettingsManager::class);
$name = 'file_docx.svg'; $name = 'file_docx.svg';
$name = match ($type) { $name = match ($type) {
@ -34,6 +34,6 @@ class TemplateURL extends URL
default => 'file_docx.svg', default => 'file_docx.svg',
}; };
return static::build($config->get('url.public'), "/images/$name"); return static::build($settings->getSetting('url.storage.public'), "/images/$name");
} }
} }

View File

@ -5,9 +5,8 @@ namespace App\Http\Controllers\API\Files;
use App\Helpers\Path\PathInfo; use App\Helpers\Path\PathInfo;
use App\Helpers\URL\URL; use App\Helpers\URL\URL;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Services\JWT; use App\OnlyOffice\Managers\JWTManager;
use App\Services\ServerConfig; use App\OnlyOffice\Managers\SettingsManager;
use App\Services\StorageConfig;
use App\UseCases\Document\Find\FindDocumentQuery; use App\UseCases\Document\Find\FindDocumentQuery;
use App\UseCases\Document\Find\FindDocumentQueryHandler; use App\UseCases\Document\Find\FindDocumentQueryHandler;
use Exception; use Exception;
@ -17,10 +16,10 @@ use Illuminate\Support\Str;
class ReferenceController extends Controller class ReferenceController extends Controller
{ {
public function get(Request $request, StorageConfig $storageConfig, ServerConfig $serverConfig, JWT $jwt) public function get(Request $request, SettingsManager $settings, JWTManager $jwt)
{ {
$storagePrivateUrl = $storageConfig->get('url.private'); $storagePrivateUrl = $settings->getSetting('url.storage.private');
$storagePublicUrl = $storageConfig->get('url.public'); $storagePublicUrl = $settings->getSetting('url.storage.public');
$referenceData = $request->input('referenceData'); $referenceData = $request->input('referenceData');
$link = $request->input('link'); $link = $request->input('link');
$path = $request->input('path'); $path = $request->input('path');
@ -94,8 +93,8 @@ class ReferenceController extends Controller
'link' => "$storagePublicUrl/editor?fileID=$filename", 'link' => "$storagePublicUrl/editor?fileID=$filename",
]; ];
if ($serverConfig->get('jwt.enabled')) { if ($settings->getSetting('jwt.enabled')) {
$data['token'] = $jwt->encode($data); $data['token'] = $jwt->encode($data, $settings->getSetting('jwt.secret'));
} }
return response()->json($data); return response()->json($data);

View File

@ -19,14 +19,14 @@
namespace App\Http\Controllers\API; namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Repositories\FormatRepository; use App\OnlyOffice\Managers\FormatManager;
class FormatController extends Controller class FormatController extends Controller
{ {
public function index(FormatRepository $formats) public function index(FormatManager $formats)
{ {
return response()->json([ return response()->json([
'formats' => $formats->all(), 'formats' => $formats->getFormatsList(),
]); ]);
} }
} }

View File

@ -18,32 +18,20 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Helpers\Path\Path;
use App\Helpers\Path\PathInfo; use App\Helpers\Path\PathInfo;
use App\Helpers\URL\FileURL;
use App\Helpers\URL\TemplateURL;
use App\Helpers\URL\URL; use App\Helpers\URL\URL;
use App\Services\JWT; use App\OnlyOffice\Managers\DocumentManager;
use App\Services\ServerConfig; use App\OnlyOffice\Managers\JWTManager;
use App\Services\StorageConfig; use App\OnlyOffice\Managers\SettingsManager;
use App\OnlyOffice\Services\CallbackService;
use App\UseCases\Common\Http\DownloadFileCommand; use App\UseCases\Common\Http\DownloadFileCommand;
use App\UseCases\Common\Http\DownloadFileRequest; use App\UseCases\Common\Http\DownloadFileRequest;
use App\UseCases\Docs\Command\ForceSaveCommad;
use App\UseCases\Docs\Command\ForceSaveRequest;
use App\UseCases\Docs\Conversion\ConvertCommand;
use App\UseCases\Docs\Conversion\ConvertRequest;
use App\UseCases\Document\Create\CreateDocumentCommand; use App\UseCases\Document\Create\CreateDocumentCommand;
use App\UseCases\Document\Create\CreateDocumentFromTemplateCommand; use App\UseCases\Document\Create\CreateDocumentFromTemplateCommand;
use App\UseCases\Document\Create\CreateDocumentFromTemplateRequest; use App\UseCases\Document\Create\CreateDocumentFromTemplateRequest;
use App\UseCases\Document\Create\CreateDocumentRequest; use App\UseCases\Document\Create\CreateDocumentRequest;
use App\UseCases\Document\Find\FindDocumentQuery; use App\UseCases\Document\Find\FindDocumentQuery;
use App\UseCases\Document\Find\FindDocumentQueryHandler; use App\UseCases\Document\Find\FindDocumentQueryHandler;
use App\UseCases\Document\Save\ForceSaveDocumentCommand;
use App\UseCases\Document\Save\ForceSaveDocumentRequest;
use App\UseCases\Document\Save\SaveDocumentCommand;
use App\UseCases\Document\Save\SaveDocumentFormCommand;
use App\UseCases\Document\Save\SaveDocumentFormRequest;
use App\UseCases\Document\Save\SaveDocumentRequest;
use App\UseCases\Editor\Create\CreateConfigCommand; use App\UseCases\Editor\Create\CreateConfigCommand;
use App\UseCases\Editor\Create\CreateConfigRequest; use App\UseCases\Editor\Create\CreateConfigRequest;
use App\UseCases\File\Find\FileExistsQuery; use App\UseCases\File\Find\FileExistsQuery;
@ -55,16 +43,16 @@ use App\UseCases\User\Find\FindUserQueryHandler;
use Exception; use Exception;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str; use Onlyoffice\DocsIntegrationSdk\Models\Callback;
use Onlyoffice\DocsIntegrationSdk\Models\CallbackDocStatus;
use Onlyoffice\DocsIntegrationSdk\Models\CallbackForceSaveType;
use Onlyoffice\DocsIntegrationSdk\Models\History;
class EditorController extends Controller class EditorController extends Controller
{ {
public function __construct( public function __construct(private SettingsManager $settings) {}
private StorageConfig $storageConfig,
private ServerConfig $serverConfig,
) {}
public function index(Request $request, JWT $jwt) public function index(Request $request, JWTManager $jwt)
{ {
$request->validate([ $request->validate([
'fileUrl' => 'required_without_all:fileID,fileExt|string', 'fileUrl' => 'required_without_all:fileID,fileExt|string',
@ -86,8 +74,8 @@ class EditorController extends Controller
$lang = $request->cookie('ulang', 'en'); $lang = $request->cookie('ulang', 'en');
$fileExt = $request->input('fileExt'); $fileExt = $request->input('fileExt');
$withSample = $request->has('sample') && $request->sample === 'true'; $withSample = $request->has('sample') && $request->sample === 'true';
$storagePublicUrl = $this->storageConfig->get('url.public'); $storagePublicUrl = $this->settings->getSetting('url.storage.public');
$storagePrivateUrl = $this->storageConfig->get('url.private'); $storagePrivateUrl = $this->settings->getSetting('url.storage.private');
$user = app(FindUserQueryHandler::class) $user = app(FindUserQueryHandler::class)
->__invoke(new FindUserQuery($userId)); ->__invoke(new FindUserQuery($userId));
@ -142,7 +130,7 @@ class EditorController extends Controller
$file = app(FindDocumentQueryHandler::class) $file = app(FindDocumentQueryHandler::class)
->__invoke(new FindDocumentQuery($filename, $request->ip())); ->__invoke(new FindDocumentQuery($filename, $request->ip()));
if (! $file['format']->type) { if (! $file['format']->getType()) {
$message = 'The format '.$file['format']->extension().' has undefined format.'; $message = 'The format '.$file['format']->extension().' has undefined format.';
Log::error($message); Log::error($message);
@ -152,10 +140,13 @@ class EditorController extends Controller
]); ]);
} }
$downloadUrl = FileURL::download($filename, $request->ip()); $file['user'] = $userId;
$templatesImageUrl = TemplateURL::image($file['format']->type->value); $file['address'] = $request->ip();
$createUrl = FileURL::create($file['format']->extension(), $user['id']); $fileId = $file['key'];
$callbackUrl = FileURL::callback($filename, $request->ip());
$documentManager = new DocumentManager($file);
$downloadUrl = $documentManager->getFileUrl($fileId);
$imagesUrl = "$storagePublicUrl/images/"; $imagesUrl = "$storagePublicUrl/images/";
$mode = $request->action ?? 'edit'; $mode = $request->action ?? 'edit';
@ -172,10 +163,10 @@ class EditorController extends Controller
lang: $lang, lang: $lang,
userAddress: $request->ip(), userAddress: $request->ip(),
serverAddress: $storagePublicUrl, serverAddress: $storagePublicUrl,
createUrl: $createUrl, createUrl: $documentManager->getCreateUrl($fileId),
templatesImageUrl: $templatesImageUrl, templatesImageUrl: $documentManager->getTemplateImageUrl($fileId),
actionLink: $actionLink, actionLink: $actionLink,
callbackUrl: $callbackUrl, callbackUrl: $documentManager->getCallbackUrl($fileId),
imagesUrl: $imagesUrl, imagesUrl: $imagesUrl,
directUrl: $directUrlEnabled ? $downloadUrl : '', directUrl: $directUrlEnabled ? $downloadUrl : '',
)); ));
@ -227,14 +218,15 @@ class EditorController extends Controller
} }
// check if the secret key to generate token exists // check if the secret key to generate token exists
if ($this->serverConfig->get('jwt.enabled')) { if ($this->settings->getSetting('jwt.enabled')) {
$config['token'] = $jwt->encode($config); // encode config into the token // encode config into the token
$config['token'] = $jwt->encode($config, $this->settings->getSetting('jwt.secret'));
// encode the dataInsertImage object into the token // encode the dataInsertImage object into the token
$dataInsertImage['token'] = $jwt->encode($dataInsertImage); $dataInsertImage['token'] = $jwt->encode($dataInsertImage, $this->settings->getSetting('jwt.secret'));
// encode the dataDocument object into the token // encode the dataDocument object into the token
$dataDocument['token'] = $jwt->encode($dataDocument); $dataDocument['token'] = $jwt->encode($dataDocument, $this->settings->getSetting('jwt.secret'));
// encode the dataSpreadsheet object into the token // encode the dataSpreadsheet object into the token
$dataSpreadsheet['token'] = $jwt->encode($dataSpreadsheet); $dataSpreadsheet['token'] = $jwt->encode($dataSpreadsheet, $this->settings->getSetting('jwt.secret'));
} }
$historyLayout = ''; $historyLayout = '';
@ -267,8 +259,8 @@ class EditorController extends Controller
$editorConfig = [ $editorConfig = [
'fileName' => $file['filename'], 'fileName' => $file['filename'],
'docType' => $file['format']->type, 'docType' => $file['format']->getType(),
'apiUrl' => $this->serverConfig->get('url.api'), 'apiUrl' => $this->settings->getSetting('url.api'),
'dataInsertImage' => mb_strimwidth( 'dataInsertImage' => mb_strimwidth(
json_encode($dataInsertImage), json_encode($dataInsertImage),
1, 1,
@ -308,152 +300,36 @@ class EditorController extends Controller
} }
$data = $request->input('payload'); $data = $request->input('payload');
$status = $data['status']; $data['filename'] = $filename;
$data['address'] = $address;
$actions = array_key_exists('actions', $data) ? $data['actions'] : [];
$changesUrl = array_key_exists('changesurl', $data) ? $data['changesurl'] : '';
$formsDataUrl = array_key_exists('formsdataurl', $data) ? $data['formsdataurl'] : '';
$fileType = array_key_exists('filetype', $data) ? $data['filetype'] : '';
$forceSaveType = array_key_exists('forcesavetype', $data) ? new CallbackForceSaveType($data['forcesavetype']) : null;
$history = array_key_exists('history', $data) && $data['history']
? new History($data['history']['serverVersion'], $data['history']['changes'])
: null;
$users = array_key_exists('users', $data) ? $data['users'] : [];
$url = array_key_exists('url', $data) ? $data['url'] : '';
switch ($status) { $callback = new Callback(
case 1: $actions,
if ($data['actions'] && $data['actions'][0]['type'] == 0) { $changesUrl,
$user = $data['actions'][0]['userid']; $fileType,
if (array_search($user, $data['users']) === false) { $forceSaveType,
app(ForceSaveCommad::class)
->__invoke(new ForceSaveRequest(key: $data['key']));
}
}
break;
case 2:
case 3:
$url = $data['url'];
$key = $data['key'];
$user = $data['users'][0];
$changes = null;
$url = Str::replace(URL::origin($url), $this->serverConfig->get('url.private'), $url);
$fileExtension = PathInfo::extension($filename);
$downloadExtension = PathInfo::extension($url);
if ($fileExtension !== $downloadExtension) {
$result = app(ConvertCommand::class)
->__invoke(new ConvertRequest(
filename: $filename,
fileType: $downloadExtension,
outputType: $fileExtension,
url: $url,
password: null,
user: $user,
userAddress: $address,
));
if (array_key_exists('step', $result) || array_key_exists('error', $result)) {
$filename = PathInfo::filename($filename).".$downloadExtension";
} else {
$url = $result['fileUrl'];
}
}
$content = app(DownloadFileCommand::class)
->__invoke(new DownloadFileRequest(url: $url))['content'];
if (array_key_exists('changesurl', $data)) {
$changesUrl = $data['changesurl'];
$changesUrl = Str::replace(URL::origin($changesUrl), $this->serverConfig->get('url.private'), $changesUrl);
$changes = app(DownloadFileCommand::class)
->__invoke(new DownloadFileRequest(url: $changesUrl))['content'];
}
$history = array_key_exists('history', $data) ? $data['history']['changes'] : null;
$serverVersion = array_key_exists('history', $data) ? $data['history']['serverVersion'] : null;
$user = $data['users'][0];
app(SaveDocumentCommand::class)->__invoke(
new SaveDocumentRequest(
Path::join($address, $filename),
$fileExtension,
$key,
$content,
$user,
$serverVersion,
$history, $history,
$changes, $data['key'],
) new CallbackDocStatus($data['status']),
); $url,
$users,
break; '',
case 6:
case 7:
$isSubmitForm = $data['forcesavetype'] === 3;
if ($isSubmitForm && ! array_key_exists('formsdataurl', $data)) {
abort(500, 'Document editing service did not return formsDataUrl');
}
$url = $data['url'];
$key = $data['key'];
$user = $data['users'][0];
$url = Str::replace(URL::origin($url), $this->serverConfig->get('url.private'), $url);
$fileExtension = PathInfo::extension($filename);
$downloadExtension = PathInfo::extension($url);
if ($fileExtension !== $downloadExtension) {
$result = app(ConvertCommand::class)
->__invoke(new ConvertRequest(
filename: $filename,
fileType: $downloadExtension,
outputType: $fileExtension,
url: $url,
password: null,
user: $user,
userAddress: $address,
));
if (array_key_exists('step', $result) || array_key_exists('error', $result)) {
$filename = PathInfo::filename($filename).".$downloadExtension";
} else {
$url = $result['fileUrl'];
}
}
$content = app(DownloadFileCommand::class)
->__invoke(new DownloadFileRequest(url: $url))['content'];
if ($isSubmitForm) {
$formsDataUrl = $data['formsdataurl'];
$formsDataUrl = Str::replace(
URL::origin($formsDataUrl),
$this->serverConfig->get('url.private'),
$formsDataUrl $formsDataUrl
); );
$formData = app(DownloadFileCommand::class) $callbackService = new CallbackService($this->settings, app(JWTManager::class), $data);
->__invoke(new DownloadFileRequest(url: $formsDataUrl))['content']; $result = $callbackService->processCallback($callback, $filename);
app(SaveDocumentFormCommand::class) return response()->json($result);
->__invoke(new SaveDocumentFormRequest(
filename: $filename,
userDirectory: $address,
user: $user,
formContent: $content,
formDataContent: $formData,
));
} else {
app(ForceSaveDocumentCommand::class)
->__invoke(
new ForceSaveDocumentRequest(
filename: $filename,
userDirectory: $address,
content: $content
)
);
}
break;
}
return response()->json([
'error' => 0,
]);
} }
} }

View File

@ -22,10 +22,9 @@ use App\Helpers\Path\Path;
use App\Helpers\Path\PathInfo; use App\Helpers\Path\PathInfo;
use App\Helpers\URL\FileURL; use App\Helpers\URL\FileURL;
use App\Helpers\URL\URL; use App\Helpers\URL\URL;
use App\Repositories\FormatRepository; use App\OnlyOffice\Managers\FormatManager;
use App\Services\JWT; use App\OnlyOffice\Managers\JWTManager;
use App\Services\ServerConfig; use App\OnlyOffice\Managers\SettingsManager;
use App\Services\StorageConfig;
use App\UseCases\Common\Http\DownloadFileCommand; use App\UseCases\Common\Http\DownloadFileCommand;
use App\UseCases\Common\Http\DownloadFileRequest; use App\UseCases\Common\Http\DownloadFileRequest;
use App\UseCases\Docs\Command\UpdateMetaCommand; use App\UseCases\Docs\Command\UpdateMetaCommand;
@ -54,9 +53,8 @@ use Illuminate\Support\Str;
class FileController extends Controller class FileController extends Controller
{ {
public function __construct( public function __construct(
private ServerConfig $serverConfig, private SettingsManager $settings,
private StorageConfig $storageConfig, private FormatManager $formatManager,
private FormatRepository $formatRepository,
) {} ) {}
public function index(Request $request) public function index(Request $request)
@ -130,7 +128,7 @@ class FileController extends Controller
$user = $request->input('user', ''); $user = $request->input('user', '');
$url = Str::replace(URL::origin($request->url), $this->serverConfig->get('url.private'), $request->url); $url = Str::replace(URL::origin($request->url), $this->settings->getSetting('url.server.private'), $request->url);
$downloadedFile = app(DownloadFileCommand::class) $downloadedFile = app(DownloadFileCommand::class)
->__invoke(new DownloadFileRequest(url: $url)); ->__invoke(new DownloadFileRequest(url: $url));
@ -188,13 +186,13 @@ class FileController extends Controller
], 500); ], 500);
} }
if (empty($this->formatRepository->find($result['fileType'])->actions)) { if (empty($this->formatManager->find($result['fileType'])->getActions())) {
return response() return response()
->json([ ->json([
'step' => 100, 'step' => 100,
'filename' => str_replace( 'filename' => str_replace(
$this->serverConfig->get('url.private'), $this->settings->getSetting('url.server.private'),
$this->serverConfig->get('url.public'), $this->settings->getSetting('url.server.public'),
$result['fileUrl'] $result['fileUrl']
), ),
'error' => 'FileTypeIsNotSupported', 'error' => 'FileTypeIsNotSupported',
@ -317,7 +315,7 @@ class FileController extends Controller
return response(status: 201); return response(status: 201);
} }
public function config(Request $request, JWT $jwt) public function config(Request $request, JWTManager $jwt)
{ {
try { try {
$request->validate([ $request->validate([
@ -361,8 +359,8 @@ class FileController extends Controller
], ],
]; ];
if ($this->serverConfig->get('jwt.enabled')) { if ($this->settings->getSetting('jwt.enabled')) {
$config['token'] = $jwt->encode($config); $config['token'] = $jwt->encode($config, $this->settings->getSetting('jwt.secret'));
} }
return response() return response()

View File

@ -19,8 +19,7 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Helpers\URL\URL; use App\Helpers\URL\URL;
use App\Services\ServerConfig; use App\OnlyOffice\Managers\SettingsManager;
use App\Services\StorageConfig;
use App\UseCases\Document\Find\FindAllDocumentsQuery; use App\UseCases\Document\Find\FindAllDocumentsQuery;
use App\UseCases\Document\Find\FindAllDocumentsQueryHandler; use App\UseCases\Document\Find\FindAllDocumentsQueryHandler;
use App\UseCases\Language\Find\FindAllLanguagesQueryHandler; use App\UseCases\Language\Find\FindAllLanguagesQueryHandler;
@ -31,12 +30,12 @@ use Illuminate\Support\Str;
class IndexController extends Controller class IndexController extends Controller
{ {
public function index(Request $request, ServerConfig $serverConfig, StorageConfig $storageConfig) public function index(Request $request, SettingsManager $settings)
{ {
$directUrlEnabled = $request->has('directUrl') && $request->directUrl === 'true'; $directUrlEnabled = $request->has('directUrl') && $request->directUrl === 'true';
$directUrlArg = 'directUrl='.($directUrlEnabled ? 'true' : 'false'); $directUrlArg = 'directUrl='.($directUrlEnabled ? 'true' : 'false');
$preloaderUrl = $serverConfig->get('url.preloader'); $preloaderUrl = $settings->getSetting('url.preloader');
$files = app(FindAllDocumentsQueryHandler::class) $files = app(FindAllDocumentsQueryHandler::class)
->__invoke(new FindAllDocumentsQuery($request->ip())); ->__invoke(new FindAllDocumentsQuery($request->ip()));
@ -50,7 +49,7 @@ class IndexController extends Controller
foreach ($files as &$file) { foreach ($files as &$file) {
$url = route('files.download', ['fileName' => urlencode($file['filename']), 'dmode' => true]); $url = route('files.download', ['fileName' => urlencode($file['filename']), 'dmode' => true]);
$file['url'] = Str::replace(URL::origin($url), $storageConfig->get('url.public'), $url); $file['url'] = Str::replace(URL::origin($url), $settings->getSetting('url.storage.public'), $url);
} }
return view('index', [ return view('index', [

View File

@ -2,8 +2,8 @@
namespace App\Http\Middleware; namespace App\Http\Middleware;
use App\Services\JWT; use App\OnlyOffice\Managers\JWTManager;
use App\Services\ServerConfig; use App\OnlyOffice\Managers\SettingsManager;
use Closure; use Closure;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
@ -17,18 +17,17 @@ class CheckAndDecodeJWTPayload
*/ */
public function handle(Request $request, Closure $next): Response public function handle(Request $request, Closure $next): Response
{ {
$config = app(ServerConfig::class); $jwt = app(JWTManager::class);
$jwt = app(JWT::class); $settings = app(SettingsManager::class);
$payload = null; $payload = null;
$embeded = $request->has('dmode'); $embeded = $request->has('dmode');
if ($config->get('jwt.enabled') && $embeded == null && $config->get('jwt.use_for_request')) { if ($settings->getSetting('jwt.enabled') && $embeded == null && $settings->getSetting('jwt.use_for_request')) {
if ($request->token) { if ($request->token) {
$payload = $jwt->decode($request->token); $payload = $jwt->decode($request->token, $settings->getSetting('jwt.secret'));
$payload = json_decode(json_encode($payload), true); $payload = json_decode(json_encode($payload), true);
} elseif ($request->hasHeader($config->get('jwt.header'))) { } elseif ($request->hasHeader($settings->getSetting('jwt.header'))) {
$payload = $jwt->decode($request->bearerToken()); $payload = $jwt->decode($request->bearerToken(), $settings->getSetting('jwt.secret'));
$payload = json_decode($payload);
} else { } else {
abort(499, 'Expected JWT token'); abort(499, 'Expected JWT token');
} }

View File

@ -2,8 +2,8 @@
namespace App\Http\Middleware; namespace App\Http\Middleware;
use App\Services\JWT; use App\OnlyOffice\Managers\JWTManager;
use App\Services\ServerConfig; use App\OnlyOffice\Managers\SettingsManager;
use Closure; use Closure;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
@ -17,13 +17,13 @@ class EnsureJWTTokenIsPresent
*/ */
public function handle(Request $request, Closure $next): Response public function handle(Request $request, Closure $next): Response
{ {
$config = app(ServerConfig::class); $jwt = app(JWTManager::class);
$jwt = app(JWT::class); $settings = app(SettingsManager::class);
$embeded = $request->has('dmode'); $embeded = $request->has('dmode');
if ($config->get('jwt.enabled') && $embeded == null && $config->get('jwt.use_for_request')) { if ($settings->getSetting('jwt.enabled') && $embeded == null && $settings->getSetting('jwt.use_for_request')) {
if ($request->hasHeader($config->get('jwt.header'))) { if ($request->hasHeader($settings->getSetting('jwt.header'))) {
$token = $jwt->decode($request->bearerToken()); $token = $jwt->decode($request->bearerToken(), $settings->getSetting('jwt.secret'));
if (empty($token)) { if (empty($token)) {
abort(498, 'Invalid JWT signature'); abort(498, 'Invalid JWT signature');

View File

@ -18,6 +18,8 @@
namespace App\Models; namespace App\Models;
use App\OnlyOffice\Models\Format;
class Document class Document
{ {
public function __construct( public function __construct(

View File

@ -42,7 +42,7 @@ class Editor
'url' => $this->document->url, 'url' => $this->document->url,
'directUrl' => $this->config->directUrl, 'directUrl' => $this->config->directUrl,
], ],
'documentType' => $this->document->format->type, 'documentType' => $this->document->format->getType(),
'editorConfig' => $this->buildEditorConfig(), 'editorConfig' => $this->buildEditorConfig(),
'type' => $this->config->type, 'type' => $this->config->type,
]; ];

View File

@ -18,8 +18,8 @@
namespace App\Models\Editor; namespace App\Models\Editor;
use App\Models\Format;
use App\Models\User; use App\Models\User;
use App\OnlyOffice\Models\Format;
class EditorPermissions class EditorPermissions
{ {
@ -101,12 +101,12 @@ class EditorPermissions
private function editable(): bool private function editable(): bool
{ {
return $this->action === 'edit' && $this->format->editable(); return $this->action === 'edit' && $this->format->isEditable();
} }
private function fillable(): bool private function fillable(): bool
{ {
return (($this->action === 'edit' && ! $this->format->editable()) return (($this->action === 'edit' && ! $this->format->isEditable())
|| $this->action === 'fillForms') && $this->format->fillable(); || $this->action === 'fillForms') && $this->format->isFillable();
} }
} }

View File

@ -0,0 +1,81 @@
<?php
/**
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace App\OnlyOffice\Managers;
use App\Helpers\URL\FileURL;
use App\Helpers\URL\TemplateURL;
use Onlyoffice\DocsIntegrationSdk\Manager\Document\DocumentManager as OnlyOfficeDocumentManager;
class DocumentManager extends OnlyOfficeDocumentManager
{
private array $file;
public function __construct(array $file, $systemLangCode = 'en')
{
$formats = app(FormatManager::class);
$settings = app(SettingsManager::class);
parent::__construct($settings, $formats, $systemLangCode);
$this->file = $file;
}
public function getDocumentKey(string $fileId, bool $embedded)
{
return $this->file['key'];
}
public function getDocumentName(string $fileId)
{
return $this->file['filename'];
}
public static function getLangMapping()
{
return null;
}
public function getFileUrl(string $fileId)
{
return FileURL::download($this->file['filename'], $this->file['address']);
}
public function getCallbackUrl(string $fileId)
{
return FileURL::callback($this->file['filename'], $this->file['address']);
}
public function getTemplateImageUrl(string $fileId)
{
return TemplateURL::image($this->file['format']->getType());
}
public function getGobackUrl(string $fileId)
{
return $this->file['goback'] !== null ? $this->file['goback'] : '';
}
public function getCreateUrl(string $fileId)
{
return FileURL::create($this->file['format']->extension(), $this->file['user']);
}
public function getFile(): array
{
return $this->file;
}
}

View File

@ -0,0 +1,59 @@
<?php
/**
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace App\OnlyOffice\Managers;
use App\OnlyOffice\Models\Format;
use Onlyoffice\DocsIntegrationSdk\Manager\Formats\FormatsManager;
class FormatManager extends FormatsManager
{
public function __construct($nameAssoc = false)
{
parent::__construct();
$this->createCustomList();
}
private function createCustomList()
{
$newFormats = [];
foreach ($this->formatsList as $format) {
$newFormats[] = new Format(
$format->getName(),
$format->getType(),
$format->getActions(),
$format->getConvert(),
$format->getMimes(),
);
}
$this->formatsList = $newFormats;
}
public function find(string $extension): ?Format
{
foreach ($this->formatsList as $format) {
if ($format->extension() === $extension) {
return $format;
}
}
return null;
}
}

View File

@ -16,22 +16,28 @@
* limitations under the License. * limitations under the License.
*/ */
namespace App\Services\Docs\Command; namespace App\OnlyOffice\Managers;
class ForgottenFileRequest extends CommandRequest use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Onlyoffice\DocsIntegrationSdk\Manager\Security\JwtManager as OnlyOfficeJWTManager;
class JWTManager extends OnlyOfficeJWTManager
{ {
public function get(string $key): array public function __construct(SettingsManager $settings)
{ {
$content = [ parent::__construct($settings);
'c' => 'getForgotten', }
'key' => $key,
];
$result = $this->send($content, $key); public function encode($payload, $key, $algorithm = 'HS256')
{
return JWT::encode($payload, $key, $algorithm);
}
return [ public function decode($token, $key, $algorithm = 'HS256')
'key' => $result['key'], {
'url' => $result['url'], $payload = JWT::decode($token, new Key($key, $algorithm));
];
return $payload;
} }
} }

View File

@ -16,12 +16,19 @@
* limitations under the License. * limitations under the License.
*/ */
namespace App\Services; namespace App\OnlyOffice\Managers;
class ServerConfig extends Config use Exception;
use Onlyoffice\DocsIntegrationSdk\Manager\Settings\SettingsManager as OnlyOfficeSettingsManager;
class SettingsManager extends OnlyOfficeSettingsManager
{ {
private array $config;
public function __construct() public function __construct()
{ {
parent::__construct();
$publicServerUrl = rtrim(env('DOCUMENT_SERVER_PUBLIC_URL', 'http://documentserver'), '/'); $publicServerUrl = rtrim(env('DOCUMENT_SERVER_PUBLIC_URL', 'http://documentserver'), '/');
$privateServerUrl = rtrim(env('DOCUMENT_SERVER_PRIVATE_URL', $publicServerUrl), '/'); $privateServerUrl = rtrim(env('DOCUMENT_SERVER_PRIVATE_URL', $publicServerUrl), '/');
$apiUrl = $publicServerUrl.'/'.env('DOCUMENT_SERVER_API_PATH', 'web-apps/apps/api/documents/api.js'); $apiUrl = $publicServerUrl.'/'.env('DOCUMENT_SERVER_API_PATH', 'web-apps/apps/api/documents/api.js');
@ -30,8 +37,14 @@ class ServerConfig extends Config
$commandUrl = $privateServerUrl.'/'.env('DOCUMENT_SERVER_COMMAND_PATH', 'command'); $commandUrl = $privateServerUrl.'/'.env('DOCUMENT_SERVER_COMMAND_PATH', 'command');
$jwtSecret = env('DOCUMENT_SERVER_JWT_SECRET', 'secret'); $jwtSecret = env('DOCUMENT_SERVER_JWT_SECRET', 'secret');
$jwtUseForRequest = env('DOCUMENT_SERVER_JWT_USE_FOR_REQUEST', true); $jwtUseForRequest = env('DOCUMENT_SERVER_JWT_USE_FOR_REQUEST', true);
$publicStorageUrl = rtrim(env('DOCUMENT_STORAGE_PUBLIC_URL', request()->schemeAndHttpHost()), '/');
$privateStorageUrl = rtrim(env('DOCUMENT_STORAGE_PRIVATE_URL', $publicStorageUrl), '/');
$this->config = [ $this->config = [
'documentServerInternalUrl' => $privateServerUrl,
'jwtKey' => $jwtSecret,
'jwtHeader' => env('DOCUMENT_SERVER_JWT_HEADER', 'Authorization'),
'jwtPrefix' => env('DOCUMENT_SERVER_JWT_HEADER', 'Bearer '),
'conversion' => [ 'conversion' => [
'timeout' => env('DOCUMENT_SERVER_CONVERSION_TIMEOUT', 120 * 1000), 'timeout' => env('DOCUMENT_SERVER_CONVERSION_TIMEOUT', 120 * 1000),
'url' => $conversionUrl, 'url' => $conversionUrl,
@ -47,11 +60,48 @@ class ServerConfig extends Config
], ],
'url' => [ 'url' => [
'api' => $apiUrl, 'api' => $apiUrl,
'public' => $publicServerUrl,
'private' => $privateServerUrl,
'preloader' => $preloaderUrl, 'preloader' => $preloaderUrl,
'command' => $commandUrl, 'command' => $commandUrl,
'server' => [
'public' => $publicServerUrl,
'private' => $privateServerUrl,
],
'storage' => [
'private' => $privateStorageUrl,
'public' => $publicStorageUrl,
],
],
'file' => [
'max_size' => env('DOCUMENT_STORAGE_MAXIMUM_FILE_SIZE', 5 * 1024 * 1024),
], ],
]; ];
} }
public function getServerUrl()
{
return $this->get('url.server.public');
}
public function getSetting($settingName)
{
return $this->get($settingName);
}
public function setSetting($settingName, $value, $createSetting = false) {}
private function get(string $key, mixed $default = null): mixed
{
$keys = explode('.', $key);
$result = $this->config;
try {
foreach ($keys as $key) {
$result = $result[$key];
}
} catch (Exception $e) {
$result = $default;
}
return $result;
}
} }

View File

@ -0,0 +1,90 @@
<?php
/**
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace App\OnlyOffice\Miscellaneous;
use App\OnlyOffice\Services\RequestService;
class CommandRequest
{
public static function forceSave(string $key)
{
$requestService = app(RequestService::class);
$data = [
'c' => 'forcesave',
'key' => $key,
];
$result = $requestService->commandRequest('forcesave', $data);
return $result;
}
public static function deleteForgotten(string $key)
{
$requestService = app(RequestService::class);
$data = [
'c' => 'deleteForgotten',
'key' => $key,
];
$result = $requestService->commandRequest('deleteForgotten', $data);
return $result;
}
public static function getForgotten(string $key)
{
$requestService = app(RequestService::class);
$data = [
'c' => 'getForgotten',
'key' => $key,
];
$result = $requestService->commandRequest('getForgotten', $data);
return $result;
}
public static function getForgottenList()
{
$requestService = app(RequestService::class);
$result = $requestService->commandRequest('getForgottenList');
return $result;
}
public static function updateMeta(string $key, array $meta)
{
$requestService = app(RequestService::class);
$data = [
'c' => 'meta',
'key' => $key,
'meta' => $meta,
];
$result = $requestService->commandRequest('meta', $data);
return $result;
}
}

View File

@ -0,0 +1,53 @@
<?php
/**
* (c) Copyright Ascensio System SIA 2025
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace App\OnlyOffice\Miscellaneous;
use App\Exceptions\ConversionError;
use App\Exceptions\ConversionNotComplete;
use App\OnlyOffice\Services\RequestService;
class ConvertRequest
{
public function convert(array $data)
{
$requestService = app(RequestService::class);
$result = $requestService->sendRequestToConvertService(
$data['url'],
$data['filetype'],
$data['outputtype'],
$data['key'],
false,
$data['lang'],
);
if (property_exists($result, 'Error')) {
throw new ConversionError($result->Error);
}
if (! property_exists($result, 'EndConvert')) {
throw new ConversionNotComplete($result->Percent, $result->Filename, $result->FileUrl);
}
return [
'fileType' => $result->FileType,
'fileUrl' => $result->FileUrl,
];
}
}

View File

@ -0,0 +1,55 @@
<?php
//
// (c) Copyright Ascensio System SIA 2024
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
namespace App\OnlyOffice\Models;
use App\Enums\FormatType;
use Onlyoffice\DocsIntegrationSdk\Models\Format as OnlyOfficeFormat;
class Format extends OnlyOfficeFormat
{
public function isAutoConvertable(): bool
{
return in_array('auto-convert', $this->actions);
}
public function extension(): string
{
return $this->name;
}
public function isWord(): bool
{
return $this->type === FormatType::WORD->value;
}
public function isCell(): bool
{
return $this->type === FormatType::CELL->value;
}
public function isSlide(): bool
{
return $this->type === FormatType::SLIDE->value;
}
public function isPDF(): bool
{
return $this->type === FormatType::PDF->value;
}
}

View File

@ -0,0 +1,225 @@
<?php
/**
* (c) Copyright Ascensio System SIA 2024.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace App\OnlyOffice\Services;
use App\Helpers\Path\Path;
use App\Helpers\Path\PathInfo;
use App\Helpers\URL\URL;
use App\UseCases\Common\Http\DownloadFileCommand;
use App\UseCases\Common\Http\DownloadFileRequest;
use App\UseCases\Docs\Command\ForceSaveCommad;
use App\UseCases\Docs\Command\ForceSaveRequest;
use App\UseCases\Docs\Conversion\ConvertCommand;
use App\UseCases\Docs\Conversion\ConvertRequest;
use App\UseCases\Document\Save\ForceSaveDocumentCommand;
use App\UseCases\Document\Save\ForceSaveDocumentRequest;
use App\UseCases\Document\Save\SaveDocumentCommand;
use App\UseCases\Document\Save\SaveDocumentFormCommand;
use App\UseCases\Document\Save\SaveDocumentFormRequest;
use App\UseCases\Document\Save\SaveDocumentRequest;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Onlyoffice\DocsIntegrationSdk\Models\CallbackForceSaveType;
use Onlyoffice\DocsIntegrationSdk\Service\Callback\CallbackService as OnlyOfficeCallbackService;
class CallbackService extends OnlyOfficeCallbackService
{
private $data;
public function __construct($settingsManager, $jwtManager, $data = [])
{
parent::__construct($settingsManager, $jwtManager);
$this->data = $data;
}
public function processTrackerStatusEditing($callback, string $fileid)
{
return $this->processTrackerStatusEditingAndClosed($callback, $fileid);
}
public function processTrackerStatusMustsave($callback, string $fileid)
{
return $this->processTrackerStatusMustsaveAndCorrupted($callback, $fileid);
}
public function processTrackerStatusCorrupted($callback, string $fileid)
{
return $this->processTrackerStatusMustsaveAndCorrupted($callback, $fileid);
}
public function processTrackerStatusClosed($callback, string $fileid)
{
return $this->processTrackerStatusEditingAndClosed($callback, $fileid);
}
public function processTrackerStatusForcesave($callback, string $fileid)
{
$isSubmitForm = $callback->getForceSaveType()->getValue() === CallbackForceSaveType::SUBMIT_FORM;
if ($isSubmitForm && ! $callback->getFormsDataUrl()) {
Log::error('Document editing service did not return formsDataUrl');
return ['error' => 1];
}
$url = $callback->getUrl();
$key = $callback->getKey();
$user = $callback->getUsers()[0];
$filename = $this->data['filename'];
$address = $this->data['address'];
$url = $this->settingsManager->replaceDocumentServerUrlToInternal($url);
$fileExtension = PathInfo::extension($filename);
$downloadExtension = PathInfo::extension($url);
if ($fileExtension !== $downloadExtension) {
$result = app(ConvertCommand::class)
->__invoke(new ConvertRequest(
filename: $filename,
fileType: $downloadExtension,
outputType: $fileExtension,
url: $url,
password: null,
user: $user,
userAddress: $address,
));
if (array_key_exists('step', $result) || array_key_exists('error', $result)) {
$filename = PathInfo::filename($filename).".$downloadExtension";
} else {
$url = $result['fileUrl'];
}
}
$content = app(DownloadFileCommand::class)
->__invoke(new DownloadFileRequest(url: $url))['content'];
if ($isSubmitForm) {
$formsDataUrl = $this->settingsManager->replaceDocumentServerUrlToInternal($callback->getFormsDataUrl());
$formData = app(DownloadFileCommand::class)
->__invoke(new DownloadFileRequest(url: $formsDataUrl))['content'];
app(SaveDocumentFormCommand::class)
->__invoke(new SaveDocumentFormRequest(
filename: $filename,
userDirectory: $address,
user: $user,
formContent: $content,
formDataContent: $formData,
));
} else {
app(ForceSaveDocumentCommand::class)
->__invoke(
new ForceSaveDocumentRequest(
filename: $filename,
userDirectory: $address,
content: $content
)
);
}
$result['error'] = 0;
return $result;
}
public function processTrackerStatusMustsaveAndCorrupted($callback, string $fileid)
{
$url = $callback->getUrl();
$key = $callback->getKey();
$user = $callback->getUsers()[0];
$changes = null;
$filename = $this->data['filename'];
$address = $this->data['address'];
$url = $this->settingsManager->replaceDocumentServerUrlToInternal($url);
$fileExtension = PathInfo::extension($filename);
$downloadExtension = PathInfo::extension($url);
if ($fileExtension !== $downloadExtension) {
$result = app(ConvertCommand::class)
->__invoke(new ConvertRequest(
filename: $filename,
fileType: $downloadExtension,
outputType: $fileExtension,
url: $url,
password: null,
user: $user,
userAddress: $address,
));
if (array_key_exists('step', $result) || array_key_exists('error', $result)) {
$filename = PathInfo::filename($filename).".$downloadExtension";
} else {
$url = $result['fileUrl'];
}
}
$content = app(DownloadFileCommand::class)
->__invoke(new DownloadFileRequest(url: $url))['content'];
$changesUrl = $callback->getChangesurl();
if ($changesUrl) {
$changesUrl = Str::replace(URL::origin($changesUrl), $this->settingsManager->getSetting('url.server.private'), $changesUrl);
$changes = app(DownloadFileCommand::class)
->__invoke(new DownloadFileRequest(url: $changesUrl))['content'];
}
$historyObject = $callback->getHistory();
$history = $historyObject ? $historyObject->getChanges() : null;
$serverVersion = $historyObject ? $historyObject->getServerVersion() : null;
app(SaveDocumentCommand::class)->__invoke(
new SaveDocumentRequest(
Path::join($address, $filename),
$fileExtension,
$key,
$content,
$user,
$serverVersion,
$history,
$changes,
)
);
return [
'error' => 0,
];
}
public function processTrackerStatusEditingAndClosed($callback, string $fileid)
{
$actions = $callback->getActions();
if ($actions && $actions[0]['type'] == 0) {
$user = $actions[0]['userid'];
if (array_search($user, $callback->getUsers()) === false) {
app(ForceSaveCommad::class)
->__invoke(new ForceSaveRequest(key: $callback->getKey()));
}
}
$result['error'] = 0;
return $result;
}
}

View File

@ -0,0 +1,72 @@
<?php
/**
* (c) Copyright Ascensio System SIA 2024.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace App\OnlyOffice\Services;
use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use Onlyoffice\DocsIntegrationSdk\Service\Request\HttpClientInterface;
class HttpClient implements HttpClientInterface
{
private $status;
private $body;
public function __construct()
{
$this->status = null;
$this->body = null;
}
/**
* Request to Document Server with turn off verification.
*
* @param string $url - request address
* @param string $method - request method
* @param array $opts - request options
*/
public function request($url, $method = 'GET', $opts = [])
{
$httpClient = new Client(['base_uri' => $url]);
try {
$response = $httpClient->request($method, $url, $opts);
$this->body = $response->getBody()->getContents();
$this->status = $response->getStatusCode();
} catch (RequestException $requestException) {
throw new Exception($requestException->getMessage());
}
}
/**
* Get the status code
*/
public function getStatusCode()
{
return $this->status;
}
/**
* Get the response body.
*/
public function getBody()
{
return $this->body;
}
}

View File

@ -16,27 +16,21 @@
* limitations under the License. * limitations under the License.
*/ */
namespace App\Services; namespace App\OnlyOffice\Services;
use Exception; use App\OnlyOffice\Managers\JWTManager;
use App\OnlyOffice\Managers\SettingsManager;
use Onlyoffice\DocsIntegrationSdk\Service\Request\RequestService as OnlyOfficeRequestService;
abstract class Config class RequestService extends OnlyOfficeRequestService
{ {
protected array $config; public function __construct(SettingsManager $settingsManager, HttpClient $httpClient, JWTManager $jwtManager)
public function get(string $key, mixed $default = null): mixed
{ {
$keys = explode('.', $key); parent::__construct($settingsManager, $httpClient, $jwtManager);
$result = $this->config;
try {
foreach ($keys as $key) {
$result = $result[$key];
}
} catch (Exception $e) {
$result = $default;
} }
return $result; public function getFileUrlForConvert()
{
return '';
} }
} }

View File

@ -2,7 +2,7 @@
namespace App\Providers; namespace App\Providers;
use App\Repositories\FormatRepository; use App\OnlyOffice\Managers\FormatManager;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider class AppServiceProvider extends ServiceProvider
@ -12,10 +12,8 @@ class AppServiceProvider extends ServiceProvider
*/ */
public function register(): void public function register(): void
{ {
$this->app->singleton(FormatRepository::class, function () { $this->app->singleton(FormatManager::class, function () {
$path = public_path('assets/document-formats/onlyoffice-docs-formats.json'); return new FormatManager;
return new FormatRepository($path);
}); });
} }

View File

@ -1,76 +0,0 @@
<?php
/**
* (c) Copyright Ascensio System SIA 2025
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace App\Services\Docs\Command;
use App\Exceptions\CommandServiceError;
use App\Services\JWT;
use App\Services\ServerConfig;
use Exception;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
class CommandRequest
{
private array $headers = [];
public function __construct(private ServerConfig $config, private JWT $jwt) {}
private function withJWTHeader(array $content): void
{
$token = $this->jwt->encode(['payload' => $content]);
$this->headers = [$this->config->get('jwt.header') => "Bearer $token"];
}
public function send(array $content, ?string $key = null): mixed
{
if ($this->config->get('jwt.enabled')) {
$this->withJWTHeader($content);
$content['token'] = $this->jwt->encode($content);
}
$client = Http::withHeaders($this->headers)
->asJson()
->acceptJson();
$url = $this->config->get('url.command');
if (Str::of($url)->isUrl(['https'])
&& ! $this->config->get('ssl_verify')) {
$client = $client->withoutVerifying();
}
if ($key) {
$url = "$url?shardkey=".urlencode($key);
}
$response = $client->post($url, $content);
if (! $response->ok()) {
throw new Exception('Could not execute the command.');
}
$result = $response->json();
if (array_key_exists('error', $result) && $result['error'] !== 0) {
throw new CommandServiceError($result['error']);
}
return $result;
}
}

View File

@ -1,34 +0,0 @@
<?php
/**
* (c) Copyright Ascensio System SIA 2025
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace App\Services\Docs\Command;
class ForceSaveRequest extends CommandRequest
{
public function save(string $key): array
{
$content = [
'c' => 'forcesave',
'key' => $key,
];
$result = $this->send($content, $key);
return $result;
}
}

View File

@ -1,34 +0,0 @@
<?php
/**
* (c) Copyright Ascensio System SIA 2025
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace App\Services\Docs\Command;
class ForgottenDeleteRequest extends CommandRequest
{
public function delete(string $key): string
{
$content = [
'c' => 'deleteForgotten',
'key' => $key,
];
$result = $this->send($content, $key);
return $result['key'];
}
}

View File

@ -1,33 +0,0 @@
<?php
/**
* (c) Copyright Ascensio System SIA 2025
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace App\Services\Docs\Command;
class ForgottenListRequest extends CommandRequest
{
public function get(): array
{
$content = [
'c' => 'getForgottenList',
];
$result = $this->send($content);
return $result['keys'];
}
}

View File

@ -1,84 +0,0 @@
<?php
/**
* (c) Copyright Ascensio System SIA 2025
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace App\Services\Docs\Conversion;
use App\Exceptions\ConversionError;
use App\Exceptions\ConversionNotComplete;
use App\Services\JWT;
use App\Services\ServerConfig;
use Exception;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
class ConversionRequest
{
private array $headers = [];
public function __construct(private ServerConfig $config, private JWT $jwt) {}
private function withJWTHeader(array $content): void
{
$token = $this->jwt->encode(['payload' => $content]);
$this->headers = [$this->config->get('jwt.header') => "Bearer $token"];
}
public function send(array $content, ?string $key = null): mixed
{
if ($this->config->get('jwt.enabled')) {
$this->withJWTHeader($content);
$content['token'] = $this->jwt->encode($content);
}
$client = Http::withHeaders($this->headers)
->timeout($this->config->get('conversion.timeout'))
->asJson()
->acceptJson();
$url = $this->config->get('conversion.url');
if (
Str::of($url)->isUrl(['https'])
&& ! $this->config->get('ssl_verify')
) {
$client = $client->withoutVerifying();
}
if ($key) {
$url = "$url?shardkey=".urlencode($key);
}
$response = $client->post($url, $content);
if (! $response->ok()) {
throw new Exception('Could not convert the file');
}
$result = $response->json();
if (array_key_exists('error', $result)) {
throw new ConversionError($result['error']);
}
if (! $result['endConvert']) {
throw new ConversionNotComplete($result['percent'], $result['filename'], $result['fileUrl']);
}
return $result;
}
}

View File

@ -1,65 +0,0 @@
<?php
/**
* (c) Copyright Ascensio System SIA 2025
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace App\Services;
use Firebase\JWT\JWT as FirebaseJWT;
use Firebase\JWT\Key;
class JWT
{
private string $secret;
private string $algorithm;
public function __construct(ServerConfig $config)
{
$this->secret = $config->get('jwt.secret');
$this->algorithm = $config->get('jwt.algorithm');
}
/**
* Encode a payload object into a token using a secret key
*
* @param array $payload
*/
public function encode(mixed $payload): string
{
return FirebaseJWT::encode($payload, $this->secret, $this->algorithm);
}
/**
* Decode a token into a payload object using a secret key
*
*
* @return string
*/
public function decode(string $token)
{
try {
$payload = FirebaseJWT::decode(
$token,
new Key($this->secret, $this->algorithm),
);
} catch (\UnexpectedValueException $e) {
$payload = '';
}
return $payload;
}
}

View File

@ -1,38 +0,0 @@
<?php
/**
* (c) Copyright Ascensio System SIA 2025
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace App\Services;
class StorageConfig extends Config
{
public function __construct()
{
$publicStorageUrl = rtrim(env('DOCUMENT_STORAGE_PUBLIC_URL', request()->schemeAndHttpHost()), '/');
$privateStorageUrl = rtrim(env('DOCUMENT_STORAGE_PRIVATE_URL', $publicStorageUrl), '/');
$this->config = [
'url' => [
'private' => $privateStorageUrl,
'public' => $publicStorageUrl,
],
'file' => [
'max_size' => env('DOCUMENT_STORAGE_MAXIMUM_FILE_SIZE', 5 * 1024 * 1024),
],
];
}
}

View File

@ -18,8 +18,8 @@
namespace App\UseCases\Docs\Command; namespace App\UseCases\Docs\Command;
use App\Exceptions\CommandServiceError; use App\OnlyOffice\Miscellaneous\CommandRequest;
use App\Services\Docs\Command\ForceSaveRequest as ForceSave; use Exception;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
class ForceSaveCommad class ForceSaveCommad
@ -27,9 +27,9 @@ class ForceSaveCommad
public function __invoke(ForceSaveRequest $request): void public function __invoke(ForceSaveRequest $request): void
{ {
try { try {
app(ForceSave::class) app(CommandRequest::class)
->save($request->key); ->forceSave($request->key);
} catch (CommandServiceError $e) { } catch (Exception $e) {
Log::debug($e->getMessage()); Log::debug($e->getMessage());
} }
} }

View File

@ -2,21 +2,15 @@
namespace App\UseCases\Docs\Command; namespace App\UseCases\Docs\Command;
use App\Services\Docs\Command\CommandRequest; use App\OnlyOffice\Miscellaneous\CommandRequest;
class UpdateMetaCommand class UpdateMetaCommand
{ {
public function __invoke(UpdateMetaRequest $request): void public function __invoke(UpdateMetaRequest $request): void
{ {
$content = [ $meta = ['title' => $request->title];
'c' => 'meta',
'key' => $request->key,
'meta' => [
'title' => $request->title,
],
];
app(CommandRequest::class) app(CommandRequest::class)
->send($content, $request->key); ->updateMeta($request->key, $meta);
} }
} }

View File

@ -22,26 +22,20 @@ use App\Exceptions\ConversionError;
use App\Exceptions\ConversionNotComplete; use App\Exceptions\ConversionNotComplete;
use App\Helpers\Path\PathInfo; use App\Helpers\Path\PathInfo;
use App\Helpers\URL\FileURL; use App\Helpers\URL\FileURL;
use App\Repositories\FormatRepository; use App\OnlyOffice\Managers\FormatManager;
use App\Services\Docs\Conversion\ConversionRequest; use App\OnlyOffice\Miscellaneous\ConvertRequest as ConvertRequestAdapter;
use App\Services\JWT;
use App\Services\ServerConfig;
use Exception; use Exception;
use Illuminate\Support\Str; use Illuminate\Support\Str;
class ConvertCommand class ConvertCommand
{ {
public function __construct( public function __construct(private FormatManager $formatManager) {}
private ServerConfig $serverConfig,
private FormatRepository $formatRepository,
private JWT $jwt,
) {}
public function __invoke(ConvertRequest $request): mixed public function __invoke(ConvertRequest $request): mixed
{ {
$format = $this->formatRepository->find($request->fileType); $format = $this->formatManager->find($request->fileType);
if (! $format->convertible() && $request->outputType == 'ooxml') { if (! $format->isAutoConvertable() && $request->outputType == 'ooxml') {
throw new Exception("The format $request->fileType is not convertible."); throw new Exception("The format $request->fileType is not convertible.");
} }
@ -61,8 +55,7 @@ class ConvertCommand
]; ];
try { try {
$result = app(ConversionRequest::class) $result = app(ConvertRequestAdapter::class)->convert($content);
->send($content, $key);
$result['filename'] = PathInfo::filename($request->filename).'.'.$result['fileType']; $result['filename'] = PathInfo::filename($request->filename).'.'.$result['fileType'];
} catch (ConversionNotComplete $e) { } catch (ConversionNotComplete $e) {
return [ return [

View File

@ -24,8 +24,8 @@ use App\Helpers\UniqueFilename;
use App\Models\File; use App\Models\File;
use App\Models\Version; use App\Models\Version;
use App\Models\VersionInfo; use App\Models\VersionInfo;
use App\OnlyOffice\Managers\FormatManager;
use App\Repositories\FileRepository; use App\Repositories\FileRepository;
use App\Repositories\FormatRepository;
use App\Repositories\UserRepository; use App\Repositories\UserRepository;
use App\Repositories\VersionRepository; use App\Repositories\VersionRepository;
use Illuminate\Support\Str; use Illuminate\Support\Str;
@ -35,7 +35,7 @@ class CreateDocumentCommand
{ {
public function __construct( public function __construct(
private FileRepository $fileRepository, private FileRepository $fileRepository,
private FormatRepository $formatRepository, private FormatManager $formatManager,
private UserRepository $userRepository, private UserRepository $userRepository,
private VersionRepository $versionRepository, private VersionRepository $versionRepository,
) {} ) {}
@ -45,10 +45,10 @@ class CreateDocumentCommand
$filePath = Path::join($request->userDirectory, $request->filename); $filePath = Path::join($request->userDirectory, $request->filename);
$filePath = UniqueFilename::for($filePath); $filePath = UniqueFilename::for($filePath);
$format = $this->formatRepository->find($request->fileType); $format = $this->formatManager->find($request->fileType);
$user = $this->userRepository->find($request->user); $user = $this->userRepository->find($request->user);
if ($format === null || empty($format->actions)) { if ($format === null || empty($format->getActions())) {
throw new UnexpectedValueException("The $request->fileType format is not supported"); throw new UnexpectedValueException("The $request->fileType format is not supported");
} }

View File

@ -3,15 +3,15 @@
namespace App\UseCases\Document\Find; namespace App\UseCases\Document\Find;
use App\Helpers\Path\PathInfo; use App\Helpers\Path\PathInfo;
use App\OnlyOffice\Managers\FormatManager;
use App\Repositories\FileRepository; use App\Repositories\FileRepository;
use App\Repositories\FormatRepository;
use App\Repositories\VersionRepository; use App\Repositories\VersionRepository;
class FindAllDocumentsQueryHandler class FindAllDocumentsQueryHandler
{ {
public function __construct( public function __construct(
private FileRepository $fileRepository, private FileRepository $fileRepository,
private FormatRepository $formatRepository, private FormatManager $formatManager,
private VersionRepository $versionRepository, private VersionRepository $versionRepository,
) {} ) {}
@ -27,7 +27,7 @@ class FindAllDocumentsQueryHandler
$result[] = [ $result[] = [
'filename' => PathInfo::basename($file->filename), 'filename' => PathInfo::basename($file->filename),
'version' => $currentVersion, 'version' => $currentVersion,
'format' => $this->formatRepository->find(PathInfo::extension($file->filename)), 'format' => $this->formatManager->find(PathInfo::extension($file->filename)),
'lastModified' => $file->modified, 'lastModified' => $file->modified,
]; ];
} }

View File

@ -4,15 +4,18 @@ namespace App\UseCases\Document\Find;
use App\Helpers\Path\PathInfo; use App\Helpers\Path\PathInfo;
use App\Helpers\URL\FileURL; use App\Helpers\URL\FileURL;
use App\OnlyOffice\Managers\JWTManager;
use App\OnlyOffice\Managers\SettingsManager;
use App\Repositories\UserRepository; use App\Repositories\UserRepository;
use App\Repositories\VersionRepository; use App\Repositories\VersionRepository;
use App\Services\JWT;
class FindDocumentHistoryQueryHandler class FindDocumentHistoryQueryHandler
{ {
public function __construct( public function __construct(
private VersionRepository $versionRepository, private VersionRepository $versionRepository,
private UserRepository $userRepository, private UserRepository $userRepository,
private SettingsManager $settings,
private JWTManager $jwt,
) {} ) {}
public function __invoke(FindDocumentHistoryQuery $request): array public function __invoke(FindDocumentHistoryQuery $request): array
@ -59,7 +62,7 @@ class FindDocumentHistoryQueryHandler
$item['url'] = FileURL::download( $item['url'] = FileURL::download(
PathInfo::basename($request->filename), $request->userAddress PathInfo::basename($request->filename), $request->userAddress
); );
$item['token'] = app(JWT::class)->encode($item); $item['token'] = $this->jwt->encode($item, $this->settings->getSetting('jwt.secret'));
$history['history'][] = $item; $history['history'][] = $item;
} }

View File

@ -4,9 +4,9 @@ namespace App\UseCases\Document\Find;
use App\Helpers\Path\Path; use App\Helpers\Path\Path;
use App\Helpers\Path\PathInfo; use App\Helpers\Path\PathInfo;
use App\OnlyOffice\Managers\FormatManager;
use App\Repositories\FileRepository; use App\Repositories\FileRepository;
use App\Repositories\ForceSavedFilesRepository; use App\Repositories\ForceSavedFilesRepository;
use App\Repositories\FormatRepository;
use App\Repositories\UserRepository; use App\Repositories\UserRepository;
use App\Repositories\VersionRepository; use App\Repositories\VersionRepository;
use DomainException; use DomainException;
@ -18,7 +18,7 @@ class FindDocumentQueryHandler
private VersionRepository $versionRepository, private VersionRepository $versionRepository,
private ForceSavedFilesRepository $forceSavedFilesRepository, private ForceSavedFilesRepository $forceSavedFilesRepository,
private UserRepository $userRepository, private UserRepository $userRepository,
private FormatRepository $formatRepository, private FormatManager $formatManager,
) {} ) {}
public function __invoke(FindDocumentQuery $request): array public function __invoke(FindDocumentQuery $request): array
@ -49,7 +49,7 @@ class FindDocumentQueryHandler
'content' => $file->content, 'content' => $file->content,
'size' => $file->size, 'size' => $file->size,
'mimeType' => $file->mime, 'mimeType' => $file->mime,
'format' => $this->formatRepository->find(PathInfo::extension($request->filename)), 'format' => $this->formatManager->find(PathInfo::extension($request->filename)),
]; ];
return $document; return $document;

View File

@ -21,19 +21,19 @@ namespace App\UseCases\Editor\Create;
use App\Models\Document; use App\Models\Document;
use App\Models\Editor\Editor; use App\Models\Editor\Editor;
use App\Models\Editor\EditorConfig; use App\Models\Editor\EditorConfig;
use App\Repositories\FormatRepository; use App\OnlyOffice\Managers\FormatManager;
use App\Repositories\UserRepository; use App\Repositories\UserRepository;
class CreateConfigCommand class CreateConfigCommand
{ {
public function __construct( public function __construct(
private UserRepository $userRepository, private UserRepository $userRepository,
private FormatRepository $formatRepository, private FormatManager $formatManager,
) {} ) {}
public function __invoke(CreateConfigRequest $request): array public function __invoke(CreateConfigRequest $request): array
{ {
$format = $this->formatRepository->find($request->fileExtension); $format = $this->formatManager->find($request->fileExtension);
$user = $this->userRepository->find($request->user); $user = $this->userRepository->find($request->user);
if ($user->goback !== null) { if ($user->goback !== null) {

View File

@ -18,12 +18,13 @@
namespace App\UseCases\Forgotten\Delete; namespace App\UseCases\Forgotten\Delete;
use App\Services\Docs\Command\ForgottenDeleteRequest; use App\OnlyOffice\Miscellaneous\CommandRequest;
class DeleteForgottenFileCommand class DeleteForgottenFileCommand
{ {
public function __invoke(DeleteForgottenFileRequest $request): void public function __invoke(DeleteForgottenFileRequest $request): void
{ {
app()->make(ForgottenDeleteRequest::class)->delete($request->key); app(CommandRequest::class)
->deleteForgotten($request->key);
} }
} }

View File

@ -20,40 +20,41 @@ namespace App\UseCases\Forgotten\Find;
use App\Helpers\Path\PathInfo; use App\Helpers\Path\PathInfo;
use App\Helpers\URL\URL; use App\Helpers\URL\URL;
use App\Repositories\FormatRepository; use App\OnlyOffice\Managers\FormatManager;
use App\Services\Docs\Command\ForgottenFileRequest; use App\OnlyOffice\Managers\SettingsManager;
use App\Services\Docs\Command\ForgottenListRequest; use App\OnlyOffice\Miscellaneous\CommandRequest;
use App\Services\ServerConfig;
use Illuminate\Support\Str; use Illuminate\Support\Str;
class FindAllForgottenFilesQueryHandler class FindAllForgottenFilesQueryHandler
{ {
public function __construct( public function __construct(
private ServerConfig $serverConfig, private SettingsManager $settings,
private FormatRepository $formatRepository, private FormatManager $formatManager,
) {} ) {}
public function __invoke(FindAllForgottenFilesQuery $query): array public function __invoke(FindAllForgottenFilesQuery $query): array
{ {
$filesList = []; $filesList = [];
$commandRequest = app(CommandRequest::class);
$keys = app()->make(ForgottenListRequest::class)->get(); $result = $commandRequest->getForgottenList();
$keys = $result->keys;
foreach ($keys as $key) { foreach ($keys as $key) {
$filesList[] = app()->make(ForgottenFileRequest::class)->get($key); $filesList[] = $commandRequest->getForgotten($key);
} }
$files = []; $files = [];
foreach ($filesList as $fileItem) { foreach ($filesList as $fileItem) {
$url = $fileItem['url']; $url = $fileItem->url;
$url = Str::replace(URL::origin($url), $this->serverConfig->get('url.public'), $url); $url = Str::replace(URL::origin($url), $this->settings->getSetting('url.server.public'), $url);
$files[] = [ $files[] = [
'key' => $fileItem['key'], 'key' => $fileItem->key,
'filename' => $url, 'filename' => $url,
'url' => $url, 'url' => $url,
'format' => $this->formatRepository->find(PathInfo::extension($fileItem['url'])), 'format' => $this->formatManager->find(PathInfo::extension($fileItem->url)),
]; ];
} }

View File

@ -3,7 +3,8 @@
"php": "^8.2", "php": "^8.2",
"firebase/php-jwt": "^6.10", "firebase/php-jwt": "^6.10",
"laravel/framework": "^11.0", "laravel/framework": "^11.0",
"laravel/tinker": "^2.9" "laravel/tinker": "^2.9",
"onlyoffice/docs-integration-sdk": "^1.1"
}, },
"require-dev": { "require-dev": {
"fakerphp/faker": "^1.23", "fakerphp/faker": "^1.23",

View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "15b06064f4351d124f81a5718daddb7c", "content-hash": "349f218d77cda1f9ef25791dae86f9d4",
"packages": [ "packages": [
{ {
"name": "brick/math", "name": "brick/math",
@ -2380,6 +2380,59 @@
], ],
"time": "2024-03-06T16:17:14+00:00" "time": "2024-03-06T16:17:14+00:00"
}, },
{
"name": "onlyoffice/docs-integration-sdk",
"version": "v1.1.0",
"source": {
"type": "git",
"url": "https://github.com/ONLYOFFICE/docs-integration-sdk-php.git",
"reference": "3715cb022c182551f4bad43f5869c0536260e5ed"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ONLYOFFICE/docs-integration-sdk-php/zipball/3715cb022c182551f4bad43f5869c0536260e5ed",
"reference": "3715cb022c182551f4bad43f5869c0536260e5ed",
"shasum": ""
},
"require": {
"vlucas/phpdotenv": "^5.6"
},
"type": "library",
"autoload": {
"psr-4": {
"Onlyoffice\\DocsIntegrationSdk\\": "src/",
"Onlyoffice\\DocsIntegrationSdk\\Util\\": "src/util/",
"Onlyoffice\\DocsIntegrationSdk\\Models\\": "src/models/",
"Onlyoffice\\DocsIntegrationSdk\\Manager\\Formats\\": "src/manager/formats/",
"Onlyoffice\\DocsIntegrationSdk\\Service\\Request\\": "src/service/request/",
"Onlyoffice\\DocsIntegrationSdk\\Manager\\Document\\": "src/manager/document/",
"Onlyoffice\\DocsIntegrationSdk\\Manager\\Security\\": "src/manager/security/",
"Onlyoffice\\DocsIntegrationSdk\\Manager\\Settings\\": "src/manager/settings/",
"Onlyoffice\\DocsIntegrationSdk\\Service\\DocEditorConfig\\": "src/service/doceditorconfig/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Ascensio System SIA"
}
],
"description": "ONLYOFFICE Docs integration SDK",
"homepage": "https://www.onlyoffice.com",
"keywords": [
"onlyoffice"
],
"support": {
"email": "support@onlyoffice.com",
"forum": "https://forum.onlyoffice.com/",
"issues": "https://github.com/ONLYOFFICE/docs-integration-sdk-php/issues",
"source": "https://github.com/ONLYOFFICE/docs-integration-sdk-php"
},
"time": "2025-01-15T13:52:01+00:00"
},
{ {
"name": "phpoption/phpoption", "name": "phpoption/phpoption",
"version": "1.9.2", "version": "1.9.2",

View File

@ -85,7 +85,7 @@
@foreach ($files as $file) @foreach ($files as $file)
<tr class="tableRow" title="{{ $file['key'] }}"> <tr class="tableRow" title="{{ $file['key'] }}">
<td> <td>
<a class="stored-edit action-link {{ $file['format']->type }}" href="{{ $file['filename'] }}" target="_blank"> <a class="stored-edit action-link {{ $file['format']->getType() }}" href="{{ $file['filename'] }}" target="_blank">
<span>{{ $file['key'] }}</span> <span>{{ $file['key'] }}</span>
</a> </a>
</td> </td>

View File

@ -168,11 +168,11 @@
@foreach ($files as $file) @foreach ($files as $file)
<tr class="tableRow" title="{{ $file['filename'] }} [{{ $file['version'] }}]"> <tr class="tableRow" title="{{ $file['filename'] }} [{{ $file['version'] }}]">
<td class="contentCells"> <td class="contentCells">
<a class="stored-edit {{ $file['format']->type }}" href="editor?fileID={{ urlencode($file['filename']) }}&user={{ "$user&$directUrlArg" }}" target="_blank"> <a class="stored-edit {{ $file['format']->getType() }}" href="editor?fileID={{ urlencode($file['filename']) }}&user={{ "$user&$directUrlArg" }}" target="_blank">
<span>{{ $file['filename'] }}</span> <span>{{ $file['filename'] }}</span>
</a> </a>
</td> </td>
@if ($file['format']->editable()) @if ($file['format']->isEditable())
<td class="contentCells contentCells-icon"> <td class="contentCells contentCells-icon">
<a href="editor?fileID={{ urlencode($file['filename']) }}&user={{ htmlentities($user) . "&$directUrlArg" }}'&action=edit&type=desktop" target="_blank"> <a href="editor?fileID={{ urlencode($file['filename']) }}&user={{ htmlentities($user) . "&$directUrlArg" }}'&action=edit&type=desktop" target="_blank">
<img src="/images/desktop.svg" alt="Open in editor for full size screens" title="Open in editor for full size screens" /> <img src="/images/desktop.svg" alt="Open in editor for full size screens" title="Open in editor for full size screens" />
@ -211,7 +211,7 @@
<td class="contentCells contentCells-icon"></td> <td class="contentCells contentCells-icon"></td>
<td class="contentCells contentCells-icon"></td> <td class="contentCells contentCells-icon"></td>
@endif @endif
@if ($file['format']->fillable()) @if ($file['format']->isFillable())
<td class="contentCells contentCells-shift contentCells-icon firstContentCellShift"> <td class="contentCells contentCells-shift contentCells-icon firstContentCellShift">
<a href="editor?fileID={{ urlencode($file['filename']) }}&user={{ htmlentities($user) . "&$directUrlArg" }}&action=fillForms&type=desktop" target="_blank"> <a href="editor?fileID={{ urlencode($file['filename']) }}&user={{ htmlentities($user) . "&$directUrlArg" }}&action=fillForms&type=desktop" target="_blank">
<img src="/images/fill-forms.svg" alt="Open in editor for filling in forms" title="Open in editor for filling in forms" /> <img src="/images/fill-forms.svg" alt="Open in editor for filling in forms" title="Open in editor for filling in forms" />
@ -220,7 +220,7 @@
@else @else
<td class="contentCells contentCells-shift contentCells-icon firstContentCellShift"></td> <td class="contentCells contentCells-shift contentCells-icon firstContentCellShift"></td>
@endif @endif
@elseif ($file['format']->fillable()) @elseif ($file['format']->isFillable())
<td class="contentCells contentCells-icon"> <td class="contentCells contentCells-icon">
<a href="editor?fileID={{ urlencode($file['filename']) }}&user={{ htmlentities($user) . "&$directUrlArg" }}&action=fillForms&type=desktop" target="_blank"> <a href="editor?fileID={{ urlencode($file['filename']) }}&user={{ htmlentities($user) . "&$directUrlArg" }}&action=fillForms&type=desktop" target="_blank">
<img src="/images/mobile-fill-forms.svg" alt="Open in editor for filling in forms for mobile devices" title="Open in editor for filling in forms for mobile devices" /> <img src="/images/mobile-fill-forms.svg" alt="Open in editor for filling in forms for mobile devices" title="Open in editor for filling in forms for mobile devices" />
@ -252,9 +252,9 @@
<img src="/images/embeded.svg" alt="Open in embedded mode" title="Open in embedded mode" /> <img src="/images/embeded.svg" alt="Open in embedded mode" title="Open in embedded mode" />
</a> </a>
</td> </td>
@if ($file['format']->type != null) @if ($file['format']->getType() != null)
<td class="contentCells contentCells-icon"> <td class="contentCells contentCells-icon">
<a class="convert-file" data="{{ $file['filename'] }}" data-type="{{ $file['format']->type }}"> <a class="convert-file" data="{{ $file['filename'] }}" data-type="{{ $file['format']->getType() }}">
<img class="icon-action" src="/images/convert.svg" alt="Convert" title="Convert" /> <img class="icon-action" src="/images/convert.svg" alt="Convert" title="Convert" />
</a> </a>
</td> </td>