Compare commits

..

18 Commits

192 changed files with 3586 additions and 4355 deletions

View File

@ -21,9 +21,11 @@ jobs:
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/csharp-mvc
mkdir -p ./deploy/'DotNet (Csharp MVC) Example'
mkdir -p ./deploy/'DotNet (Csharp MVN) Example'
rsync -av --exclude='deploy' ./ ./deploy/'DotNet (Csharp MVC) Example'
rm -rf ./deploy/'DotNet (Csharp MVC) Example'/assets/.git
cd ./deploy/'DotNet (Csharp MVC) Example'/assets
rm -rf ./.git/
rm .git
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:

View File

@ -18,11 +18,14 @@ jobs:
- name: Build Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/csharp
mkdir -p ./deploy/'DotNet (Csharp) Example'
rsync -av --exclude='deploy' ./ ./deploy/'DotNet (Csharp) Example'
rm -rf ./deploy/'DotNet (Csharp) Example'/assets/.git
cd ./deploy/'DotNet (Csharp) Example'/assets
rm -rf ./.git/
rm .git
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:

View File

@ -18,12 +18,14 @@ jobs:
- name: Build Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/java
mkdir -p ./deploy/'Java Example'
rsync -av --exclude='deploy' ./ ./deploy/'Java Example'
rm -rf ./deploy/'Java Example'/src/main/resources/assets/document-formats/.git
rm -rf ./deploy/'Java Example'/src/main/resources/assets/document-templates/.git
cd ./deploy/'Java Example'/src/main/resources/assets
rm -rf ./.git/
rm .git
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:

View File

@ -18,12 +18,14 @@ jobs:
- name: Build Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/nodejs
mkdir -p ./deploy/'Node.js Example'
rsync -av --exclude='deploy' ./ ./deploy/'Node.js Example'
rm -rf ./deploy/'Node.js Example'/public/assets/document-formats/.git
rm -rf ./deploy/'Node.js Example'/public/assets/document-templates/.git
cd ./deploy/'Node.js Example'/public/assets
rm -rf ./.git/
rm .git
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:

View File

@ -18,12 +18,14 @@ jobs:
- name: Build Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/php
mkdir -p ./deploy/'PHP Example'
rsync -av --exclude='deploy' ./ ./deploy/'PHP Example'
rm -rf ./deploy/'PHP Example'/assets/document-formats/.git
rm -rf ./deploy/'PHP Example'/assets/document-templates/.git
cd ./deploy/'PHP Example'/assets
rm -rf ./.git/
rm .git
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:

View File

@ -18,12 +18,14 @@ jobs:
- name: Build Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/python
mkdir -p ./deploy/'Python Example'
rsync -av --exclude='deploy' ./ ./deploy/'Python Example'
rm -rf ./deploy/'Python Example'/assets/document-formats/.git
rm -rf ./deploy/'Python Example'/assets/document-templates/.git
cd ./deploy/'Python Example'/assets
rm -rf ./.git/
rm .git
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:

View File

@ -18,12 +18,14 @@ jobs:
- name: Build Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/ruby
mkdir -p ./deploy/'Ruby Example'
rsync -av --exclude='deploy' ./ ./deploy/'Ruby Example'
rm -rf ./deploy/'Ruby Example'/public/assets/document-formats/.git
rm -rf ./deploy/'Ruby Example'/public/assets/document-templates/.git
cd ./deploy/'Ruby Example'/public/assets
rm -rf ./.git/
rm .git
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:

View File

@ -23,8 +23,9 @@ jobs:
cd ./web/documentserver-example/java-spring
mkdir -p ./deploy/'Java Spring Example'
rsync -av --exclude='deploy' ./ ./deploy/'Java Spring Example'
rm -rf ./deploy/'Java Spring Example'/src/main/resources/assets/document-formats/.git
rm -rf ./deploy/'Java Spring Example'/src/main/resources/assets/document-templates/.git
cd ./deploy/'Java Spring Example'/src/main/resources/assets
rm -rf ./.git/
rm .git
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:

View File

@ -26,4 +26,4 @@ jobs:
tools: cs2pr, phpcs
- name: Lint
run: phpcs src index.php
run: phpcs .

View File

@ -32,9 +32,9 @@ jobs:
- name: Lint Flake8
run: |
flake8 --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 --count --max-complexity=10 --max-line-length=79 --statistics
flake8 ./**/*.py --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 ./**/*.py --count --max-complexity=10 --max-line-length=79 --statistics
- name: Lint Pylint
run: |
find . -type f -name "*.py" | xargs pylint
pylint ./**/*.py

View File

@ -16,22 +16,16 @@ jobs:
run:
working-directory: ./web/documentserver-example/ruby
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2.2'
- name: Update Submodules
run: |
git submodule update --init --recursive
- name: Install Dependencies
run: |
bundle update
- name: Rubocop
run: |
bundle exec rubocop
- name: Checkout Repository
uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.0'
bundler-cache: true
- name: Install dependencies
run: |
bundle install
- name: Rubocop
run: |
gem install rubocop
rubocop

View File

@ -13,10 +13,8 @@ jobs:
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Clone Submodules
run: |
cd ${{ github.workspace }}
git submodule update --init --recursive
- name: Install Zip
run: sudo apt-get install zip
- name: Get Info
run: |
echo "version=$(grep -Eo '[0-9]+(\.[0-9]+)+' CHANGELOG.md | head -n 1)" >> $GITHUB_OUTPUT
@ -27,66 +25,91 @@ jobs:
- name: Build Csharp MVC Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/csharp-mvc
mkdir -p ./'DotNet (Csharp MVC) Example'
rsync -av --exclude='DotNet (Csharp MVC) Example' ./ ./'DotNet (Csharp MVC) Example'
cd ./'DotNet (Csharp MVC) Example'/assets
rm -rf .git
rm -rf ./.git/
rm .git
- name: Build Csharp Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/csharp
mkdir -p ./'DotNet (Csharp) Example'
rsync -av --exclude='DotNet (Csharp) Example' ./ ./'DotNet (Csharp) Example'
rm -rf ./'DotNet (Csharp) Example'/assets/.git
cd ./'DotNet (Csharp) Example'/assets
rm -rf ./.git/
rm .git
- name: Build Java Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/java
mkdir -p ./'Java Example'
rsync -av --exclude='Java Example' ./ ./'Java Example'
rm -rf ./'Java Example'/src/main/resources/assets/document-formats/.git
rm -rf ./'Java Example'/src/main/resources/assets/document-templates/.git
cd ./'Java Example'/src/main/resources/assets
rm -rf ./.git/
rm .git
- name: Build Nodejs Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/nodejs
mkdir -p ./'Node.js Example'
rsync -av --exclude='Node.js Example' ./ ./'Node.js Example'
rm -rf ./'Node.js Example'/public/assets/document-formats/.git
rm -rf ./'Node.js Example'/public/assets/document-templates/.git
cd ./'Node.js Example'/public/assets
rm -rf ./.git/
rm .git
- name: Build PHP Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/php
mkdir -p ./'PHP Example'
rsync -av --exclude='PHP Example' ./ ./'PHP Example'
rm -rf ./'PHP Example'/assets/document-formats/.git
rm -rf ./'PHP Example'/assets/document-templates/.git
cd ./'PHP Example'/assets
rm -rf ./.git/
rm .git
- name: Build Python Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/python
mkdir -p ./'Python Example'
rsync -av --exclude='Python Example' ./ ./'Python Example'
rm -rf ./'Python Example'/assets/document-formats/.git
rm -rf ./'Python Example'/assets/document-templates/.git
cd ./'Python Example'/assets
rm -rf ./.git/
rm .git
- name: Build Ruby Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/ruby
mkdir -p ./'Ruby Example'
rsync -av --exclude='Ruby Example' ./ ./'Ruby Example'
rm -rf ./'Ruby Example'/public/assets/document-formats/.git
rm -rf ./'Ruby Example'/public/assets/document-templates/.git
cd ./'Ruby Example'/public/assets
rm -rf ./.git/
rm .git
- name: Build Spring Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/java-spring
mkdir -p ./'Java Spring Example'
rsync -av --exclude='Java Spring Example' ./ ./'Java Spring Example'
rm -rf ./'Java Spring Example'/src/main/resources/assets/document-formats/.git
rm -rf ./'Java Spring Example'/src/main/resources/assets/document-templates/.git
cd ./'Java Spring Example'/src/main/resources/assets
rm -rf ./.git/
rm .git
- name: Pack Artifacts
run: |
cd ${{ github.workspace }}/web/documentserver-example/csharp-mvc

28
.gitmodules vendored
View File

@ -1,3 +1,7 @@
[submodule "web/documentserver-example/java/src/main/resources/assets"]
path = web/documentserver-example/java/src/main/resources/assets
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/csharp-mvc/assets"]
path = web/documentserver-example/csharp-mvc/assets
url = https://github.com/ONLYOFFICE/document-templates
@ -6,6 +10,14 @@
path = web/documentserver-example/csharp/assets
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/ruby/public/assets"]
path = web/documentserver-example/ruby/public/assets
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/java-spring/src/main/resources/assets"]
path = web/documentserver-example/java-spring/src/main/resources/assets
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/nodejs/public/assets/document-templates"]
path = web/documentserver-example/nodejs/public/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
@ -26,23 +38,7 @@
path = web/documentserver-example/python/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/java/src/main/resources/assets/document-templates"]
path = web/documentserver-example/java/src/main/resources/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/ruby/assets/document-templates"]
path = web/documentserver-example/ruby/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/java-spring/src/main/resources/assets/document-templates"]
path = web/documentserver-example/java-spring/src/main/resources/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/python/assets/document-formats"]
path = web/documentserver-example/python/assets/document-formats
url = https://github.com/ONLYOFFICE/document-formats
branch = master
[submodule "web/documentserver-example/ruby/assets/document-formats"]
path = web/documentserver-example/ruby/assets/document-formats
url = https://github.com/ONLYOFFICE/document-formats
branch = master

View File

@ -307,14 +307,6 @@ PHPUnit - The PHP Unit Testing framework. (https://github.com/sebastianb
License: BSD 3-Clause
License File: phpunit.license
property-access - Provides functions to read and write from/to an object or array using a simple string notation. (https://github.com/symfony/property-access/blob/6.3/LICENSE)
License: MIT
License File: property-access.license
serializer - Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON. (https://github.com/symfony/serializer/blob/6.3/LICENSE)
License: MIT
License File: serializer.license
web/documentserver-example/python
@ -354,10 +346,6 @@ jQuery.UI - jQuery UI is an open source library of interface components —
License: MIT
License File: jQuery.UI.license
msgspec - A fast serialization and validation library, with builtin support for JSON, MessagePack, YAML, and TOML. (https://github.com/jcrist/msgspec/blob/0.18.1/LICENSE)
License: BSD 3-Clause
License File: msgspec.license
mypy - Optional static typing for Python. (https://github.com/python/mypy/blob/master/LICENSE)
License: MIT
License File: mypy.license

View File

@ -1,24 +1,14 @@
# Change Log
## 1.7.0
- nodejs: onRequestSelectDocument method
- nodejs: onRequestSelectSpreadsheet method
- nodejs: onRequestOpen
- nodejs: submitForm
- nodejs: key in referenceData
- nodejs: change reference source
- php: using a repo with a list of formats
- nodejs: using a repo with a list of formats
- nodejs: delete file without reloading the page
- nodejs: getting history by a separate request
- nodejs: restore from history
- php: using a repo with a list of formats
- php: restore from history
- python: restore from history
- ruby: restore from history
- csharp-mvc: getting history by a separate request
- csharp-mvc: restore from history
- csharp: getting history by a separate request
- csharp: restore from history
- php: restore from history
## 1.6.0
- nodejs: setUsers for region protection

View File

@ -17,6 +17,7 @@
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Web;
@ -235,6 +236,123 @@ namespace OnlineEditorsExampleMVC.Models
return jss.Serialize(config);
}
// get the document history
public void GetHistory(out string history, out string historyData)
{
var storagePath = WebConfigurationManager.AppSettings["storage-path"];
var jss = new JavaScriptSerializer();
var histDir = DocManagerHelper.HistoryDir(DocManagerHelper.StoragePath(FileName, null));
history = null;
historyData = null;
if (DocManagerHelper.GetFileVersion(histDir) > 0) // if the file was modified (the file version is greater than 0)
{
var currentVersion = DocManagerHelper.GetFileVersion(histDir);
var hist = new List<Dictionary<string, object>>();
var histData = new Dictionary<string, object>();
for (var i = 1; i <= currentVersion; i++) // run through all the file versions
{
var obj = new Dictionary<string, object>();
var dataObj = new Dictionary<string, object>();
var verDir = DocManagerHelper.VersionDir(histDir, i); // get the path to the given file version
var key = i == currentVersion ? Key : File.ReadAllText(Path.Combine(verDir, "key.txt")); // get document key
obj.Add("key", key);
obj.Add("version", i);
if (i == 1) // check if the version number is equal to 1
{
var infoPath = Path.Combine(histDir, "createdInfo.json"); // get meta data of this file
if (File.Exists(infoPath))
{
var info = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(infoPath));
obj.Add("created", info["created"]); // write meta information to the object (user information and creation date)
obj.Add("user", new Dictionary<string, object>() {
{ "id", info["id"] },
{ "name", info["name"] },
});
}
}
var ext = Path.GetExtension(FileName).ToLower();
dataObj.Add("fileType", ext.Replace(".", ""));
dataObj.Add("key", key);
// write file url to the data object
string prevFileUrl;
string directPrevFileUrl;
if (Path.IsPathRooted(storagePath) && !string.IsNullOrEmpty(storagePath))
{
prevFileUrl = i == currentVersion ? DocManagerHelper.GetHistoryDownloadUrl(FileName, i.ToString(), "prev" + ext)
: DocManagerHelper.GetDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""));
directPrevFileUrl = i == currentVersion ? DocManagerHelper.GetHistoryDownloadUrl(FileName, i.ToString(), "prev" + ext, false)
: DocManagerHelper.GetDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""), false);
}
else {
prevFileUrl = i == currentVersion ? FileUri
: DocManagerHelper.GetHistoryDownloadUrl(FileName, i.ToString(), "prev" + ext);
directPrevFileUrl = i == currentVersion ? DocManagerHelper.GetHistoryDownloadUrl(FileName, i.ToString(), "prev" + ext, false)
: DocManagerHelper.GetDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""), false);
}
dataObj.Add("url", prevFileUrl);
if (IsEnabledDirectUrl)
{
dataObj.Add("directUrl", directPrevFileUrl);
}
dataObj.Add("version", i);
if (i > 1) // check if the version number is greater than 1 (the file was modified)
{
// get the path to the changes.json file
var changes = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(Path.Combine(DocManagerHelper.VersionDir(histDir, i - 1), "changes.json")));
var changesArray = (ArrayList)changes["changes"];
var change = changesArray.Count > 0
? (Dictionary<string, object>)changesArray[0]
: new Dictionary<string, object>();
// write information about changes to the object
obj.Add("changes", change.Count > 0 ? changes["changes"] : null);
obj.Add("serverVersion", changes["serverVersion"]);
obj.Add("created", change.Count > 0 ? change["created"] : null);
obj.Add("user", change.Count > 0 ? change["user"] : null);
var prev = (Dictionary<string, object>)histData[(i - 2).ToString()]; // get the history data from the previous file version
dataObj.Add("previous", IsEnabledDirectUrl ? new Dictionary<string, object>() { // write information about previous file version to the data object with direct url
{ "fileType", prev["fileType"] },
{ "key", prev["key"] }, // write key and url information about previous file version
{ "url", prev["url"] },
{ "directUrl", prev["directUrl"] },
} : new Dictionary<string, object>() { // write information about previous file version to the data object without direct url
{ "fileType", prev["fileType"] },
{ "key", prev["key"] }, // write key and url information about previous file version
{ "url", prev["url"] },
});
// write the path to the diff.zip archive with differences in this file version
var changesUrl = DocManagerHelper.GetHistoryDownloadUrl(FileName, (i - 1).ToString(), "diff.zip");
dataObj.Add("changesUrl", changesUrl);
}
if(JwtManager.Enabled)
{
var token = JwtManager.Encode(dataObj);
dataObj.Add("token", token);
}
hist.Add(obj); // add object dictionary to the hist list
histData.Add((i - 1).ToString(), dataObj); // write data object information to the history data
}
// write history information about the current file version to the history object
history = jss.Serialize(new Dictionary<string, object>()
{
{ "currentVersion", currentVersion },
{ "history", hist }
});
historyData = jss.Serialize(histData);
}
}
// get a document which will be compared with the current document
public void GetCompareFileData(out string compareConfig)
{

View File

@ -190,47 +190,6 @@
}
};
var onRequestHistory = function () {
let xhr = new XMLHttpRequest();
xhr.open("GET", "webeditor.ashx?type=gethistory&filename=<%= Model.FileName %>");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send();
xhr.onload = function () {
console.log(xhr.responseText);
docEditor.refreshHistory(JSON.parse(xhr.responseText));
}
};
var onRequestHistoryData = function (event) {
var ver = event.data;
let xhr = new XMLHttpRequest();
xhr.open("GET", "webeditor.ashx?type=getversiondata&filename=<%= Model.FileName %>&version=" + ver + "&directUrl=" + !!config.document.directUrl);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send();
xhr.onload = function () {
console.log(xhr.responseText);
docEditor.setHistoryData(JSON.parse(xhr.responseText)); // send the link to the document for viewing the version history
}
};
var onRequestRestore = function (event) {
var fileName = "<%= Model.FileName %>";
var version = event.data.version;
var data = {
fileName: fileName,
version: version
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "webeditor.ashx?type=restore&directUrl=" + !!config.document.directUrl);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
docEditor.refreshHistory(JSON.parse(xhr.responseText));
}
}
config = <%= Model.GetDocConfig(Request, Url) %>;
config.width = "100%";
@ -248,19 +207,30 @@
"onRequestMailMergeRecipients": onRequestMailMergeRecipients,
};
<% string hist, histData; %>
<% Model.GetHistory(out hist, out histData); %>
<% string usersForMentions; %>
<% Model.GetUsersMentions(Request, out usersForMentions); %>
if (config.editorConfig.user.id) {
// the user is trying to show the document version history
config.events['onRequestHistory'] = onRequestHistory;
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = onRequestHistoryData;
// the user is trying to go back to the document from viewing the document version history
config.events['onRequestHistoryClose'] = function () {
document.location.reload();
};
config.events['onRequestRestore'] = onRequestRestore;
<% if (!string.IsNullOrEmpty(hist) && !string.IsNullOrEmpty(histData))
{ %>
// the user is trying to show the document version history
config.events['onRequestHistory'] = function () {
docEditor.refreshHistory(<%= hist %>); // show the document version history
};
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = function (event) {
var ver = event.data;
var histData = <%= histData %>;
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
// the user is trying to go back to the document from viewing the document version history
config.events['onRequestHistoryClose'] = function () {
document.location.reload();
};
<% } %>
// add mentions for not anonymous users
<% if (!string.IsNullOrEmpty(usersForMentions))

View File

@ -17,7 +17,6 @@
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
@ -51,15 +50,6 @@ namespace OnlineEditorsExampleMVC
case "downloadhistory":
DownloadHistory(context);
break;
case "gethistory":
GetHistory(context);
break;
case "getversiondata":
GetVersionData(context);
break;
case "restore":
Restore(context);
break;
case "convert":
Convert(context);
break;
@ -523,173 +513,6 @@ namespace OnlineEditorsExampleMVC
get { return false; }
}
private static void GetHistory(HttpContext context)
{
var jss = new JavaScriptSerializer();
var fileName = context.Request["filename"];
var history = GetHistory(fileName);
context.Response.Write(jss.Serialize(history));
}
private static void GetVersionData(HttpContext context)
{
var storagePath = WebConfigurationManager.AppSettings["storage-path"];
var jss = new JavaScriptSerializer();
var fileName = context.Request["filename"];
int version;
if (!int.TryParse(context.Request["version"], out version))
{
context.Response.Write("{ \"error\": \"Version number invalid!\"}");
return;
}
var versionData = new Dictionary<string, object>();
var histDir = DocManagerHelper.HistoryDir(DocManagerHelper.StoragePath(fileName, null));
var lastVersion = DocManagerHelper.GetFileVersion(histDir);
var verDir = DocManagerHelper.VersionDir(histDir, version);
var key = version == lastVersion
? ServiceConverter.GenerateRevisionId(DocManagerHelper.CurUserHostAddress()
+ "/" + fileName + "/"
+ File.GetLastWriteTime(DocManagerHelper.StoragePath(fileName, null)).GetHashCode())
: File.ReadAllText(Path.Combine(verDir, "key.txt"));
var ext = Path.GetExtension(fileName).ToLower();
versionData.Add("fileType", ext.Replace(".", ""));
versionData.Add("key", key);
// write file url to the data object
string prevFileUrl;
string directPrevFileUrl;
if (Path.IsPathRooted(storagePath) && !string.IsNullOrEmpty(storagePath))
{
prevFileUrl = version == lastVersion ? DocManagerHelper.GetDownloadUrl(fileName)
: DocManagerHelper.GetDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""));
directPrevFileUrl = version == lastVersion ? DocManagerHelper.GetDownloadUrl(fileName, false)
: DocManagerHelper.GetDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""), false);
}
else
{
prevFileUrl = version == lastVersion ? DocManagerHelper.GetFileUri(fileName, true)
: DocManagerHelper.GetHistoryDownloadUrl(fileName, version.ToString(), "prev" + ext);
directPrevFileUrl = version == lastVersion ? DocManagerHelper.GetFileUri(fileName, false)
: DocManagerHelper.GetHistoryDownloadUrl(fileName, version.ToString(), "prev" + ext, false);
}
versionData.Add("url", prevFileUrl);
var isEnableDirectUrl = string.Equals(DocManagerHelper.GetDirectUrl(), "true");
if (isEnableDirectUrl)
{
versionData.Add("directUrl", directPrevFileUrl); // write direct url to the data object
}
versionData.Add("version", version);
if (version > 1)
{
var prevVerDir = DocManagerHelper.VersionDir(histDir, version - 1);
var prevUrl = Path.IsPathRooted(storagePath) && !string.IsNullOrEmpty(storagePath)
? DocManagerHelper.GetDownloadUrl(Directory.GetFiles(prevVerDir, "prev.*")[0].Replace(storagePath + "\\", ""))
: DocManagerHelper.GetHistoryDownloadUrl(fileName, (version - 1).ToString(), "prev" + ext);
var prevKey = File.ReadAllText(Path.Combine(prevVerDir, "key.txt"));
Dictionary<string, object> dataPrev = new Dictionary<string, object>() { // write information about previous file version to the data object
{ "fileType", ext.Replace(".", "") },
{ "key", prevKey }, // write key and url information about previous file version
{ "url", prevUrl }
};
string directPrevUrl;
if (isEnableDirectUrl)
{
directPrevUrl = Path.IsPathRooted(storagePath) && !string.IsNullOrEmpty(storagePath)
? DocManagerHelper.GetDownloadUrl(Directory.GetFiles(prevVerDir, "prev.*")[0].Replace(storagePath + "\\", ""), false)
: DocManagerHelper.GetHistoryDownloadUrl(fileName, version.ToString(), "prev" + ext, false);
dataPrev.Add("directUrl", directPrevUrl);
}
versionData.Add("previous", dataPrev);
if (File.Exists(Path.Combine(prevVerDir, "diff.zip")))
{
var changesUrl = DocManagerHelper.GetHistoryDownloadUrl(fileName, (version - 1).ToString(), "diff.zip");
versionData.Add("changesUrl", changesUrl);
}
}
if (JwtManager.Enabled)
{
var token = JwtManager.Encode(versionData);
versionData.Add("token", token);
}
context.Response.Write(jss.Serialize(versionData));
}
private static void Restore(HttpContext context)
{
string fileData;
try
{
using (var receiveStream = context.Request.InputStream)
using (var readStream = new StreamReader(receiveStream))
{
fileData = readStream.ReadToEnd();
if (string.IsNullOrEmpty(fileData)) return;
}
}
catch (Exception e)
{
throw new HttpException((int)HttpStatusCode.BadRequest, e.Message);
}
var jss = new JavaScriptSerializer();
var body = jss.Deserialize<Dictionary<string, object>>(fileData);
var fileName = (string)body["fileName"];
var version = (int)body["version"];
var key = ServiceConverter.GenerateRevisionId(DocManagerHelper.CurUserHostAddress()
+ "/" + fileName + "/"
+ File.GetLastWriteTime(DocManagerHelper.StoragePath(fileName, null)).GetHashCode());
var histDir = DocManagerHelper.HistoryDir(DocManagerHelper.StoragePath(fileName, null));
var currentVersionDir = DocManagerHelper.VersionDir(histDir, DocManagerHelper.GetFileVersion(histDir));
var verDir = DocManagerHelper.VersionDir(histDir, version);
if (!Directory.Exists(currentVersionDir)) Directory.CreateDirectory(currentVersionDir);
var ext = Path.GetExtension(fileName).ToLower();
File.Copy(DocManagerHelper.StoragePath(fileName, null), Path.Combine(currentVersionDir, "prev" + ext));
File.WriteAllText(Path.Combine(currentVersionDir, "key.txt"), key);
var changesPath = Path.Combine(DocManagerHelper.VersionDir(histDir, version - 1), "changes.json");
if (File.Exists(changesPath))
{
File.Copy(changesPath, Path.Combine(currentVersionDir, "changes.json"));
}
File.Copy(Path.Combine(verDir, "prev" + ext), DocManagerHelper.StoragePath(fileName, null), true);
var fileInfo = new FileInfo(DocManagerHelper.StoragePath(fileName, null));
fileInfo.LastWriteTimeUtc = DateTime.UtcNow;
var history = GetHistory(fileName);
context.Response.Write(jss.Serialize(history));
}
// download a history file
private static void DownloadHistory(HttpContext context)
{
@ -864,70 +687,6 @@ namespace OnlineEditorsExampleMVC
context.Response.Write(jss.Serialize(data));
}
// get the document history
private static Dictionary<string, object> GetHistory(string fileName)
{
var jss = new JavaScriptSerializer();
var histDir = DocManagerHelper.HistoryDir(DocManagerHelper.StoragePath(fileName, null));
var history = new Dictionary<string, object>();
var currentVersion = DocManagerHelper.GetFileVersion(histDir);
var currentKey = ServiceConverter.GenerateRevisionId(DocManagerHelper.CurUserHostAddress()
+ "/" + fileName + "/"
+ File.GetLastWriteTime(DocManagerHelper.StoragePath(fileName, null)).GetHashCode());
var versionList = new List<Dictionary<string, object>>();
for (var versionNum = 1; versionNum <= currentVersion; versionNum++)
{
var versionObj = new Dictionary<string, object>();
var verDir = DocManagerHelper.VersionDir(histDir, versionNum); // get the path to the given file version
var key = versionNum == currentVersion ? currentKey : File.ReadAllText(Path.Combine(verDir, "key.txt")); // get document key
versionObj.Add("key", key);
versionObj.Add("version", versionNum);
var changesPath = Path.Combine(DocManagerHelper.VersionDir(histDir, versionNum - 1), "changes.json");
if (versionNum == 1 || !File.Exists(changesPath)) // check if the version number is equal to 1
{
var infoPath = Path.Combine(histDir, "createdInfo.json"); // get meta data of this file
if (File.Exists(infoPath))
{
var info = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(infoPath));
versionObj.Add("created", info["created"]); // write meta information to the object (user information and creation date)
versionObj.Add("user", new Dictionary<string, object>()
{
{ "id", info["id"] },
{ "name", info["name"] },
});
}
}
else if (versionNum > 1) // check if the version number is greater than 1 (the file was modified)
{
// get the path to the changes.json file
var changes = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(changesPath));
var changesArray = (ArrayList)changes["changes"];
var change = changesArray.Count > 0
? (Dictionary<string, object>)changesArray[0]
: new Dictionary<string, object>();
// write information about changes to the object
versionObj.Add("changes", change.Count > 0 ? changes["changes"] : null);
versionObj.Add("serverVersion", changes["serverVersion"]);
versionObj.Add("created", change.Count > 0 ? change["created"] : null);
versionObj.Add("user", change.Count > 0 ? change["user"] : null);
}
versionList.Add(versionObj);
}
history.Add("currentVersion", currentVersion);
history.Add("history", versionList);
return history;
}
}
}

