2011-10-07 01:44:55 +02:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* EGroupware - eTemplate custom fields widget
|
|
|
|
*
|
|
|
|
* @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-10-07 01:44:55 +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;
|
|
|
|
|
2011-10-07 01:44:55 +02:00
|
|
|
/**
|
|
|
|
* Widgets for custom fields and listing custom fields
|
2021-03-31 17:49:43 +02:00
|
|
|
*
|
|
|
|
* @todo: fix the two undefined variables ($value and $field)
|
2011-10-07 01:44:55 +02:00
|
|
|
*/
|
2016-03-19 14:06:07 +01:00
|
|
|
class Customfields extends Transformer
|
2011-10-07 01:44:55 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Allowd types of customfields
|
|
|
|
*
|
|
|
|
* The additionally allowed app-names from the link-class, will be add by the edit-method only,
|
|
|
|
* as the link-class has to be called, which can NOT be instanciated by the constructor, as
|
|
|
|
* we get a loop in the instanciation.
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected static $cf_types = array(
|
|
|
|
'text' => 'Text',
|
2020-07-21 23:36:45 +02:00
|
|
|
'passwd' => 'Password',
|
2015-03-23 09:38:30 +01:00
|
|
|
'int' => 'Integer',
|
2011-10-07 01:44:55 +02:00
|
|
|
'float' => 'Float',
|
|
|
|
'label' => 'Label',
|
|
|
|
'select' => 'Selectbox',
|
|
|
|
'ajax_select' => 'Search',
|
|
|
|
'radio' => 'Radiobutton',
|
|
|
|
'checkbox' => 'Checkbox',
|
|
|
|
'date' => 'Date',
|
|
|
|
'date-time'=> 'Date+Time',
|
|
|
|
'select-account' => 'Select account',
|
|
|
|
'button' => 'Button', // button to execute javascript
|
|
|
|
'url' => 'Url',
|
2015-09-08 16:23:11 +02:00
|
|
|
'url-email'=> 'EMail',
|
2011-10-07 01:44:55 +02:00
|
|
|
'url-phone'=> 'Phone number',
|
|
|
|
'htmlarea' => 'Formatted Text (HTML)',
|
|
|
|
'link-entry' => 'Select entry', // should be last type, as the individual apps get added behind
|
|
|
|
);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var $prefix string Prefix for every custiomfield name returned in $content (# for general (admin) customfields)
|
|
|
|
*/
|
|
|
|
protected static $prefix = '#';
|
2012-05-03 16:17:47 +02:00
|
|
|
|
2012-03-23 00:36:31 +01:00
|
|
|
// Make settings available globally
|
2011-10-14 19:56:29 +02:00
|
|
|
const GLOBAL_VALS = '~custom_fields~';
|
2011-10-07 01:44:55 +02:00
|
|
|
|
2012-03-23 00:36:31 +01:00
|
|
|
// Used if there's no ID provided
|
|
|
|
const GLOBAL_ID = 'custom_fields';
|
|
|
|
|
2011-10-07 01:44:55 +02:00
|
|
|
protected $legacy_options = 'sub-type,use-private,field-names';
|
|
|
|
|
|
|
|
protected static $transformation = array(
|
|
|
|
'type' => array(
|
|
|
|
'customfields-types' => array(
|
|
|
|
'type' => 'select',
|
|
|
|
'sel_options' => array()
|
|
|
|
),
|
|
|
|
'customfields-list' => array(
|
|
|
|
'readonly' => true
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2012-04-24 21:46:24 +02:00
|
|
|
public function __construct($xml)
|
2011-10-07 01:44:55 +02:00
|
|
|
{
|
2020-12-17 17:17:38 +01:00
|
|
|
$this->attrs['prefix'] = self::$prefix;
|
2011-10-07 01:44:55 +02:00
|
|
|
parent::__construct($xml);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fill type options in self::$request->sel_options to be used on the client
|
|
|
|
*
|
|
|
|
* @param string $cname
|
2014-10-01 21:10:59 +02:00
|
|
|
* @param array $expand values for keys 'c', 'row', 'c_', 'row_', 'cont'
|
2011-10-07 01:44:55 +02:00
|
|
|
*/
|
2014-10-01 21:10:59 +02:00
|
|
|
public function beforeSendToClient($cname, array $expand=null)
|
2011-10-07 01:44:55 +02:00
|
|
|
{
|
2011-10-11 20:15:51 +02:00
|
|
|
// No name, no way to get parameters client-side.
|
2012-03-23 00:36:31 +01:00
|
|
|
if(!$this->id) $this->id = self::GLOBAL_ID;
|
2011-10-11 20:15:51 +02:00
|
|
|
|
2014-10-01 21:10:59 +02:00
|
|
|
$form_name = self::form_name($cname, $this->id, $expand);
|
2011-10-14 19:56:29 +02:00
|
|
|
|
|
|
|
// Store properties at top level, so all customfield widgets can share
|
2015-02-10 01:13:31 +01:00
|
|
|
if($this->attrs['app'])
|
2011-10-14 19:56:29 +02:00
|
|
|
{
|
2015-02-10 01:13:31 +01:00
|
|
|
$app = $this->attrs['app'];
|
|
|
|
}
|
|
|
|
else
|
2014-02-24 15:47:55 +01:00
|
|
|
{
|
2015-02-10 01:13:31 +01:00
|
|
|
$app =& $this->getElementAttribute(self::GLOBAL_VALS, 'app');
|
|
|
|
if($this->getElementAttribute($form_name, 'app'))
|
|
|
|
{
|
|
|
|
$app =& $this->getElementAttribute($form_name, 'app');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Checking creates it even if it wasn't there
|
|
|
|
unset(self::$request->modifications[$form_name]['app']);
|
|
|
|
}
|
2011-10-14 19:56:29 +02:00
|
|
|
}
|
2011-10-07 01:44:55 +02:00
|
|
|
|
2012-06-06 06:13:19 +02:00
|
|
|
if($this->getElementAttribute($form_name, 'customfields'))
|
|
|
|
{
|
|
|
|
$customfields =& $this->getElementAttribute($form_name, 'customfields');
|
|
|
|
}
|
|
|
|
elseif($app)
|
|
|
|
{
|
|
|
|
// Checking creates it even if it wasn't there
|
|
|
|
unset(self::$request->modifications[$form_name]['customfields']);
|
|
|
|
$customfields =& $this->getElementAttribute(self::GLOBAL_VALS, 'customfields');
|
|
|
|
}
|
|
|
|
|
2020-12-17 17:17:38 +01:00
|
|
|
if(!$app && !$customfields)
|
2011-10-07 01:44:55 +02:00
|
|
|
{
|
2021-03-31 17:49:43 +02:00
|
|
|
$app =& self::setElementAttribute(self::GLOBAL_VALS, 'app', $GLOBALS['egw_info']['flags']['currentapp']);
|
2017-06-07 17:54:09 +02:00
|
|
|
if ($this->attrs['sub-app']) $app .= '-'.$this->attrs['sub-app'];
|
2021-03-31 17:49:43 +02:00
|
|
|
$customfields =& self::setElementAttribute(self::GLOBAL_VALS, 'customfields', Api\Storage\Customfields::get($app));
|
2011-10-07 01:44:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// if we are in the etemplate editor or the app has no cf's, load the cf's from the app the tpl belongs too
|
2016-03-21 22:21:40 +01:00
|
|
|
if ($app && $app != 'stylite' && $app != $GLOBALS['egw_info']['flags']['currentapp'] && !isset($customfields) &&
|
|
|
|
($GLOBALS['egw_info']['flags']['currentapp'] == 'etemplate' || !$this->attrs['customfields']) || !isset($customfields))
|
2011-10-07 01:44:55 +02:00
|
|
|
{
|
|
|
|
// app changed
|
2021-03-31 17:49:43 +02:00
|
|
|
$customfields = Api\Storage\Customfields::get($app);
|
2011-10-07 01:44:55 +02:00
|
|
|
}
|
2020-12-17 17:17:38 +01:00
|
|
|
if($this->attrs['customfields'])
|
|
|
|
{
|
|
|
|
$customfields = $this->attrs['customfields'];
|
|
|
|
}
|
2011-10-07 01:44:55 +02:00
|
|
|
// Filter fields
|
2013-11-27 18:17:37 +01:00
|
|
|
if($this->attrs['field-names'])
|
|
|
|
{
|
2015-03-27 17:32:51 +01:00
|
|
|
$fields_name = explode(',', $this->attrs['field-names']);
|
|
|
|
foreach($fields_name as &$f)
|
2014-02-24 15:47:55 +01:00
|
|
|
{
|
2015-03-27 17:32:51 +01:00
|
|
|
if ($f[0] == "!")
|
|
|
|
{
|
|
|
|
$f= substr($f,1);
|
|
|
|
$negate_fields[]= $f;
|
|
|
|
}
|
|
|
|
$field_filters []= $f;
|
2014-02-24 15:47:55 +01:00
|
|
|
}
|
2013-11-27 18:17:37 +01:00
|
|
|
}
|
2015-05-28 13:29:43 +02:00
|
|
|
|
2011-10-07 01:44:55 +02:00
|
|
|
$fields = $customfields;
|
2013-08-20 13:57:44 +02:00
|
|
|
|
2013-11-27 18:17:37 +01:00
|
|
|
$use_private = self::expand_name($this->attrs['use-private'],0,0,'','',self::$cont);
|
|
|
|
$this->attrs['sub-type'] = self::expand_name($this->attrs['sub-type'],0,0,'','',self::$cont);
|
|
|
|
|
2011-10-07 01:44:55 +02:00
|
|
|
foreach((array)$fields as $key => $field)
|
|
|
|
{
|
|
|
|
// remove private or non-private cf's, if only one kind should be displayed
|
2013-11-28 19:32:36 +01:00
|
|
|
if ((string)$use_private !== '' && (boolean)$field['private'] != (boolean)$use_private)
|
2011-10-07 01:44:55 +02:00
|
|
|
{
|
|
|
|
unset($fields[$key]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove filtered fields
|
2015-03-27 17:32:51 +01:00
|
|
|
if($field_filters && in_array($key, $negate_fields) && in_array($key, $field_filters))
|
2011-10-07 01:44:55 +02:00
|
|
|
{
|
|
|
|
unset($fields[$key]);
|
|
|
|
}
|
2017-10-06 16:27:37 +02:00
|
|
|
|
|
|
|
// Rmove fields for none private cutomfields when name refers to a single custom field
|
|
|
|
$matches = null;
|
2020-12-17 17:17:38 +01:00
|
|
|
if (($pos=strpos($form_name,$this->attrs['prefix'])) !== false &&
|
|
|
|
preg_match($preg = '/'.$this->attrs['prefix'].'([^\]]+)/',$form_name,$matches) && !isset($fields[$name=$matches[1]]))
|
2017-10-06 16:27:37 +02:00
|
|
|
{
|
|
|
|
unset($fields[$key]);
|
|
|
|
}
|
2011-10-07 01:44:55 +02:00
|
|
|
}
|
|
|
|
// check if name refers to a single custom field --> show only that
|
2014-02-24 15:47:55 +01:00
|
|
|
$matches = null;
|
2020-12-17 17:17:38 +01:00
|
|
|
if (($pos=strpos($form_name,$this->attrs['prefix'])) !== false && // allow the prefixed name to be an array index too
|
|
|
|
preg_match($preg = '/'.$this->attrs['prefix'].'([^\]]+)/',$form_name,$matches) && isset($fields[$name=$matches[1]]))
|
2011-10-07 01:44:55 +02:00
|
|
|
{
|
|
|
|
$fields = array($name => $fields[$name]);
|
2020-12-17 17:17:38 +01:00
|
|
|
$value = array($this->attrs['prefix'].$name => $value);
|
|
|
|
$form_name = $this->attrs['prefix'].$name;
|
2011-10-07 01:44:55 +02:00
|
|
|
}
|
|
|
|
|
2012-03-12 23:29:51 +01:00
|
|
|
if(!is_array($fields)) $fields = array();
|
2011-10-07 01:44:55 +02:00
|
|
|
switch($type = $this->type)
|
|
|
|
{
|
|
|
|
case 'customfields-types':
|
|
|
|
foreach(self::$cf_types as $lname => $label)
|
|
|
|
{
|
|
|
|
$sel_options[$lname] = lang($label);
|
|
|
|
$fields_with_vals[]=$lname;
|
|
|
|
}
|
2016-03-19 14:06:07 +01:00
|
|
|
$link_types = array_intersect_key(Api\Link::app_list('query'), Api\Link::app_list('title'));
|
2015-10-05 17:50:30 +02:00
|
|
|
// Explicitly add in filemanager, which does not support query or title
|
|
|
|
$link_types['filemanager'] = lang('filemanager');
|
|
|
|
|
2011-10-07 01:44:55 +02:00
|
|
|
ksort($link_types);
|
2014-02-24 15:47:55 +01:00
|
|
|
foreach($link_types as $lname => $label)
|
|
|
|
{
|
|
|
|
$sel_options[$lname] = '- '.$label;
|
|
|
|
}
|
2011-10-07 01:44:55 +02:00
|
|
|
self::$transformation['type'][$type]['sel_options'] = $sel_options;
|
|
|
|
self::$transformation['type'][$type]['no_lang'] = true;
|
2014-10-01 21:10:59 +02:00
|
|
|
return parent::beforeSendToClient($cname, $expand);
|
2011-10-07 01:44:55 +02:00
|
|
|
case 'customfields-list':
|
|
|
|
foreach(array_reverse($fields) as $lname => $field)
|
|
|
|
{
|
2014-02-24 15:47:55 +01:00
|
|
|
if (!empty($this->attrs['sub-type']) && !empty($field['type2']) &&
|
|
|
|
strpos(','.$field['type2'].',',','.$field['type2'].',') === false) continue; // not for our content type//
|
2020-12-17 17:17:38 +01:00
|
|
|
if (isset($value[$this->attrs['prefix'].$lname]) && $value[$this->attrs['prefix'].$lname] !== '') //break;
|
2011-10-07 01:44:55 +02:00
|
|
|
{
|
|
|
|
$fields_with_vals[]=$lname;
|
|
|
|
}
|
|
|
|
//$stop_at_field = $name;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
foreach(array_reverse($fields) as $lname => $field)
|
|
|
|
{
|
|
|
|
$fields_with_vals[]=$lname;
|
|
|
|
}
|
|
|
|
}
|
2015-01-12 15:10:40 +01:00
|
|
|
// need to encode values/select-options to keep their order
|
|
|
|
foreach($customfields as &$data)
|
|
|
|
{
|
|
|
|
if (!empty($data['values']))
|
|
|
|
{
|
2016-03-19 14:06:07 +01:00
|
|
|
Select::fix_encoded_options($data['values']);
|
2015-01-12 15:10:40 +01:00
|
|
|
}
|
|
|
|
}
|
2011-10-14 19:56:29 +02:00
|
|
|
if($fields != $customfields)
|
|
|
|
{
|
|
|
|
// This widget has different settings from global
|
2021-03-31 17:49:43 +02:00
|
|
|
self::setElementAttribute($form_name, 'customfields', $fields);
|
|
|
|
self::setElementAttribute($form_name, 'fields', array_merge(
|
2013-03-20 21:47:54 +01:00
|
|
|
array_fill_keys(array_keys($customfields), false),
|
|
|
|
array_fill_keys(array_keys($fields), true)
|
|
|
|
));
|
2011-10-14 19:56:29 +02:00
|
|
|
}
|
2014-10-01 21:10:59 +02:00
|
|
|
parent::beforeSendToClient($cname, $expand);
|
2012-03-22 17:34:45 +01:00
|
|
|
|
|
|
|
// Re-format date custom fields from Y-m-d
|
2012-06-06 06:13:19 +02:00
|
|
|
$field_settings =& self::get_array(self::$request->modifications, "{$this->id}[customfields]",true);
|
2014-02-24 15:47:55 +01:00
|
|
|
if (true) $field_settings = array();
|
2016-03-19 14:06:07 +01:00
|
|
|
$link_types = Api\Link::app_list();
|
2012-03-22 17:34:45 +01:00
|
|
|
foreach($fields as $fname => $field)
|
|
|
|
{
|
2012-06-06 06:13:19 +02:00
|
|
|
// Run beforeSendToClient for each field
|
2014-02-24 15:47:55 +01:00
|
|
|
$widget = $this->_widget($fname, $field);
|
2012-06-06 06:13:19 +02:00
|
|
|
if(method_exists($widget, 'beforeSendToClient'))
|
|
|
|
{
|
2014-10-01 21:10:59 +02:00
|
|
|
$widget->beforeSendToClient($this->id == self::GLOBAL_ID ? '' : $this->id, $expand);
|
2014-02-24 15:47:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Instanciate (server-side) widget used to implement custom-field, to run its beforeSendToClient or validate method
|
|
|
|
*
|
|
|
|
* @param string $fname custom field name
|
|
|
|
* @param array $field custom field data
|
2016-03-19 14:06:07 +01:00
|
|
|
* @return Etemplate\Widget
|
2014-02-24 15:47:55 +01:00
|
|
|
*/
|
|
|
|
protected function _widget($fname, array $field)
|
|
|
|
{
|
|
|
|
static $link_types = null;
|
2016-03-19 14:06:07 +01:00
|
|
|
if (!isset($link_types)) $link_types = Api\Link::app_list ();
|
2014-02-24 15:47:55 +01:00
|
|
|
|
|
|
|
$type = $field['type'];
|
|
|
|
// Link-tos needs to change from appname to link-to
|
|
|
|
if($link_types[$field['type']])
|
|
|
|
{
|
2015-09-02 21:52:47 +02:00
|
|
|
if($type == 'filemanager')
|
|
|
|
{
|
|
|
|
$type = 'vfs-upload';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$type = 'link-to';
|
|
|
|
}
|
2014-02-24 15:47:55 +01:00
|
|
|
}
|
2016-11-07 17:22:33 +01:00
|
|
|
$xml = '<'.$type.' type="'.$type.'" id="'.self::$prefix.$fname.'"/>';
|
|
|
|
$widget = self::factory($type, $xml, self::$prefix.$fname);
|
2014-02-24 15:47:55 +01:00
|
|
|
$widget->id = self::$prefix.$fname;
|
|
|
|
$widget->attrs['type'] = $type;
|
2016-11-07 17:22:33 +01:00
|
|
|
$widget->set_attrs($xml);
|
2017-06-07 17:54:09 +02:00
|
|
|
|
2014-02-24 15:47:55 +01:00
|
|
|
// some type-specific (default) attributes
|
|
|
|
switch($type)
|
|
|
|
{
|
|
|
|
case 'date':
|
|
|
|
case 'date-time':
|
2017-11-10 17:30:20 +01:00
|
|
|
if (!empty($field['values']['format']))
|
|
|
|
{
|
2019-03-18 16:04:45 +01:00
|
|
|
$widget->attrs['data_format'] = $field['values']['format'];
|
2017-11-10 17:30:20 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-03-18 16:04:45 +01:00
|
|
|
$widget->attrs['data_format'] = $type == 'date' ? 'Y-m-d' : 'Y-m-d H:i:s';
|
2017-11-10 17:30:20 +01:00
|
|
|
}
|
2015-04-21 21:46:33 +02:00
|
|
|
if($field['values']['min']) $widget->attrs['min'] = $field['values']['min'];
|
|
|
|
if($field['values']['max']) $widget->attrs['min'] = $field['values']['max'];
|
2014-02-24 15:47:55 +01:00
|
|
|
break;
|
|
|
|
|
2015-09-02 21:52:47 +02:00
|
|
|
case 'vfs-upload':
|
|
|
|
$widget->attrs['path'] = $field['app'] . ':' .
|
2016-03-19 14:06:07 +01:00
|
|
|
self::expand_name('$cont['.Api\Link::get_registry($field['app'],'view_id').']',0,0,0,0,self::$request->content).
|
2015-09-02 21:52:47 +02:00
|
|
|
':'.$field['label'];
|
|
|
|
break;
|
2016-03-19 14:06:07 +01:00
|
|
|
|
2014-02-24 15:47:55 +01:00
|
|
|
case 'link-to':
|
|
|
|
$widget->attrs['only_app'] = $field['type'];
|
|
|
|
break;
|
|
|
|
|
2014-09-09 10:36:34 +02:00
|
|
|
case 'text':
|
|
|
|
break;
|
2020-06-12 18:56:44 +02:00
|
|
|
case 'passwd':
|
2020-07-21 23:36:45 +02:00
|
|
|
// Defaults for a customfield are different than a regular password field
|
|
|
|
$defaults = Array(
|
|
|
|
'viewable' => true,
|
|
|
|
'plaintext' => false,
|
|
|
|
'suggest' => 16
|
|
|
|
);
|
|
|
|
foreach($defaults as $f => $d_value)
|
|
|
|
{
|
2020-10-13 23:20:33 +02:00
|
|
|
$widget->attrs[$f] = is_array($field['values']) && array_key_exists($f, $field['values']) ? $field['values'][$f] : $d_value;
|
2020-07-21 23:36:45 +02:00
|
|
|
}
|
2020-06-12 18:56:44 +02:00
|
|
|
break;
|
2014-09-09 10:36:34 +02:00
|
|
|
|
|
|
|
default:
|
2015-04-21 18:47:33 +02:00
|
|
|
if (substr($type, 0, 7) !== 'select-' && $type != 'ajax_select') break;
|
2014-09-09 10:36:34 +02:00
|
|
|
// fall-through for all select-* widgets
|
2014-02-24 15:47:55 +01:00
|
|
|
case 'select':
|
2018-02-28 13:41:13 +01:00
|
|
|
$widget->attrs['multiple'] = $field['rows'] > 1;
|
2014-02-24 15:47:55 +01:00
|
|
|
// fall through
|
|
|
|
case 'radio':
|
2018-04-09 16:02:00 +02:00
|
|
|
if (!empty($field['values']) && count($field['values']) == 1 && isset($field['values']['@']))
|
2013-06-19 20:11:30 +02:00
|
|
|
{
|
2016-03-19 14:06:07 +01:00
|
|
|
$field['values'] = Api\Storage\Customfields::get_options_from_file($field['values']['@']);
|
2013-06-19 20:11:30 +02:00
|
|
|
}
|
2014-09-09 10:36:34 +02:00
|
|
|
// keep extra values set by app code, eg. addressbook advanced search
|
|
|
|
if (is_array(self::$request->sel_options[self::$prefix.$fname]))
|
|
|
|
{
|
|
|
|
self::$request->sel_options[self::$prefix.$fname] += (array)$field['values'];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
self::$request->sel_options[self::$prefix.$fname] = $field['values'];
|
|
|
|
}
|
2014-02-24 15:47:55 +01:00
|
|
|
//error_log(__METHOD__."('$fname', ".array2string($field).") request->sel_options['".self::$prefix.$fname."']=".array2string(self::$request->sel_options[$this->id]));
|
2015-05-28 13:29:43 +02:00
|
|
|
// to keep order of numeric values, we have to explicit run fix_encoded_options, as sel_options are already encoded
|
|
|
|
$options = self::$request->sel_options[self::$prefix.$fname];
|
|
|
|
if (is_array($options))
|
|
|
|
{
|
2016-03-19 14:06:07 +01:00
|
|
|
Select::fix_encoded_options($options);
|
2015-05-28 13:29:43 +02:00
|
|
|
self::$request->sel_options[self::$prefix.$fname] = $options;
|
|
|
|
}
|
2014-02-24 15:47:55 +01:00
|
|
|
break;
|
2012-03-22 17:34:45 +01:00
|
|
|
}
|
2014-02-24 15:47:55 +01:00
|
|
|
return $widget;
|
2011-10-07 01:44:55 +02:00
|
|
|
}
|
2012-03-23 00:36:31 +01: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-03-23 00:36:31 +01: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-03-23 00:36:31 +01:00
|
|
|
{
|
2012-05-03 16:17:47 +02:00
|
|
|
if ($this->id)
|
2012-03-23 00:36:31 +01:00
|
|
|
{
|
2012-05-03 16:17:47 +02:00
|
|
|
$form_name = self::form_name($cname, $this->id, $expand);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$form_name = self::GLOBAL_ID;
|
|
|
|
}
|
2012-03-23 00:36:31 +01:00
|
|
|
|
2015-07-27 18:52:55 +02:00
|
|
|
$all_readonly = $this->is_readonly($cname, $form_name);
|
|
|
|
$value_in = self::get_array($content, $form_name);
|
|
|
|
// if we have no id / use self::GLOBAL_ID, we have to set $value_in in global namespace for regular widgets validation to find
|
|
|
|
if (!$this->id) $content = array_merge($content, $value_in);
|
|
|
|
//error_log(__METHOD__."($cname, ...) form_name=$form_name, use-private={$this->attrs['use-private']}, value_in=".array2string($value_in));
|
2020-12-17 17:17:38 +01:00
|
|
|
if($this->getElementAttribute($form_name, 'customfields'))
|
|
|
|
{
|
|
|
|
$customfields =& $this->getElementAttribute($form_name, 'customfields');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$customfields =& $this->getElementAttribute(self::GLOBAL_VALS, 'customfields');
|
|
|
|
}
|
2015-07-27 18:52:55 +02:00
|
|
|
if(is_array($value_in))
|
2012-05-03 16:17:47 +02:00
|
|
|
{
|
2018-02-28 13:41:13 +01:00
|
|
|
foreach(array_keys($value_in) as $field)
|
2012-05-03 16:17:47 +02:00
|
|
|
{
|
2020-12-17 18:07:34 +01:00
|
|
|
$field_settings = $customfields[$fname=substr($field,strlen($this->attrs['prefix']))];
|
2014-06-02 15:29:26 +02:00
|
|
|
|
2015-07-27 18:52:55 +02:00
|
|
|
if ((string)$this->attrs['use-private'] !== '' && // are only (non-)private fields requested
|
|
|
|
(boolean)$field_settings['private'] != ($this->attrs['use-private'] != '0'))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2012-05-03 16:17:47 +02:00
|
|
|
|
2015-07-27 18:52:55 +02:00
|
|
|
// check if single field is set readonly, used in apps as it was only way to make cfs readonly in old eT
|
|
|
|
// single fields set to false in $readonly overwrite a global __ALL__
|
|
|
|
$cf_readonly = $this->is_readonly($form_name != self::GLOBAL_ID ? $form_name : $cname, $field);
|
|
|
|
if ($cf_readonly || $all_readonly && $cf_readonly !== false)
|
|
|
|
{
|
|
|
|
continue;
|
2012-03-23 00:36:31 +01:00
|
|
|
}
|
2015-07-27 18:52:55 +02:00
|
|
|
// run validation method of widget implementing this custom field
|
|
|
|
$widget = $this->_widget($fname, $field_settings);
|
|
|
|
// widget has no validate method, eg. is only displaying stuff --> nothing to validate
|
|
|
|
if (!method_exists($widget, 'validate')) continue;
|
|
|
|
$widget->validate($form_name != self::GLOBAL_ID ? $form_name : $cname, $expand, $content, $validated);
|
2020-12-17 18:07:34 +01:00
|
|
|
$field_name = $this->id[0] == self::$prefix && $customfields[substr($this->id,strlen($this->attrs['prefix']))] ? $this->id : self::form_name($form_name != self::GLOBAL_ID ? $form_name : $cname, $field);
|
2015-07-27 18:52:55 +02:00
|
|
|
$valid =& self::get_array($validated, $field_name, true);
|
|
|
|
|
2017-04-10 18:39:04 +02:00
|
|
|
// Arrays are not valid, but leave filemanager alone, we'll catch it
|
|
|
|
// when saving. This allows files for new entries.
|
|
|
|
if (is_array($valid) && $field_settings['type'] !== 'filemanager') $valid = implode(',', $valid);
|
2017-06-07 17:54:09 +02:00
|
|
|
|
2015-07-27 18:52:55 +02:00
|
|
|
// NULL is valid for most fields, but not custom fields due to backend handling
|
|
|
|
// See so_sql_cf->save()
|
|
|
|
if (is_null($valid)) $valid = false;
|
|
|
|
//error_log(__METHOD__."() $field_name: ".array2string($value).' --> '.array2string($valid));
|
2014-05-16 11:29:10 +02:00
|
|
|
}
|
2015-07-27 18:52:55 +02:00
|
|
|
}
|
|
|
|
elseif ($this->type == 'customfields-types')
|
|
|
|
{
|
|
|
|
// Transformation doesn't handle validation
|
|
|
|
$valid =& self::get_array($validated, $this->id ? $form_name : $field, true);
|
|
|
|
if (true) $valid = $value_in;
|
|
|
|
//error_log(__METHOD__."() $form_name $field: ".array2string($value).' --> '.array2string($value));
|
2012-03-23 00:36:31 +01:00
|
|
|
}
|
|
|
|
}
|
2011-10-07 01:44:55 +02:00
|
|
|
}
|