diff --git a/addressbook/inc/class.addressbook_merge.inc.php b/addressbook/inc/class.addressbook_merge.inc.php
index 3835bcc1d6..67319a3110 100644
--- a/addressbook/inc/class.addressbook_merge.inc.php
+++ b/addressbook/inc/class.addressbook_merge.inc.php
@@ -18,4 +18,4 @@ use EGroupware\Api\Contacts\Merge;
*
* @deprecated use Api\Contacts\Merge
*/
-class addressbook_merge extends Merge {}
\ No newline at end of file
+class addressbook_merge extends Merge {}
diff --git a/api/js/jsapi/app_base.js b/api/js/jsapi/app_base.js
index 0872cf6a06..f04abdb260 100644
--- a/api/js/jsapi/app_base.js
+++ b/api/js/jsapi/app_base.js
@@ -1895,18 +1895,55 @@ var AppJS = (function(){ "use strict"; return Class.extend(
* @param {egwAction} _action egw actions
* @param {egwActionObject[]} _senders selected nm row
* @param {egwActionObject} _target Drag source. Not used here.
+ * @param {Boolean} _writable Allow edit access from the share.
* @param {Boolean} _files Allow access to files from the share.
+ * @param {Function} _callback Callback with results
* @returns {Boolean} returns false if not successful
*/
- share_link: function(_action, _senders, _target, _files){
+ share_link: function(_action, _senders, _target, _writable, _files, _callback){
var path = _senders[0].id;
+ if(typeof _writable === 'undefined' && _action.parent && _action.parent.getActionById('shareWritable'))
+ {
+ _writable = _action.parent.getActionById('shareWritable').checked || false;
+ }
if(typeof _files === 'undefined' && _action.parent && _action.parent.getActionById('shareFiles'))
{
_files = _action.parent.getActionById('shareFiles').checked || false;
}
- egw.json('EGroupware\\Api\\Sharing::ajax_create', [_action.id, path, _files],
- this._share_link_callback, this, true, this).sendRequest();
- return true;
+
+ return egw.json('EGroupware\\Api\\Sharing::ajax_create', [_action.id, path, _writable, _files],
+ _callback ? _callback : this._share_link_callback, this, true, this).sendRequest();
+ },
+
+ share_merge: function(_action, _senders, _target)
+ {
+ var parent = _action.parent.parent;
+ var _writable = false;
+ var _files = false;
+ if(parent && parent.getActionById('shareWritable'))
+ {
+ _writable = parent.getActionById('shareWritable').checked || false;
+ }
+ if(parent && parent.getActionById('shareFiles'))
+ {
+ _files = parent.getActionById('shareFiles').checked || false;
+ }
+
+ // Share only works on one at a time
+ var promises = [];
+ for(var i = 0; i < _senders.length; i++)
+ {
+ promises.push(new Promise(function(resolve, reject) {
+ this.share_link(_action, [_senders[i]], _target, _writable, _files, resolve);
+ }.bind(this)));
+ }
+
+ // But merge into email can handle several
+ Promise.all(promises.map(p => p.catch(e => e)))
+ .then(function(values) {
+ // Process document after all shares created
+ return nm_action(_action, _senders, _target);
+ });
},
/**
@@ -1938,7 +1975,7 @@ var AppJS = (function(){ "use strict"; return Class.extend(
jQuery("body").off("click", "[name=share_link]", copy_link_to_clipboard);
return true;
},
- title: _data.title ? _data.title : egw.lang("%1 Share Link", _data.action ==='shareWritableLink'? egw.lang("Writable"): egw.lang("Readonly")),
+ title: _data.title ? _data.title : egw.lang("%1 Share Link", _data.writable ? egw.lang("Writable"): egw.lang("Readonly")),
template: _data.template,
width: 450,
value: {content:{ "share_link": _data.share_link }}
diff --git a/api/src/Contacts/Merge.php b/api/src/Contacts/Merge.php
index 06b7843d01..47930ae094 100644
--- a/api/src/Contacts/Merge.php
+++ b/api/src/Contacts/Merge.php
@@ -218,6 +218,9 @@ class Merge extends Api\Storage\Merge
echo '
{{'.$name.'}} | '.$label." |
\n";
}
+ echo ''.lang('EPL Only').": |
";
+ echo '{{share}} | '.lang('Public sharing URL')." |
\n";
+
Api\Translation::add_app('calendar');
echo ''.lang('Calendar fields:')." # = 1, 2, ..., 20, -1 |
";
foreach(array(
@@ -278,7 +281,7 @@ class Merge extends Api\Storage\Merge
// Change merge into email actions so we can customize them
static::customise_mail_actions($actions);
-
+
return $actions;
}
diff --git a/api/src/Link/Sharing.php b/api/src/Link/Sharing.php
index 6bcd6aab90..746d98dd48 100644
--- a/api/src/Link/Sharing.php
+++ b/api/src/Link/Sharing.php
@@ -76,49 +76,33 @@ class Sharing extends \EGroupware\Api\Sharing
*/
public static function get_actions($appname, $group = 6)
{
- $actions = array(
- 'share' => array(
- 'caption' => lang('Share'),
- 'icon' => 'api/share',
- 'group' => $group,
- 'allowOnMultiple' => false,
- 'children' => array(
- 'shareReadonlyLink' => array(
- 'caption' => lang('Readonly Share'),
- 'group' => 1,
- 'icon' => 'view',
- 'order' => 11,
- 'enabled' => "javaScript:app.$appname.is_share_enabled",
- 'onExecute' => "javaScript:app.$appname.share_link"
- ),
- 'shareWritableLink' => array(
- 'caption' => lang('Writable Share'),
- 'group' => 1,
- 'icon' => 'edit',
- 'allowOnMultiple' => false,
- 'order' => 11,
- 'enabled' => "javaScript:app.$appname.is_share_enabled",
- 'onExecute' => "javaScript:app.$appname.share_link"
- ),
- 'shareFiles' => array(
- 'caption' => lang('Share files'),
- 'group' => 2,
- 'enabled' => "javaScript:app.$appname.is_share_enabled",
- 'checkbox' => true
- )
- ),
- ));
- if(!$GLOBALS['egw_info']['apps']['stylite'])
+ $actions = parent::get_actions($appname, $group);
+
+ // Add in merge to mail document
+ if ($GLOBALS['egw_info']['user']['apps']['mail'] && class_exists($appname.'_merge'))
{
- array_unshift($actions['share']['children'], array(
- 'caption' => lang('EPL Only'),
- 'group' => 0
- ));
- foreach($actions['share']['children'] as &$child)
+ $documents = call_user_func(array($appname.'_merge', 'document_action'),
+ $GLOBALS['egw_info']['user']['preferences']['addressbook']['document_dir'],
+ 1, 'Insert in document', 'shareDocument_'
+ );
+ $documents['order'] = 20;
+
+ // Mail only
+ foreach($documents['children'] as $key => &$document)
{
- $child['enabled'] = false;
+ if(strpos($document['target'],'compose_') === FALSE)
+ {
+ unset($documents['children'][$key]);
+ continue;
+ }
+
+ $document['allowOnMultiple'] = true;
+ $document['onExecute'] = "javaScript:app.$appname.share_merge";
}
+ $documents['enabled'] = !!($GLOBALS['egw_info']['user']['apps']['stylite']);
+ $actions['share']['children']['shareDocuments'] = $documents;
}
+
return $actions;
}
diff --git a/api/src/Sharing.php b/api/src/Sharing.php
index be879a7ca9..2e63bfce5a 100644
--- a/api/src/Sharing.php
+++ b/api/src/Sharing.php
@@ -389,31 +389,31 @@ class Sharing
'allowOnMultiple' => false,
'children' => array(
'shareReadonlyLink' => array(
- 'caption' => lang('Readonly Share'),
+ 'caption' => lang('Share link'),
'group' => 1,
'icon' => 'view',
'order' => 11,
'enabled' => "javaScript:app.$appname.is_share_enabled",
'onExecute' => "javaScript:app.$appname.share_link"
),
- 'shareWritableLink' => array(
- 'caption' => lang('Writable Share'),
- 'group' => 1,
+ 'shareWritable' => array(
+ 'caption' => lang('Writable'),
+ 'group' => 2,
'icon' => 'edit',
- 'allowOnMultiple' => false,
- 'order' => 11,
+ 'allowOnMultiple' => true,
'enabled' => "javaScript:app.$appname.is_share_enabled",
- 'onExecute' => "javaScript:app.$appname.share_link"
+ 'checkbox' => true
),
'shareFiles' => array(
'caption' => lang('Share files'),
'group' => 2,
+ 'allowOnMultiple' => true,
'enabled' => "javaScript:app.$appname.is_share_enabled",
'checkbox' => true
)
),
));
- if(!$GLOBALS['egw_info']['apps']['stylite'])
+ if(!$GLOBALS['egw_info']['user']['apps']['stylite'])
{
array_unshift($actions['share']['children'], array(
'caption' => lang('EPL Only'),
@@ -591,24 +591,28 @@ class Sharing
*
* @param String $action
* @param String $path
+ * @param boolean $writable
* @param boolean $files
*/
- public static function ajax_create($action, $path, $files)
+ public static function ajax_create($action, $path, $writable = false, $files = false)
{
$class = self::get_share_class(array('share_path' => $path));
$share = $class::create(
$path,
- $action == 'shareWritableLink' ? Sharing::WRITABLE : Sharing::READONLY,
- basename($selected),
+ $action == $writable ? Sharing::WRITABLE : Sharing::READONLY,
+ basename($path),
array(),
array(
- 'share_writable' => $action == 'shareWritableLink',
+ 'share_writable' => $writable,
'include_files' => $files
)
);
+ // Store share in session so Merge can find this one and not create a read-only one
+ \EGroupware\Api\Cache::setSession(__CLASS__, $path, $share);
$arr = array(
'action' => $action,
+ 'writable' => $writable,
'share_link' => $class::share2link($share),
'template' => Etemplate\Widget\Template::rel2url('/filemanager/templates/default/share_dialog.xet')
);
diff --git a/api/src/Storage/Merge.php b/api/src/Storage/Merge.php
index c9b3d60307..aef875b630 100644
--- a/api/src/Storage/Merge.php
+++ b/api/src/Storage/Merge.php
@@ -450,6 +450,58 @@ abstract class Merge
return $array;
}
+ /**
+ * Get share placeholder
+ *
+ * If the placeholder is present in the content, the share will be automatically
+ * created.
+ */
+ protected function share_placeholder($app, $id, $prefix, &$content)
+ {
+ $replacements = array();
+
+ // Skip if no content or content has no share placeholder
+ if(!$content || strpos($content, '$$share') === FALSE)
+ {
+ return $replacements;
+ }
+
+ if(!$GLOBALS['egw_info']['user']['apps']['stylite'])
+ {
+ $replacements['$$'.$prefix.'share$$'] = lang('EPL Only');
+ return $replacements;
+ }
+
+ // Get or create the share
+ // Check if some other process created the share (with custom options)
+ // and put it in the session cache for us
+ $path = "$app::$id";
+ $session = \EGroupware\Api\Cache::getSession(Api\Sharing::class, $path);
+ if($session && $session['share_path'] == $path)
+ {
+ $share = $session;
+ }
+ else
+ {
+ // Need to create the share here.
+ // No way to know here if it should be writable, or who it's going to
+ $mode = /* ? ? Sharing::WRITABLE :*/ Api\Sharing::READONLY;
+ $recipients = array();
+ $extra = array();
+
+ //$extra['share_writable'] |= ($mode == Sharing::WRITABLE ? 1 : 0);
+
+ $share = \EGroupware\Stylite\Link\Sharing::create($path, $mode, NULL, $recipients, $extra);
+ }
+
+ if($share)
+ {
+ $replacements['$$'.$prefix.'share$$'] = $link = Api\Sharing::share2link($share);
+ }
+
+ return $replacements;
+ }
+
/**
* Format a datetime
*
@@ -850,6 +902,9 @@ abstract class Merge
$replacements['$$datetime$$'] = Api\DateTime::to('now');
$replacements['$$time$$'] = Api\DateTime::to('now',false);
+ $app = $this->get_app();
+ $replacements += $this->share_placeholder($app, $id, $prefix, $content);
+
// does our extending class registered table-plugins AND document contains table tags
if ($this->table_plugins && preg_match_all('/\\$\\$table\\/([A-Za-z0-9_]+)\\$\\$(.*?)\\$\\$endtable\\$\\$/s',$content,$matches,PREG_SET_ORDER))
{
@@ -1438,6 +1493,31 @@ abstract class Merge
}
}
+ /**
+ * Figure out which app we're running as
+ *
+ * @return string
+ */
+ protected function get_app()
+ {
+ switch (get_class($this))
+ {
+ case 'EGroupware\Api\Contacts\Merge':
+ $app = 'addressbook';
+ break;
+ default:
+ $app = str_replace('_merge','',get_class($this));
+ if(!in_array($app, $GLOBALS['egw_info']['apps']))
+ {
+ $app = false;
+ }
+ break;
+
+ }
+
+ return $app;
+ }
+
/**
* Get the replacements for any entry specified by app & id
*