View File

@ -1,7 +1,7 @@
<?xml version="1.0"?>
<appSettings>
<clear />
<add key="version" value="1.7.0"/>
<add key="version" value="1.6.0"/>
<add key="filesize-max" value="52428800"/>
<add key="storage-path" value=""/>

View File

@ -633,12 +633,5 @@ namespace OnlineEditorsExample
string isEnabledDirectUrl = HttpUtility.ParseQueryString(HttpContext.Current.Request.Url.Query).Get("directUrl");
return "&directUrl=" + (isEnabledDirectUrl != null ? isEnabledDirectUrl : "false");
}
// get direct url flag
public static bool IsEnabledDirectUrl()
{
string isEnabledDirectUrl = HttpUtility.ParseQueryString(HttpContext.Current.Request.Url.Query).Get("directUrl");
return isEnabledDirectUrl != null ? Convert.ToBoolean(isEnabledDirectUrl) : false;
}
}
}

View File

@ -221,49 +221,20 @@
};
if (config.editorConfig.user.id) {
config.events['onRequestHistory'] = function (event) { // the user is trying to show the document version history
let xhr = new XMLHttpRequest();
xhr.open("GET", "webeditor.ashx?type=gethistory&filename=<%= FileName %>");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send();
xhr.onload = function () {
console.log(xhr.responseText);
docEditor.refreshHistory(JSON.parse(xhr.responseText));
}
};
config.events['onRequestHistoryData'] = function (event) { // the user is trying to click the specific document version in the document version history
var ver = event.data;
let xhr = new XMLHttpRequest();
xhr.open("GET", "webeditor.ashx?type=getversiondata&filename=<%= FileName %>&version=" + ver + "&directUrl=" + !!config.document.directUrl);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send();
xhr.onload = function () {
console.log(xhr.responseText);
docEditor.setHistoryData(JSON.parse(xhr.responseText)); // send the link to the document for viewing the version history
}
};
config.events['onRequestHistoryClose'] = function () { // the user is trying to go back to the document from viewing the document version history
document.location.reload();
};
config.events['onRequestRestore'] = function (event) {
var fileName = "<%= FileName %>";
var version = event.data.version;
var data = {
fileName: fileName,
version: version
<% if (!string.IsNullOrEmpty(History) && !string.IsNullOrEmpty(HistoryData))
{ %>
config.events['onRequestHistory'] = function () { // the user is trying to show the document version history
docEditor.refreshHistory(<%= History %>); // show the document version history
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "webeditor.ashx?type=restore&directUrl=" + !!config.document.directUrl);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
docEditor.refreshHistory(JSON.parse(xhr.responseText));
}
};
config.events['onRequestHistoryData'] = function (event) { // the user is trying to click the specific document version in the document version history
var ver = event.data;
var histData = <%= HistoryData %>;
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
config.events['onRequestHistoryClose'] = function () { // the user is trying to go back to the document from viewing the document version history
document.location.reload();
};
<% } %>
// add mentions for not anonymous users
<% if (!string.IsNullOrEmpty(UsersForMentions))

View File

@ -17,6 +17,7 @@
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Web;
@ -60,6 +61,8 @@ namespace OnlineEditorsExample
}
protected string DocConfig { get; private set; }
protected string History { get; private set; }
protected string HistoryData { get; private set; }
protected string InsertImageConfig { get; private set; }
protected string CompareFileData { get; private set; }
protected string DataMailMergeRecipients { get; private set; }
@ -192,7 +195,7 @@ namespace OnlineEditorsExample
{
{ "title", FileName },
{ "url", getDownloadUrl(FileName) },
{ "directUrl", _Default.IsEnabledDirectUrl() ? directUrl : "" },
{ "directUrl", IsEnabledDirectUrl() ? directUrl : "" },
{ "fileType", ext.Trim('.') },
{ "key", Key },
{
@ -317,10 +320,134 @@ namespace OnlineEditorsExample
// get users for mentions
List<Dictionary<string, object>> usersData = Users.getUsersForMentions(user.id);
UsersForMentions = !user.id.Equals("uid-0") ? jss.Serialize(usersData) : null;
Dictionary<string, object> hist;
Dictionary<string, object> histData;
// get the document history
GetHistory(out hist, out histData);
if (hist != null && histData != null)
{
History = jss.Serialize(hist);
HistoryData = jss.Serialize(histData);
}
}
catch { }
}
// get the document history
private void GetHistory(out Dictionary<string, object> history, out Dictionary<string, object> historyData)
{
var storagePath = WebConfigurationManager.AppSettings["storage-path"];
var jss = new JavaScriptSerializer();
var histDir = _Default.HistoryDir(_Default.StoragePath(FileName, null));
history = null;
historyData = null;
if (_Default.GetFileVersion(histDir) > 0) // if the file was modified (the file version is greater than 0)
{
var currentVersion = _Default.GetFileVersion(histDir);
var hist = new List<Dictionary<string, object>>();
var histData = new Dictionary<string, object>();
for (var i = 1; i <= currentVersion; i++) // run through all the file versions
{
var obj = new Dictionary<string, object>();
var dataObj = new Dictionary<string, object>();
var verDir = _Default.VersionDir(histDir, i); // get the path to the given file version
var key = i == currentVersion ? Key : File.ReadAllText(Path.Combine(verDir, "key.txt")); // get document key
obj.Add("key", key);
obj.Add("version", i);
if (i == 1) // check if the version number is equal to 1
{
var infoPath = Path.Combine(histDir, "createdInfo.json"); // get meta data of this file
if (File.Exists(infoPath)) {
var info = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(infoPath));
obj.Add("created", info["created"]); // write meta information to the object (user information and creation date)
obj.Add("user", new Dictionary<string, object>() {
{ "id", info["id"] },
{ "name", info["name"] },
});
}
}
var ext = Path.GetExtension(FileName).ToLower();
dataObj.Add("fileType", ext.Replace(".", ""));
dataObj.Add("key", key);
// write file url to the data object
var directPrevFileUrl = i == currentVersion ? _Default.FileUri(FileName, false) : MakePublicHistoryUrl(FileName, i.ToString(), "prev" + ext, false);
var prevFileUrl = i == currentVersion ? FileUri : MakePublicHistoryUrl(FileName, i.ToString(), "prev" + ext);
if (Path.IsPathRooted(storagePath))
{
prevFileUrl = i == currentVersion ? getDownloadUrl(FileName) : getDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""));
directPrevFileUrl = i == currentVersion ? getDownloadUrl(FileName, false) : getDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""), false);
}
dataObj.Add("url", prevFileUrl); // write file url to the data object
if (IsEnabledDirectUrl())
{
dataObj.Add("directUrl", directPrevFileUrl); // write direct url to the data object
}
dataObj.Add("version", i);
if (i > 1) // check if the version number is greater than 1 (the file was modified)
{
// get the path to the changes.json file
var changes = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(Path.Combine(_Default.VersionDir(histDir, i - 1), "changes.json")));
var changesArray = (ArrayList)changes["changes"];
var change = changesArray.Count > 0
? (Dictionary<string, object>)changesArray[0]
: new Dictionary<string, object>();
// write information about changes to the object
obj.Add("changes", change.Count > 0 ? changes["changes"] : null);
obj.Add("serverVersion", changes["serverVersion"]);
obj.Add("created", change.Count > 0 ? change["created"] : null);
obj.Add("user", change.Count > 0 ? change["user"] : null);
var prev = (Dictionary<string, object>)histData[(i - 2).ToString()]; // get the history data from the previous file version
Dictionary<string, object> dataPrev = new Dictionary<string, object>() { // write information about previous file version to the data object
{ "fileType", prev["fileType"] },
{ "key", prev["key"] }, // write key and url information about previous file version
{ "url", prev["url"] }
};
if (IsEnabledDirectUrl())
{
dataPrev.Add("directUrl", prev["directUrl"]);
}
dataObj.Add("previous", dataPrev);
// write the path to the diff.zip archive with differences in this file version
var changesUrl = MakePublicHistoryUrl(FileName, (i - 1).ToString(), "diff.zip");
dataObj.Add("changesUrl", changesUrl);
}
if (JwtManager.Enabled)
{
var token = JwtManager.Encode(dataObj);
dataObj.Add("token", token);
}
hist.Add(obj); // add object dictionary to the hist list
histData.Add((i - 1).ToString(), dataObj); // write data object information to the history data
}
// write history information about the current file version to the history object
history = new Dictionary<string, object>()
{
{ "currentVersion", currentVersion },
{ "history", hist }
};
historyData = histData;
}
}
// get a logo config
private Dictionary<string, object> GetLogoConfig()
{
@ -342,7 +469,7 @@ namespace OnlineEditorsExample
{ "url", InsertImageUrl.ToString()}
};
if (_Default.IsEnabledDirectUrl())
if (IsEnabledDirectUrl())
{
logoConfig.Add("directUrl", DirectImageUrl.ToString());
}
@ -379,7 +506,7 @@ namespace OnlineEditorsExample
{ "url", compareFileUrl.ToString() }
};
if (_Default.IsEnabledDirectUrl())
if (IsEnabledDirectUrl())
{
dataCompareFile.Add("directUrl", DirectFileUrl.ToString());
}
@ -418,7 +545,7 @@ namespace OnlineEditorsExample
{ "url", mailmergeUrl.ToString() }
};
if (_Default.IsEnabledDirectUrl())
if (IsEnabledDirectUrl())
{
mailMergeConfig.Add("directUrl", DirectMailMergeUrl.ToString());
}
@ -462,6 +589,21 @@ namespace OnlineEditorsExample
return _Default.GetServerUrl(true) + fullPath.Substring(root.Length).Replace(Path.DirectorySeparatorChar, '/');
}
// create the public history url
private string MakePublicHistoryUrl(string filename, string version, string file, Boolean isServer = true)
{
var userAddress = isServer ? "&userAddress=" + HttpUtility.UrlEncode(_Default.CurUserHostAddress(HttpContext.Current.Request.UserHostAddress)) : "";
var fileUrl = new UriBuilder(_Default.GetServerUrl(isServer));
fileUrl.Path = HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "webeditor.ashx";
fileUrl.Query = "type=downloadhistory&fileName=" + HttpUtility.UrlEncode(filename)
+ "&ver=" + version + "&file=" + file
+ userAddress;
return fileUrl.ToString();
}
// create demo document
private static void Try(string type, string sample, HttpRequest request)
{
@ -510,5 +652,12 @@ namespace OnlineEditorsExample
{ "name", uname }
}));
}
// get direct url flag
private static bool IsEnabledDirectUrl()
{
string isEnabledDirectUrl = HttpUtility.ParseQueryString(HttpContext.Current.Request.Url.Query).Get("directUrl");
return isEnabledDirectUrl != null ? Convert.ToBoolean(isEnabledDirectUrl) : false;
}
}
}

View File

