mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-22 07:53:39 +01:00
* Api: Add some options to merge: merge individually, merge & link, merge & email, download
This commit is contained in:
parent
50dfa86150
commit
ff94af1f7d
145
api/js/etemplate/Et2Dialog/Et2MergeDialog.ts
Normal file
145
api/js/etemplate/Et2Dialog/Et2MergeDialog.ts
Normal file
@ -0,0 +1,145 @@
|
||||
import {customElement} from "lit/decorators/custom-element.js";
|
||||
import {Et2Widget} from "../Et2Widget/Et2Widget";
|
||||
import {css, html, LitElement} from "lit";
|
||||
import shoelace from "../Styles/shoelace";
|
||||
import {Et2VfsSelectDialog} from "../Et2Vfs/Et2VfsSelectDialog";
|
||||
import {property} from "lit/decorators/property.js";
|
||||
import {Et2Dialog} from "./Et2Dialog";
|
||||
import {state} from "lit/decorators/state.js";
|
||||
|
||||
@customElement("et2-merge-dialog")
|
||||
export class Et2MergeDialog extends Et2Widget(LitElement)
|
||||
{
|
||||
static get styles()
|
||||
{
|
||||
return [
|
||||
super.styles,
|
||||
shoelace,
|
||||
css`
|
||||
:host {
|
||||
}
|
||||
|
||||
et2-details::part(content) {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
@property()
|
||||
application : string
|
||||
|
||||
@property()
|
||||
path : string
|
||||
|
||||
// Can't merge "& send" if no email template selected
|
||||
@state()
|
||||
canEmail = false;
|
||||
|
||||
private get dialog() : Et2VfsSelectDialog
|
||||
{
|
||||
return <Et2VfsSelectDialog><unknown>this.shadowRoot.querySelector("et2-vfs-select-dialog");
|
||||
}
|
||||
|
||||
public async getComplete() : Promise<{
|
||||
documents : { path : string, mime : string }[],
|
||||
options : { [key : string] : string | boolean }
|
||||
}>
|
||||
{
|
||||
await this.updateComplete;
|
||||
const [button, value] = await this.dialog.getComplete();
|
||||
|
||||
if(!button)
|
||||
{
|
||||
return {documents: [], options: this.optionValues};
|
||||
}
|
||||
|
||||
const documents = [];
|
||||
Array.from(<ArrayLike<string>>value).forEach(value =>
|
||||
{
|
||||
const fileInfo = this.dialog.fileInfo(value) ?? [];
|
||||
documents.push({path: value, mime: fileInfo.mime})
|
||||
});
|
||||
let options = this.optionValues;
|
||||
if(button == Et2Dialog.OK_BUTTON)
|
||||
{
|
||||
options.download = true;
|
||||
}
|
||||
return {documents: documents, options: options};
|
||||
}
|
||||
|
||||
public get optionValues()
|
||||
{
|
||||
const optionValues = {
|
||||
download: false
|
||||
};
|
||||
this.dialog.querySelectorAll(":not([slot='footer'])").forEach(e =>
|
||||
{
|
||||
if(typeof e.getValue == "function")
|
||||
{
|
||||
optionValues[e.getAttribute("id")] = e.getValue() === "true" ? true : e.getValue();
|
||||
}
|
||||
});
|
||||
return optionValues;
|
||||
}
|
||||
|
||||
private option(component_name)
|
||||
{
|
||||
return this.dialog.querySelector("et2-details > [id='" + component_name + "']");
|
||||
}
|
||||
|
||||
protected handleFileSelect(event)
|
||||
{
|
||||
// Disable PDF checkbox for only email files selected
|
||||
let canPDF = false;
|
||||
const oldCanEmail = this.canEmail;
|
||||
this.canEmail = false;
|
||||
|
||||
this.dialog.value.forEach(path =>
|
||||
{
|
||||
if(this.dialog.fileInfo(path).mime !== "message/rfc822")
|
||||
{
|
||||
canPDF = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.canEmail = true;
|
||||
}
|
||||
});
|
||||
this.option("pdf").disabled = !canPDF;
|
||||
this.requestUpdate("canEmail", oldCanEmail);
|
||||
}
|
||||
|
||||
|
||||
render()
|
||||
{
|
||||
return html`
|
||||
<et2-vfs-select-dialog
|
||||
class=egw_app_merge_document"
|
||||
path=${this.path}
|
||||
multiple="true"
|
||||
buttonLabel="Download"
|
||||
.title="${this.egw().lang("Insert in document")}"
|
||||
.open=${true}
|
||||
@et2-select=${this.handleFileSelect}
|
||||
>
|
||||
${this.canEmail ?
|
||||
html`
|
||||
<et2-button slot="footer" id="send" label="Merge & send" image="mail"
|
||||
noSubmit="true"></et2-button> ` :
|
||||
html`
|
||||
<et2-button slot="footer" id="send" label="Merge" image="etemplate/merge"
|
||||
noSubmit="true"></et2-button>`
|
||||
}
|
||||
<et2-details>
|
||||
<span slot="summary">${this.egw().lang("Merge options")}</span>
|
||||
<et2-checkbox label="Save as PDF" id="pdf"></et2-checkbox>
|
||||
<et2-checkbox id="link"
|
||||
label="${this.egw().lang("Link to each %1", <string>this.egw().link_get_registry(this.application, "entry") || this.egw().lang("entry"))}"
|
||||
></et2-checkbox>
|
||||
<et2-checkbox label="Merge individually" id="individual"></et2-checkbox>
|
||||
</et2-details>
|
||||
</et2-vfs-select-dialog>`;
|
||||
}
|
||||
}
|
@ -49,6 +49,7 @@ import './Et2Date/Et2DateTimeReadonly';
|
||||
import './Et2Date/Et2DateTimeToday';
|
||||
import './Et2Description/Et2Description';
|
||||
import './Et2Dialog/Et2Dialog';
|
||||
import './Et2Dialog/Et2MergeDialog';
|
||||
import './Et2DropdownButton/Et2DropdownButton';
|
||||
import './Et2Email/Et2Email';
|
||||
import './Expose/Et2ImageExpose';
|
||||
|
@ -17,13 +17,14 @@ import {et2_createWidget} from "../etemplate/et2_core_widget";
|
||||
import type {IegwAppLocal} from "./egw_global";
|
||||
import Sortable from 'sortablejs/modular/sortable.complete.esm.js';
|
||||
import {et2_valueWidget} from "../etemplate/et2_core_valueWidget";
|
||||
import {nm_action} from "../etemplate/et2_extension_nextmatch_actions";
|
||||
import {fetchAll, nm_action} from "../etemplate/et2_extension_nextmatch_actions";
|
||||
import {Et2Dialog} from "../etemplate/Et2Dialog/Et2Dialog";
|
||||
import {Et2Favorites} from "../etemplate/Et2Favorites/Et2Favorites";
|
||||
import {loadWebComponent} from "../etemplate/Et2Widget/Et2Widget";
|
||||
import {Et2VfsSelectDialog} from "../etemplate/Et2Vfs/Et2VfsSelectDialog";
|
||||
import {Et2Checkbox} from "../etemplate/Et2Checkbox/Et2Checkbox";
|
||||
import type {EgwAction} from "../egw_action/EgwAction";
|
||||
import {Et2MergeDialog} from "../etemplate/Et2Dialog/Et2MergeDialog";
|
||||
import {EgwActionObject} from "../egw_action/EgwActionObject";
|
||||
import type {Et2Details} from "../etemplate/Layout/Et2Details/Et2Details";
|
||||
|
||||
/**
|
||||
* Type for push-message
|
||||
@ -804,7 +805,6 @@ export abstract class EgwApp
|
||||
// Find what we need
|
||||
let nm = null;
|
||||
let action = _action;
|
||||
let as_pdf = null;
|
||||
|
||||
// Find Select all
|
||||
while(nm == null && action.parent != null)
|
||||
@ -824,28 +824,76 @@ export abstract class EgwApp
|
||||
let split = _selected[i].id.split("::");
|
||||
ids.push(split[1]);
|
||||
}
|
||||
let document = await this._getMergeDocument(nm?.getInstanceManager(), _action);
|
||||
if(!document.document)
|
||||
let document = await this._getMergeDocument(nm?.getInstanceManager(), _action, _selected);
|
||||
if(!document.documents || document.documents.length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let vars = {
|
||||
..._action.data.merge_data,
|
||||
document: document.document,
|
||||
pdf: document.pdf ?? false,
|
||||
options: document.options,
|
||||
select_all: all,
|
||||
id: ids
|
||||
};
|
||||
if(document.mime == "message/rfc822")
|
||||
if(document.options.link)
|
||||
{
|
||||
vars.options.app = this.appname;
|
||||
}
|
||||
// Just one file, an email - merge & edit or merge & send
|
||||
if(document.documents.length == 1 && document.documents[0].mime == "message/rfc822")
|
||||
{
|
||||
vars.document = document.documents[0].path;
|
||||
return this._mergeEmail(_action.clone(), vars);
|
||||
}
|
||||
else
|
||||
{
|
||||
vars.id = JSON.stringify(ids);
|
||||
vars.document = document.documents.map(f => f.path);
|
||||
}
|
||||
if(document.documents.length == 1 && !document.options.individual)
|
||||
{
|
||||
// Only 1 document, we can open it
|
||||
vars.id = JSON.stringify(ids);
|
||||
this.egw.open_link(this.egw.link('/index.php', vars), '_blank');
|
||||
}
|
||||
else
|
||||
{
|
||||
// Multiple files, or merging individually - will result in multiple documents that we can't just open
|
||||
vars.menuaction = vars.menuaction.replace("merge_entries", "ajax_merge_multiple");
|
||||
vars.menuaction += "&merge=" + vars.merge;
|
||||
let mergedFiles = [];
|
||||
|
||||
// Check for an email template - all other files will be merged & attached
|
||||
let email = document.documents.find(f => f.mime == "message/rfc822");
|
||||
|
||||
// Can we do this in one, or do we have to split it up for feedback?
|
||||
if(!vars.options.individual && !email)
|
||||
{
|
||||
// Handle it all on the server in one request
|
||||
mergedFiles = await this.egw.request(vars.menuaction, [vars.id, vars.document, vars.options]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Merging documents, merge email, attach to email, send.
|
||||
// Handled like this here so we can give feedback, server could do it all in one request
|
||||
let idGroup = await new Promise<string[]>((resolve) =>
|
||||
{
|
||||
if(all)
|
||||
{
|
||||
fetchAll(ids, nm, idsArr => resolve(vars.options.individual ? idsArr : [idsArr]));
|
||||
}
|
||||
else
|
||||
{
|
||||
resolve(vars.options.individual ? ids : [ids])
|
||||
}
|
||||
});
|
||||
Et2Dialog.long_task(null /*done*/, this.egw.lang("Merging"),
|
||||
email ? this.egw.lang("Merging into %1 and sending", email.path) : this.egw.lang("Merging into %1", vars.document.join(", ")),
|
||||
vars.menuaction,
|
||||
idGroup.map((ids) => {return [Array.isArray(ids) ? ids : [ids], vars.document, vars.options];}), this.egw
|
||||
);
|
||||
}
|
||||
}
|
||||
this.egw.open_link(this.egw.link('/index.php', vars), '_blank');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -855,10 +903,9 @@ export abstract class EgwApp
|
||||
* @protected
|
||||
*/
|
||||
|
||||
protected _getMergeDocument(et2?, action? : EgwAction) : Promise<{
|
||||
document : string,
|
||||
pdf : boolean,
|
||||
mime : string
|
||||
protected _getMergeDocument(et2?, action? : EgwAction, selected? : EgwActionObject[]) : Promise<{
|
||||
documents : { path : string; mime : string }[];
|
||||
options : { [p : string] : string | boolean }
|
||||
}>
|
||||
{
|
||||
let path = action?.data?.merge_data?.directory ?? "";
|
||||
@ -871,51 +918,28 @@ export abstract class EgwApp
|
||||
d = "/" + d;
|
||||
}
|
||||
});
|
||||
let fileSelect = <Et2VfsSelectDialog><unknown>loadWebComponent('et2-vfs-select-dialog', {
|
||||
class: "egw_app_merge_document",
|
||||
title: this.egw.lang("Insert in document"),
|
||||
mode: "open",
|
||||
path: path ?? dirs?.pop() ?? "",
|
||||
open: true
|
||||
let fileSelect = <Et2MergeDialog><unknown>loadWebComponent('et2-merge-dialog', {
|
||||
application: this.appname,
|
||||
path: dirs.pop() || ""
|
||||
}, et2.widgetContainer);
|
||||
if(!et2)
|
||||
{
|
||||
document.body.append(fileSelect);
|
||||
}
|
||||
let pdf = <Et2Checkbox><unknown>loadWebComponent("et2-checkbox", {
|
||||
slot: "footer",
|
||||
label: "As PDF"
|
||||
}, fileSelect);
|
||||
|
||||
// Disable PDF checkbox for emails
|
||||
fileSelect.addEventListener("et2-select", e =>
|
||||
// Start details open when you have multiple selected
|
||||
fileSelect.updateComplete.then(() =>
|
||||
{
|
||||
let canPDF = true;
|
||||
fileSelect.value.forEach(path =>
|
||||
{
|
||||
if(fileSelect.fileInfo(path).mime == "message/rfc822")
|
||||
{
|
||||
canPDF = false;
|
||||
}
|
||||
});
|
||||
pdf.disabled = !canPDF;
|
||||
// @ts-ignore
|
||||
(<Et2Details>fileSelect.shadowRoot.querySelector('et2-details')).open = selected.length > 1;
|
||||
});
|
||||
return fileSelect.getComplete().then((values) =>
|
||||
{
|
||||
if(!values[0])
|
||||
{
|
||||
return {document: '', pdf: false, mime: ""};
|
||||
}
|
||||
// Remove when done
|
||||
fileSelect.getComplete().then(() => {fileSelect.remove();});
|
||||
|
||||
const value = values[1].pop() ?? "";
|
||||
const fileInfo = fileSelect.fileInfo(value) ?? {};
|
||||
fileSelect.remove();
|
||||
return {document: value, pdf: pdf.getValue(), mime: fileInfo.mime ?? ""};
|
||||
});
|
||||
return fileSelect.getComplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Merging into an email
|
||||
* Merge into an email, then open it in compose for a single, send directly for multiple
|
||||
*
|
||||
* @param {object} data
|
||||
* @protected
|
||||
|
@ -31,7 +31,8 @@ class Merge extends Api\Storage\Merge
|
||||
var $public_functions = array(
|
||||
'download_by_request' => true,
|
||||
'show_replacements' => true,
|
||||
"merge_entries" => true
|
||||
'merge_entries' => true,
|
||||
'ajax_merge_multiple' => true,
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -7002,9 +7002,10 @@ class Mail
|
||||
* @param string&|false $_folder (passed by reference) will set the folder used. must be set with a folder, but will hold modifications if
|
||||
* folder is modified. Set to false to not keep the message.
|
||||
* @param string& $importID ID for the imported message, used by attachments to identify them unambiguously
|
||||
* @param string[] $attachments Files attached to the email - the same files for every email
|
||||
* @return mixed array of messages with success and failed messages or exception
|
||||
*/
|
||||
function importMessageToMergeAndSend(Storage\Merge $bo_merge, $document, $SendAndMergeTocontacts, &$_folder, &$importID='')
|
||||
function importMessageToMergeAndSend(Storage\Merge $bo_merge, $document, $SendAndMergeTocontacts, &$_folder, &$importID = '', $attachments = [])
|
||||
{
|
||||
$importfailed = false;
|
||||
$processStats = array('success'=>array(),'failed'=>array());
|
||||
@ -7075,6 +7076,10 @@ class Mail
|
||||
|
||||
$mailObject->addReplyTo(Horde_Idna::encode($activeMailProfile['ident_email']),Mail::generateIdentityString($activeMailProfile,false));
|
||||
}
|
||||
foreach($attachments as $file)
|
||||
{
|
||||
$mailObject->addAttachment($file);
|
||||
}
|
||||
if(count($SendAndMergeTocontacts) > 1)
|
||||
{
|
||||
foreach(Mailer::$type2header as $type => $h)
|
||||
|
@ -15,6 +15,7 @@ namespace EGroupware\Api\Storage;
|
||||
|
||||
use DOMDocument;
|
||||
use EGroupware\Api;
|
||||
use EGroupware\Api\Mail;
|
||||
use EGroupware\Api\Vfs;
|
||||
use EGroupware\Collabora\Conversion;
|
||||
use EGroupware\Stylite;
|
||||
@ -2091,7 +2092,7 @@ abstract class Merge
|
||||
* @return string with error-message on error
|
||||
* @throws Api\Exception
|
||||
*/
|
||||
public function merge_file($document, $ids, &$name = '', $dirs = '', &$header = null)
|
||||
public function merge_file($document, $ids, &$name = '', $dirs = '', &$header = null, $attachments = [])
|
||||
{
|
||||
//error_log(__METHOD__."('$document', ".array2string($ids).", '$name', dirs='$dirs') ->".function_backtrace());
|
||||
if(($error = $this->check_document($document, $dirs)))
|
||||
@ -2108,7 +2109,7 @@ abstract class Merge
|
||||
try
|
||||
{
|
||||
$_folder = $this->keep_emails ? '' : FALSE;
|
||||
$msgs = $mail_bo->importMessageToMergeAndSend($this, $content_url, $ids, $_folder);
|
||||
$msgs = $mail_bo->importMessageToMergeAndSend($this, $content_url, $ids, $_folder, $import_id, $attachments);
|
||||
}
|
||||
catch (Api\Exception\WrongUserinput $e)
|
||||
{
|
||||
@ -2484,12 +2485,17 @@ abstract class Merge
|
||||
*
|
||||
* @param string[]|null $ids Allows extending classes to process IDs in their own way. Leave null to pull from request.
|
||||
* @param Merge|null $document_merge Already instantiated Merge object to do the merge.
|
||||
* @param boolean|null $pdf Convert result to PDF
|
||||
* @param Array options
|
||||
* @param boolean options[individual] Instead of merging all entries into the file, merge each entry into its own file
|
||||
* @param boolean options[pdf] Convert result to PDF
|
||||
* @param boolean options[link] Link generated file to the entry
|
||||
* @param boolean $return Return the path of the generated document instead of opening or downloading
|
||||
* @throws Api\Exception
|
||||
* @throws Api\Exception\AssertionFailed
|
||||
*/
|
||||
public static function merge_entries(array $ids = null, Merge &$document_merge = null, $pdf = null)
|
||||
public static function merge_entries(array $ids = null, Merge &$document_merge = null, $options = [], bool $return = null)
|
||||
{
|
||||
// Setup & get what we need
|
||||
if(is_null($document_merge) && class_exists($_REQUEST['merge']) && is_subclass_of($_REQUEST['merge'], 'EGroupware\\Api\\Storage\\Merge'))
|
||||
{
|
||||
$document_merge = new $_REQUEST['merge']();
|
||||
@ -2499,10 +2505,17 @@ abstract class Merge
|
||||
$document_merge = new Api\Contacts\Merge();
|
||||
}
|
||||
|
||||
if(($error = $document_merge->check_document($_REQUEST['document'], '')))
|
||||
$documents = (array)$_REQUEST['document'];
|
||||
|
||||
// Check for an email
|
||||
$email = null;
|
||||
foreach($documents as $key => $d)
|
||||
{
|
||||
error_log(__METHOD__ . "({$_REQUEST['document']}) $error");
|
||||
return;
|
||||
if(Vfs::mime_content_type($d) == 'message/rfc822')
|
||||
{
|
||||
$email = $d;
|
||||
unset($documents[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
if(is_null(($ids)))
|
||||
@ -2513,14 +2526,116 @@ abstract class Merge
|
||||
{
|
||||
$ids = self::get_all_ids($document_merge);
|
||||
}
|
||||
|
||||
if(is_null($pdf))
|
||||
foreach(['pdf', 'individual', 'link'] as $option)
|
||||
{
|
||||
$pdf = (boolean)$_REQUEST['pdf'];
|
||||
$$option = is_null($options) ? (boolean)$_REQUEST['options'][$option] : (boolean)$options[$option];
|
||||
}
|
||||
$app = (is_null($options) ? $_REQUEST['options']['app'] : $options['app']) ?? $GLOBALS['egw_info']['flags']['currentapp'];
|
||||
|
||||
if(is_null($return))
|
||||
{
|
||||
$return = (boolean)$_REQUEST['return'];
|
||||
}
|
||||
|
||||
$filename = $document_merge->get_filename($_REQUEST['document'], $ids);
|
||||
$result = $document_merge->merge_file($_REQUEST['document'], $ids, $filename, '', $header);
|
||||
$id_group = $individual ? $ids : [$ids];
|
||||
$merged = $attach = [];
|
||||
$target = '';
|
||||
foreach($id_group as $ids)
|
||||
{
|
||||
foreach($documents as $document)
|
||||
{
|
||||
if($document != $email)
|
||||
{
|
||||
// Generate file
|
||||
$target = $document_merge->merge_entries_into_document((array)$ids, $document);
|
||||
}
|
||||
|
||||
// PDF conversion
|
||||
if($pdf)
|
||||
{
|
||||
$converted = $document_merge->pdf_conversion($target);
|
||||
$target = $converted;
|
||||
}
|
||||
$merged[] = $target;
|
||||
$attach[] = Vfs::PREFIX . $target;
|
||||
|
||||
// Link to entry
|
||||
if($link)
|
||||
{
|
||||
foreach((array)$ids as $id)
|
||||
{
|
||||
Api\Link::link($app, $id, Api\Link::VFS_APPNAME, $target);
|
||||
}
|
||||
}
|
||||
}
|
||||
// One email per id group
|
||||
if($email)
|
||||
{
|
||||
// Trick merge into not trying to open in compose
|
||||
if(is_string($ids))
|
||||
{
|
||||
$ids = [$ids];
|
||||
}
|
||||
if(count((array)$ids) == 1)
|
||||
{
|
||||
$ids[] = null;
|
||||
}
|
||||
try
|
||||
{
|
||||
$document_merge->merge_entries_into_document($ids, $email, $attach);
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
// Merge on an email will throw exception if it can't make the file, which is always
|
||||
$merged[] = str_replace("Unable to generate merge file\n", '', $e->getMessage());
|
||||
}
|
||||
$attach = [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Find out what to do with it - can't handle multiple documents directly
|
||||
if($return || count($merged) > 1)
|
||||
{
|
||||
return $merged;
|
||||
}
|
||||
|
||||
// Merge done, present to user
|
||||
if($document_merge->get_editable_mimes()[Vfs::mime_content_type($target)] &&
|
||||
!in_array(Vfs::mime_content_type($target), explode(',', $GLOBALS['egw_info']['user']['preferences']['filemanager']['collab_excluded_mimes'])))
|
||||
{
|
||||
\Egroupware\Api\Egw::redirect_link('/index.php', array(
|
||||
'menuaction' => 'collabora.EGroupware\\Collabora\\Ui.editor',
|
||||
'path' => $target
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
\Egroupware\Api\Egw::redirect_link(Vfs::download_url($target, true));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the given IDs into the given document, saves to VFS, and returns the path
|
||||
*
|
||||
* @param array $ids
|
||||
* @param $pdf
|
||||
* @return string|void
|
||||
* @throws Api\Exception\AssertionFailed
|
||||
* @throws Api\Exception\NotFound
|
||||
* @throws Api\Exception\WrongParameter
|
||||
* @throws Vfs\Exception\ProtectedDirectory
|
||||
*/
|
||||
protected function merge_entries_into_document(array $ids = [], $document, $attachments = [])
|
||||
{
|
||||
if(($error = $this->check_document($document, '')))
|
||||
{
|
||||
error_log(__METHOD__ . "({$_REQUEST['document']}) $error");
|
||||
return;
|
||||
}
|
||||
|
||||
$filename = $this->get_filename($document, $ids);
|
||||
$result = $this->merge_file($document, $ids, $filename, '', $header, $attachments);
|
||||
|
||||
if(!is_file($result) || !is_readable($result))
|
||||
{
|
||||
@ -2528,7 +2643,7 @@ abstract class Merge
|
||||
}
|
||||
// Put it into the vfs using user's preferred directory if writable,
|
||||
// or expected home dir (/home/username) if not
|
||||
$target = $document_merge->get_save_path($filename);
|
||||
$target = $this->get_save_path($filename);
|
||||
|
||||
// Make sure we won't overwrite something already there
|
||||
$target = Vfs::make_unique($target);
|
||||
@ -2536,7 +2651,52 @@ abstract class Merge
|
||||
copy($result, Vfs::PREFIX . $target);
|
||||
unlink($result);
|
||||
|
||||
// Find out what to do with it
|
||||
return $target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a file into PDF
|
||||
*
|
||||
* Removes the original file
|
||||
*
|
||||
* @param $path
|
||||
* @return mixed|string Path to converted file
|
||||
* @throws Api\Exception\AssertionFailed
|
||||
* @throws Api\Exception\NotFound
|
||||
* @throws Api\Exception\WrongParameter
|
||||
* @throws Vfs\Exception\ProtectedDirectory
|
||||
*/
|
||||
protected function pdf_conversion($path)
|
||||
{
|
||||
$editable_mimes = $this->get_editable_mimes();
|
||||
if($editable_mimes[Vfs::mime_content_type($path)])
|
||||
{
|
||||
$error = '';
|
||||
$converted_path = '';
|
||||
$convert = new Conversion();
|
||||
$convert->convert($path, $converted_path, 'pdf', $error);
|
||||
|
||||
if($error)
|
||||
{
|
||||
error_log(__METHOD__ . "({$_REQUEST['document']}) $path => $converted_path Error in PDF conversion: $error");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove original
|
||||
Vfs::unlink($path);
|
||||
$path = $converted_path;
|
||||
}
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of editable mime types
|
||||
*
|
||||
* @return array|String[]
|
||||
*/
|
||||
protected function get_editable_mimes()
|
||||
{
|
||||
$editable_mimes = array();
|
||||
try
|
||||
{
|
||||
@ -2554,38 +2714,61 @@ abstract class Merge
|
||||
// ignore failed discovery
|
||||
unset($e);
|
||||
}
|
||||
return $editable_mimes;
|
||||
}
|
||||
|
||||
// PDF conversion
|
||||
if($editable_mimes[Vfs::mime_content_type($target)] && $pdf)
|
||||
|
||||
/**
|
||||
* Merge one or more entries into one or more documents.
|
||||
*
|
||||
* @param array|null $ids
|
||||
* @param \EGroupware\Api\Contacts\Merge|null $document_merge
|
||||
* @param $documents
|
||||
* @param $options
|
||||
* @return string[] location(s) of merged files
|
||||
*/
|
||||
public static function ajax_merge_multiple(array $ids = [], $documents = [], $options = [])
|
||||
{
|
||||
$response = Api\Json\Response::get();
|
||||
$_REQUEST['document'] = $documents;
|
||||
$app = $options['app'] ?? $GLOBALS['egw_info']['flags']['currentapp'];
|
||||
$message = implode(', ', Api\Link::titles($app, $ids)) . ":\n";
|
||||
|
||||
try
|
||||
{
|
||||
$error = '';
|
||||
$converted_path = '';
|
||||
$convert = new Conversion();
|
||||
$convert->convert($target, $converted_path, 'pdf', $error);
|
||||
$merge_result = static::merge_entries($ids, $document_merge, $options, true);
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
$response->error($message . $e->getMessage());
|
||||
}
|
||||
|
||||
if($error)
|
||||
foreach($merge_result as $result)
|
||||
{
|
||||
if(is_string($result))
|
||||
{
|
||||
error_log(__METHOD__ . "({$_REQUEST['document']}) $target => $converted_path Error in PDF conversion: $error");
|
||||
if($options['download'])
|
||||
{
|
||||
$response->apply('egw.open_link', [Vfs::download_url($result, true), '_browser']);
|
||||
}
|
||||
$message .= $result . "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove original
|
||||
Vfs::unlink($target);
|
||||
$target = $converted_path;
|
||||
if($result['failed'])
|
||||
{
|
||||
$response->error($message . join(", ", $result['failed']));
|
||||
}
|
||||
else
|
||||
{
|
||||
if($result['success'])
|
||||
{
|
||||
$message .= join(", ", $result['success']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if($editable_mimes[Vfs::mime_content_type($target)] &&
|
||||
!in_array(Vfs::mime_content_type($target), explode(',', $GLOBALS['egw_info']['user']['preferences']['filemanager']['collab_excluded_mimes'])))
|
||||
{
|
||||
\Egroupware\Api\Egw::redirect_link('/index.php', array(
|
||||
'menuaction' => 'collabora.EGroupware\\Collabora\\Ui.editor',
|
||||
'path' => $target
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
\Egroupware\Api\Egw::redirect_link(Vfs::download_url($target, true));
|
||||
}
|
||||
$response->data($message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user