2011-09-08 01:32:24 +02:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* EGroupware - eTemplate serverside of linking widgets
|
|
|
|
*
|
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
2016-03-19 14:06:07 +01:00
|
|
|
* @package api
|
|
|
|
* @subpackage etemplate
|
2011-09-08 01:32:24 +02:00
|
|
|
* @link http://www.egroupware.org
|
|
|
|
* @author Nathan Gray
|
|
|
|
* @copyright 2011 Nathan Gray
|
|
|
|
* @version $Id$
|
|
|
|
*/
|
|
|
|
|
2016-03-19 14:06:07 +01:00
|
|
|
namespace EGroupware\Api\Etemplate\Widget;
|
|
|
|
|
|
|
|
use EGroupware\Api\Etemplate;
|
|
|
|
use EGroupware\Api;
|
|
|
|
|
|
|
|
// explicitly import old not yet ported classes
|
|
|
|
use common; // egw_exit
|
|
|
|
|
2011-09-08 01:32:24 +02:00
|
|
|
/**
|
|
|
|
* eTemplate link widgets
|
|
|
|
* Deals with creation and display of links between entries in various participating egw applications
|
|
|
|
*/
|
2016-03-19 14:06:07 +01:00
|
|
|
class Link extends Etemplate\Widget
|
2011-09-08 01:32:24 +02:00
|
|
|
{
|
|
|
|
|
2014-07-08 18:51:01 +02:00
|
|
|
public $public_functions = array(
|
|
|
|
'download_zip' => true
|
|
|
|
);
|
|
|
|
|
2013-08-19 19:42:08 +02:00
|
|
|
protected $legacy_options = 'only_app';
|
|
|
|
|
2011-09-08 01:32:24 +02:00
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* @param string|XMLReader $xml string with xml or XMLReader positioned on the element to construct
|
2016-03-19 14:06:07 +01:00
|
|
|
* @throws Api\Exception\WrongParameter
|
2011-09-08 01:32:24 +02:00
|
|
|
*/
|
|
|
|
public function __construct($xml = '')
|
|
|
|
{
|
|
|
|
if($xml) {
|
|
|
|
parent::__construct($xml);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Changes all link widgets to template
|
|
|
|
protected static $transformation = array(
|
|
|
|
'type' => array(
|
|
|
|
'link-list'=>array(
|
|
|
|
'value' => array('__callback__'=>'get_links'),
|
|
|
|
'type' => 'template',
|
|
|
|
'id' => 'etemplate.link_widget.list'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
);
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set up what we know on the server side.
|
2011-09-08 14:24:53 +02:00
|
|
|
*
|
2011-09-08 01:32:24 +02:00
|
|
|
* Set the options for the application select.
|
|
|
|
*
|
|
|
|
* @param string $cname
|
2014-10-01 21:10:59 +02:00
|
|
|
* @param array $expand values for keys 'c', 'row', 'c_', 'row_', 'cont'
|
2011-09-08 01:32:24 +02:00
|
|
|
*/
|
2014-10-01 21:10:59 +02:00
|
|
|
public function beforeSendToClient($cname, array $expand=null)
|
2011-09-08 01:32:24 +02:00
|
|
|
{
|
|
|
|
$attrs = $this->attrs;
|
2014-10-01 21:10:59 +02:00
|
|
|
$form_name = self::form_name($cname, $this->id, $expand);
|
2011-09-08 01:32:24 +02:00
|
|
|
$value =& self::get_array(self::$request->content, $form_name, true);
|
|
|
|
|
2013-06-19 20:11:30 +02:00
|
|
|
if($value && !is_array($value) && !$this->attrs['only_app'])
|
2011-09-08 01:32:24 +02:00
|
|
|
{
|
2011-09-14 02:06:04 +02:00
|
|
|
// Try to explode
|
2016-03-19 14:06:07 +01:00
|
|
|
if(count(explode(':',$value)) < 2)
|
|
|
|
{
|
|
|
|
throw new Api\Exception\WrongParameter("Wrong value sent to $this, needs to be an array. ".array2string($value));
|
2011-09-14 02:06:04 +02:00
|
|
|
}
|
2013-06-11 17:36:01 +02:00
|
|
|
list($app, $id) = explode(':', $value,2);
|
|
|
|
$value = array('app' => $app, 'id' => $id);
|
2011-09-08 01:32:24 +02:00
|
|
|
}
|
2011-09-09 18:46:55 +02:00
|
|
|
elseif (!$value)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2011-09-08 14:24:53 +02:00
|
|
|
|
2011-09-08 01:32:24 +02:00
|
|
|
|
2011-09-09 18:30:20 +02:00
|
|
|
// ToDo: implement on client-side
|
|
|
|
if (!$attrs['help']) self::setElementAttribute($form_name, 'help', 'view this linked entry in its application');
|
2011-09-08 01:32:24 +02:00
|
|
|
|
|
|
|
if($attrs['type'] == 'link-list') {
|
2013-06-19 20:11:30 +02:00
|
|
|
$app = $value['to_app'];
|
|
|
|
$id = $value['to_id'];
|
2016-03-19 14:06:07 +01:00
|
|
|
$links = Api\Link::get_links($app,$id,'','link_lastmod DESC',true, $value['show_deleted']);
|
2011-09-08 01:32:24 +02:00
|
|
|
foreach($links as $link) {
|
|
|
|
$value[] = $link;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find links that match the given parameters
|
|
|
|
*/
|
|
|
|
public static function ajax_link_search($app, $type, $pattern, $options=array()) {
|
|
|
|
$options['type'] = $type ? $type : $options['type'];
|
2014-09-08 21:15:01 +02:00
|
|
|
if(!$options['num_rows']) $options['num_rows'] = 1000;
|
2016-03-19 14:06:07 +01:00
|
|
|
$links = Api\Link::query($app, $pattern, $options);
|
2015-11-06 20:09:42 +01:00
|
|
|
$linksc = array_combine(array_map(create_function('$k', 'return (string)" ".$k;'), array_keys($links)), $links);
|
2016-03-20 14:02:55 +01:00
|
|
|
$response = Api\Json\Response::get();
|
2015-11-06 20:09:42 +01:00
|
|
|
$response->data($linksc);
|
2011-09-08 01:32:24 +02:00
|
|
|
}
|
|
|
|
|
2011-09-13 20:23:43 +02:00
|
|
|
/**
|
|
|
|
* Return title for a given app/id pair
|
|
|
|
*
|
|
|
|
* @param string $app
|
|
|
|
* @param string|int $id
|
|
|
|
* @return string|boolean string with title, boolean false of permission denied or null if not found
|
|
|
|
*/
|
|
|
|
public static function ajax_link_title($app,$id)
|
|
|
|
{
|
2016-03-19 14:06:07 +01:00
|
|
|
$title = Api\Link::title($app, $id);
|
2011-09-13 21:55:06 +02:00
|
|
|
//error_log(__METHOD__."('$app', '$id') = ".array2string($title));
|
2016-03-20 14:02:55 +01:00
|
|
|
Api\Json\Response::get()->data($title);
|
2011-09-13 20:23:43 +02:00
|
|
|
}
|
|
|
|
|
2011-09-13 21:55:06 +02:00
|
|
|
/**
|
|
|
|
* Return titles for all given app and id's
|
|
|
|
*
|
|
|
|
* @param array $app_ids array with app => array(id, ...) pairs
|
|
|
|
* @return array with app => id => title
|
|
|
|
*/
|
|
|
|
public static function ajax_link_titles(array $app_ids)
|
|
|
|
{
|
|
|
|
$response = array();
|
|
|
|
foreach($app_ids as $app => $ids)
|
|
|
|
{
|
2013-10-03 09:12:53 +02:00
|
|
|
if(count($ids))
|
|
|
|
{
|
2016-03-19 14:06:07 +01:00
|
|
|
$response[$app] = Api\Link::titles($app, $ids);
|
2013-10-03 09:12:53 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-10-10 12:49:41 +02:00
|
|
|
error_log(__METHOD__."(".array2string($app_ids).") got invalid title request: app=$app, ids=" . array2string($ids));
|
2013-10-03 09:12:53 +02:00
|
|
|
}
|
2011-09-13 21:55:06 +02:00
|
|
|
}
|
2016-03-20 14:02:55 +01:00
|
|
|
Api\Json\Response::get()->data($response);
|
2011-09-13 21:55:06 +02:00
|
|
|
}
|
|
|
|
|
2011-09-09 02:05:46 +02:00
|
|
|
/**
|
|
|
|
* Create links
|
|
|
|
*/
|
2016-03-19 14:06:07 +01:00
|
|
|
public static function ajax_link($app, $id, Array $links)
|
|
|
|
{
|
2011-09-09 02:05:46 +02:00
|
|
|
// Files need to know full path in tmp directory
|
2014-01-14 11:16:36 +01:00
|
|
|
foreach($links as $key => $link) {
|
2016-03-19 14:06:07 +01:00
|
|
|
if($link['app'] == Api\Link::VFS_APPNAME) {
|
2011-09-09 02:05:46 +02:00
|
|
|
if (is_dir($GLOBALS['egw_info']['server']['temp_dir']) && is_writable($GLOBALS['egw_info']['server']['temp_dir']))
|
2011-09-13 20:23:43 +02:00
|
|
|
{
|
|
|
|
$path = $GLOBALS['egw_info']['server']['temp_dir'] . '/' . $link['id'];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$path = $link['id'].'+';
|
|
|
|
}
|
2011-09-09 02:05:46 +02:00
|
|
|
$link['tmp_name'] = $path;
|
2014-01-14 11:16:36 +01:00
|
|
|
$links[$key]['id'] = $link;
|
2011-09-09 02:05:46 +02:00
|
|
|
}
|
|
|
|
}
|
2016-03-19 14:06:07 +01:00
|
|
|
$result = Api\Link::link($app, $id, $links);
|
2011-09-09 18:30:20 +02:00
|
|
|
|
2016-03-20 14:02:55 +01:00
|
|
|
$response = Api\Json\Response::get();
|
2013-10-10 19:00:30 +02:00
|
|
|
$response->data(is_array($id) ? $id : $result !== false);
|
2011-09-09 02:05:46 +02:00
|
|
|
}
|
|
|
|
|
2016-03-19 17:16:59 +01:00
|
|
|
public static function ajax_link_list($value)
|
2016-03-19 14:06:07 +01:00
|
|
|
{
|
2011-09-08 01:32:24 +02:00
|
|
|
$app = $value['to_app'];
|
|
|
|
$id = $value['to_id'];
|
|
|
|
|
2016-03-19 14:06:07 +01:00
|
|
|
$links = Api\Link::get_links($app,$id,$value['only_app'],'link_lastmod DESC',true, $value['show_deleted']);
|
2011-09-14 02:06:04 +02:00
|
|
|
foreach($links as &$link)
|
|
|
|
{
|
2016-03-19 14:06:07 +01:00
|
|
|
$link['title'] = Api\Link::title($link['app'],$link['id'],$link);
|
|
|
|
if ($link['app'] == Api\Link::VFS_APPNAME)
|
2011-09-14 02:06:04 +02:00
|
|
|
{
|
|
|
|
$link['target'] = '_blank';
|
|
|
|
$link['label'] = 'Delete';
|
|
|
|
$link['help'] = lang('Delete this file');
|
2016-03-19 14:06:07 +01:00
|
|
|
$link['title'] = Api\Vfs::decodePath($link['title']);
|
|
|
|
$link['icon'] = Api\Link::vfs_path($link['app2'],$link['id2'],$link['id'],true);
|
|
|
|
$link['download_url'] = Api\Vfs::download_url($link['icon']);
|
2015-08-26 19:08:37 +02:00
|
|
|
// Make links to directories load in filemanager
|
2016-03-19 14:06:07 +01:00
|
|
|
if($link['type'] == Api\Vfs::DIR_MIME_TYPE)
|
2015-08-26 19:08:37 +02:00
|
|
|
{
|
|
|
|
$link['target'] = 'filemanager';
|
|
|
|
}
|
2011-09-14 02:06:04 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-03-19 14:06:07 +01:00
|
|
|
$link['icon'] = Api\Link::get_registry($link['app'], 'icon');
|
2011-09-14 02:06:04 +02:00
|
|
|
$link['label'] = 'Unlink';
|
|
|
|
$link['help'] = lang('Remove this link (not the entry itself)');
|
|
|
|
}
|
|
|
|
}
|
2012-05-03 16:17:47 +02:00
|
|
|
|
2016-03-20 14:02:55 +01:00
|
|
|
$response = Api\Json\Response::get();
|
2011-09-14 02:06:04 +02:00
|
|
|
// Strip keys, unneeded and cause index problems on the client side
|
|
|
|
$response->data(array_values($links));
|
|
|
|
}
|
|
|
|
|
2012-06-19 20:59:53 +02:00
|
|
|
/**
|
|
|
|
* Allow changing of comment after link is created
|
|
|
|
*/
|
|
|
|
public static function ajax_link_comment($link_id, $comment)
|
|
|
|
{
|
|
|
|
$result = false;
|
|
|
|
if((int)$link_id > 0)
|
|
|
|
{
|
2016-03-19 14:06:07 +01:00
|
|
|
Api\Link::update_remark((int)$link_id, $comment);
|
2012-06-19 20:59:53 +02:00
|
|
|
$result = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-03-19 14:06:07 +01:00
|
|
|
$link = Api\Link::get_link((int)$link_id);
|
|
|
|
if($link && $link['app'] == Api\Link::VFS_APPNAME)
|
2012-06-19 20:59:53 +02:00
|
|
|
{
|
2016-03-19 14:06:07 +01:00
|
|
|
$files = Api\Link::list_attached($link['app2'],$link['id2']);
|
2015-11-06 20:09:42 +01:00
|
|
|
$file = $files[(int)$link_id];
|
2016-03-19 14:06:07 +01:00
|
|
|
$path = Api\Link::vfs_path($link['app2'],$link['id2'],$file['id']);
|
|
|
|
$result = Api\Vfs::proppatch($path, array(array('name' => 'comment', 'val' => $comment)));
|
2012-06-19 20:59:53 +02:00
|
|
|
}
|
|
|
|
}
|
2016-03-20 14:02:55 +01:00
|
|
|
$response = Api\Json\Response::get();
|
2012-06-19 20:59:53 +02:00
|
|
|
$response->data($result !== false);
|
|
|
|
}
|
|
|
|
|
2012-06-27 01:01:04 +02:00
|
|
|
/**
|
|
|
|
* Symlink an existing file in filemanager
|
|
|
|
*/
|
|
|
|
public static function link_existing($app_id, $files)
|
|
|
|
{
|
2015-09-08 18:02:18 +02:00
|
|
|
list($app, $id, $dest_file) = explode(':', $app_id);
|
|
|
|
if($id && $dest_file && trim($dest_file) !== '')
|
|
|
|
{
|
|
|
|
$id .= "/$dest_file";
|
|
|
|
}
|
2012-06-27 01:01:04 +02:00
|
|
|
|
|
|
|
if(!is_array($files)) $files = array($files);
|
2016-03-19 14:06:07 +01:00
|
|
|
foreach($files as $target)
|
|
|
|
{
|
|
|
|
Api\Link::link_file($app, $id, $target);
|
2012-06-27 01:01:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-19 17:16:59 +01:00
|
|
|
public static function ajax_delete($value)
|
2016-03-19 14:06:07 +01:00
|
|
|
{
|
2016-03-20 14:02:55 +01:00
|
|
|
$response = Api\Json\Response::get();
|
2016-03-19 14:06:07 +01:00
|
|
|
$response->data(Api\Link::unlink($value));
|
2011-09-08 01:32:24 +02:00
|
|
|
}
|
2012-04-16 23:52:31 +02:00
|
|
|
|
2014-07-08 18:51:01 +02:00
|
|
|
/**
|
|
|
|
* Download the files linked to the given entry as one ZIP.
|
|
|
|
*
|
|
|
|
* Because of the $public_functions entry, this is callable as a menuaction.
|
|
|
|
* This lets us just open the URL with app & id parametrs and get a ZIP. If
|
|
|
|
* the entry has no linked files, the ZIP will still be returned, but it will
|
|
|
|
* be empty.
|
|
|
|
*/
|
2016-03-19 17:16:59 +01:00
|
|
|
public static function download_zip()
|
2014-07-08 18:51:01 +02:00
|
|
|
{
|
|
|
|
$app = $_GET['app'];
|
|
|
|
$id = $_GET['id'];
|
2016-03-19 14:06:07 +01:00
|
|
|
if(Api\Link::file_access($app, $id))
|
2014-07-08 18:51:01 +02:00
|
|
|
{
|
2016-03-19 14:06:07 +01:00
|
|
|
$app_path = Api\Link::vfs_path($app,$id,'',true);
|
2014-10-01 21:10:59 +02:00
|
|
|
|
2014-07-08 18:51:01 +02:00
|
|
|
// Pass the files linked, not the entry path
|
2016-03-19 14:06:07 +01:00
|
|
|
$files = Api\Vfs::find($app_path);
|
2014-07-08 18:51:01 +02:00
|
|
|
if($files[0] == $app_path)
|
|
|
|
{
|
|
|
|
array_shift($files);
|
|
|
|
}
|
2016-03-19 14:06:07 +01:00
|
|
|
Api\Vfs::download_zip($files, Api\Link::title($app, $id));
|
2014-07-08 18:51:01 +02:00
|
|
|
common::egw_exit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-16 23:52:31 +02:00
|
|
|
/**
|
|
|
|
* Validate input
|
|
|
|
*
|
|
|
|
* Following attributes get checked:
|
|
|
|
* - needed: value must NOT be empty
|
|
|
|
* - min, max: int and float widget only
|
|
|
|
* - maxlength: maximum length of string (longer strings get truncated to allowed size)
|
|
|
|
* - preg: perl regular expression incl. delimiters (set by default for int, float and colorpicker)
|
|
|
|
* - int and float get casted to their type
|
|
|
|
*
|
|
|
|
* @param string $cname current namespace
|
2012-05-03 16:17:47 +02:00
|
|
|
* @param array $expand values for keys 'c', 'row', 'c_', 'row_', 'cont'
|
2012-04-16 23:52:31 +02:00
|
|
|
* @param array $content
|
|
|
|
* @param array &$validated=array() validated content
|
|
|
|
*/
|
2012-05-03 16:17:47 +02:00
|
|
|
public function validate($cname, array $expand, array $content, &$validated=array())
|
2012-04-16 23:52:31 +02:00
|
|
|
{
|
2012-05-03 16:17:47 +02:00
|
|
|
$form_name = self::form_name($cname, $this->id, $expand);
|
2012-04-16 23:52:31 +02:00
|
|
|
|
2012-05-03 16:17:47 +02:00
|
|
|
if (!$this->is_readonly($cname, $form_name))
|
|
|
|
{
|
2012-04-24 18:33:56 +02:00
|
|
|
$value = $value_in =& self::get_array($content, $form_name);
|
|
|
|
|
2016-03-19 14:06:07 +01:00
|
|
|
// keep values added into request by other ajax-functions, eg. files draged into htmlarea (Vfs)
|
2015-11-09 20:21:19 +01:00
|
|
|
if ((!$value || !$value['to_id']) && is_array($expand['cont'][$this->id]) && !empty($expand['cont'][$this->id]['to_id']))
|
2015-11-06 20:09:42 +01:00
|
|
|
{
|
|
|
|
$value['to_id'] = $expand['cont'][$this->id]['to_id'];
|
|
|
|
}
|
|
|
|
|
2014-02-25 18:04:43 +01:00
|
|
|
// Link widgets can share IDs, make sure to preserve values from others
|
|
|
|
$already = self::get_array($validated,$form_name);
|
|
|
|
if($already != null)
|
|
|
|
{
|
|
|
|
$value = array_merge($value,$already);
|
|
|
|
}
|
2014-02-24 21:26:26 +01:00
|
|
|
// Automatically do link if user selected entry but didn't click 'Link' button
|
|
|
|
$link = self::get_array($content, self::form_name($cname, $this->id . '_link_entry'));
|
2014-02-25 18:04:43 +01:00
|
|
|
if($this->type =='link-to' && is_array($link) && $link['app'] && $link['id'] )
|
2014-02-24 21:26:26 +01:00
|
|
|
{
|
2014-02-25 18:04:43 +01:00
|
|
|
// Do we have enough information to link automatically?
|
|
|
|
if(is_array($value) && $value['to_id'])
|
|
|
|
{
|
2016-03-19 14:06:07 +01:00
|
|
|
Api\Link::link($value['to_app'], $value['to_id'], $link['app'], $link['id']);
|
2014-02-25 18:04:43 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Not enough information, leave it to the application
|
|
|
|
if(!is_array($value['to_id'])) $value['to_id'] = array();
|
|
|
|
$value['to_id'][] = $link;
|
|
|
|
}
|
2014-02-24 21:26:26 +01:00
|
|
|
}
|
2014-03-27 15:30:14 +01:00
|
|
|
|
2014-02-25 18:04:43 +01:00
|
|
|
// Look for files - normally handled by ajax
|
2012-04-24 18:33:56 +02:00
|
|
|
$files = self::get_array($content, self::form_name($cname, $this->id . '_file'));
|
|
|
|
if(is_array($files) && !(is_array($value) && $value['to_id']))
|
|
|
|
{
|
|
|
|
$value = array();
|
|
|
|
if (is_dir($GLOBALS['egw_info']['server']['temp_dir']) && is_writable($GLOBALS['egw_info']['server']['temp_dir']))
|
|
|
|
{
|
|
|
|
$path = $GLOBALS['egw_info']['server']['temp_dir'] . '/';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$path = '';
|
|
|
|
}
|
|
|
|
foreach($files as $name => $attrs)
|
|
|
|
{
|
2014-02-25 18:04:43 +01:00
|
|
|
if(!is_array($value['to_id'])) $value['to_id'] = array();
|
2012-04-24 18:33:56 +02:00
|
|
|
$value['to_id'][] = array(
|
2016-03-19 14:06:07 +01:00
|
|
|
'app' => Api\Link::VFS_APPNAME,
|
2012-04-24 18:33:56 +02:00
|
|
|
'id' => array(
|
|
|
|
'name' => $attrs['name'],
|
|
|
|
'type' => $attrs['type'],
|
|
|
|
'tmp_name' => $path.$name
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2012-04-16 23:52:31 +02:00
|
|
|
$valid =& self::get_array($validated, $form_name, true);
|
2015-11-06 20:09:42 +01:00
|
|
|
if (true) $valid = $value;
|
2014-03-27 15:30:14 +01:00
|
|
|
//error_log($this);
|
|
|
|
//error_log(" " . array2string($valid));
|
2012-04-16 23:52:31 +02:00
|
|
|
}
|
|
|
|
}
|
2011-09-08 01:32:24 +02:00
|
|
|
}
|