@ -26,9 +26,7 @@ using System.Diagnostics;
using System.Web.Configuration;
using System.Linq;
using System.Net;
using System.Collections;
using System.Net.Sockets;
using ASC.Api.DocumentConverter;
namespace OnlineEditorsExample
{
@ -50,15 +48,6 @@ namespace OnlineEditorsExample
case "downloadhistory":
DownloadHistory(context);
break;
case "gethistory":
GetHistory(context);
break;
case "getversiondata":
GetVersionData(context);
break;
case "restore":
Restore(context);
break;
case "convert":
Convert(context);
break;
@ -344,164 +333,6 @@ namespace OnlineEditorsExample
get { return false; }
}
private static void GetHistory(HttpContext context)
{
var jss = new JavaScriptSerializer();
var fileName = context.Request["filename"];
var history = GetHistory(fileName);
context.Response.Write(jss.Serialize(history));
}
private static void GetVersionData(HttpContext context)
{
var storagePath = WebConfigurationManager.AppSettings["storage-path"];
var jss = new JavaScriptSerializer();
var fileName = context.Request["filename"];
int version;
if (!int.TryParse(context.Request["version"], out version))
{
context.Response.Write("{ \"error\": \"Version number invalid!\"}");
return;
}
var versionData = new Dictionary<string, object>();
var histDir = _Default.HistoryDir(_Default.StoragePath(fileName, null));
var lastVersion = _Default.GetFileVersion(histDir);
var verDir = _Default.VersionDir(histDir, version);
var lastVersionUri = _Default.FileUri(fileName, true);
var key = version == lastVersion
? ServiceConverter.GenerateRevisionId(_Default.CurUserHostAddress(null)
+ "/" + Path.GetFileName(lastVersionUri)
+ "/" + File.GetLastWriteTime(_Default.StoragePath(fileName, null)).GetHashCode())
: File.ReadAllText(Path.Combine(verDir, "key.txt"));
var ext = Path.GetExtension(fileName).ToLower();
versionData.Add("fileType", ext.Replace(".", ""));
versionData.Add("key", key);
var directPrevFileUrl = version == lastVersion ? _Default.FileUri(fileName, false) : MakePublicHistoryUrl(fileName, version.ToString(), "prev" + ext, false);
var prevFileUrl = version == lastVersion ? lastVersionUri : MakePublicHistoryUrl(fileName, version.ToString(), "prev" + ext);
if (Path.IsPathRooted(storagePath))
{
prevFileUrl = version == lastVersion ? DocEditor.getDownloadUrl(fileName) : DocEditor.getDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""));
directPrevFileUrl = version == lastVersion ? DocEditor.getDownloadUrl(fileName, false) : DocEditor.getDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""), false);
}
versionData.Add("url", prevFileUrl);
if (_Default.IsEnabledDirectUrl())
{
versionData.Add("directUrl", directPrevFileUrl); // write direct url to the data object
}
versionData.Add("version", version);
if (version > 1)
{
var prevVerDir = _Default.VersionDir(histDir, version - 1);
var prevUrl = MakePublicHistoryUrl(fileName, (version - 1).ToString(), "prev" + ext);
if (Path.IsPathRooted(storagePath))
prevUrl = DocEditor.getDownloadUrl(Directory.GetFiles(prevVerDir, "prev.*")[0].Replace(storagePath + "\\", ""));
var prevKey = File.ReadAllText(Path.Combine(prevVerDir, "key.txt"));
Dictionary<string, object> dataPrev = new Dictionary<string, object>() { // write information about previous file version to the data object
{ "fileType", ext.Replace(".", "") },
{ "key", prevKey }, // write key and url information about previous file version
{ "url", prevUrl }
};
string directPrevUrl;
if (_Default.IsEnabledDirectUrl())
{
directPrevUrl = Path.IsPathRooted(storagePath)
? DocEditor.getDownloadUrl(Directory.GetFiles(prevVerDir, "prev.*")[0].Replace(storagePath + "\\", ""), false)
: MakePublicHistoryUrl(fileName, (version - 1).ToString(), "prev" + ext, false);
dataPrev.Add("directUrl", directPrevUrl); // write direct url to the data object
}
versionData.Add("previous", dataPrev);
if (File.Exists(Path.Combine(prevVerDir, "diff.zip")))
{
var changesUrl = MakePublicHistoryUrl(fileName, (version - 1).ToString(), "diff.zip");
versionData.Add("changesUrl", changesUrl);
}
}
if (JwtManager.Enabled)
{
var token = JwtManager.Encode(versionData);
versionData.Add("token", token);
}
context.Response.Write(jss.Serialize(versionData));
}
private void Restore(HttpContext context)
{
string fileData;
try
{
using (var receiveStream = context.Request.InputStream)
using (var readStream = new StreamReader(receiveStream))
{
fileData = readStream.ReadToEnd();
if (string.IsNullOrEmpty(fileData)) return;
}
}
catch (Exception e)
{
throw new HttpException((int)HttpStatusCode.BadRequest, e.Message);
}
var jss = new JavaScriptSerializer();
var body = jss.Deserialize<Dictionary<string, object>>(fileData);
var fileName = (string)body["fileName"];
var version = (int)body["version"];
var lastVersionUri = _Default.FileUri(fileName, true);
var key = ServiceConverter.GenerateRevisionId(_Default.CurUserHostAddress(null)
+ "/" + Path.GetFileName(lastVersionUri)
+ "/" + File.GetLastWriteTime(_Default.StoragePath(fileName, null)).GetHashCode());
var histDir = _Default.HistoryDir(_Default.StoragePath(fileName, null));
var currentVersionDir = _Default.VersionDir(histDir, _Default.GetFileVersion(histDir));
var verDir = _Default.VersionDir(histDir, version);
if (!Directory.Exists(currentVersionDir)) Directory.CreateDirectory(currentVersionDir);
var ext = Path.GetExtension(fileName).ToLower();
File.Copy(_Default.StoragePath(fileName, null), Path.Combine(currentVersionDir, "prev" + ext));
File.WriteAllText(Path.Combine(currentVersionDir, "key.txt"), key);
var changesPath = Path.Combine(_Default.VersionDir(histDir, version - 1), "changes.json");
if (File.Exists(changesPath))
{
File.Copy(changesPath, Path.Combine(currentVersionDir, "changes.json"));
}
File.Copy(Path.Combine(verDir, "prev" + ext), _Default.StoragePath(fileName, null), true);
var fileInfo = new FileInfo(_Default.StoragePath(fileName, null));
fileInfo.LastWriteTimeUtc = DateTime.UtcNow;
var history = GetHistory(fileName);
context.Response.Write(jss.Serialize(history));
}
private static void DownloadHistory(HttpContext context)
{
try
@ -673,84 +504,5 @@ namespace OnlineEditorsExample
context.Response.Write(jss.Serialize(data));
}
// get the document history
private static Dictionary<string, object> GetHistory(string fileName)
{
var jss = new JavaScriptSerializer();
var histDir = _Default.HistoryDir(_Default.StoragePath(fileName, null));
var history = new Dictionary<string, object>();
var currentVersion = _Default.GetFileVersion(histDir);
var currentFileUri = _Default.FileUri(fileName, true);
var currentKey = ServiceConverter.GenerateRevisionId(_Default.CurUserHostAddress(null)
+ "/" + Path.GetFileName(currentFileUri)
+ "/" + File.GetLastWriteTime(_Default.StoragePath(fileName, null)).GetHashCode());
var versionList = new List<Dictionary<string, object>>();
for (var versionNum = 1; versionNum <= currentVersion; versionNum++)
{
var versionObj = new Dictionary<string, object>();
var verDir = _Default.VersionDir(histDir, versionNum); // get the path to the given file version
var key = versionNum == currentVersion ? currentKey : File.ReadAllText(Path.Combine(verDir, "key.txt")); // get document key
versionObj.Add("key", key);
versionObj.Add("version", versionNum);
var changesPath = Path.Combine(_Default.VersionDir(histDir, versionNum - 1), "changes.json");
if (versionNum == 1 || !File.Exists(changesPath)) // check if the version number is equal to 1
{
var infoPath = Path.Combine(histDir, "createdInfo.json"); // get meta data of this file
if (File.Exists(infoPath))
{
var info = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(infoPath));
versionObj.Add("created", info["created"]); // write meta information to the object (user information and creation date)
versionObj.Add("user", new Dictionary<string, object>()
{
{ "id", info["id"] },
{ "name", info["name"] },
});
}
}
else if (versionNum > 1) // check if the version number is greater than 1 (the file was modified)
{
// get the path to the changes.json file
var changes = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(changesPath));
var changesArray = (ArrayList)changes["changes"];
var change = changesArray.Count > 0
? (Dictionary<string, object>)changesArray[0]
: new Dictionary<string, object>();
// write information about changes to the object
versionObj.Add("changes", change.Count > 0 ? changes["changes"] : null);
versionObj.Add("serverVersion", changes["serverVersion"]);
versionObj.Add("created", change.Count > 0 ? change["created"] : null);
versionObj.Add("user", change.Count > 0 ? change["user"] : null);
}
versionList.Add(versionObj);
}
history.Add("currentVersion", currentVersion);
history.Add("history", versionList);
return history;
}
// create the public history url
private static string MakePublicHistoryUrl(string filename, string version, string file, Boolean isServer = true)
{
var userAddress = isServer ? "&userAddress=" + HttpUtility.UrlEncode(_Default.CurUserHostAddress(HttpContext.Current.Request.UserHostAddress)) : "";
var fileUrl = new UriBuilder(_Default.GetServerUrl(isServer));
fileUrl.Path = HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "webeditor.ashx";
fileUrl.Query = "type=downloadhistory&fileName=" + HttpUtility.UrlEncode(filename)
+ "&ver=" + version + "&file=" + file
+ userAddress;
return fileUrl.ToString();
}
}
}

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
<clear />
<add key="version" value="1.7.0"/>
<add key="version" value="1.6.0"/>
<add key="filesize-max" value="52428800"/>
<add key="storage-path" value=""/>

View File

@ -35,8 +35,6 @@ import com.onlyoffice.integration.documentserver.util.file.FileUtility;
import com.onlyoffice.integration.documentserver.util.service.ServiceConverter;
import com.onlyoffice.integration.documentserver.managers.document.DocumentManager;
import com.onlyoffice.integration.documentserver.managers.callback.CallbackManager;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.springframework.beans.factory.annotation.Autowired;
@ -51,7 +49,6 @@ import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@ -59,20 +56,14 @@ import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
@ -364,13 +355,13 @@ public class FileController {
@GetMapping("/assets")
public ResponseEntity<Resource> assets(@RequestParam("name")
final String name) { // get sample files from the assests
String fileName = Path.of("assets", "document-templates", "sample", fileUtility.getFileName(name)).toString();
String fileName = Path.of("assets", "sample", fileUtility.getFileName(name)).toString();
return downloadFile(fileName);
}
@GetMapping("/csv")
public ResponseEntity<Resource> csv() { // download a csv file
String fileName = Path.of("assets", "document-templates", "sample", "csv.csv").toString();
String fileName = Path.of("assets", "sample", "csv.csv").toString();
return downloadFile(fileName);
}
@ -537,88 +528,4 @@ public class FileController {
return "{ \"error\" : 1, \"message\" : \"" + e.getMessage() + "\"}";
}
}
@PutMapping("/restore")
@ResponseBody
public String restore(@RequestBody final JSONObject body) {
try {
String sourceBasename = (String) body.get("fileName");
Integer version = (Integer) body.get("version");
String userID = (String) body.get("userId");
String sourceStringFile = storagePathBuilder.getFileLocation(sourceBasename);
File sourceFile = new File(sourceStringFile);
Path sourcePathFile = sourceFile.toPath();
String historyDirectory = storagePathBuilder.getHistoryDir(sourcePathFile.toString());
Integer bumpedVersion = storagePathBuilder.getFileVersion(historyDirectory, false);
String bumpedVersionStringDirectory = documentManager.versionDir(historyDirectory, bumpedVersion, true);
File bumpedVersionDirectory = new File(bumpedVersionStringDirectory);
if (!bumpedVersionDirectory.exists()) {
bumpedVersionDirectory.mkdir();
}
Path bumpedKeyPathFile = Paths.get(bumpedVersionStringDirectory, "key.txt");
String bumpedKeyStringFile = bumpedKeyPathFile.toString();
File bumpedKeyFile = new File(bumpedKeyStringFile);
String bumpedKey = serviceConverter.generateRevisionId(
storagePathBuilder.getStorageLocation()
+ "/"
+ sourceBasename
+ "/"
+ Long.toString(sourceFile.lastModified())
);
FileWriter bumpedKeyFileWriter = new FileWriter(bumpedKeyFile);
bumpedKeyFileWriter.write(bumpedKey);
bumpedKeyFileWriter.close();
Integer userInnerID = Integer.parseInt(userID.replace("uid-", ""));
User user = userService.findUserById(userInnerID).get();
Path bumpedChangesPathFile = Paths.get(bumpedVersionStringDirectory, "changes.json");
String bumpedChangesStringFile = bumpedChangesPathFile.toString();
File bumpedChangesFile = new File(bumpedChangesStringFile);
JSONObject bumpedChangesUser = new JSONObject();
// Don't add the `uid-` prefix.
// https://github.com/ONLYOFFICE/document-server-integration/issues/437#issuecomment-1663526562
bumpedChangesUser.put("id", user.getId());
bumpedChangesUser.put("name", user.getName());
JSONObject bumpedChangesChangesItem = new JSONObject();
bumpedChangesChangesItem.put("created", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
bumpedChangesChangesItem.put("user", bumpedChangesUser);
JSONArray bumpedChangesChanges = new JSONArray();
bumpedChangesChanges.add(bumpedChangesChangesItem);
JSONObject bumpedChanges = new JSONObject();
bumpedChanges.put("serverVersion", null);
bumpedChanges.put("changes", bumpedChangesChanges);
String bumpedChangesContent = bumpedChanges.toJSONString();
FileWriter bumpedChangesFileWriter = new FileWriter(bumpedChangesFile);
bumpedChangesFileWriter.write(bumpedChangesContent);
bumpedChangesFileWriter.close();
String sourceExtension = fileUtility.getFileExtension(sourceBasename);
String previousBasename = "prev" + sourceExtension;
Path bumpedFile = Paths.get(bumpedVersionStringDirectory, previousBasename);
Files.move(sourcePathFile, bumpedFile);
String recoveryVersionStringDirectory = documentManager.versionDir(historyDirectory, version, true);
Path recoveryPathFile = Paths.get(recoveryVersionStringDirectory, previousBasename);
String recoveryStringFile = recoveryPathFile.toString();
FileInputStream recoveryStream = new FileInputStream(recoveryStringFile);
storageMutator.createFile(sourcePathFile, recoveryStream);
recoveryStream.close();
JSONObject responseBody = new JSONObject();
responseBody.put("error", null);
responseBody.put("success", true);
return responseBody.toJSONString();
} catch (Exception error) {
error.printStackTrace();
JSONObject responseBody = new JSONObject();
responseBody.put("error", error.getMessage());
responseBody.put("success", false);
return responseBody.toJSONString();
}
}
}

View File

@ -217,14 +217,8 @@ public class DefaultDocumentManager implements DocumentManager {
public String createDemo(final String fileExt, final Boolean sample, final String uid, final String uname) {
String demoName = (sample ? "sample." : "new.")
+ fileExt; // create sample or new template file with the necessary extension
String demoPath =
"assets"
+ File.separator
+ "document-templates"
+ File.separator
+ (sample ? "sample" : "new")
+ File.separator
+ demoName;
String demoPath = "assets" + File.separator + (sample ? "sample" : "new")
+ File.separator + demoName; // get the path to the sample document
// get a file name with an index if the file with such a name already exists
String fileName = getCorrectName(demoName);

View File

@ -1,4 +1,4 @@
server.version=1.7.0
server.version=1.6.0
server.address=
server.port=4000

View File

@ -172,28 +172,6 @@
}
};
function onRequestRestore(event) {
const query = new URLSearchParams(window.location.search)
const config = [[${model}]]
const payload = {
fileName: query.get('fileName'),
version: event.data.version,
userId: config.editorConfig.user.id
}
const request = new XMLHttpRequest()
request.open('PUT', 'restore')
request.setRequestHeader('Content-Type', 'application/json')
request.send(JSON.stringify(payload))
request.onload = function () {
if (request.status != 200) {
response = JSON.parse(request.response)
innerAlert(response.error)
return
}
document.location.reload()
}
}
config.width = "100%";
config.height = "100%";
config.events = {
@ -206,7 +184,6 @@
"onRequestInsertImage": onRequestInsertImage,
"onRequestCompareFile": onRequestCompareFile,
"onRequestMailMergeRecipients": onRequestMailMergeRecipients,
"onRequestRestore": onRequestRestore
};
var histArray = [[${fileHistory}]];

View File

@ -48,7 +48,6 @@ import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
@ -58,9 +57,7 @@ import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
@ -129,9 +126,6 @@ public class IndexServlet extends HttpServlet {
case "reference":
reference(request, response, writer);
break;
case "restore":
restore(request, response, writer);
break;
default:
break;
}
@ -457,7 +451,7 @@ public class IndexServlet extends HttpServlet {
private static void csv(final HttpServletRequest request,
final HttpServletResponse response,
final PrintWriter writer) {
String fileName = "assets/document-templates/sample/csv.csv";
String fileName = "assets/sample/csv.csv";
URL fileUrl = Thread.currentThread().getContextClassLoader().getResource(fileName);
Path filePath = null;
try {
@ -472,7 +466,7 @@ public class IndexServlet extends HttpServlet {
private static void assets(final HttpServletRequest request,
final HttpServletResponse response,
final PrintWriter writer) {
String fileName = "assets/document-templates/sample/" + FileUtility.getFileName(request.getParameter("name"));
String fileName = "assets/sample/" + FileUtility.getFileName(request.getParameter("name"));
URL fileUrl = Thread.currentThread().getContextClassLoader().getResource(fileName);
Path filePath = null;
try {
@ -734,97 +728,6 @@ public class IndexServlet extends HttpServlet {
}
}
private static void restore(final HttpServletRequest request,
final HttpServletResponse response,
final PrintWriter writer) {
try {
Scanner scanner = new Scanner(request.getInputStream());
scanner.useDelimiter("\\A");
String bodyString = scanner.hasNext() ? scanner.next() : "";
scanner.close();
JSONParser parser = new JSONParser();
JSONObject body = (JSONObject) parser.parse(bodyString);
String sourceBasename = (String) body.get("fileName");
Integer version = ((Long) body.get("version")).intValue();
String userID = (String) body.get("userId");
String sourceStringFile = DocumentManager.storagePath(sourceBasename, null);
File sourceFile = new File(sourceStringFile);
Path sourcePathFile = sourceFile.toPath();
String historyDirectory = DocumentManager.historyDir(sourceStringFile);
Integer bumpedVersion = DocumentManager.getFileVersion(historyDirectory);
String bumpedVersionStringDirectory = DocumentManager.versionDir(historyDirectory, bumpedVersion);
File bumpedVersionDirectory = new File(bumpedVersionStringDirectory);
if (!bumpedVersionDirectory.exists()) {
bumpedVersionDirectory.mkdir();
}
Path bumpedKeyPathFile = Paths.get(bumpedVersionStringDirectory, "key.txt");
String bumpedKeyStringFile = bumpedKeyPathFile.toString();
File bumpedKeyFile = new File(bumpedKeyStringFile);
String bumpedKey = ServiceConverter.generateRevisionId(
DocumentManager.curUserHostAddress(null)
+ "/"
+ sourceBasename
+ "/"
+ Long.toString(sourceFile.lastModified())
);
FileWriter bumpedKeyFileWriter = new FileWriter(bumpedKeyFile);
bumpedKeyFileWriter.write(bumpedKey);
bumpedKeyFileWriter.close();
User user = Users.getUser(userID);
Path bumpedChangesPathFile = Paths.get(bumpedVersionStringDirectory, "changes.json");
String bumpedChangesStringFile = bumpedChangesPathFile.toString();
File bumpedChangesFile = new File(bumpedChangesStringFile);
JSONObject bumpedChangesUser = new JSONObject();
bumpedChangesUser.put("id", user.getId());
bumpedChangesUser.put("name", user.getName());
JSONObject bumpedChangesChangesItem = new JSONObject();
bumpedChangesChangesItem.put("created", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
bumpedChangesChangesItem.put("user", bumpedChangesUser);
JSONArray bumpedChangesChanges = new JSONArray();
bumpedChangesChanges.add(bumpedChangesChangesItem);
JSONObject bumpedChanges = new JSONObject();
bumpedChanges.put("serverVersion", null);
bumpedChanges.put("changes", bumpedChangesChanges);
String bumpedChangesContent = bumpedChanges.toJSONString();
FileWriter bumpedChangesFileWriter = new FileWriter(bumpedChangesFile);
bumpedChangesFileWriter.write(bumpedChangesContent);
bumpedChangesFileWriter.close();
String sourceExtension = FileUtility.getFileExtension(sourceBasename);
String previousBasename = "prev" + sourceExtension;
Path bumpedFile = Paths.get(bumpedVersionStringDirectory, previousBasename);
Files.move(sourcePathFile, bumpedFile);
String recoveryVersionStringDirectory = DocumentManager.versionDir(historyDirectory, version);
Path recoveryPathFile = Paths.get(recoveryVersionStringDirectory, previousBasename);
String recoveryStringFile = recoveryPathFile.toString();
FileInputStream recoveryStream = new FileInputStream(recoveryStringFile);
DocumentManager.createFile(sourcePathFile, recoveryStream);
recoveryStream.close();
JSONObject responseBody = new JSONObject();
responseBody.put("error", null);
responseBody.put("success", true);
String responseContent = responseBody.toJSONString();
writer.write(responseContent);
} catch (Exception error) {
error.printStackTrace();
JSONObject responseBody = new JSONObject();
responseBody.put("error", error.getMessage());
responseBody.put("success", false);
String responseContent = responseBody.toJSONString();
writer.write(responseContent);
}
}
// process get request
@Override
protected void doGet(final HttpServletRequest request,
@ -839,12 +742,6 @@ public class IndexServlet extends HttpServlet {
processRequest(request, response);
}
@Override
protected void doPut(final HttpServletRequest request,
final HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
// get servlet information
@Override
public String getServletInfo() {

View File

@ -306,12 +306,7 @@ public final class DocumentManager {
String demoName = (sample ? "sample." : "new.") + fileExt;
// get the path to the sample document
String demoPath = "assets"
+ File.separator
+ "document-templates"
+ File.separator
+ (sample ? "sample" : "new")
+ File.separator;
String demoPath = "assets" + File.separator + (sample ? "sample" : "new") + File.separator;
// get a file name with an index if the file with such a name already exists
String fileName = getCorrectName(demoName, null);

View File

@ -1,4 +1,4 @@
version=1.7.0
version=1.6.0
filesize-max=5242880
storage-folder=app_data

View File

@ -173,26 +173,6 @@
}
};
function onRequestRestore(event) {
const query = new URLSearchParams(window.location.search)
const payload = {
fileName: query.get('fileName'),
version: event.data.version,
userId: config.editorConfig.user.id
}
const request = new XMLHttpRequest()
request.open('PUT', 'IndexServlet?type=restore')
request.send(JSON.stringify(payload))
request.onload = function () {
if (request.status != 200) {
response = JSON.parse(request.response)
innerAlert(response.error)
return
}
document.location.reload()
}
}
config = JSON.parse('<%= FileModel.serialize(Model) %>');
config.width = "100%";
config.height = "100%";
@ -206,7 +186,6 @@
"onRequestInsertImage": onRequestInsertImage,
"onRequestCompareFile": onRequestCompareFile,
"onRequestMailMergeRecipients": onRequestMailMergeRecipients,
"onRequestRestore": onRequestRestore
};
<%

View File

@ -521,14 +521,12 @@ app.post('/reference', (req, res) => { // define a handler for renaming file
const data = {
fileType: fileUtility.getFileExtension(fileName).slice(1),
key: req.DocManager.getKey(fileName),
url: req.DocManager.getDownloadUrl(fileName, true),
directUrl: req.body.directUrl ? req.DocManager.getDownloadUrl(fileName) : null,
referenceData: {
fileKey: JSON.stringify({ fileName, userAddress: req.DocManager.curUserHostAddress() }),
instanceId: req.DocManager.getServerUrl(),
},
link: `${req.DocManager.getServerUrl()}/editor?fileName=${encodeURIComponent(fileName)}`,
path: fileName,
};
@ -551,16 +549,13 @@ app.put('/restore', (req, res) => { // define a handler for restore file version
const filePath = req.DocManager.storagePath(fileName, userAddress);
const historyPath = req.DocManager.historyPath(fileName, userAddress);
const newVersion = req.DocManager.countVersion(historyPath) + 1;
const versionPath = path.join(`${historyPath}`, `${version}`, `prev${fileUtility.getFileExtension(fileName)}`);
const newVersionPath = path.join(`${historyPath}`, `${newVersion}`);
const versionPath = `${historyPath}\\${version}\\prev${fileUtility.getFileExtension(fileName)}`;
const newVersionPath = `${historyPath}\\${newVersion}`;
if (fileSystem.existsSync(versionPath)) {
req.DocManager.createDirectory(newVersionPath);
req.DocManager.copyFile(
filePath,
path.join(`${newVersionPath}`, `prev${fileUtility.getFileExtension(fileName)}`),
);
fileSystem.writeFileSync(path.join(`${newVersionPath}`, 'key.txt'), key);
req.DocManager.copyFile(filePath, `${newVersionPath}\\prev${fileUtility.getFileExtension(fileName)}`);
fileSystem.writeFileSync(`${newVersionPath}\\key.txt`, key);
req.DocManager.copyFile(versionPath, filePath);
result.success = true;
} else {
@ -687,6 +682,7 @@ app.post('/track', async (req, res) => { // define a handler for tracking file c
try {
const resp = documentService.getResponseUri(data);
await callbackProcessSave(resp.uri, body, fileName, userAddress, fileName);
return;
} catch (ex) {
console.log(ex);
await callbackProcessSave(downloadUri, body, fileName, userAddress, newFileName);
@ -715,22 +711,18 @@ app.post('/track', async (req, res) => { // define a handler for tracking file c
const downloadExt = `.${body.fileType}`;
const isSubmitForm = body.forcesavetype === 3; // SubmitForm
let correctName = fileName;
let correctName = '';
let forcesavePath = '';
if (isSubmitForm) {
// new file
if (newFileName) {
correctName = req.DocManager.getCorrectName(
`${fileUtility.getFileName(fileName, true)}-form${downloadExt}`,
userAddress,
);
correctName = req.DocManager.getCorrectName(`${fileUtility.getFileName(fileName, true)}
-form${downloadExt}`, userAddress);
} else {
const ext = fileUtility.getFileExtension(fileName);
correctName = req.DocManager.getCorrectName(
`${fileUtility.getFileName(fileName, true)}-form${ext}`,
userAddress,
);
correctName = req.DocManager.getCorrectName(`${fileUtility.getFileName(fileName, true)}
-form${ext}`, userAddress);
}
forcesavePath = req.DocManager.storagePath(correctName, userAddress);
} else {
@ -786,6 +778,7 @@ app.post('/track', async (req, res) => { // define a handler for tracking file c
try {
const resp = documentService.getResponseUri(data);
await callbackProcessForceSave(resp.uri, body, fileName, userAddress, false);
return;
} catch (ex) {
console.log(ex);
await callbackProcessForceSave(downloadUri, body, fileName, userAddress, true);
@ -954,7 +947,7 @@ app.get('/editor', (req, res) => { // define a handler for editing document
if (!canEdit && mode === 'edit') {
mode = 'view';
}
const submitForm = mode === 'fillForms' && userid === 'uid-1';
const submitForm = mode === 'fillForms' && userid === 'uid-1' && !1;
// file config data
const argss = {
@ -1012,14 +1005,14 @@ app.get('/editor', (req, res) => { // define a handler for editing document
url: `${req.DocManager.getServerUrl(true)}/images/logo.png`,
directUrl: !userDirectUrl ? null : `${req.DocManager.getServerUrl()}/images/logo.png`,
},
dataDocument: {
dataCompareFile: {
fileType: 'docx',
url: `${req.DocManager.getServerUrl(true)}/assets/document-templates/sample/sample.docx`,
directUrl: !userDirectUrl
? null
: `${req.DocManager.getServerUrl()}/assets/document-templates/sample/sample.docx`,
},
dataSpreadsheet: {
dataMailMergeRecipients: {
fileType: 'csv',
url: `${req.DocManager.getServerUrl(true)}/csv`,
directUrl: !userDirectUrl ? null : `${req.DocManager.getServerUrl()}/csv`,
@ -1044,13 +1037,13 @@ app.get('/editor', (req, res) => { // define a handler for editing document
cfgSignatureSecret,
{ expiresIn: cfgSignatureSecretExpiresIn },
);
argss.dataDocument.token = jwt.sign(
argss.dataDocument,
argss.dataCompareFile.token = jwt.sign(
argss.dataCompareFile,
cfgSignatureSecret,
{ expiresIn: cfgSignatureSecretExpiresIn },
);
argss.dataSpreadsheet.token = jwt.sign(
argss.dataSpreadsheet,
argss.dataMailMergeRecipients.token = jwt.sign(
argss.dataMailMergeRecipients,
cfgSignatureSecret,
{ expiresIn: cfgSignatureSecretExpiresIn },
);

View File

@ -1,5 +1,5 @@
{
"version": "1.7.0",
"version": "1.6.0",
"log": {
"appenders": [
{

View File

@ -152,9 +152,9 @@ DocManager.prototype.saveFileData = function saveFileData(fileName, userid, user
// get full creation date of the document
const dateCreate = fileSystem.statSync(this.storagePath(fileName, address)).mtime;
const minutes = (dateCreate.getMinutes() < 10 ? '0' : '') + dateCreate.getMinutes().toString();
const month = (dateCreate.getMonth() < 9 ? '0' : '') + (parseInt(dateCreate.getMonth().toString(), 10) + 1);
const month = (dateCreate.getMonth() < 10 ? '0' : '') + (parseInt(dateCreate.getMonth().toString(), 10) + 1);
const sec = (dateCreate.getSeconds() < 10 ? '0' : '') + dateCreate.getSeconds().toString();
const dateFormat = `${dateCreate.getFullYear()}-${month}-${dateCreate.getDate()} `
const dateFormat = `${dateCreate.getFullYear()}-${month}-${dateCreate.getDate()}`
+ `${dateCreate.getHours()}:${minutes}:${sec}`;
const fileInfo = this.historyPath(fileName, address, true); // get file history information
@ -389,14 +389,14 @@ DocManager.prototype.getTemplateImageUrl = function getTemplateImageUrl(fileType
}
if (fileType === fileUtility.fileType.cell) { // for cell type
return `${serverUrl}/images/file_xlsx.svg`;
return `${path}/images/file_xlsx.svg`;
}
if (fileType === fileUtility.fileType.slide) { // for slide type
return `${serverUrl}/images/file_pptx.svg`;
return `${path}/images/file_pptx.svg`;
}
return `${serverUrl}/images/file_docx.svg`; // the default value
return `${path}/images/file_docx.svg`; // the default value
};
// get document key
@ -534,7 +534,7 @@ DocManager.prototype.getHistory = function getHistory(fileName, content, keyVers
if (content && contentJson) {
userNameFromJson = oldVersion ? contentJson.username : contentJson.user.name;
userIdFromJson = oldVersion ? contentJson.userid : contentJson.user.id;
userIdFromJson = oldVersion ? contentJson.userid : contentJson.user.userid;
createdFromJson = oldVersion ? contentJson.date : contentJson.created;
}

View File

@ -90,7 +90,9 @@ fileUtility.getFillExtensions = function getFillExtensions() {
fileUtility.getConvertExtensions = function getConvertExtensions() {
return supportedFormats.filter(
(format) => format.actions.includes('auto-convert'),
(format) => (format.type === 'word' && format.convert.includes('docx'))
|| (format.type === 'cell' && format.convert.includes('xlsx'))
|| (format.type === 'slide' && format.convert.includes('pptx')),
).reduce((extensions, format) => [...extensions, format.name], []);
};

View File

@ -52,7 +52,7 @@ const descrUser1 = [
'The file favorite state is undefined',
'Can create files from templates using data from the editor',
'Can see the information about all users',
'Can submit forms',
// "Can submit forms"
];
const descrUser2 = [
@ -62,7 +62,7 @@ const descrUser2 = [
'This file is marked as favorite',
'Can create new files from the editor',
'Can see the information about users from Group2 and users who dont belong to any group',
'Cant submit forms',
// "Cant submit forms"
];
const descrUser3 = [
@ -75,7 +75,7 @@ const descrUser3 = [
'Cant print the file',
'Can create new files from the editor',
'Can see the information about Group2 users',
'Cant submit forms',
// "Cant submit forms"
];
const descrUser0 = [
@ -91,7 +91,7 @@ const descrUser0 = [
'Can\'t view chat',
'Can\'t protect file',
'View file without collaboration',
'Cant submit forms',
// "Cant submit forms"
];
const users = [

View File

@ -34,15 +34,13 @@ const requestDiscovery = async function requestDiscovery(url) {
urllib.request(urlModule.parse(url + configServer.get('wopi.discovery')), { method: 'GET' }, (err, data) => {
if (data) {
// create the discovery XML file with the parameters from the response
const xmlParseOptions = {
const discovery = xmlParser.parse(data.toString(), {
attributeNamePrefix: '',
ignoreAttributes: false,
parseAttributeValue: true,
attrValueProcessor: (val) => he.decode(val, { isAttributeValue: true }),
};
const parser = new xmlParser.XMLParser(xmlParseOptions);
// create the discovery XML file with the parameters from the response
const discovery = parser.parse(data.toString());
// eslint-disable-next-line no-unused-vars
attrValueProcessor: (val, attrName) => he.decode(val, { isAttributeValue: true }),
});
if (discovery['wopi-discovery']) {
discovery['wopi-discovery']['net-zone'].app.forEach((app) => {
let appAction = app.action;

View File

@ -1,12 +1,12 @@
{
"name": "OnlineEditorsExampleNodeJS",
"version": "1.6.0",
"version": "4.1.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "OnlineEditorsExampleNodeJS",
"version": "1.6.0",
"version": "4.1.0",
"license": "Apache",
"dependencies": {
"body-parser": "^1.19.0",
@ -14,7 +14,7 @@
"debug": "^4.2.0",
"ejs": "^3.1.5",
"express": "^4.17.1",
"fast-xml-parser": "^4.3.1",
"fast-xml-parser": "^3.19.0",
"formidable": "^1.2.2",
"he": "^1.2.0",
"jsonwebtoken": "^9.0.0",
@ -1509,24 +1509,15 @@
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
},
"node_modules/fast-xml-parser": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.1.tgz",
"integrity": "sha512-viVv3xb8D+SiS1W4cv4tva3bni08kAkx0gQnWrykMM8nXPc1FxqZPU00dCEVjkiCg4HoXd2jC4x29Nzg/l2DAA==",
"funding": [
{
"type": "paypal",
"url": "https://paypal.me/naturalintelligence"
},
{
"type": "github",
"url": "https://github.com/sponsors/NaturalIntelligence"
}
],
"dependencies": {
"strnum": "^1.0.5"
},
"version": "3.19.0",
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.19.0.tgz",
"integrity": "sha512-4pXwmBplsCPv8FOY1WRakF970TjNGnGnfbOnLqjlYvMiF1SR3yOHyxMR/YCXpPTOspNF5gwudqktIP4VsWkvBg==",
"bin": {
"fxparser": "src/cli/cli.js"
"xml2js": "cli.js"
},
"funding": {
"type": "paypal",
"url": "https://paypal.me/naturalintelligence"
}
},
"node_modules/fastq": {
@ -3524,11 +3515,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/strnum": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
"integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="
},
"node_modules/supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@ -5007,12 +4993,9 @@
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
},
"fast-xml-parser": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.1.tgz",
"integrity": "sha512-viVv3xb8D+SiS1W4cv4tva3bni08kAkx0gQnWrykMM8nXPc1FxqZPU00dCEVjkiCg4HoXd2jC4x29Nzg/l2DAA==",
"requires": {
"strnum": "^1.0.5"
}
"version": "3.19.0",
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.19.0.tgz",
"integrity": "sha512-4pXwmBplsCPv8FOY1WRakF970TjNGnGnfbOnLqjlYvMiF1SR3yOHyxMR/YCXpPTOspNF5gwudqktIP4VsWkvBg=="
},
"fastq": {
"version": "1.13.0",
@ -6528,11 +6511,6 @@
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true
},
"strnum": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
"integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",

View File

@ -22,7 +22,7 @@
"debug": "^4.2.0",
"ejs": "^3.1.5",
"express": "^4.17.1",
"fast-xml-parser": "^4.3.1",
"fast-xml-parser": "^3.19.0",
"formidable": "^1.2.2",
"he": "^1.2.0",
"jsonwebtoken": "^9.0.0",

View File

@ -1 +1,8 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3c0-1.65685 1.34315-3 3-3h20l7 7v30c0 1.6569-1.3431 3-3 3H3c-1.65685 0-3-1.3431-3-3V3z" fill="#1E7AAA"/><path d="M23 0l7 7h-4c-1.6569 0-3-1.34315-3-3V0z" fill="#000" fill-opacity=".25"/><path d="M6 15h18v1H6v-1zM6 19h18v1H6v-1zM6 23h18v1H6v-1zM6 27h18v1H6v-1z" fill="#fff"/></svg>
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 3C0 1.34315 1.34315 0 3 0H21.674C22.4697 0 23.2327 0.316071 23.7953 0.87868L29.1213 6.20465C29.6839 6.76726 30 7.53032 30 8.32597V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#3779A6"/>
<path d="M22.9167 0L30.0001 7.08333H25.9167C24.2599 7.08333 22.9167 5.74019 22.9167 4.08333V0Z" fill="#1D5880"/>
<path d="M6.17627 14.7059H23.8233V15.8823H6.17627V14.7059Z" fill="white"/>
<path d="M6.17627 18.5294H23.8233V19.7059H6.17627V18.5294Z" fill="white"/>
<path d="M6.17627 22.3529H23.8233V23.5294H6.17627V22.3529Z" fill="white"/>
<path d="M6.17627 26.1765H23.8233V27.3529H6.17627V26.1765Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 738 B

View File

@ -1 +1,6 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3c0-1.65685 1.34315-3 3-3h20l7 7v30c0 1.6569-1.3431 3-3 3H3c-1.65685 0-3-1.3431-3-3V3z" fill="#27ABA3"/><path d="M23 0l7 7h-4c-1.6569 0-3-1.34315-3-3V0z" fill="#008078"/><path fill-rule="evenodd" clip-rule="evenodd" d="M24 14H6v7h18v-7zm-.8182 5.9978H6.81818V15H23.1818v4.9978zM24 23H6v7h18v-7zm-.8182 5.9978H6.81818V24H23.1818v4.9978z" fill="#fff"/></svg>
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 3C0 1.34315 1.34315 0 3 0H22.9167L30 7.08333V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#27ABA3"/>
<path d="M22.9165 0L29.9998 7.08333H25.9165C24.2597 7.08333 22.9165 5.74019 22.9165 4.08333V0Z" fill="#008078"/>
<rect x="6.5" y="15.5" width="17" height="5" stroke="white"/>
<rect x="6.5" y="23.5" width="17" height="5" stroke="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 463 B

After

Width:  |  Height:  |  Size: 477 B

View File

@ -1 +1,8 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3c0-1.65685 1.34315-3 3-3h20l7 7v30c0 1.6569-1.3431 3-3 3H3c-1.65685 0-3-1.3431-3-3V3z" fill="#F36700"/><path d="M23 0l7 7h-4c-1.6569 0-3-1.34315-3-3V0z" fill="#000" fill-opacity=".25"/><path stroke="#fff" stroke-opacity=".95" d="M6.5 15.5h17v12h-17z"/></svg>
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 3C0 1.34315 1.34315 0 3 0H22.9167L30 7.08333V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#F36700"/>
<path d="M22.9167 0L30.0001 7.08333H25.9168C24.2599 7.08333 22.9167 5.74019 22.9167 4.08333V0Z" fill="#AB531F"/>
<path d="M6.17627 16.1275H23.8233V17.3039H6.17627V16.1275Z" fill="white"/>
<path d="M6.17627 28.7745L6.17627 16.1275L7.35274 16.1275L7.35274 28.7745H6.17627Z" fill="white"/>
<path d="M23.8233 16.1275V28.7745H22.6469V16.1275L23.8233 16.1275Z" fill="white"/>
<path d="M6.17627 27.598H23.8233V28.7745H6.17627L6.17627 27.598Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 366 B

After

Width:  |  Height:  |  Size: 691 B

View File

@ -1 +1,6 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3c0-1.65685 1.34315-3 3-3h20l7 7v30c0 1.6569-1.3431 3-3 3H3c-1.65685 0-3-1.3431-3-3V3z" fill="#D0D5DA"/><path d="M23 0l7 7h-4c-1.6569 0-3-1.34315-3-3V0z" fill="#646464"/><path fill-rule="evenodd" clip-rule="evenodd" d="M7.5 23c-.27614 0-.5.2239-.5.5v4c0 .2761.22386.5.5.5h15c.2761 0 .5-.2239.5-.5v-4c0-.2761-.2239-.5-.5-.5h-2c-.2761 0-.5-.2239-.5-.5s.2239-.5.5-.5h2c.8284 0 1.5.6716 1.5 1.5v4c0 .8284-.6716 1.5-1.5 1.5h-15c-.82843 0-1.5-.6716-1.5-1.5v-4c0-.8284.67157-1.5 1.5-1.5h2c.27614 0 .5.2239.5.5s-.22386.5-.5.5h-2z" fill="#646464"/><path fill-rule="evenodd" clip-rule="evenodd" d="M20 20.0001L15 14l-5 6.0001h3v4c0 .5523.4477 1 1 1h2c.5523 0 1-.4477 1-1v-4h3z" fill="#646464"/></svg>
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M30 7.44186L22 0H3C1.22739 0 0 0.822551 0 2.32558V37.2093C0 38.7123 1.22739 40 3 40H27C28.7726 40 30 38.7123 30 37.2093V7.44186Z" fill="#D0D5DA"/>
<path d="M24.1042 7.27273H29.9631L22 0V5.32334C22 6.4105 22.949 7.27273 24.1042 7.27273Z" fill="#646464"/>
<path d="M16.9562 22.3485H12.9746V17.803H10.9839L14.9654 14.1667L18.947 17.803H16.9562V22.3485Z" fill="#646464"/>
<path d="M20.9378 23.7121C20.9378 24.1666 20.4401 24.6212 19.9424 24.6212H9.98848C9.49078 24.6212 8.99309 24.1666 8.99309 23.7121V22.3485C8.99309 21.8939 9.49078 21.4394 9.98848 21.4394H10.9839V20.0757H9.49078C8.49539 20.0757 7.5 20.9848 7.5 21.8939V24.1666C7.5 25.0757 8.61982 25.9848 9.49078 25.9848H20.4401C21.3111 25.9848 22.4309 25.0757 22.4309 24.1666V21.8939C22.4309 20.9848 21.4355 20.0757 20.4401 20.0757H18.947V21.4394H19.9424C20.4401 21.4394 20.9378 21.8939 20.9378 22.3485V23.7121Z" fill="#646464"/>
</svg>

Before

Width:  |  Height:  |  Size: 797 B

After

Width:  |  Height:  |  Size: 992 B

View File

@ -1 +1,12 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3c0-1.65685 1.34315-3 3-3h20l7 7v30c0 1.6569-1.3431 3-3 3H3c-1.65685 0-3-1.3431-3-3V3z" fill="#6AAA1E"/><path d="M23 0l7 7h-4c-1.6569 0-3-1.34315-3-3V0z" fill="#000" fill-opacity=".25"/><path fill-rule="evenodd" clip-rule="evenodd" d="M6 15h18v13H7.00001v-1H12v-3H7v4H6V15zm7 12h4v-3h-4v3zm5 0h5v-3h-5v3zm5-7v3h-5v-3h5zm-6 0v3h-4v-3h4zm-5 0v3H7v-3h5zm11-1v-3h-5v3h5zm-10-3h4v3h-4v-3zm-1 3v-3H7v3h5z" fill="#fff" fill-opacity=".95"/></svg>
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 3C0 1.34315 1.34315 0 3 0H22.9167L30 7.08333V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#78A73B"/>
<path d="M22.9167 0L30.0001 7.08333H25.9168C24.2599 7.08333 22.9167 5.74019 22.9167 4.08333V0Z" fill="#5A7D2B"/>
<path d="M6.17644 15.2941H23.8235V16.4706H6.17644V15.2941Z" fill="white"/>
<path d="M6.17644 19.1177H23.8235V20.2941H6.17644V19.1177Z" fill="white"/>
<path d="M6.17644 22.9412H23.8235V24.1177H6.17644V22.9412Z" fill="white"/>
<path d="M6.17644 26.7647H23.8235V27.9412H6.17644V26.7647Z" fill="white"/>
<path d="M5.88232 27.9412L5.88232 15.2941L7.0588 15.2941L7.0588 27.9412H5.88232Z" fill="white"/>
<path d="M11.4706 27.9412L11.4706 15.2941L12.647 15.2941V27.9412H11.4706Z" fill="white"/>
<path d="M17.0588 27.9412L17.0588 15.2941L18.2353 15.2941V27.9412H17.0588Z" fill="white"/>
<path d="M22.647 27.9412V15.2941H23.8235V27.9412H22.647Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 545 B

After

Width:  |  Height:  |  Size: 1004 B

View File

@ -172,21 +172,18 @@
};
var onRequestInsertImage = function(event) { // the user is trying to insert an image by clicking the Image from Storage button
var data = <%- JSON.stringify(dataInsertImage) %>;
data.c = event.data.c;
docEditor.insertImage(data); // insert an image into the file
docEditor.insertImage({ // insert an image into the file
"c": event.data.c,
<%- JSON.stringify(dataInsertImage).substring(1, JSON.stringify(dataInsertImage).length - 1)%>
})
};
var onRequestSelectDocument = function() { // the user is trying to select document by clicking the Document from Storage button
var data = <%- JSON.stringify(dataDocument) %>;
data.c = event.data.c;
docEditor.setRequestedDocument(data); // select a document
var onRequestCompareFile = function() { // the user is trying to select document for comparing by clicking the Document from Storage button
docEditor.setRevisedFile(<%- JSON.stringify(dataCompareFile) %>); // select a document for comparing
};
var onRequestSelectSpreadsheet = function (event) { // the user is trying to select recipients data by clicking the Mail merge button
var data = <%- JSON.stringify(dataSpreadsheet) %>;
data.c = event.data.c;
docEditor.setRequestedSpreadsheet(data); // insert recipient data for mail merge into the file
var onRequestMailMergeRecipients = function (event) { // the user is trying to select recipients data by clicking the Mail merge button
docEditor.setMailMergeRecipients(<%- JSON.stringify(dataMailMergeRecipients) %>); // insert recipient data for mail merge into the file
};
var onRequestUsers = function (event) {
@ -214,50 +211,26 @@
innerAlert("onRequestSendNotify: " + data);
};
var onRequestOpen = function(event) { // user open external data source
innerAlert("onRequestOpen");
var windowName = event.data.windowName;
requestReference(event.data, function (data) {
if (data.error) {
var winEditor = window.open("", windowName);
winEditor.close();
innerAlert(data.error, true);
return;
}
var link = data.link;
window.open(link, windowName);
});
};
var onRequestReferenceData = function(event) { // user refresh external data source
innerAlert("onRequestReferenceData");
requestReference(event.data, function (data) {
docEditor.setReferenceData(data);
});
};
var requestReference = function(data, callback) {
innerAlert(data);
innerAlert(event.data);
event.data.directUrl = !!config.document.directUrl;
let xhr = new XMLHttpRequest();
xhr.open("POST", "reference");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(data));
xhr.send(JSON.stringify(event.data));
xhr.onload = function () {
innerAlert(xhr.responseText);
callback(JSON.parse(xhr.responseText));
docEditor.setReferenceData(JSON.parse(xhr.responseText));
}
};
var onRequestReferenceSource = function (event) {
innerAlert("onRequestReferenceSource");
let xhr = new XMLHttpRequest();
xhr.open("GET", "files/");
xhr.open("GET", "files");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send();
xhr.onload = function () {
@ -347,9 +320,8 @@
"onMakeActionLink": onMakeActionLink,
"onMetaChange": onMetaChange,
"onRequestInsertImage": onRequestInsertImage,
"onRequestSelectDocument": onRequestSelectDocument,
"onRequestSelectSpreadsheet": onRequestSelectSpreadsheet,
"onRequestOpen": onRequestOpen,
"onRequestCompareFile": onRequestCompareFile,
"onRequestMailMergeRecipients": onRequestMailMergeRecipients,
};
if (<%- JSON.stringify(editor.userid) %> != null) {

View File

@ -35,11 +35,3 @@ License File: PHP_CodeSniffer.license
PHPUnit - The PHP Unit Testing framework. (https://github.com/sebastianbergmann/phpunit/blob/main/LICENSE)
License: BSD 3-Clause
License File: phpunit.license
property-access - Provides functions to read and write from/to an object or array using a simple string notation. (https://github.com/symfony/property-access/blob/6.3/LICENSE)
License: MIT
License File: property-access.license
serializer - Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON. (https://github.com/symfony/serializer/blob/6.3/LICENSE)
License: MIT
License File: serializer.license

View File

@ -1,14 +0,0 @@
FROM php:8.2.8-fpm-alpine3.18 AS example
WORKDIR /srv
COPY . .
RUN \
chown -R www-data:www-data /srv && \
apk update && \
apk add --no-cache \
composer \
make && \
make prod
CMD ["make", "server-prod"]
FROM nginx:1.23.4-alpine3.17 AS proxy
COPY proxy/nginx.conf /etc/nginx/nginx.conf

View File

@ -4,16 +4,16 @@ ADDRESS := $(ADDRESS)
PORT := $(PORT)
.PHONY: help
help: # Show help message for each of the Makefile recipes.
help: # Show help message for each of the Makefile recipes.
@grep -E "^[a-z-]+: #" $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ": # "}; {printf "%s: %s\n", $$1, $$2}'
.PHONY: dev
dev: # Install development dependencies.
dev: # Install development dependencies.
@composer install
.PHONY: prod
prod: # Install production dependencies.
prod: # Install production dependencies.
@composer install --no-dev
ifeq ($(ADDRESS),)
@ -33,7 +33,7 @@ server-dev: \
endif
.PHONY: server-dev
server-dev: # Start the development server on localhost at $PORT (default: 9000).
server-dev: # Start the development server on localhost at $PORT (default: 9000).
@php --server $(ADDRESS):$(PORT)
ifeq ($(ADDRESS),)
@ -53,20 +53,15 @@ server-prod: \
endif
.PHONY: server-prod
server-prod: # Start the production server on 0.0.0.0 at $PORT (default: 9000).
server-prod: # Start the production server on 0.0.0.0 at $PORT (default: 9000).
@php-fpm --fpm-config php-fpm.conf
.PHONY: compose-prod
compose-prod: # Up containers in a production environment.
@docker-compose build
@docker-compose up --detach
.PHONY: lint
lint: # Lint the source code for the style.
@./vendor/bin/phpcs src index.php
lint: # Lint the source code for the style.
@./vendor/bin/phpcs .
.PHONY: test
test: # Run tests recursively.
test: # Run tests recursively.
@./vendor/bin/phpunit \
--test-suffix "Tests.php" \
--display-incomplete \
@ -74,4 +69,12 @@ test: # Run tests recursively.
--display-errors \
--display-notices \
--display-warnings \
src
common
@./vendor/bin/phpunit \
--test-suffix "Tests.php" \
--display-incomplete \
--display-deprecations \
--display-errors \
--display-notices \
--display-warnings \
configuration

View File

@ -1,85 +1,212 @@
## Overview
This example will help you integrate ONLYOFFICE Docs into your web application written on PHP.
This example will help you integrate ONLYOFFICE Docs into your web application written in PHP.
> [!WARNING]
> It is intended for testing purposes and demonstrating functionality of the editors. **DO NOT** use this integration example on your own server without proper code modifications. In case you enabled the test example, disable it before going for production.
**Please note**: It is intended for testing purposes and demonstrating functionality of the editors. Do NOT use this integration example on your own server without proper code modifications! In case you enabled the test example, disable it before going for production.
## Installation
## For Windows
The PHP example offers various installation options, but we highly recommend using Docker for this purpose.
### Step 1. Install ONLYOFFICE Docs
### Using Docker
Download and install ONLYOFFICE Docs (packaged as Document Server).
To run the example using [Docker](https://docker.com), you will need [Docker Desktop 4.17.0](https://docs.docker.com/desktop) or [Docker Engine 20.10.23](https://docs.docker.com/engine) with [Docker Compose 2.15.1](https://docs.docker.com/compose). Additionally, you might want to consider installing [GNU Make 4.4.1](https://gnu.org/software/make), although it is optional. These are the minimum versions required for the tools.
See the detailed guide to learn how to [install Document Server for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx?from=api_php_example).
Once you have everything installed, download the release archive and unarchive it.
### Step 2. Download the PHP code for the editors integration
```sh
$ curl --output PHP.Example.zip --location https://github.com/ONLYOFFICE/document-server-integration/releases/latest/download/PHP.Example.zip
$ unzip PHP.Example.zip
Download the [PHP example](https://api.onlyoffice.com/editors/demopreview) from our site.
To connect the editors to your website, specify the path to the editors installation and the path to the storage folder in the *config.json* file:
```
"storagePath" = "";
"docServSiteUrl" = "https://documentserver/";
```
Then open the example directory and [up containers](./Makefile#L60).
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed and the **storagePath** is the path where files will be created and stored. You can set an absolute path. For example, *D:\\\\folder*. Please note that on Windows OS the double backslash must be used as a separator.
```sh
$ cd "PHP Example"
$ make compose-prod
```
If you want to experiment with the editor configuration, modify the [parameters](https://api.onlyoffice.com/editors/advanced) in the *doceditor.php* file.
By default, the server starts at `localhost:80`.
### Step 3. Install the prerequisites
To configure the example, you can edit the environment variables in [`docker-compose.yml`](./docker-compose.yml). See [below](#configuration) for more information about environment variables.
You can use any web server capable of running PHP code to run the example. We will demonstrate how to run the PHP example using the **Internet Information Services (IIS)** web server. To set up and configure PHP on IIS, **PHP Manager for IIS** will be used.
### On Local Machine
* **IIS**: version 7 or later (refer to [Microsoft official website](https://www.iis.net/learn/application-frameworks/scenario-build-a-php-website-on-iis/configuring-step-1-install-iis-and-php) to learn how to install IIS);
* **PHP** (download it from the [http://php.net](https://php.net/downloads.php) site);
* **PHP Manager for IIS** (download it from the [Microsoft open source site](https://phpmanager.codeplex.com/releases/view/69115)).
* **Composer** (download it from the [Composer official website](https://getcomposer.org/download/)).
Before diving into the example, you will need to install ONLYOFFICE Document Server (also known as Docs). Check the detailed guide to learn how to install it on [Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx), [Linux](https://helpcenter.onlyoffice.com/installation/docs-developer-install-ubuntu.aspx), or [Docker](https://helpcenter.onlyoffice.com/installation/docs-developer-install-docker.aspx).
### Step 4. IIS configuration
To run the example on your local machine, you will need [PHP 8.2.11](https://php.net) with [Composer 2.6.5](https://getcomposer.org). Additionally, you might want to consider installing [GNU Make 4.4.1](https://gnu.org/software/make), although it is optional. These are the minimum versions required for the tools.
1. **PHP Manager for IIS** configuration.
Once you have everything installed, download the release archive and unarchive it.
After PHP Manager for IIS installation is complete, launch the **IIS Manager:**
```sh
$ curl --output PHP.Example.zip --location https://github.com/ONLYOFFICE/document-server-integration/releases/latest/download/PHP.Example.zip
$ unzip PHP.Example.zip
```
**Start** -> **Control Panel** -> **System and Security** -> **Administrative Tools** -> **Internet Information Services (IIS) Manager**
Then open the example directory, [install dependencies](./Makefile#L16), and [start the server](./Makefile#L40).
and find the **PHP Manager** feature in the **Features View** in IIS.
```sh
$ cd "PHP Example"
$ make prod
$ make server-prod
```
![manager](screenshots/manager.png)
By default, the server starts at `0.0.0.0:9000`.
You need to register the installed PHP version in IIS using PHP Manager.
To configure the example, you can pass the environment variables before the command that starts the server. See [below](#configuration) for more information about environment variables.
Double-click **PHP Manager** to open it, click the **Register new PHP version** task and specify the full path to the main PHP executable file location. For example: *C:\Program Files\PHP\php-cgi.exe*.
## Post Installation
![php-version-1](screenshots/php-version-1.jpg)
After clicking **OK**, the new **PHP version** will be registered with IIS and will become active.
![php-version-2](screenshots/php-version-2.jpg)
2. Configure IIS to handle PHP requests.
For IIS to host PHP applications, you must add handler mapping that tells IIS to pass all the PHP-specific requests to the PHP application framework by using the **FastCGI** protocol.
Double-click the **Handler Mappings** feature:
![handlerclick](screenshots/handlerclick.png)
In the **Action** panel, click **Add Module Mapping**. In the **Add Module Mapping** dialog box, specify the configuration settings as follows:
* **Request path**: *.php,
* **Module**: FastCgiModule,
* **Executable**: "C:\[Path to your PHP installation]\php-cgi.exe",
* **Name**: PHP via FastCGI.
Click **OK**.
![handler-add](screenshots/handler-add.png)
After IIS manager configuration is complete, everything is ready for running the PHP example.
### Step 5. Run *composer install*:
```
php composer.phar install
```
### Step 6. Run your website with the editors
1. Add your website in the IIS Manager.
On the **Connections** panel right-click the **Sites** node in the tree, then click **Add Website**.
![add](screenshots/add.png)
2. In the **Add Website** dialog box, specify the name of the folder with the PHP project in the **Site name** box.
Specify the path to the folder with your project in the **Physical path** box.
Specify the unique value used only for this website in the **Port** box.
![php-add](screenshots/php-add.png)
3. Browse your website with the IIS manager:
Right-click the site -> **Manage Website** -> **Browse**
![browse](screenshots/browse.png)
### Step 7. Check accessibility
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
## Configuration
## For Linux
The example is configured by changing environment variables.
### Step 1. Install ONLYOFFICE Docs
| Name | Description | Example |
| ----------------------------- | ----------------------------------------------------------------------- | ----------------------- |
| `ADDRESS` | The address where the server should be started. | `0.0.0.0` |
| `PORT` | The port on which the server should be running. | `80` |
| `DOCUMENT_SERVER_PRIVATE_URL` | The URL through which the server will communicate with Document Server. | `http://proxy:8080` |
| `DOCUMENT_SERVER_PUBLIC_URL` | The URL through which a user will communicate with Document Server. | `http://localhost:8080` |
| `EXAMPLE_URL` | The URL through which Document Server will communicate with the server. | `http://proxy` |
| `JWT_SECRET` | JWT authorization secret. Leave blank to disable authorization. | `your-256-bit-secret` |
Download and install ONLYOFFICE Docs (packaged as Document Server).
## Security Info
See the detailed guide to learn how to [install Document Server for Linux](https://helpcenter.onlyoffice.com/installation/docs-developer-install-ubuntu.aspx?from=api_php_example).
### Step 2. Install the prerequisites and run the website with the editors
1. Install **Apache** and **PHP**:
```
apt-get install -y apache2 php7.0 libapache2-mod-php7.0
```
2. Install **Composer**:
To install composer globally, use the following command which will download and install Composer as a system-wide command named composer, under /usr/local/bin:
```
curl -sS https://getcomposer.org/installer -o /tmp/composer-setup.php
sudo php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer
```
3. Download the archive with the PHP example and unpack the archive:
```
cd /var/www/html
```
```
wget https://api.onlyoffice.com/app_data/editor/PHP%20Example.zip
```
```
unzip PHP\ Example.zip
```
4. Change the current directory for the project directory:
```
cd PHP\ Example/
```
5. Edit the *config.json* configuration file. Specify the name of your local server with the ONLYOFFICE Document Server installed.
```
nano config.json
```
Edit the following lines:
```
"storagePath" = "";
"docServSiteUrl" = "https://documentserver/";
```
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed and the **STORAGE_PATH** is the path where files will be created and stored. You can set an absolute path.
6. Run *composer install*:
```
php composer.phar install
```
7. Set permission for site:
```
chown -R www-data:www-data /var/www/html
```
8. Restart apache:
```
service apache2 restart
```
9. See the result in your browser using the address:
```
http://localhost/PHP%20Example/
```
### Step 3. Check accessibility
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
## Important security info
Please keep in mind the following security aspects when you are using test examples:
- There is no protection of the storage from unauthorized access since there is no need for authorization.
- There are no checks against parameter substitution in links, since the parameters are generated by the code according to the pre-arranged scripts.
- There are no data checks in requests of saving the file after editing, since each test example is intended for requests only from ONLYOFFICE Document Server.
- There are no prohibitions on using test examples from other sites, since they are intended to interact with ONLYOFFICE Document Server from another domain.
* There is no protection of the storage from unauthorized access since there is no need for authorization.
* There are no checks against parameter substitution in links, since the parameters are generated by the code according to the pre-arranged scripts.
* There are no data checks in requests of saving the file after editing, since each test example is intended for requests only from ONLYOFFICE Document Server.
* There are no prohibitions on using test examples from other sites, since they are intended to interact with ONLYOFFICE Document Server from another domain.

View File

@ -15,14 +15,14 @@
* limitations under the License.
*/
namespace Example;
namespace OnlineEditorsExamplePhp;
use Exception;
use Example\Common\Path;
use Example\Configuration\ConfigurationManager;
use Example\Format\FormatManager;
use Example\Helpers\ExampleUsers;
use Example\Helpers\JwtManager;
use OnlineEditorsExamplePhp\Common\Path;
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
use OnlineEditorsExamplePhp\Helpers\ConfigManager;
use OnlineEditorsExamplePhp\Helpers\ExampleUsers;
use OnlineEditorsExamplePhp\Helpers\JwtManager;
/**
* Check if the request is an AJAX request
@ -57,14 +57,14 @@ function getHttpOrigin()
function saveas()
{
try {
$configManager = new ConfigurationManager();
$formatManager = new FormatManager();
$config_manager = new ConfigurationManager();
$post = json_decode(file_get_contents('php://input'), true);
$fileurl = $post["url"];
$title = $post["title"];
$extension = mb_strtolower(pathinfo($title, PATHINFO_EXTENSION));
$allexts = $formatManager->allExtensions();
$configManager = new ConfigManager();
$allexts = $configManager->getSuppotredExtensions();
$filename = GetCorrectName($title);
if (!in_array($extension, $allexts)) {
@ -72,10 +72,10 @@ function saveas()
return $result;
}
$headers = get_headers($fileurl, 1);
$contentLength = $headers["Content-Length"];
$content_length = $headers["Content-Length"];
$data = file_get_contents(str_replace(" ", "%20", $fileurl));
if ($data === false || $contentLength <= 0 || $contentLength > $configManager->maximumFileSize()) {
if ($data === false || $content_length <= 0 || $content_length > $config_manager->maximum_file_size()) {
$result["error"] = "File size is incorrect";
return $result;
}
@ -101,9 +101,9 @@ function saveas()
*/
function upload()
{
$configManager = new ConfigurationManager();
$formatManager = new FormatManager();
$config_manager = new ConfigurationManager();
$configManager = new ConfigManager();
if ($_FILES['files']['error'] > 0) {
$result["error"] = 'Error ' . json_encode($_FILES['files']['error']);
return $result;
@ -124,13 +124,13 @@ function upload()
$ext = mb_strtolower(pathinfo($_FILES['files']['name'], PATHINFO_EXTENSION)); // get file extension
// check if the file size is correct (it should be less than the max file size, but greater than 0)
if ($filesize <= 0 || $filesize > $configManager->maximumFileSize()) {
if ($filesize <= 0 || $filesize > $config_manager->maximum_file_size()) {
$result["error"] = 'File size is incorrect'; // if not, then an error occurs
return $result;
}
// check if the file extension is supported by the editor
if (!in_array($ext, $formatManager->allExtensions())) {
if (!in_array($ext, $configManager->getSuppotredExtensions())) {
$result["error"] = 'File type is not supported'; // if not, then an error occurs
return $result;
}
@ -173,7 +173,7 @@ function track()
return $data;
}
$trackerStatus = [
$_trackerStatus = [
0 => 'NotFound',
1 => 'Editing',
2 => 'MustSave',
@ -182,7 +182,7 @@ function track()
6 => 'MustForceSave',
7 => 'CorruptedForceSave',
];
$status = $trackerStatus[$data->status]; // get status from the request body
$status = $_trackerStatus[$data->status]; // get status from the request body
$userAddress = $_GET["userAddress"];
$fileName = basename($_GET["fileName"]);
@ -220,17 +220,16 @@ function track()
*/
function convert()
{
$formatManager = new FormatManager();
$post = json_decode(file_get_contents('php://input'), true);
$fileName = basename($post["filename"]);
$filePass = $post["filePass"];
$lang = $_COOKIE["ulang"] ?? "";
$extension = mb_strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
$internalExtension = "ooxml";
$configManager = new ConfigManager();
// check if the file with such an extension can be converted
if (in_array($extension, $formatManager->convertibleExtensions()) &&
if (in_array($extension, $configManager->getConvertExtensions()) &&
$internalExtension != "") {
$fileUri = $post["fileUri"];
if ($fileUri == null || $fileUri == "") {
@ -341,7 +340,7 @@ function files()
function assets()
{
$fileName = basename($_GET["name"]);
$filePath = dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' .
$filePath = dirname(__FILE__) .
DIRECTORY_SEPARATOR . "assets" . DIRECTORY_SEPARATOR . "document-templates"
. DIRECTORY_SEPARATOR . "sample" . DIRECTORY_SEPARATOR . $fileName;
downloadFile($filePath);
@ -355,7 +354,7 @@ function assets()
function csv()
{
$fileName = "csv.csv";
$filePath = dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' .
$filePath = dirname(__FILE__) .
DIRECTORY_SEPARATOR . "assets" . DIRECTORY_SEPARATOR . "document-templates"
. DIRECTORY_SEPARATOR . "sample" . DIRECTORY_SEPARATOR . $fileName;
downloadFile($filePath);
@ -369,7 +368,7 @@ function csv()
function historyDownload()
{
try {
$configManager = new ConfigurationManager();
$config_manager = new ConfigurationManager();
$fileName = basename($_GET["fileName"]); // get the file name
$userAddress = $_GET["userAddress"];
@ -379,7 +378,8 @@ function historyDownload()
$jwtManager = new JwtManager();
if ($jwtManager->isJwtEnabled()) {
$jwtHeader = $configManager->jwtHeader();
$configManager = new ConfigManager();
$jwtHeader = $config_manager->jwt_header();
if (!empty(apache_request_headers()[$jwtHeader])) {
$token = $jwtManager->jwtDecode(mb_substr(
apache_request_headers()[$jwtHeader],
@ -416,7 +416,7 @@ function historyDownload()
function download()
{
try {
$configManager = new ConfigurationManager();
$config_manager = new ConfigurationManager();
$fileName = $_GET["fileName"];
$userAddress = $_GET["userAddress"] ?? null;
@ -424,7 +424,7 @@ function download()
$jwtManager = new JwtManager();
if ($jwtManager->isJwtEnabled() && $isEmbedded == null && $userAddress) {
$jwtHeader = $configManager->jwtHeader();
$jwtHeader = $config_manager->jwt_header();
if (!empty(apache_request_headers()[$jwtHeader])) {
$token = $jwtManager->jwtDecode(mb_substr(
apache_request_headers()[$jwtHeader],
@ -464,10 +464,7 @@ function downloadFile($filePath)
// write headers to the response object
@header('Content-Length: ' . filesize($filePath));
@header(
'Content-Disposition: attachment; filename*=UTF-8\'\'' .
str_replace("+", "%20", urlencode(basename($filePath)))
);
@header('Content-Disposition: attachment; filename*=UTF-8\'\'' . str_replace("+", "%20", urlencode(basename($filePath))));
@header('Content-Type: ' . mime_content_type($filePath));
@header('Access-Control-Allow-Origin: *');
@ -591,31 +588,31 @@ function restore()
$input = file_get_contents('php://input');
$body = json_decode($input);
$sourceBasename = $body->fileName;
$source_basename = $body->fileName;
$version = $body->version;
$userID = $body->userId;
$user_id = $body->userId;
$sourceFile = getStoragePath($sourceBasename);
$historyDirectory = getHistoryDir($sourceFile);
$source_file = getStoragePath($source_basename);
$history_directory = getHistoryDir($source_file);
$bumpedVersion = getFileVersion($historyDirectory);
$bumpedVersionStringDirectory = getVersionDir($historyDirectory, $bumpedVersion);
if (!file_exists($bumpedVersionStringDirectory)) {
mkdir($bumpedVersionStringDirectory);
$bumped_version = getFileVersion($history_directory);
$bumped_version_string_directory = getVersionDir($history_directory, $bumped_version);
if (!file_exists($bumped_version_string_directory)) {
mkdir($bumped_version_string_directory);
}
$bumpedVersionDirectory = new Path($bumpedVersionStringDirectory);
$bumped_version_directory = new Path($bumped_version_string_directory);
$bumpedKeyFile = $bumpedVersionDirectory->joinPath('key.txt');
$bumpedKeyStringFile = $bumpedKeyFile->string();
$bumpedKey = getDocEditorKey($sourceBasename);
file_put_contents($bumpedKeyStringFile, $bumpedKey, LOCK_EX);
$bumped_key_file = $bumped_version_directory->join_path('key.txt');
$bumped_key_string_file = $bumped_key_file->string();
$bumped_key = getDocEditorKey($source_basename);
file_put_contents($bumped_key_string_file, $bumped_key, LOCK_EX);
$users = new ExampleUsers();
$user = $users->getUser($userID);
$user = $users->getUser($user_id);
$bumpedChangesFile = $bumpedVersionDirectory->joinPath('changes.json');
$bumpedChangesStringFile = $bumpedChangesFile->string();
$bumpedChanges = [
$bumped_changes_file = $bumped_version_directory->join_path('changes.json');
$bumped_changes_string_file = $bumped_changes_file->string();
$bumped_changes = [
'serverVersion' => null,
'changes' => array(
[
@ -627,21 +624,21 @@ function restore()
]
)
];
$bumpedChangesContent = json_encode($bumpedChanges, JSON_PRETTY_PRINT);
file_put_contents($bumpedChangesStringFile, $bumpedChangesContent, LOCK_EX);
$bumped_changes_content = json_encode($bumped_changes, JSON_PRETTY_PRINT);
file_put_contents($bumped_changes_string_file, $bumped_changes_content, LOCK_EX);
$sourceExtension = pathinfo($sourceBasename, PATHINFO_EXTENSION);
$previousBasename = "prev.{$sourceExtension}";
$source_extension = pathinfo($source_basename, PATHINFO_EXTENSION);
$previous_basename = "prev.{$source_extension}";
$bumpedFile = $bumpedVersionDirectory->joinPath($previousBasename);
$bumpedStringFile = $bumpedFile->string();
copy($sourceFile, $bumpedStringFile);
$bumped_file = $bumped_version_directory->join_path($previous_basename);
$bumped_string_file = $bumped_file->string();
copy($source_file, $bumped_string_file);
$recoveryVersionStringDirectory = getVersionDir($historyDirectory, $version);
$recoveryVersionDirectory = new Path($recoveryVersionStringDirectory);
$recoveryFile = $recoveryVersionDirectory->joinPath($previousBasename);
$recoveryStringFile = $recoveryFile->string();
copy($recoveryStringFile, $sourceFile);
$recovery_version_string_directory = getVersionDir($history_directory, $version);
$recovery_version_directory = new Path($recovery_version_string_directory);
$recovery_file = $recovery_version_directory->join_path($previous_basename);
$recovery_string_file = $recovery_file->string();
copy($recovery_string_file, $source_file);
return [
'error' => null,

View File

@ -15,9 +15,8 @@
// limitations under the License.
//
namespace Example\Common;
namespace OnlineEditorsExamplePhp\Common;
enum HTTPStatus: int
{
case NotFound = 404;
enum HTTPStatus: int {
case not_found = 404;
}

View File

@ -15,53 +15,45 @@
// limitations under the License.
//
namespace Example\Common;
namespace OnlineEditorsExamplePhp\Common;
final class Path
{
final class Path {
private string $separator = DIRECTORY_SEPARATOR;
private string $string;
public function __construct(string $path)
{
public function __construct(string $path) {
$this->string = $path;
}
public function string(): string
{
public function string(): string {
return $this->string;
}
public function dirname(): ?string
{
public function dirname(): ?string {
$string = $this->string();
$parsed = pathinfo($string, PATHINFO_DIRNAME);
return $parsed ?: null;
}
public function basename(): ?string
{
public function basename(): ?string {
$string = $this->string();
$parsed = pathinfo($string, PATHINFO_BASENAME);
return $parsed ?: null;
}
public function extension(): ?string
{
public function extension(): ?string {
$string = $this->string();
$parsed = pathinfo($string, PATHINFO_EXTENSION);
return $parsed ?: null;
}
public function filename(): ?string
{
public function filename(): ?string {
$string = $this->string();
$parsed = pathinfo($string, PATHINFO_FILENAME);
return $parsed ?: null;
}
public function normalize(): self
{
public function normalize(): self {
$string = $this->string();
$filtered = array();
$slugs = explode($this->separator, $string);
@ -76,14 +68,13 @@ final class Path
$filtered[] = $slug;
}
$joined = implode($this->separator, $filtered);
$escapedSeparator = preg_quote($this->separator, $this->separator);
$separatorRegex = "/{$escapedSeparator}{2,}/";
$separated = preg_replace($separatorRegex, $this->separator, $joined);
$escaped_separator = preg_quote($this->separator, $this->separator);
$separator_regex = "/{$escaped_separator}{2,}/";
$separated = preg_replace($separator_regex, $this->separator, $joined);
return new Path($separated);
}
public function joinPath(string $path): self
{
public function join_path(string $path): self {
$string = $this->string();
$separator =
str_ends_with($string, $this->separator) ||
@ -93,48 +84,43 @@ final class Path
return new Path("{$string}{$separator}{$path}");
}
public function absolute(): bool
{
public function absolute(): bool {
$string = $this->string();
$ntRegex = '/^[A-Za-z]:\\\\/';
if (preg_match($ntRegex, $string)) {
$nt_regex = '/^[A-Za-z]:\\\\/';
if (preg_match($nt_regex, $string)) {
return true;
}
$ntSeparator = '\\';
if (str_starts_with($string, $ntSeparator)) {
$nt_separator = '\\';
if (str_starts_with($string, $nt_separator)) {
return true;
}
$posixSeparator = '/';
if (str_starts_with($string, $posixSeparator)) {
$posix_separator = '/';
if (str_starts_with($string, $posix_separator)) {
return true;
}
return false;
}
public function exists(): bool
{
public function exists(): bool {
$string = $this->string();
return file_exists($string);
}
public function contents(): string
{
public function contents(): string {
$string = $this->string();
return file_get_contents($string);
}
public function directory(): bool
{
public function directory(): bool {
$string = $this->string();
return is_dir($string);
}
public function makeDirectory(): bool
{
public function make_directory(): bool {
$string = $this->string();
return mkdir($string);
}

View File

@ -15,29 +15,23 @@
// limitations under the License.
//
namespace Example\Common\Tests;
use PHPUnit\Framework\TestCase;
use Example\Common\Path;
use OnlineEditorsExamplePhp\Common\Path;
final class PathAbsolutePOSIXTests extends TestCase
{
public function testRecognizesAnEmptyAsANonAbsolute()
{
final class PathAbsolutePOSIXTests extends TestCase {
public function test_recognizes_an_empty_as_a_non_absolute() {
$path = new Path('');
$absolute = $path->absolute();
$this->assertFalse($absolute);
}
public function testRecognizesARelativeAsANonAbsolute()
{
public function test_recognizes_a_relative_as_a_non_absolute() {
$path = new Path('.');
$absolute = $path->absolute();
$this->assertFalse($absolute);
}
public function testRecognizesAnAbsoluteAsAnAbsolute()
{
public function test_recognizes_an_absolute_as_an_absolute() {
$path = new Path('/');
$absolute = $path->absolute();
$this->assertTrue($absolute);

View File

@ -15,77 +15,67 @@
// limitations under the License.
//
namespace Example\Common\Tests;
use PHPUnit\Framework\TestCase;
use Example\Common\Path;
use OnlineEditorsExamplePhp\Common\Path;
final class PathJoinPOSIXTests extends TestCase
{
public function testJoinsARelativeToAnEmptyOne()
{
final class PathJoinPOSIXTests extends TestCase {
public function test_joins_a_relative_to_an_empty_one() {
$path = new Path('');
$joined = $path->joinPath('srv');
$joined = $path->join_path('srv');
$this->assertEquals($joined->dirname(), '/');
$this->assertEquals($joined->basename(), 'srv');
$this->assertEquals($joined->extension(), null);
$this->assertEquals($joined->filename(), 'srv');
}
public function testJoinsARelativeToARelativeOne()
{
public function test_joins_a_relative_to_a_relative_one() {
$path = new Path('.');
$joined = $path->joinPath('srv');
$joined = $path->join_path('srv');
$this->assertEquals($joined->dirname(), '.');
$this->assertEquals($joined->basename(), 'srv');
$this->assertEquals($joined->extension(), null);
$this->assertEquals($joined->filename(), 'srv');
}
public function testJoinsARelativeToAnAbsoluteOne()
{
public function test_joins_a_relative_to_an_absolute_one() {
$path = new Path('/');
$joined = $path->joinPath('srv');
$joined = $path->join_path('srv');
$this->assertEquals($joined->dirname(), '/');
$this->assertEquals($joined->basename(), 'srv');
$this->assertEquals($joined->extension(), null);
$this->assertEquals($joined->filename(), 'srv');
}
public function testJoinsAnAbsoluteToAnEmptyOne()
{
public function test_joins_an_absolute_to_an_empty_one() {
$path = new Path('');
$joined = $path->joinPath('/srv');
$joined = $path->join_path('/srv');
$this->assertEquals($joined->dirname(), '/');
$this->assertEquals($joined->basename(), 'srv');
$this->assertEquals($joined->extension(), null);
$this->assertEquals($joined->filename(), 'srv');
}
public function testJoinsAnAbsoluteToARelativeOne()
{
public function test_joins_an_absolute_to_a_relative_one() {
$path = new Path('.');
$joined = $path->joinPath('/srv');
$joined = $path->join_path('/srv');
$this->assertEquals($joined->dirname(), '.');
$this->assertEquals($joined->basename(), 'srv');
$this->assertEquals($joined->extension(), null);
$this->assertEquals($joined->filename(), 'srv');
}
public function testJoinsAnAbsoluteToAnAbsoluteOne()
{
public function test_joins_an_absolute_to_an_absolute_one() {
$path = new Path('/');
$joined = $path->joinPath('/srv');
$joined = $path->join_path('/srv');
$this->assertEquals($joined->dirname(), '/');
$this->assertEquals($joined->basename(), 'srv');
$this->assertEquals($joined->extension(), null);
$this->assertEquals($joined->filename(), 'srv');
}
public function testJoinsAnUnnormalized()
{
public function test_joins_an_unnormalized() {
$path = new Path('');
$joined = $path->joinPath('../srv');
$joined = $path->join_path('../srv');
$this->assertEquals($joined->dirname(), '/..');
$this->assertEquals($joined->basename(), 'srv');
$this->assertEquals($joined->extension(), null);

View File

@ -15,15 +15,11 @@
// limitations under the License.
//
namespace Example\Common\Tests;
use PHPUnit\Framework\TestCase;
use Example\Common\Path;
use OnlineEditorsExamplePhp\Common\Path;
final class PathNormalizePOSIXTests extends TestCase
{
public function testNormalizes()
{
final class PathNormalizePOSIXTests extends TestCase {
public function test_normalizes() {
$path = new Path('./srv///sub/.././sub/file.docx');
$normalized = $path->normalize();
$this->assertEquals($normalized->dirname(), 'srv/sub');

View File

@ -15,157 +15,133 @@
// limitations under the License.
//
namespace Example\Common\Tests;
use PHPUnit\Framework\TestCase;
use Example\Common\Path;
use OnlineEditorsExamplePhp\Common\Path;
final class PathStringPOSIXTests extends TestCase
{
public function testGeneratesWithAnEmpty()
{
final class PathStringPOSIXTests extends TestCase {
public function test_generates_with_an_empty() {
$path = new Path('');
$string = $path->string();
$this->assertEquals($string, '');
}
public function testGeneratesWithAnEmptyRelative()
{
public function test_generates_with_an_empty_relative() {
$path = new Path('.');
$string = $path->string();
$this->assertEquals($string, '.');
}
public function testGeneratesWithAnEmptyAbsolute()
{
public function test_generates_with_an_empty_absolute() {
$path = new Path('/');
$string = $path->string();
$this->assertEquals($string, '/');
}
public function testGeneratesWithARelative()
{
public function test_generates_with_a_relative() {
$path = new Path('srv');
$string = $path->string();
$this->assertEquals($string, 'srv');
}
public function testGeneratesWithARelativeContainingADirectory()
{
public function test_generates_with_a_relative_containing_a_directory() {
$path = new Path('srv/sub');
$string = $path->string();
$this->assertEquals($string, 'srv/sub');
}
public function testGeneratesWithARelativeContainingAFile()
{
public function test_generates_with_a_relative_containing_a_file() {
$path = new Path('srv/file.json');
$string = $path->string();
$this->assertEquals($string, 'srv/file.json');
}
public function testGeneratesWithARelativeContainingADirectoryWithAFile()
{
public function test_generates_with_a_relative_containing_a_directory_with_a_file() {
$path = new Path('srv/sub/file.json');
$string = $path->string();
$this->assertEquals($string, 'srv/sub/file.json');
}
public function testGeneratesWithAnUnnormalizedRelative()
{
public function test_generates_with_an_unnormalized_relative() {
$path = new Path('srv////sub///file.json');
$string = $path->string();
$this->assertEquals($string, 'srv////sub///file.json');
}
public function testGeneratesWithAnNormalizedRelative()
{
public function test_generates_with_an_normalized_relative() {
$path = new Path('srv////sub///file.json');
$normalized = $path->normalize();
$string = $normalized->string();
$this->assertEquals($string, 'srv/sub/file.json');
}
public function testGeneratesWithAnExplicitRelative()
{
public function test_generates_with_an_explicit_relative() {
$path = new Path('./srv');
$string = $path->string();
$this->assertEquals($string, './srv');
}
public function testGeneratesWithAnExplicitRelativeContainingADirectory()
{
public function test_generates_with_an_explicit_relative_containing_a_directory() {
$path = new Path('./srv/sub');
$string = $path->string();
$this->assertEquals($string, './srv/sub');
}
public function testGeneratesWithAnExplicitRelativeContainingAFile()
{
public function test_generates_with_an_explicit_relative_containing_a_file() {
$path = new Path('./srv/file.json');
$string = $path->string();
$this->assertEquals($string, './srv/file.json');
}
public function testGeneratesWithAnExplicitRelativeContainingADirectoryWithAFile()
{
public function test_generates_with_an_explicit_relative_containing_a_directory_with_a_file() {
$path = new Path('./srv/sub/file.json');
$string = $path->string();
$this->assertEquals($string, './srv/sub/file.json');
}
public function testGeneratesWithAnExplicitUnnormalizedRelative()
{
public function test_generates_with_an_explicit_unnormalized_relative() {
$path = new Path('./srv////sub///file.json');
$string = $path->string();
$this->assertEquals($string, './srv////sub///file.json');
}
public function testGeneratesWithAnExplicitNormalizedRelative()
{
public function test_generates_with_an_explicit_normalized_relative() {
$path = new Path('./srv////sub///file.json');
$normalized = $path->normalize();
$string = $normalized->string();
$this->assertEquals($string, 'srv/sub/file.json');
}
public function testGeneratesWithAnAbsolute()
{
public function test_generates_with_an_absolute() {
$path = new Path('/srv');
$string = $path->string();
$this->assertEquals($string, '/srv');
}
public function testGeneratesWithAnAbsoluteContainingADirectory()
{
public function test_generates_with_an_absolute_containing_a_directory() {
$path = new Path('/srv/sub');
$string = $path->string();
$this->assertEquals($string, '/srv/sub');
}
public function testGeneratesWithAnAbsoluteContainingAFile()
{
public function test_generates_with_an_absolute_containing_a_file() {
$path = new Path('/srv/file.json');
$string = $path->string();
$this->assertEquals($string, '/srv/file.json');
}
public function testGeneratesWithAnAbsoluteContainingADirectoryWithAFile()
{
public function test_generates_with_an_absolute_containing_a_directory_with_a_file() {
$path = new Path('/srv/sub/file.json');
$string = $path->string();
$this->assertEquals($string, '/srv/sub/file.json');
}
public function testGeneratesWithAnUnnormalizedAbsolute()
{
public function test_generates_with_an_unnormalized_absolute() {
$path = new Path('/srv////sub///file.json');
$string = $path->string();
$this->assertEquals($string, '/srv////sub///file.json');
}
public function testGeneratesWithAnNormalizedAbsolute()
{
public function test_generates_with_an_normalized_absolute() {
$path = new Path('/srv////sub///file.json');
$normalized = $path->normalize();
$string = $normalized->string();

View File

@ -15,71 +15,60 @@
// limitations under the License.
//
namespace Example\Common;
namespace OnlineEditorsExamplePhp\Common;
final class URL
{
final class URL {
private string $string;
public function __construct(string $url)
{
public function __construct(string $url) {
$this->string = $url;
}
public function string(): string
{
public function string(): string {
return $this->string;
}
public function scheme(): ?string
{
public function scheme(): ?string {
$string = $this->string();
return parse_url($string, PHP_URL_SCHEME) ?: null;
}
public function host(): ?string
{
public function host(): ?string {
$string = $this->string();
return parse_url($string, PHP_URL_HOST) ?: null;
}
public function port(): ?int
{
public function port(): ?int {
$string = $this->string();
return parse_url($string, PHP_URL_PORT) ?: null;
}
public function user(): ?string
{
public function user(): ?string {
$string = $this->string();
return parse_url($string, PHP_URL_USER) ?: null;
}
public function pass(): ?string
{
public function pass(): ?string {
$string = $this->string();
return parse_url($string, PHP_URL_PASS) ?: null;
}
public function path(): ?string
{
public function path(): ?string {
$string = $this->string();
return parse_url($string, PHP_URL_PATH) ?: null;
}
public function query(): ?string
{
public function query(): ?string {
$string = $this->string();
return parse_url($string, PHP_URL_QUERY) ?: null;
}
public function fragment(): ?string
{
public function fragment(): ?string {
$string = $this->string();
return parse_url($string, PHP_URL_FRAGMENT) ?: null;
}
public static function fromComponents(
public static function from_components(
?string $scheme,
?string $host,
?int $port,
@ -117,20 +106,19 @@ final class URL
return new URL($string);
}
public function joinPath(string $path): self
{
$currentPath = $this->path();
public function join_path(string $path): self {
$current_path = $this->path();
$separator =
$currentPath &&
$current_path &&
(
str_ends_with($currentPath, '/') ||
str_ends_with($current_path, '/') ||
str_starts_with($path, '/')
) ||
!$currentPath && str_starts_with($path, '/')
!$current_path && str_starts_with($path, '/')
? ''
: '/';
$separated = "{$currentPath}{$separator}{$path}";
return URL::fromComponents(
$separated = "{$current_path}{$separator}{$path}";
return URL::from_components(
$this->scheme(),
$this->host(),
$this->port(),

View File

@ -15,16 +15,12 @@
// limitations under the License.
//
namespace Example\Common\Tests;
use PHPUnit\Framework\TestCase;
use Example\Common\URL;
use OnlineEditorsExamplePhp\Common\URL;
final class URLFromComponentsTests extends TestCase
{
public function testCreates()
{
$url = URL::fromComponents(
final class URLFromComponentsTests extends TestCase {
public function test_creates() {
$url = URL::from_components(
'http',
'localhost',
8080,

View File

@ -15,17 +15,13 @@
// limitations under the License.
//
namespace Example\Common\Tests;
use PHPUnit\Framework\TestCase;
use Example\Common\URL;
use OnlineEditorsExamplePhp\Common\URL;
final class URLJoinPathTests extends TestCase
{
public function testJoinsARelativeToAnEmptyOne()
{
final class URLJoinPathTests extends TestCase {
public function test_joins_a_relative_to_an_empty_one() {
$url = new URL('http://localhost');
$joined = $url->joinPath('first');
$joined = $url->join_path('first');
$this->assertEquals('http', $joined->scheme());
$this->assertEquals('localhost', $joined->host());
$this->assertEquals(null, $joined->port());
@ -36,10 +32,9 @@ final class URLJoinPathTests extends TestCase
$this->assertEquals(null, $joined->fragment());
}
public function testJoinsARelative()
{
public function test_joins_a_relative() {
$url = new URL('http://localhost/first');
$joined = $url->joinPath('second');
$joined = $url->join_path('second');
$this->assertEquals('http', $joined->scheme());
$this->assertEquals('localhost', $joined->host());
$this->assertEquals(null, $joined->port());
@ -50,10 +45,9 @@ final class URLJoinPathTests extends TestCase
$this->assertEquals(null, $joined->fragment());
}
public function testJoinsAnAbsoluteToAnEmptyOne()
{
public function test_joins_an_absolute_to_an_empty_one() {
$url = new URL('http://localhost');
$joined = $url->joinPath('/first');
$joined = $url->join_path('/first');
$this->assertEquals('http', $joined->scheme());
$this->assertEquals('localhost', $joined->host());
$this->assertEquals(null, $joined->port());
@ -64,10 +58,9 @@ final class URLJoinPathTests extends TestCase
$this->assertEquals(null, $joined->fragment());
}
public function testJoinsAnAbsolute()
{
public function test_joins_an_absolute() {
$url = new URL('http://localhost/first');
$joined = $url->joinPath('/second');
$joined = $url->join_path('/second');
$this->assertEquals('http', $joined->scheme());
$this->assertEquals('localhost', $joined->host());
$this->assertEquals(null, $joined->port());

View File

@ -15,15 +15,11 @@
// limitations under the License.
//
namespace Example\Common\Tests;
use PHPUnit\Framework\TestCase;
use Example\Common\URL;
use OnlineEditorsExamplePhp\Common\URL;
final class URLStringTests extends TestCase
{
public function testGenerates()
{
final class URLStringTests extends TestCase {
public function test_generates() {
$url = new URL('http://user:password@localhost:8080/path?q=value#fragment');
$string = $url->string();
$this->assertEquals(

View File

@ -1,9 +1,7 @@
{
"require": {
"ext-mbstring": "*",
"firebase/php-jwt": "^6.8.1",
"symfony/serializer": "^6.3",
"symfony/property-access": "^6.3"
"firebase/php-jwt": "^6.8.1"
},
"require-dev": {
"squizlabs/php_codesniffer": "^3.7.2",
@ -11,12 +9,11 @@
},
"autoload": {
"psr-4": {
"Example\\Common\\": "src/common/",
"Example\\Configuration\\" : "src/configuration/",
"Example\\Format\\" : "src/format/",
"Example\\Helpers\\" : "src/helpers/",
"Example\\Proxy\\": "src/proxy/",
"Example\\Views\\" : "src/views/"
"OnlineEditorsExamplePhp\\" : "",
"OnlineEditorsExamplePhp\\Common\\": "common/",
"OnlineEditorsExamplePhp\\Configuration\\" : "configuration/",
"OnlineEditorsExamplePhp\\Helpers\\" : "helpers/",
"OnlineEditorsExamplePhp\\Views\\" : "views/"
}
}
}

View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "5d476b9c61f48836ee5e6c9cab7a1980",
"content-hash": "1408ebe84361a11eb7a751e9603b937f",
"packages": [
{
"name": "firebase/php-jwt",
@ -68,742 +68,6 @@
"source": "https://github.com/firebase/php-jwt/tree/v6.8.1"
},
"time": "2023-07-14T18:33:00+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v3.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "7c3aff79d10325257a001fcf92d991f24fc967cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf",
"reference": "7c3aff79d10325257a001fcf92d991f24fc967cf",
"shasum": ""
},
"require": {
"php": ">=8.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.4-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2023-05-23T14:45:45+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-ctype": "*"
},
"suggest": {
"ext-ctype": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"ctype",
"polyfill",
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Grapheme\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's grapheme_* functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"grapheme",
"intl",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's Normalizer class and related functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"intl",
"normalizer",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-mbstring": "*"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/property-access",
"version": "v6.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/property-access.git",
"reference": "db9358571ce63f09c439c2fee6c12e5b090b69ac"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/property-access/zipball/db9358571ce63f09c439c2fee6c12e5b090b69ac",
"reference": "db9358571ce63f09c439c2fee6c12e5b090b69ac",
"shasum": ""
},
"require": {
"php": ">=8.1",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/property-info": "^5.4|^6.0"
},
"require-dev": {
"symfony/cache": "^5.4|^6.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\PropertyAccess\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides functions to read and write from/to an object or array using a simple string notation",
"homepage": "https://symfony.com",
"keywords": [
"access",
"array",
"extraction",
"index",
"injection",
"object",
"property",
"property-path",
"reflection"
],
"support": {
"source": "https://github.com/symfony/property-access/tree/v6.3.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2023-05-19T08:06:44+00:00"
},
{
"name": "symfony/property-info",
"version": "v6.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/property-info.git",
"reference": "7f3a03716112269741fe2a809f8f791a371d1fcd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/property-info/zipball/7f3a03716112269741fe2a809f8f791a371d1fcd",
"reference": "7f3a03716112269741fe2a809f8f791a371d1fcd",
"shasum": ""
},
"require": {
"php": ">=8.1",
"symfony/string": "^5.4|^6.0"
},
"conflict": {
"phpdocumentor/reflection-docblock": "<5.2",
"phpdocumentor/type-resolver": "<1.5.1",
"symfony/dependency-injection": "<5.4"
},
"require-dev": {
"doctrine/annotations": "^1.10.4|^2",
"phpdocumentor/reflection-docblock": "^5.2",
"phpstan/phpdoc-parser": "^1.0",
"symfony/cache": "^5.4|^6.0",
"symfony/dependency-injection": "^5.4|^6.0",
"symfony/serializer": "^5.4|^6.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\PropertyInfo\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Kévin Dunglas",
"email": "dunglas@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Extracts information about PHP class' properties using metadata of popular sources",
"homepage": "https://symfony.com",
"keywords": [
"doctrine",
"phpdoc",
"property",
"symfony",
"type",
"validator"
],
"support": {
"source": "https://github.com/symfony/property-info/tree/v6.3.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2023-05-19T08:06:44+00:00"
},
{
"name": "symfony/serializer",
"version": "v6.3.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/serializer.git",
"reference": "1d238ee3180bc047f8ab713bfb73848d553f4407"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/serializer/zipball/1d238ee3180bc047f8ab713bfb73848d553f4407",
"reference": "1d238ee3180bc047f8ab713bfb73848d553f4407",
"shasum": ""
},
"require": {
"php": ">=8.1",
"symfony/polyfill-ctype": "~1.8"
},
"conflict": {
"doctrine/annotations": "<1.12",
"phpdocumentor/reflection-docblock": "<3.2.2",
"phpdocumentor/type-resolver": "<1.4.0",
"symfony/dependency-injection": "<5.4",
"symfony/property-access": "<5.4",
"symfony/property-info": "<5.4",
"symfony/uid": "<5.4",
"symfony/yaml": "<5.4"
},
"require-dev": {
"doctrine/annotations": "^1.12|^2",
"phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0",
"symfony/cache": "^5.4|^6.0",
"symfony/config": "^5.4|^6.0",
"symfony/console": "^5.4|^6.0",
"symfony/dependency-injection": "^5.4|^6.0",
"symfony/error-handler": "^5.4|^6.0",
"symfony/filesystem": "^5.4|^6.0",
"symfony/form": "^5.4|^6.0",
"symfony/http-foundation": "^5.4|^6.0",
"symfony/http-kernel": "^5.4|^6.0",
"symfony/mime": "^5.4|^6.0",
"symfony/property-access": "^5.4|^6.0",
"symfony/property-info": "^5.4|^6.0",
"symfony/uid": "^5.4|^6.0",
"symfony/validator": "^5.4|^6.0",
"symfony/var-dumper": "^5.4|^6.0",
"symfony/var-exporter": "^5.4|^6.0",
"symfony/yaml": "^5.4|^6.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Serializer\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/serializer/tree/v6.3.1"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2023-06-21T19:54:33+00:00"
},
{
"name": "symfony/string",
"version": "v6.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/f2e190ee75ff0f5eced645ec0be5c66fac81f51f",
"reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f",
"shasum": ""
},
"require": {
"php": ">=8.1",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
"symfony/translation-contracts": "<2.5"
},
"require-dev": {
"symfony/error-handler": "^5.4|^6.0",
"symfony/http-client": "^5.4|^6.0",
"symfony/intl": "^6.2",
"symfony/translation-contracts": "^2.5|^3.0",
"symfony/var-exporter": "^5.4|^6.0"
},
"type": "library",
"autoload": {
"files": [
"Resources/functions.php"
],
"psr-4": {
"Symfony\\Component\\String\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
"homepage": "https://symfony.com",
"keywords": [
"grapheme",
"i18n",
"string",
"unicode",
"utf-8",
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v6.3.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2023-03-21T21:06:29+00:00"
}
],
"packages-dev": [

View File

@ -15,17 +15,15 @@
// limitations under the License.
//
namespace Example\Configuration;
namespace OnlineEditorsExamplePhp\Configuration;
use Example\Common\Path;
use Example\Common\URL;
use OnlineEditorsExamplePhp\Common\Path;
use OnlineEditorsExamplePhp\Common\URL;
class ConfigurationManager
{
public string $version = '1.7.0';
final class ConfigurationManager {
public string $version = '1.6.0';
public function exampleURL(): ?URL
{
public function example_url(): ?URL {
$url = getenv('EXAMPLE_URL');
if (!$url) {
return null;
@ -33,65 +31,48 @@ class ConfigurationManager
return new URL($url);
}
public function documentServerPublicURL(): URL
{
$url = getenv('DOCUMENT_SERVER_PUBLIC_URL') ?: 'http://document-server';
public function document_server_url(): URL {
$url = getenv('DOCUMENT_SERVER_URL') ?: 'http://document-server';
return new URL($url);
}
public function documentServerPrivateURL(): URL
{
$url = getenv('DOCUMENT_SERVER_PRIVATE_URL');
if (!$url) {
return $this->documentServerPublicURL();
}
return new URL($url);
}
public function documentServerAPIURL(): URL
{
$serverURL = $this->documentServerPublicURL();
public function document_server_api_url(): URL {
$server_url = $this->document_server_url();
$path = getenv('DOCUMENT_SERVER_API_PATH')
?: 'web-apps/apps/api/documents/api.js';
return $serverURL->joinPath($path);
return $server_url->join_path($path);
}
public function documentServerPreloaderURL(): URL
{
$serverURL = $this->documentServerPublicURL();
public function document_server_preloader_url(): URL {
$server_url = $this->document_server_url();
$path = getenv('DOCUMENT_SERVER_PRELOADER_PATH')
?: 'web-apps/apps/api/documents/cache-scripts.html';
return $serverURL->joinPath($path);
return $server_url->join_path($path);
}
public function documentServerCommandURL(): URL
{
$serverURL = $this->documentServerPrivateURL();
public function document_server_command_url(): URL {
$server_url = $this->document_server_url();
$path = getenv('DOCUMENT_SERVER_COMMAND_PATH')
?: 'coauthoring/CommandService.ashx';
return $serverURL->joinPath($path);
return $server_url->join_path($path);
}
public function documentServerConverterURL(): URL
{
$serverURL = $this->documentServerPrivateURL();
public function document_server_converter_url(): URL {
$server_url = $this->document_server_url();
$path = getenv('DOCUMENT_SERVER_CONVERTER_PATH')
?: 'ConvertService.ashx';
return $serverURL->joinPath($path);
return $server_url->join_path($path);
}
public function jwtSecret(): string
{
public function jwt_secret(): string {
return getenv('JWT_SECRET') ?: '';
}
public function jwtHeader(): string
{
public function jwt_header(): string {
return getenv('JWT_HEADER') ?: 'Authorization';
}
public function jwtUseForRequest(): bool
{
public function jwt_use_for_request(): bool {
$use = getenv('JWT_USE_FOR_REQUEST');
if (!$use) {
return true;
@ -99,8 +80,7 @@ class ConfigurationManager
return filter_var($use, FILTER_VALIDATE_BOOLEAN);
}
public function sslVerifyPeerModeEnabled(): bool
{
public function ssl_verify_peer_mode_enabled(): bool {
$enabled = getenv('SSL_VERIFY_PEER_MODE_ENABLED');
if (!$enabled) {
return false;
@ -108,25 +88,22 @@ class ConfigurationManager
return filter_var($enabled, FILTER_VALIDATE_BOOLEAN);
}
public function storagePath(): Path
{
$storagePath = getenv('STORAGE_PATH') ?: 'storage';
$storageDirectory = new Path($storagePath);
if ($storageDirectory->absolute()) {
return $storageDirectory;
public function storage_path(): Path {
$storage_path = getenv('STORAGE_PATH') ?: 'storage';
$storage_directory = new Path($storage_path);
if ($storage_directory->absolute()) {
return $storage_directory;
}
$storageStringDirectory = $storageDirectory->string();
$currentDirectory = new Path(__DIR__);
$directory = $currentDirectory
->joinPath('..')
->joinPath('..')
->joinPath($storageStringDirectory);
$storage_string_directory = $storage_directory->string();
$current_directory = new Path(__DIR__);
$directory = $current_directory
->join_path('..')
->join_path($storage_string_directory);
return $directory->normalize();
}
public function singleUser(): bool
{
public function single_user(): bool {
$single = getenv('SINGLE_USER');
if (!$single) {
return false;
@ -134,8 +111,7 @@ class ConfigurationManager
return filter_var($single, FILTER_VALIDATE_BOOLEAN);
}
public function maximumFileSize(): int
{
public function maximum_file_size(): int {
$size = getenv('MAXIMUM_FILE_SIZE');
if (!$size) {
return 5 * 1024 * 1024;
@ -143,8 +119,7 @@ class ConfigurationManager
return intval($size);
}
public function conversionTimeout(): int
{
public function conversion_timeout(): int {
$timeout = getenv('CONVERSION_TIMEOUT');
if (!$timeout) {
return 120 * 1000;
@ -155,8 +130,7 @@ class ConfigurationManager
/**
* @return string[]
*/
public function languages(): array
{
public function languages(): array {
return [
'en' => "English",
'hy' => 'Armenian',

View File

@ -15,40 +15,33 @@
// limitations under the License.
//
namespace Example\Configuration\Tests;
use PHPUnit\Framework\TestCase;
use Example\Configuration\ConfigurationManager;
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
final class ConfigurationManagerConversionTimeoutTests extends TestCase
{
final class ConfigurationManagerConversionTimeoutTests extends TestCase {
public array $env;
public function __construct(string $name)
{
public function __construct(string $name) {
$this->env = getenv();
parent::__construct($name);
}
protected function setUp(): void
{
protected function setUp(): void {
foreach ($this->env as $key => $value) {
putenv("{$key}={$value}");
}
}
public function testAssignsADefaultValue()
{
$configManager = new ConfigurationManager();
$timeout = $configManager->conversionTimeout();
public function test_assigns_a_default_value() {
$config_manager = new ConfigurationManager();
$timeout = $config_manager->conversion_timeout();
$this->assertEquals(120_000, $timeout);
}
public function testAssignsAValueFromTheEnvironment()
{
public function test_assigns_a_value_from_the_environment() {
putenv('CONVERSION_TIMEOUT=10');
$configManager = new ConfigurationManager();
$timeout = $configManager->conversionTimeout();
$config_manager = new ConfigurationManager();
$timeout = $config_manager->conversion_timeout();
$this->assertEquals(10, $timeout);
}
}

View File

@ -15,43 +15,36 @@
// limitations under the License.
//
namespace Example\Configuration\Tests;
use PHPUnit\Framework\TestCase;
use Example\Configuration\ConfigurationManager;
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
final class ConfigurationManagerDocumentServerAPIURLTests extends TestCase
{
final class ConfigurationManagerDocumentServerAPIURLTests extends TestCase {
public array $env;
public function __construct(string $name)
{
public function __construct(string $name) {
$this->env = getenv();
parent::__construct($name);
}
protected function setUp(): void
{
protected function setUp(): void {
foreach ($this->env as $key => $value) {
putenv("{$key}={$value}");
}
}
public function testAssignsADefaultValue()
{
$configManager = new ConfigurationManager();
$url = $configManager->documentServerAPIURL();
public function test_assigns_a_default_value() {
$config_manager = new ConfigurationManager();
$url = $config_manager->document_server_api_url();
$this->assertEquals(
'http://document-server/web-apps/apps/api/documents/api.js',
$url->string()
);
}
public function testAssignsAValueFromTheEnvironment()
{
public function test_assigns_a_value_from_the_environment() {
putenv('DOCUMENT_SERVER_API_PATH=/api');
$configManager = new ConfigurationManager();
$url = $configManager->documentServerAPIURL();
$config_manager = new ConfigurationManager();
$url = $config_manager->document_server_api_url();
$this->assertEquals(
'http://document-server/api',
$url->string()

View File

@ -15,43 +15,36 @@
// limitations under the License.
//
namespace Example\Configuration\Tests;
use PHPUnit\Framework\TestCase;
use Example\Configuration\ConfigurationManager;
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
final class ConfigurationManagerDocumentServerCommandURLTests extends TestCase
{
final class ConfigurationManagerDocumentServerCommandURLTests extends TestCase {
public array $env;
public function __construct(string $name)
{
public function __construct(string $name) {
$this->env = getenv();
parent::__construct($name);
}
protected function setUp(): void
{
protected function setUp(): void {
foreach ($this->env as $key => $value) {
putenv("{$key}={$value}");
}
}
public function testAssignsADefaultValue()
{
$configManager = new ConfigurationManager();
$url = $configManager->documentServerCommandURL();
public function test_assigns_a_default_value() {
$config_manager = new ConfigurationManager();
$url = $config_manager->document_server_command_url();
$this->assertEquals(
'http://document-server/coauthoring/CommandService.ashx',
$url->string()
);
}
public function testAssignsAValueFromTheEnvironment()
{
public function test_assigns_a_value_from_the_environment() {
putenv('DOCUMENT_SERVER_COMMAND_PATH=/command');
$configManager = new ConfigurationManager();
$url = $configManager->documentServerCommandURL();
$config_manager = new ConfigurationManager();
$url = $config_manager->document_server_command_url();
$this->assertEquals(
'http://document-server/command',
$url->string()

View File

@ -15,43 +15,36 @@
// limitations under the License.
//
namespace Example\Configuration\Tests;
use PHPUnit\Framework\TestCase;
use Example\Configuration\ConfigurationManager;
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
final class ConfigurationManagerDocumentServerConverterURLTests extends TestCase
{
final class ConfigurationManagerDocumentServerConverterURLTests extends TestCase {
public array $env;
public function __construct(string $name)
{
public function __construct(string $name) {
$this->env = getenv();
parent::__construct($name);
}
protected function setUp(): void
{
protected function setUp(): void {
foreach ($this->env as $key => $value) {
putenv("{$key}={$value}");
}
}
public function testAssignsADefaultValue()
{
$configManager = new ConfigurationManager();
$url = $configManager->documentServerConverterURL();
public function test_assigns_a_default_value() {
$config_manager = new ConfigurationManager();
$url = $config_manager->document_server_converter_url();
$this->assertEquals(
'http://document-server/ConvertService.ashx',
$url->string()
);
}
public function testAssignsAValueFromTheEnvironment()
{
public function test_assigns_a_value_from_the_environment() {
putenv('DOCUMENT_SERVER_CONVERTER_PATH=/converter');
$configManager = new ConfigurationManager();
$url = $configManager->documentServerConverterURL();
$config_manager = new ConfigurationManager();
$url = $config_manager->document_server_converter_url();
$this->assertEquals(
'http://document-server/converter',
$url->string()

View File

@ -15,43 +15,36 @@
// limitations under the License.
//
namespace Example\Configuration\Tests;
use PHPUnit\Framework\TestCase;
use Example\Configuration\ConfigurationManager;
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
final class ConfigurationManagerDocumentServerPreloaderURLTests extends TestCase
{
final class ConfigurationManagerDocumentServerPreloaderURLTests extends TestCase {
public array $env;
public function __construct(string $name)
{
public function __construct(string $name) {
$this->env = getenv();
parent::__construct($name);
}
protected function setUp(): void
{
protected function setUp(): void {
foreach ($this->env as $key => $value) {
putenv("{$key}={$value}");
}
}
public function testAssignsADefaultValue()
{
$configManager = new ConfigurationManager();
$url = $configManager->documentServerPreloaderURL();
public function test_assigns_a_default_value() {
$config_manager = new ConfigurationManager();
$url = $config_manager->document_server_preloader_url();
$this->assertEquals(
'http://document-server/web-apps/apps/api/documents/cache-scripts.html',
$url->string()
);
}
public function testAssignsAValueFromTheEnvironment()
{
public function test_assigns_a_value_from_the_environment() {
putenv('DOCUMENT_SERVER_PRELOADER_PATH=/preloader');
$configManager = new ConfigurationManager();
$url = $configManager->documentServerPreloaderURL();
$config_manager = new ConfigurationManager();
$url = $config_manager->document_server_preloader_url();
$this->assertEquals(
'http://document-server/preloader',
$url->string()

View File

@ -15,40 +15,33 @@
// limitations under the License.
//
namespace Example\Configuration\Tests;
use PHPUnit\Framework\TestCase;
use Example\Configuration\ConfigurationManager;
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
final class ConfigurationManagerDocumentServerPublicURLTests extends TestCase
{
final class ConfigurationManagerDocumentServerURLTests extends TestCase {
public array $env;
public function __construct(string $name)
{
public function __construct(string $name) {
$this->env = getenv();
parent::__construct($name);
}
protected function setUp(): void
{
protected function setUp(): void {
foreach ($this->env as $key => $value) {
putenv("{$key}={$value}");
}
}
public function testAssignsADefaultValue()
{
$configManager = new ConfigurationManager();
$url = $configManager->documentServerPublicURL();
public function test_assigns_a_default_value() {
$config_manager = new ConfigurationManager();
$url = $config_manager->document_server_url();
$this->assertEquals('http://document-server', $url->string());
}
public function testAssignsAValueFromTheEnvironment()
{
putenv('DOCUMENT_SERVER_PUBLIC_URL=http://localhost');
$configManager = new ConfigurationManager();
$url = $configManager->documentServerPublicURL();
public function test_assigns_a_value_from_the_environment() {
putenv('DOCUMENT_SERVER_URL=http://localhost');
$config_manager = new ConfigurationManager();
$url = $config_manager->document_server_url();
$this->assertEquals('http://localhost', $url->string());
}
}

View File

@ -15,40 +15,33 @@
// limitations under the License.
//
namespace Example\Configuration\Tests;
use PHPUnit\Framework\TestCase;
use Example\Configuration\ConfigurationManager;
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
final class ConfigurationManagerExampleURLTests extends TestCase
{
final class ConfigurationManagerExampleURLTests extends TestCase {
public array $env;
public function __construct(string $name)
{
public function __construct(string $name) {
$this->env = getenv();
parent::__construct($name);
}
protected function setUp(): void
{
protected function setUp(): void {
foreach ($this->env as $key => $value) {
putenv("{$key}={$value}");
}
}
public function testAssignsADefaultValue()
{
$configManager = new ConfigurationManager();
$url = $configManager->exampleURL();
public function test_assigns_a_default_value() {
$config_manager = new ConfigurationManager();
$url = $config_manager->example_url();
$this->assertNull($url);
}
public function testAssignsAValueFromTheEnvironment()
{
public function test_assigns_a_value_from_the_environment() {
putenv('EXAMPLE_URL=http://localhost');
$configManager = new ConfigurationManager();
$url = $configManager->exampleURL();
$config_manager = new ConfigurationManager();
$url = $config_manager->example_url();
$this->assertEquals('http://localhost', $url->string());
}
}

View File

@ -15,40 +15,33 @@
// limitations under the License.
//
namespace Example\Configuration\Tests;
use PHPUnit\Framework\TestCase;
use Example\Configuration\ConfigurationManager;
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
final class ConfigurationManagerJWTHeaderTests extends TestCase
{
final class ConfigurationManagerJWTHeaderTests extends TestCase {
public array $env;
public function __construct(string $name)
{
public function __construct(string $name) {
$this->env = getenv();
parent::__construct($name);
}
protected function setUp(): void
{
protected function setUp(): void {
foreach ($this->env as $key => $value) {
putenv("{$key}={$value}");
}
}
public function testAssignsADefaultValue()
{
$configManager = new ConfigurationManager();
$header = $configManager->jwtHeader();
public function test_assigns_a_default_value() {
$config_manager = new ConfigurationManager();
$header = $config_manager->jwt_header();
$this->assertEquals('Authorization', $header);
}
public function testAssignsAValueFromTheEnvironment()
{
public function test_assigns_a_value_from_the_environment() {
putenv('JWT_HEADER=Proxy-Authorization');
$configManager = new ConfigurationManager();
$header = $configManager->jwtHeader();
$config_manager = new ConfigurationManager();
$header = $config_manager->jwt_header();
$this->assertEquals('Proxy-Authorization', $header);
}
}

View File

@ -15,40 +15,33 @@
// limitations under the License.
//
namespace Example\Configuration\Tests;
use PHPUnit\Framework\TestCase;
use Example\Configuration\ConfigurationManager;
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
final class ConfigurationManagerJWTSecretTests extends TestCase
{
final class ConfigurationManagerJWTSecretTests extends TestCase {
public array $env;
public function __construct(string $name)
{
public function __construct(string $name) {
$this->env = getenv();
parent::__construct($name);
}
protected function setUp(): void
{
protected function setUp(): void {
foreach ($this->env as $key => $value) {
putenv("{$key}={$value}");
}
}
public function testAssignsADefaultValue()
{
$configManager = new ConfigurationManager();
$secret = $configManager->jwtSecret();
public function test_assigns_a_default_value() {
$config_manager = new ConfigurationManager();
$secret = $config_manager->jwt_secret();
$this->assertEquals('', $secret);
}
public function testAssignsAValueFromTheEnvironment()
{
public function test_assigns_a_value_from_the_environment() {
putenv('JWT_SECRET=your-256-bit-secret');
$configManager = new ConfigurationManager();
$secret = $configManager->jwtSecret();
$config_manager = new ConfigurationManager();
$secret = $config_manager->jwt_secret();
$this->assertEquals('your-256-bit-secret', $secret);
}
}

View File

@ -15,40 +15,33 @@
// limitations under the License.
//
namespace Example\Configuration\Tests;
use PHPUnit\Framework\TestCase;
use Example\Configuration\ConfigurationManager;
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
final class ConfigurationManagerJWTUseForRequest extends TestCase
{
final class ConfigurationManagerJWTUseForRequest extends TestCase {
public array $env;
public function __construct(string $name)
{
public function __construct(string $name) {
$this->env = getenv();
parent::__construct($name);
}
protected function setUp(): void
{
protected function setUp(): void {
foreach ($this->env as $key => $value) {
putenv("{$key}={$value}");
}
}
public function testAssignsADefaultValue()
{
$configManager = new ConfigurationManager();
$use = $configManager->jwtUseForRequest();
public function test_assigns_a_default_value() {
$config_manager = new ConfigurationManager();
$use = $config_manager->jwt_use_for_request();
$this->assertTrue($use);
}
public function testAssignsAValueFromTheEnvironment()
{
public function test_assigns_a_value_from_the_environment() {
putenv('JWT_USE_FOR_REQUEST=false');
$configManager = new ConfigurationManager();
$use = $configManager->jwtUseForRequest();
$config_manager = new ConfigurationManager();
$use = $config_manager->jwt_use_for_request();
$this->assertFalse($use);
}
}

View File

@ -15,40 +15,33 @@
// limitations under the License.
//
namespace Example\Configuration\Tests;
use PHPUnit\Framework\TestCase;
use Example\Configuration\ConfigurationManager;
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
final class ConfigurationManagerMaximumFileSizeTests extends TestCase
{
final class ConfigurationManagerMaximumFileSizeTests extends TestCase {
public array $env;
public function __construct(string $name)
{
public function __construct(string $name) {
$this->env = getenv();
parent::__construct($name);
}
protected function setUp(): void
{
protected function setUp(): void {
foreach ($this->env as $key => $value) {
putenv("{$key}={$value}");
}
}
public function testAssignsADefaultValue()
{
$configManager = new ConfigurationManager();
$size = $configManager->maximumFileSize();
public function test_assigns_a_default_value() {
$config_manager = new ConfigurationManager();
$size = $config_manager->maximum_file_size();
$this->assertEquals(5_242_880, $size);
}
public function testAssignsAValueFromTheEnvironment()
{
public function test_assigns_a_value_from_the_environment() {
putenv('MAXIMUM_FILE_SIZE=10');
$configManager = new ConfigurationManager();
$size = $configManager->maximumFileSize();
$config_manager = new ConfigurationManager();
$size = $config_manager->maximum_file_size();
$this->assertEquals(10, $size);
}
}

View File

@ -15,40 +15,33 @@
// limitations under the License.
//
namespace Example\Configuration\Tests;
use PHPUnit\Framework\TestCase;
use Example\Configuration\ConfigurationManager;
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
final class ConfigurationManagerSSLTests extends TestCase
{
final class ConfigurationManagerSSLTests extends TestCase {
public array $env;
public function __construct(string $name)
{
public function __construct(string $name) {
$this->env = getenv();
parent::__construct($name);
}
protected function setUp(): void
{
protected function setUp(): void {
foreach ($this->env as $key => $value) {
putenv("{$key}={$value}");
}
}
public function testAssignsADefaultValue()
{
$configManager = new ConfigurationManager();
$enabled = $configManager->sslVerifyPeerModeEnabled();
public function test_assigns_a_default_value() {
$config_manager = new ConfigurationManager();
$enabled = $config_manager->ssl_verify_peer_mode_enabled();
$this->assertFalse($enabled);
}
public function testAssignsAValueFromTheEnvironment()
{
public function test_assigns_a_value_from_the_environment() {
putenv('SSL_VERIFY_PEER_MODE_ENABLED=true');
$configManager = new ConfigurationManager();
$enabled = $configManager->sslVerifyPeerModeEnabled();
$config_manager = new ConfigurationManager();
$enabled = $config_manager->ssl_verify_peer_mode_enabled();
$this->assertTrue($enabled);
}
}

View File

@ -15,40 +15,33 @@
// limitations under the License.
//
namespace Example\Configuration\Tests;
use PHPUnit\Framework\TestCase;
use Example\Configuration\ConfigurationManager;
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
final class ConfigurationManagerSingleUserTests extends TestCase
{
final class ConfigurationManagerSingleUserTests extends TestCase {
public array $env;
public function __construct(string $name)
{
public function __construct(string $name) {
$this->env = getenv();
parent::__construct($name);
}
protected function setUp(): void
{
protected function setUp(): void {
foreach ($this->env as $key => $value) {
putenv("{$key}={$value}");
}
}
public function testAssignsADefaultValue()
{
$configManager = new ConfigurationManager();
$single = $configManager->singleUser();
public function test_assigns_a_default_value() {
$config_manager = new ConfigurationManager();
$single = $config_manager->single_user();
$this->assertFalse($single);
}
public function testAssignsAValueFromTheEnvironment()
{
public function test_assigns_a_value_from_the_environment() {
putenv('SINGLE_USER=true');
$configManager = new ConfigurationManager();
$single = $configManager->singleUser();
$config_manager = new ConfigurationManager();
$single = $config_manager->single_user();
$this->assertTrue($single);
}
}

View File

@ -15,50 +15,42 @@
// limitations under the License.
//
namespace Example\Configuration\Tests;
use PHPUnit\Framework\TestCase;
use Example\Configuration\ConfigurationManager;
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
final class ConfigurationManagerStoragePathTests extends TestCase
{
final class ConfigurationManagerStoragePathTests extends TestCase {
public array $env;
public function __construct(string $name)
{
public function __construct(string $name) {
$this->env = getenv();
parent::__construct($name);
}
protected function setUp(): void
{
protected function setUp(): void {
foreach ($this->env as $key => $value) {
putenv("{$key}={$value}");
}
}
public function testAssignsADefaultValue()
{
$configManager = new ConfigurationManager();
$path = $configManager->storagePath();
public function test_assigns_a_default_value() {
$config_manager = new ConfigurationManager();
$path = $config_manager->storage_path();
$this->assertTrue($path->absolute());
$this->assertEquals($path->basename(), 'storage');
}
public function testAssignsARelativePathFromTheEnvironment()
{
public function test_assigns_a_relative_path_from_the_environment() {
putenv('STORAGE_PATH=directory');
$configManager = new ConfigurationManager();
$path = $configManager->storagePath();
$config_manager = new ConfigurationManager();
$path = $config_manager->storage_path();
$this->assertTrue($path->absolute());
$this->assertEquals($path->basename(), 'directory');
}
public function testAssignsAnAbsolutePathFromTheEnvironment()
{
public function test_assigns_an_absolute_path_from_the_environment() {
putenv('STORAGE_PATH=/directory');
$configManager = new ConfigurationManager();
$path = $configManager->storagePath();
$config_manager = new ConfigurationManager();
$path = $config_manager->storage_path();
$this->assertEquals($path->string(), '/directory');
}
}

View File

@ -15,17 +15,12 @@
// limitations under the License.
//
namespace Example\Format\Tests;
use PHPUnit\Framework\TestCase;
use Example\Format\FormatManager;
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
final class FormatManagerAllTests extends TestCase
{
public function testLoads()
{
$formatManager = new FormatManager();
$formats = $formatManager->all();
$this->assertNotEmpty($formats);
final class ConfigurationManagerTests extends TestCase {
public function test_corresponds_the_latest_version() {
$config_manager = new ConfigurationManager();
$this->assertEquals('1.6.0', $config_manager->version);
}
}

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

Before

Width:  |  Height:  |  Size: 781 B

After

Width:  |  Height:  |  Size: 781 B

View File

Before

Width:  |  Height:  |  Size: 547 B

After

Width:  |  Height:  |  Size: 547 B

View File

Before

Width:  |  Height:  |  Size: 425 B

After

Width:  |  Height:  |  Size: 425 B

View File

Before

Width:  |  Height:  |  Size: 331 B

After

Width:  |  Height:  |  Size: 331 B

View File

Before

Width:  |  Height:  |  Size: 507 B

After

Width:  |  Height:  |  Size: 507 B

View File

Before

Width:  |  Height:  |  Size: 757 B

After

Width:  |  Height:  |  Size: 757 B

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 593 B

After

Width:  |  Height:  |  Size: 593 B

View File

Before

Width:  |  Height:  |  Size: 738 B

After

Width:  |  Height:  |  Size: 738 B

View File

Before

Width:  |  Height:  |  Size: 477 B

After

Width:  |  Height:  |  Size: 477 B

View File

Before

Width:  |  Height:  |  Size: 691 B

After

Width:  |  Height:  |  Size: 691 B

View File

Before

Width:  |  Height:  |  Size: 992 B

After

Width:  |  Height:  |  Size: 992 B

View File

Before

Width:  |  Height:  |  Size: 1004 B

After

Width:  |  Height:  |  Size: 1004 B

View File

Before

Width:  |  Height:  |  Size: 379 B

After

Width:  |  Height:  |  Size: 379 B

View File

Before

Width:  |  Height:  |  Size: 233 B

After

Width:  |  Height:  |  Size: 233 B

View File

Before

Width:  |  Height:  |  Size: 832 B

After

Width:  |  Height:  |  Size: 832 B

Some files were not shown because too many files have changed in this diff Show More