diff --git a/addressbook/inc/class.addressbook_groupdav.inc.php b/addressbook/inc/class.addressbook_groupdav.inc.php
index 56146fc509..95a7d5ad86 100644
--- a/addressbook/inc/class.addressbook_groupdav.inc.php
+++ b/addressbook/inc/class.addressbook_groupdav.inc.php
@@ -696,10 +696,16 @@ class addressbook_groupdav extends Api\CalDAV\Handler
{
trim($attribute);
list($key, $value) = explode('=', $attribute);
+ // check if value is enclosed in quotes
+ if (in_array($value[0], ['"', "'"], true) && $value[0] === substr($value, -1))
+ {
+ $value = substr($value,1,-1);
+ }
switch (strtolower($key))
{
case 'charset':
- $charset = strtoupper(substr($value,1,-1));
+ $charset = strtoupper($value);
+ break;
}
}
}
diff --git a/addressbook/inc/class.addressbook_hooks.inc.php b/addressbook/inc/class.addressbook_hooks.inc.php
index 9a514656a6..9a59821007 100644
--- a/addressbook/inc/class.addressbook_hooks.inc.php
+++ b/addressbook/inc/class.addressbook_hooks.inc.php
@@ -291,41 +291,8 @@ class addressbook_hooks
if ($GLOBALS['egw_info']['user']['apps']['filemanager'])
{
- $settings['default_document'] = array(
- 'type' => 'vfs_file',
- 'size' => 60,
- 'label' => 'Default document to insert contacts',
- 'name' => 'default_document',
- 'help' => lang('If you specify a document (full vfs path) here, %1 displays an extra document icon for each entry. That icon allows to download the specified document with the data inserted.', lang('addressbook')).' '.
- lang('The document can contain placeholder like {{%1}}, to be replaced with the data.','n_fn').' '.
- lang('The following document-types are supported:'). implode(',',Api\Storage\Merge::get_file_extensions()),
- 'run_lang' => false,
- 'xmlrpc' => True,
- 'admin' => False,
- );
- $settings['document_dir'] = array(
- 'type' => 'vfs_dirs',
- 'size' => 60,
- 'label' => 'Directory with documents to insert contacts',
- 'name' => 'document_dir',
- 'help' => lang('If you specify a directory (full vfs path) here, %1 displays an action for each document. That action allows to download the specified document with the data inserted.', lang('addressbook')) . ' ' .
- lang('The document can contain placeholder like {{%1}}, to be replaced with the data.', 'n_fn') . ' ' .
- lang('The following document-types are supported:') . implode(',', Api\Storage\Merge::get_file_extensions()),
- 'run_lang' => false,
- 'xmlrpc' => True,
- 'admin' => False,
- 'default' => '/templates/addressbook',
- );
- $settings[Api\Storage\Merge::PREF_DOCUMENT_FILENAME] = array(
- 'type' => 'taglist',
- 'label' => 'Document download filename',
- 'name' => 'document_download_name',
- 'values' => Api\Storage\Merge::DOCUMENT_FILENAME_OPTIONS,
- 'help' => 'Choose the default filename for downloaded documents.',
- 'xmlrpc' => True,
- 'admin' => False,
- 'default' => 'document',
- );
+ $merge = new Api\Contacts\Merge();
+ $settings += $merge->merge_preferences();
}
if ($GLOBALS['egw_info']['user']['apps']['felamimail'] || $GLOBALS['egw_info']['user']['apps']['mail'])
diff --git a/admin/inc/class.admin_acl.inc.php b/admin/inc/class.admin_acl.inc.php
index ba1652f06f..b66175563b 100644
--- a/admin/inc/class.admin_acl.inc.php
+++ b/admin/inc/class.admin_acl.inc.php
@@ -273,7 +273,7 @@ class admin_acl
{
$rows['sel_options']['filter2'][] = array(
'value' => $appname,
- 'label' => lang(Api\Link::get_registry($appname, 'entries')) ?? lang($appname)
+ 'label' => lang(Api\Link::get_registry($appname, 'entries') ?: $appname)
);
}
usort($rows['sel_options']['filter2'], function($a,$b) {
diff --git a/admin/inc/class.admin_cmd_category.inc.php b/admin/inc/class.admin_cmd_category.inc.php
index 7059cde539..a5b88fb0e8 100644
--- a/admin/inc/class.admin_cmd_category.inc.php
+++ b/admin/inc/class.admin_cmd_category.inc.php
@@ -87,7 +87,7 @@ class admin_cmd_category extends admin_cmd
unset($set['old_parent'], $set['base_url'], $set['last_mod'], $set['all_cats'], $set['no_private']);
foreach($set as $key => $value)
{
- if(array_key_exists($key, $old) && $old[$key] == $value)
+ if ($old && array_key_exists($key, $old) && $old[$key] == $value)
{
unset($set[$key]);
unset($old[$key]);
diff --git a/admin/inc/class.admin_customfields.inc.php b/admin/inc/class.admin_customfields.inc.php
index c285bbf1d5..dc86bd89de 100644
--- a/admin/inc/class.admin_customfields.inc.php
+++ b/admin/inc/class.admin_customfields.inc.php
@@ -128,10 +128,10 @@ class admin_customfields
public function index($content = array())
{
// determine appname
- $this->appname = $this->appname ? $this->appname : ($_GET['appname'] ? $_GET['appname'] : ($content['appname'] ? $content['appname'] : false));
+ $this->appname = $this->appname ?: (!empty($_GET['appname']) ? $_GET['appname'] : (!empty($content['appname']) ? $content['appname'] : false));
if(!$this->appname) die(lang('Error! No appname found'));
- $this->use_private = !isset($_GET['use_private']) || (boolean)$_GET['use_private'] || $content['use_private'];
+ $this->use_private = !empty($_GET['use_private']) && $_GET['use_private'] !== 'undefined' || !empty($content['use_private']);
// Read fields, constructor doesn't always know appname
$this->fields = Api\Storage\Customfields::get($this->appname,true);
@@ -323,10 +323,10 @@ class admin_customfields
*/
function edit($content = null)
{
- $cf_id = $_GET['cf_id'] ? (int)$_GET['cf_id'] : (int)$content['cf_id'];
+ $cf_id = isset($_GET['cf_id']) ? (int)$_GET['cf_id'] : (int)$content['cf_id'];
// determine appname
- $this->appname = $this->appname ? $this->appname : ($_GET['appname'] ? $_GET['appname'] : ($content['cf_app'] ? $content['cf_app'] : false));
+ $this->appname = $this->appname ?: (isset($_GET['appname']) ? $_GET['appname'] : (!empty($content['cf_app']) ? $content['cf_app'] : false));
if(!$this->appname)
{
if($cf_id && $this->so)
@@ -339,7 +339,7 @@ class admin_customfields
{
die(lang('Error! No appname found'));
}
- $this->use_private = !isset($_GET['use_private']) || (boolean)$_GET['use_private'] || $content['use_private'];
+ $this->use_private = !isset($_GET['use_private']) || (boolean)$_GET['use_private'] || !empty($content['use_private']);
// Read fields, constructor doesn't always know appname
$this->fields = Api\Storage\Customfields::get($this->appname,true);
@@ -347,7 +347,7 @@ class admin_customfields
// Update based on info returned from template
if (is_array($content))
{
- $action = @key($content['button']);
+ $action = key($content['button'] ?? []);
switch($action)
{
case 'delete':
@@ -422,7 +422,7 @@ class admin_customfields
}
else
{
- $content['use_private'] = !isset($_GET['use_private']) || (boolean)$_GET['use_private'];
+ $content['use_private'] = !empty($_GET['use_private']) && $_GET['use_private'] !== 'undefined';
}
@@ -474,11 +474,11 @@ class admin_customfields
// Show sub-type row, and get types
if($this->manage_content_types)
{
- if(count($this->content_types) == 0)
+ if(empty($this->content_types))
{
$this->content_types = Api\Config::get_content_types($this->appname);
}
- if (count($this->content_types)==0)
+ if (empty($this->content_types))
{
// if you define your default types of your app with the search_link hook, they are available here, if no types were found
$this->content_types = (array)Api\Link::get_registry($this->appname, 'default_types');
@@ -592,7 +592,7 @@ class admin_customfields
*/
function create_field(&$content)
{
- $new_name = trim($content['fields'][count($content['fields'])-1]['name']);
+ $new_name = trim($content['fields'][count((array)$content['fields'])-1]['name']);
if (empty($new_name) || isset($this->fields[$new_name]))
{
$content['error_msg'] .= empty($new_name) ?
@@ -601,7 +601,7 @@ class admin_customfields
}
else
{
- $this->fields[$new_name] = $content['fields'][count($content['fields'])-1];
+ $this->fields[$new_name] = $content['fields'][count((array)$content['fields'])-1];
if(!$this->fields[$new_name]['label']) $this->fields[$new_name]['label'] = $this->fields[$new_name]['name'];
$this->save_repository();
}
diff --git a/admin/inc/class.admin_mail.inc.php b/admin/inc/class.admin_mail.inc.php
index f8539e40f5..db74bc11db 100644
--- a/admin/inc/class.admin_mail.inc.php
+++ b/admin/inc/class.admin_mail.inc.php
@@ -1258,7 +1258,7 @@ class admin_mail
if ($content['ident_id'] != $content['old_ident_id'] &&
($content['old_ident_id'] || $content['ident_id'] != $content['std_ident_id']))
{
- if ($content['ident_id'] > 0)
+ if ((int)$content['ident_id'] > 0)
{
$identity = Mail\Account::read_identity($content['ident_id'], false, $content['called_for']);
unset($identity['account_id']);
@@ -1285,7 +1285,7 @@ class admin_mail
{
$sel_options['ident_email_alias'] = array_merge(
array('' => $content['mailLocalAddress'].' ('.lang('Default').')'),
- array_combine($content['mailAlternateAddress'], $content['mailAlternateAddress']));
+ array_combine($content['mailAlternateAddress'] ?? [], $content['mailAlternateAddress'] ?? []));
// if admin explicitly set a non-alias, we need to add it to aliases to keep it after storing signature by user
if ($content['ident_email'] !== $content['mailLocalAddress'] && !isset($sel_options['ident_email_alias'][$content['ident_email']]))
{
diff --git a/admin/templates/default/categories.edit.xet b/admin/templates/default/categories.edit.xet
index a1ed1c4538..96120b6b2d 100644
--- a/admin/templates/default/categories.edit.xet
+++ b/admin/templates/default/categories.edit.xet
@@ -44,7 +44,7 @@
-
+
diff --git a/api/js/etemplate/et2_widget_placeholder.ts b/api/js/etemplate/et2_widget_placeholder.ts
index bdbef7b34a..e82b54b1c1 100644
--- a/api/js/etemplate/et2_widget_placeholder.ts
+++ b/api/js/etemplate/et2_widget_placeholder.ts
@@ -227,8 +227,9 @@ export class et2_placeholder_select extends et2_inputWidget
app.onchange = (node, widget) =>
{
preview.set_value("");
- if(['user'].indexOf(widget.get_value()) >= 0)
+ if(['user', 'filemanager'].indexOf(widget.get_value()) >= 0)
{
+ // These ones don't let you select an entry for preview (they don't work)
entry.set_disabled(true);
entry.app_select.val('user');
entry.set_value({app: 'user', id: '', query: ''});
@@ -338,7 +339,7 @@ export class et2_placeholder_select extends et2_inputWidget
{
continue;
}
- options[key].push({
+ options[this.egw().lang(key)].push({
value: key + '-' + sub,
label: this.egw().lang(sub)
});
diff --git a/api/js/etemplate/et2_widget_toolbar.ts b/api/js/etemplate/et2_widget_toolbar.ts
index e0cedc3031..dd1dec1dc5 100644
--- a/api/js/etemplate/et2_widget_toolbar.ts
+++ b/api/js/etemplate/et2_widget_toolbar.ts
@@ -50,6 +50,22 @@ export class et2_toolbar extends et2_DOMWidget implements et2_IInput
"type": "string",
"default": "more",
"description": "Define a style for list header (more ...), which can get short 3dots with no caption or bigger button with caption more ..."
+ },
+ "preference_id": {
+ "name": "Preference id",
+ "type": "string",
+ "default": false,
+ "description": "Define a custom preference id for saving the toolbar preferences." +
+ "This is useful when you have the same toolbar and you use it in a pop up but also in a tab, which have different dom ids" +
+ "When not set it defaults to the dom id of the form."
+ },
+ "preference_app": {
+ "name": "Preference application",
+ "type": "string",
+ "default": false,
+ "description": "Define a custom preference application for saving the toolbar preferences." +
+ "This is useful when you have the same toolbar and you use it in a pop up but also in a tab, wich have different application names" +
+ "When not set it defaults to the result of this.egw().app_name();"
}
};
@@ -94,6 +110,13 @@ export class et2_toolbar extends et2_DOMWidget implements et2_IInput
// Set proper id and dom_id for the widget
this.set_id(this.id);
+ if(!this.options.preference_id){
+ this.options.preference_id = this.dom_id;
+ }
+
+ if(!this.options.preference_app){
+ this.options.preference_app = this.egw().app_name();
+ }
this.actionbox = jQuery(document.createElement('div'))
.addClass("et2_toolbar_more")
@@ -232,7 +255,7 @@ export class et2_toolbar extends et2_DOMWidget implements et2_IInput
{
this.actionbox.find('.toolbar-admin-pref').click(function(e){
e.stopImmediatePropagation();
- egw.json('EGroupware\\Api\\Etemplate\\Widget\\Toolbar::ajax_get_default_prefs', [egw.app_name(), that.dom_id], function(_prefs){
+ egw.json('EGroupware\\Api\\Etemplate\\Widget\\Toolbar::ajax_get_default_prefs', [that.options.preference_app, that.options.preference_id], function(_prefs){
let prefs = [];
for (let p in _prefs)
{
@@ -242,7 +265,8 @@ export class et2_toolbar extends et2_DOMWidget implements et2_IInput
}).sendRequest(true);
});
}
- let pref = (!egwIsMobile())? egw.preference(this.dom_id, this.egw().app_name()): undefined;
+
+ let pref = (!egwIsMobile())? egw.preference(this.options.preference_id, this.options.preference_app): undefined;
if (pref && !jQuery.isArray(pref)) this.preference = pref;
//Set the default actions for the first time
@@ -461,7 +485,7 @@ export class et2_toolbar extends et2_DOMWidget implements et2_IInput
if (that.actionlist.find(".ui-draggable").length == 0)
{
that.preference = {};
- egw.set_preference(that.egw().app_name(),that.dom_id,that.preference);
+ egw.set_preference(that.options.preference_app,that.options.preference_id,that.preference);
}
},
tolerance:"touch"
@@ -525,7 +549,7 @@ export class et2_toolbar extends et2_DOMWidget implements et2_IInput
{
this.preference[_action] = _state;
if (egwIsMobile()) return;
- egw.set_preference(this.egw().app_name(),this.dom_id,this.preference);
+ egw.set_preference(this.options.preference_app,this.options.preference_id,this.preference);
}
/**
@@ -537,7 +561,7 @@ export class et2_toolbar extends et2_DOMWidget implements et2_IInput
{
let button_options = {
};
- let button = jQuery(document.createElement('button'))
+ let button = jQuery(document.createElement('button'))
.addClass("et2_button et2_button_text et2_button_with_image")
.attr('id', this.id+'-'+action.id)
.attr('type', 'button')
@@ -773,7 +797,7 @@ export class et2_toolbar extends et2_DOMWidget implements et2_IInput
id:child,
value: child,
label: _actions[key]['children'][child]['caption'],
- app: egw.app_name(),
+ app: self.options.preference_app,
icon: _actions[key]['children'][child]['iconUrl']
});
}
@@ -784,7 +808,7 @@ export class et2_toolbar extends et2_DOMWidget implements et2_IInput
id:key,
value: key,
label: _actions[key]['caption'],
- app: egw.app_name(),
+ app: self.options.preference_app,
icon: _actions[key]['iconUrl']
});
}
@@ -808,12 +832,12 @@ export class et2_toolbar extends et2_DOMWidget implements et2_IInput
_value.actions = pref;
}
egw.json('EGroupware\\Api\\Etemplate\\Widget\\Toolbar::ajax_setAdminSettings',
- [_value, self.dom_id, egw.app_name()],function(_result){
+ [_value, self.options.preference_id, self.options.preference_app],function(_result){
egw.message(_result);
}).sendRequest(true);
}
},
- title: egw.lang('admin settings for %1', this.dom_id),
+ title: egw.lang('admin settings for %1', this.options.preference_id),
buttons: buttons,
minWidth: 600,
minHeight: 300,
diff --git a/api/js/jsapi/egw_app.ts b/api/js/jsapi/egw_app.ts
index a4e5a459b7..eadedb8631 100644
--- a/api/js/jsapi/egw_app.ts
+++ b/api/js/jsapi/egw_app.ts
@@ -744,20 +744,24 @@ export abstract class EgwApp
// Find what we need
let nm = null;
let action = _action;
- let as_pdf = false;
+ let as_pdf = null;
// Find Select all
- while(nm == null && action != null)
+ while(nm == null && action.parent != null)
{
if(action.data != null && action.data.nextmatch)
{
nm = action.data.nextmatch;
}
+ if(as_pdf === null && action.getActionById('as_pdf') !== null)
+ {
+ as_pdf = action.getActionById('as_pdf').checked;
+ }
action = action.parent;
}
let all = nm?.getSelection().all || false;
- as_pdf = action.getActionById('as_pdf')?.checked || false;
+ as_pdf = as_pdf || false;
// Get list of entry IDs
let ids = [];
diff --git a/api/lang/egw_de.lang b/api/lang/egw_de.lang
index ad9510f170..ae3ec4d874 100644
--- a/api/lang/egw_de.lang
+++ b/api/lang/egw_de.lang
@@ -274,6 +274,7 @@ choose a background style. common de Wählen Sie einen Hintergrundstil.
choose a text color for the icons common de Wählen Sie eine Textfarbe für die Symbole
choose file... common de Dateien wählen...
choose the category common de Kategorie auswählen
+choose the default filename for merged documents. preferences de Wählen Sie den Standard-Dateinamen für zusammengeführte Platzhalter-Dokumente.
choose the parent category common de Wählen der übergeordneten Kategorie
choose time common de Uhrzeit auswählen
chosen parent category no longer exists common de Die ausgewählte Elternkategorie existiert nicht (mehr).
@@ -378,6 +379,7 @@ december common de Dezember
deck common de Deck (intern)
default common de Vorgabe
default category common de Standard-Kategorie
+default document to insert entries preferences de Standarddokument für Einfügen in Dokument
default height for the windows common de Vorgabewert für Höhe des Fensters
default visible actions common de standardmäßig sichtbare Aktionen
default width for the windows common de Vorgabewert für Breite des Fensters
@@ -417,6 +419,8 @@ diable the execution a bugfixscript for internet explorer 5.5 and higher to show
direction left to right common de Richtung von links nach rechts
directory common de Verzeichnis
directory does not exist, is not readable by the webserver or is not relative to the document root! common de Verzeichnis existiert nicht, ist nicht vom Webserver lesbar oder ist nicht entsprechend zur Dokumentroot!
+directory for storing merged documents preferences de Verzeichnis für zusammengeführte Platzhalter-Dokumente
+directory with documents to insert entries preferences de Vorlagen-Verzeichnis für Einfügen in Dokument
disable internet explorer png-image-bugfix common de Internet Explorer PNG-Bilder-Bugfix abschalten
disable slider effects common de Schwebeeffekte des Navigationsmenüs abschalten
disable the animated slider effects when showing or hiding menus in the page? opera and konqueror users will probably must want this. common de Die animierten Schwebeeffekte beim Anzeigen oder Verstecken des Navigationsmenüs in der Seite abschalten? Benutzer von Opera oder Konquerer müssen diese Funktion abschalten.
@@ -1500,6 +1504,7 @@ western sahara common de WEST SAHARA
what color should all the blank space on the desktop have common de Welche Farbe soll der freie Platz auf der Arbeitsfläche haben
what happens with overflowing content: visible (default), hidden, scroll, auto (browser decides) common de was passiert mit überbreitem Inhalt: sichtbar (standard), versteckt, rollend, automatisch (der Browser entscheidet)
what style would you like the image to have? common de Welchen Stil soll das Bild haben?
+when you merge entries into documents, they will be stored here. If no directory is provided, they will be stored in your home directory (%1) preferences de Wenn Sie Einträge mit Platzhalter-Dokumenten zusammenführen, werden diese hier gespeichert. Wenn Sie kein Verzeichnis angeben, werden diese in Ihrem Homeverzeichnis gespeichert (%1)
when you say yes the home and logout buttons are presented as applications in the main top applcation bar. common de Wenn Sie dies aktivieren, werden die Start und Abmelde Symbole als Anwendungen im oberen Anwendungsbalken angezeigt.
where and how will the egroupware links like preferences, about and logout be displayed. common de Wo und wie werden die EGroupware Verknüpfungen wie Einstellungen, Über ..., und Abmelden angezeigt.
which groups common de Welche Gruppen
diff --git a/api/lang/egw_en.lang b/api/lang/egw_en.lang
index 09abb18ec0..722e90c99b 100644
--- a/api/lang/egw_en.lang
+++ b/api/lang/egw_en.lang
@@ -274,6 +274,7 @@ choose a background style. common en Choose a background style
choose a text color for the icons common en Choose a text color for the icons
choose file... common en Choose file...
choose the category common en Choose the category
+choose the default filename for merged documents. preferences en Choose the default filename for merged documents.
choose the parent category common en Choose the parent category
choose time common en Choose Time
chosen parent category no longer exists common en Chosen parent category no longer exists
@@ -378,6 +379,7 @@ december common en December
deck common en Deck (internal)
default common en Default
default category common en Default category
+default document to insert entries preferences en Default document to insert entries
default height for the windows common en Default height for the windows
default visible actions common en Default visible actions
default width for the windows common en Default width for the windows
@@ -417,6 +419,8 @@ diable the execution a bugfixscript for internet explorer 5.5 and higher to show
direction left to right common en Direction left to right
directory common en Directory
directory does not exist, is not readable by the webserver or is not relative to the document root! common en Directory does not exist, is not readable by the web server or is not relative to the document root!
+directory for storing merged documents preferences en Directory for storing merged documents
+directory with documents to insert entries preferences en Directory with documents to insert entries
disable internet explorer png-image-bugfix common en Disable Internet Explorer png image bugfix
disable slider effects common en Disable slider effects
disable the animated slider effects when showing or hiding menus in the page? opera and konqueror users will probably must want this. common en Disable the animated slider effects when showing or hiding menus in the page.
@@ -857,6 +861,7 @@ maybe common en Maybe
mayotte common en MAYOTTE
medium common en Medium
menu common en Menu
+merged document filename preferences en Merged document filename
message common en Message
message ... common en Message ...
message prepared for sending. common en Message prepared for sending.
@@ -1501,6 +1506,7 @@ western sahara common en WESTERN SAHARA
what color should all the blank space on the desktop have common en What color should all the blank space on the desktop have?
what happens with overflowing content: visible (default), hidden, scroll, auto (browser decides) common en What happens with overflowing content: visible (default), hidden, scroll, auto (browser decides)
what style would you like the image to have? common en Image style
+when you merge entries into documents, they will be stored here. If no directory is provided, they will be stored in your home directory (%1) preferences en When you merge entries into documents, they will be stored here. If no directory is provided, they will be stored in your home directory (%1)
when you say yes the home and logout buttons are presented as applications in the main top applcation bar. common en If you say yes, the Home and Log out buttons are presented as applications in the main top application bar.
where and how will the egroupware links like preferences, about and logout be displayed. common en Where and how will the EGroupware links like Preferences, About and Log out be displayed.
which groups common en Which groups
diff --git a/api/src/Accounts.php b/api/src/Accounts.php
index 889f6c1907..69c9def084 100644
--- a/api/src/Accounts.php
+++ b/api/src/Accounts.php
@@ -468,7 +468,7 @@ class Accounts
$data = self::cache_read($id);
// add default description for Admins and Default group
- if ($data['account_type'] === 'g')
+ if ($data && $data['account_type'] === 'g')
{
self::add_default_group_description($data);
}
@@ -595,11 +595,15 @@ class Accounts
/**
* Return formatted username for a given account_id
*
- * @param int $account_id account id
+ * @param ?int $account_id account id, default current user
* @return string full name of user or "#$account_id" if user not found
*/
- static function username(int $account_id)
+ static function username(int $account_id=null)
{
+ if (empty($account_id))
+ {
+ $account_id = $GLOBALS['egw_info']['user']['account_id'];
+ }
if (!($account = self::cache_read($account_id)))
{
return '#'.$account_id;
@@ -985,7 +989,7 @@ class Accounts
$ret = $just_id && $data['memberships'] ? array_keys($data['memberships']) : $data['memberships'];
}
//error_log(__METHOD__."($account_id, $just_id) data=".array2string($data)." returning ".array2string($ret));
- return $ret;
+ return $ret ?? [];
}
/**
diff --git a/api/src/Auth.php b/api/src/Auth.php
index 5fdfa1c5a6..74a086de23 100644
--- a/api/src/Auth.php
+++ b/api/src/Auth.php
@@ -15,8 +15,7 @@
namespace EGroupware\Api;
// allow to set an application depending authentication type (eg. for syncml, groupdav, ...)
-if (isset($GLOBALS['egw_info']['server']['auth_type_'.$GLOBALS['egw_info']['flags']['currentapp']]) &&
- $GLOBALS['egw_info']['server']['auth_type_'.$GLOBALS['egw_info']['flags']['currentapp']])
+if (!empty($GLOBALS['egw_info']['server']['auth_type_'.$GLOBALS['egw_info']['flags']['currentapp']]))
{
$GLOBALS['egw_info']['server']['auth_type'] = $GLOBALS['egw_info']['server']['auth_type_'.$GLOBALS['egw_info']['flags']['currentapp']];
}
@@ -223,11 +222,11 @@ class Auth
{
return true;
}
- if (is_null($passwordAgeBorder) && $GLOBALS['egw_info']['server']['change_pwd_every_x_days'])
+ if (is_null($passwordAgeBorder) && !empty($GLOBALS['egw_info']['server']['change_pwd_every_x_days']))
{
$passwordAgeBorder = (DateTime::to('now','ts')-($GLOBALS['egw_info']['server']['change_pwd_every_x_days']*86400));
}
- if (is_null($daysLeftUntilChangeReq) && $GLOBALS['egw_info']['server']['warn_about_upcoming_pwd_change'])
+ if (is_null($daysLeftUntilChangeReq) && !empty($GLOBALS['egw_info']['server']['warn_about_upcoming_pwd_change']))
{
// maxage - passwordage = days left until change is required
$daysLeftUntilChangeReq = ($GLOBALS['egw_info']['server']['change_pwd_every_x_days'] - ((DateTime::to('now','ts')-($alpwchange_val?$alpwchange_val:0))/86400));
@@ -235,9 +234,9 @@ class Auth
if ($alpwchange_val == 0 || // admin requested password change
$passwordAgeBorder > $alpwchange_val || // change password every N days policy requests change
// user should be warned N days in advance about change and is not yet
- $GLOBALS['egw_info']['server']['change_pwd_every_x_days'] &&
- $GLOBALS['egw_info']['user']['apps']['preferences'] &&
- $GLOBALS['egw_info']['server']['warn_about_upcoming_pwd_change'] &&
+ !empty($GLOBALS['egw_info']['server']['change_pwd_every_x_days']) &&
+ !empty($GLOBALS['egw_info']['user']['apps']['preferences']) &&
+ !empty($GLOBALS['egw_info']['server']['warn_about_upcoming_pwd_change']) &&
$GLOBALS['egw_info']['server']['warn_about_upcoming_pwd_change'] > $daysLeftUntilChangeReq &&
$UserKnowsAboutPwdChange !== true)
{
@@ -255,8 +254,8 @@ class Auth
else
{
// login page does not inform user about passwords about to expire
- if ($GLOBALS['egw_info']['flags']['currentapp'] != 'login' &&
- ($GLOBALS['egw_info']['flags']['currentapp'] != 'home' ||
+ if ($GLOBALS['egw_info']['flags']['currentapp'] !== 'login' &&
+ ($GLOBALS['egw_info']['flags']['currentapp'] !== 'home' ||
strpos($_SERVER['SCRIPT_NAME'], '/home/') !== false))
{
$UserKnowsAboutPwdChange = true;
diff --git a/api/src/Categories.php b/api/src/Categories.php
index 9cbbb46e24..c0d4ea494d 100644
--- a/api/src/Categories.php
+++ b/api/src/Categories.php
@@ -853,7 +853,7 @@ class Categories
if (is_null(self::$cache)) self::init_cache();
- $cat = self::$cache[$cat_id];
+ $cat = self::$cache[$cat_id] ?? null;
if ($item == 'path')
{
if ($cat['parent'])
@@ -864,7 +864,7 @@ class Categories
}
if ($item == 'data')
{
- return $cat['data'] ? json_php_unserialize($cat['data'], true) : array();
+ return !empty($cat['data']) ? json_php_unserialize($cat['data'], true) : array();
}
elseif ($cat[$item])
{
diff --git a/api/src/Config.php b/api/src/Config.php
index bc90e47eb6..cfe545e13c 100755
--- a/api/src/Config.php
+++ b/api/src/Config.php
@@ -210,7 +210,7 @@ class Config
{
self::init_static();
}
- return (array)self::$configs[$app];
+ return self::$configs[$app] ?? [];
}
/**
@@ -238,7 +238,7 @@ class Config
{
$config = self::read($app);
- return is_array($config['types']) ? $config['types'] : array();
+ return !empty($config['types']) && is_array($config['types']) ? $config['types'] : [];
}
/**
diff --git a/api/src/Contacts.php b/api/src/Contacts.php
index 2409357a24..d3a5a1b2b1 100755
--- a/api/src/Contacts.php
+++ b/api/src/Contacts.php
@@ -202,9 +202,9 @@ class Contacts extends Contacts\Storage
$this->prefs['hide_accounts'] = '0';
}
// get the default addressbook from the users prefs
- $this->default_addressbook = $GLOBALS['egw_info']['user']['preferences']['addressbook']['add_default'] ?
+ $this->default_addressbook = !empty($GLOBALS['egw_info']['user']['preferences']['addressbook']['add_default']) ?
(int)$GLOBALS['egw_info']['user']['preferences']['addressbook']['add_default'] : $this->user;
- $this->default_private = substr($GLOBALS['egw_info']['user']['preferences']['addressbook']['add_default'],-1) == 'p';
+ $this->default_private = substr($GLOBALS['egw_info']['user']['preferences']['addressbook']['add_default'] ?? '',-1) == 'p';
if ($this->default_addressbook > 0 && $this->default_addressbook != $this->user &&
($this->default_private ||
$this->default_addressbook == (int)$GLOBALS['egw']->preferences->forced['addressbook']['add_default'] ||
@@ -312,14 +312,14 @@ class Contacts extends Contacts\Storage
'adr_two_countryname' => lang('country').' ('.lang('business').')',
);
//_debug_array($this->contact_fields);
- $this->own_account_acl = $GLOBALS['egw_info']['server']['own_account_acl'];
+ $this->own_account_acl = $GLOBALS['egw_info']['server']['own_account_acl'] ?? null;
if (!is_array($this->own_account_acl)) $this->own_account_acl = json_php_unserialize($this->own_account_acl, true);
// we have only one acl (n_fn) for the whole name, as not all backends store every part in an own field
if ($this->own_account_acl && in_array('n_fn',$this->own_account_acl))
{
$this->own_account_acl = array_merge($this->own_account_acl,array('n_prefix','n_given','n_middle','n_family','n_suffix'));
}
- if ($GLOBALS['egw_info']['server']['org_fileds_to_update'])
+ if (!empty($GLOBALS['egw_info']['server']['org_fileds_to_update']))
{
$this->org_fields = $GLOBALS['egw_info']['server']['org_fileds_to_update'];
if (!is_array($this->org_fields)) $this->org_fields = unserialize($this->org_fields);
@@ -337,7 +337,7 @@ class Contacts extends Contacts\Storage
}
$this->categories = new Categories($this->user,'addressbook');
- $this->delete_history = $GLOBALS['egw_info']['server']['history'];
+ $this->delete_history = $GLOBALS['egw_info']['server']['history'] ?? null;
}
/**
diff --git a/api/src/Contacts/Merge.php b/api/src/Contacts/Merge.php
index 4dc6d5a47c..169e233abc 100644
--- a/api/src/Contacts/Merge.php
+++ b/api/src/Contacts/Merge.php
@@ -155,119 +155,6 @@ class Merge extends Api\Storage\Merge
return $replacements;
}
- /**
- * Generate table with replacements for the preferences
- *
- */
- public function show_replacements()
- {
- $GLOBALS['egw_info']['flags']['app_header'] = lang('Addressbook').' - '.lang('Replacements for inserting contacts into documents');
- $GLOBALS['egw_info']['flags']['nonavbar'] = (bool)$_GET['nonavbar'];
-
- ob_start();
- echo "
\n";
- echo ''.lang('Contact fields:')." |
";
-
- $n = 0;
- foreach($this->contacts->contact_fields as $name => $label)
- {
- if (in_array($name,array('tid','label','geo'))) continue; // dont show them, as they are not used in the UI atm.
-
- if (in_array($name,array('email','org_name','tel_work','url')) && $n&1) // main values, which should be in the first column
- {
- echo "\n";
- $n++;
- }
- if (!($n&1)) echo '';
- echo '{{'.$name.'}} | '.$label.' | ';
- if($name == 'cat_id')
- {
- if ($n&1) echo "
\n";
- echo '{{categories}} | '.lang('Category path').' | ';
- $n++;
- }
- if ($n&1) echo "\n";
- $n++;
- }
-
- echo ''.lang('Custom fields').": |
";
- foreach($this->contacts->customfields as $name => $field)
- {
- echo '{{#'.$name.'}} | '.$field['label']." |
\n";
- }
-
- echo ''.lang('General fields:')." |
";
- foreach(array(
- 'link' => lang('HTML link to the current record'),
- 'links' => lang('Titles of any entries linked to the current record, excluding attached files'),
- 'attachments' => lang('List of files linked to the current record'),
- 'links_attachments' => lang('Links and attached files'),
- 'links/[appname]' => lang('Links to specified application. Example: {{links/infolog}}'),
- 'date' => lang('Date'),
- 'user/n_fn' => lang('Name of current user, all other contact fields are valid too'),
- 'user/account_lid' => lang('Username'),
- 'pagerepeat' => lang('For serial letter use this tag. Put the content, you want to repeat between two Tags.'),
- 'label' => lang('Use this tag for addresslabels. Put the content, you want to repeat, between two tags.'),
- 'labelplacement' => lang('Tag to mark positions for address labels'),
- 'IF fieldname' => lang('Example {{IF n_prefix~Mr~Hello Mr.~Hello Ms.}} - search the field "n_prefix", for "Mr", if found, write Hello Mr., else write Hello Ms.'),
- 'NELF' => lang('Example {{NELF role}} - if field role is not empty, you will get a new line with the value of field role'),
- 'NENVLF' => lang('Example {{NENVLF role}} - if field role is not empty, set a LF without any value of the field'),
- 'LETTERPREFIX' => lang('Example {{LETTERPREFIX}} - Gives a letter prefix without double spaces, if the title is empty for example'),
- 'LETTERPREFIXCUSTOM' => lang('Example {{LETTERPREFIXCUSTOM n_prefix title n_family}} - Example: Mr Dr. James Miller'),
- ) as $name => $label)
- {
- 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(
- 'title' => lang('Title'),
- 'description' => lang('Description'),
- 'participants' => lang('Participants'),
- 'location' => lang('Location'),
- 'start' => lang('Start').': '.lang('Date').'+'.lang('Time'),
- 'startday' => lang('Start').': '.lang('Weekday'),
- 'startdate'=> lang('Start').': '.lang('Date'),
- 'starttime'=> lang('Start').': '.lang('Time'),
- 'end' => lang('End').': '.lang('Date').'+'.lang('Time'),
- 'endday' => lang('End').': '.lang('Weekday'),
- 'enddate' => lang('End').': '.lang('Date'),
- 'endtime' => lang('End').': '.lang('Time'),
- 'duration' => lang('Duration'),
- 'category' => lang('Category'),
- 'priority' => lang('Priority'),
- 'updated' => lang('Updated'),
- 'recur_type' => lang('Repetition'),
- 'access' => lang('Access').': '.lang('public').', '.lang('private'),
- 'owner' => lang('Owner'),
- ) as $name => $label)
- {
- if(in_array($name, array('start',
- 'end')) && $n & 1) // main values, which should be in the first column
- {
- echo "\n";
- $n++;
- }
- if(!($n & 1))
- {
- echo '';
- }
- echo '{{calendar/#/' . $name . '}} | ' . $label . ' | ';
- if($n & 1)
- {
- echo "
\n";
- }
- $n++;
- }
- echo "
\n";
-
- $GLOBALS['egw']->framework->render(ob_get_clean());
- }
-
/**
* Get a list of placeholders provided.
*
@@ -352,10 +239,58 @@ class Merge extends Api\Storage\Merge
'label' => "Formatted private address"
];
+ $placeholders['EPL only'][] = [
+ 'value' => $this->prefix($prefix, 'share', '{'),
+ 'label' => 'Public sharing URL'
+ ];
+
$this->add_customfield_placeholders($placeholders, $prefix);
+
+ // Don't add any linked placeholders if we're not at the top level
+ // This avoids potential recursion
+ if(!$prefix)
+ {
+ $this->add_calendar_placeholders($placeholders, $prefix);
+ }
+
return $placeholders;
}
+ protected function add_calendar_placeholders(&$placeholders, $prefix)
+ {
+ Api\Translation::add_app('calendar');
+
+ // NB: The -1 is actually ‑1, a non-breaking hyphen to avoid UI issues where we split on -
+ $group = lang('Calendar fields:') . " # = 1, 2, ..., 20, ‑1";
+ foreach(array(
+ 'title' => lang('Title'),
+ 'description' => lang('Description'),
+ 'participants' => lang('Participants'),
+ 'location' => lang('Location'),
+ 'start' => lang('Start') . ': ' . lang('Date') . '+' . lang('Time'),
+ 'startday' => lang('Start') . ': ' . lang('Weekday'),
+ 'startdate' => lang('Start') . ': ' . lang('Date'),
+ 'starttime' => lang('Start') . ': ' . lang('Time'),
+ 'end' => lang('End') . ': ' . lang('Date') . '+' . lang('Time'),
+ 'endday' => lang('End') . ': ' . lang('Weekday'),
+ 'enddate' => lang('End') . ': ' . lang('Date'),
+ 'endtime' => lang('End') . ': ' . lang('Time'),
+ 'duration' => lang('Duration'),
+ 'category' => lang('Category'),
+ 'priority' => lang('Priority'),
+ 'updated' => lang('Updated'),
+ 'recur_type' => lang('Repetition'),
+ 'access' => lang('Access') . ': ' . lang('public') . ', ' . lang('private'),
+ 'owner' => lang('Owner'),
+ ) as $name => $label)
+ {
+ $placeholders[$group][] = array(
+ 'value' => $this->prefix(($prefix ? $prefix . '/' : '') . 'calendar/#', $name, '{'),
+ 'label' => $label
+ );
+ }
+ }
+
/**
* Get insert-in-document action with optional default document on top
*
diff --git a/api/src/Contacts/Sql.php b/api/src/Contacts/Sql.php
index 481d2b9fb0..a6748459fc 100644
--- a/api/src/Contacts/Sql.php
+++ b/api/src/Contacts/Sql.php
@@ -77,15 +77,15 @@ class Sql extends Api\Storage
// Get custom fields from addressbook instead of api
$this->customfields = Api\Storage\Customfields::get('addressbook');
- if ($GLOBALS['egw_info']['server']['account_repository'])
+ if (!empty($GLOBALS['egw_info']['server']['account_repository']))
{
$this->account_repository = $GLOBALS['egw_info']['server']['account_repository'];
}
- elseif ($GLOBALS['egw_info']['server']['auth_type'])
+ elseif (!empty($GLOBALS['egw_info']['server']['auth_type']))
{
$this->account_repository = $GLOBALS['egw_info']['server']['auth_type'];
}
- if ($GLOBALS['egw_info']['server']['contact_repository'])
+ if (!empty($GLOBALS['egw_info']['server']['contact_repository']))
{
$this->contact_repository = $GLOBALS['egw_info']['server']['contact_repository'];
}
@@ -742,7 +742,7 @@ class Sql extends Api\Storage
$cat_filter = array();
foreach(is_array($cats) ? $cats : (is_numeric($cats) ? array($cats) : explode(',',$cats)) as $cat)
{
- if (is_numeric($cat)) $cat_filter[] = $this->db->concat("','",cat_id,"','")." LIKE '%,$cat,%'";
+ if (is_numeric($cat)) $cat_filter[] = $this->db->concat("','", 'cat_id', "','")." LIKE '%,$cat,%'";
}
return $cat_filter;
}
diff --git a/api/src/Contacts/Storage.php b/api/src/Contacts/Storage.php
index 0cb66f4b6d..fe2b3b4531 100755
--- a/api/src/Contacts/Storage.php
+++ b/api/src/Contacts/Storage.php
@@ -256,7 +256,7 @@ class Storage
}
$this->customfields = Api\Storage\Customfields::get('addressbook');
// contacts backend (contacts in LDAP require accounts in LDAP!)
- if($GLOBALS['egw_info']['server']['contact_repository'] == 'ldap' && $this->account_repository == 'ldap')
+ if (($GLOBALS['egw_info']['server']['contact_repository']??null) === 'ldap' && $this->account_repository === 'ldap')
{
$this->contact_repository = 'ldap';
$this->somain = new Ldap();
@@ -264,7 +264,7 @@ class Storage
}
else // sql or sql->ldap
{
- if ($GLOBALS['egw_info']['server']['contact_repository'] == 'sql-ldap')
+ if (($GLOBALS['egw_info']['server']['contact_repository']??null) === 'sql-ldap')
{
$this->contact_repository = 'sql-ldap';
}
@@ -347,9 +347,9 @@ class Storage
if ($user)
{
// contacts backend (contacts in LDAP require accounts in LDAP!)
- if($GLOBALS['egw_info']['server']['contact_repository'] == 'ldap' && $this->account_repository == 'ldap')
+ if(($GLOBALS['egw_info']['server']['contact_repository']??null) === 'ldap' && $this->account_repository === 'ldap')
{
- // static grants from ldap: all rights for the own personal addressbook and the group ones of the meberships
+ // static grants from ldap: all rights for the own personal addressbook and the group ones of the memberships
$grants = array($user => ~0);
foreach($GLOBALS['egw']->accounts->memberships($user,true) as $gid)
{
@@ -415,9 +415,9 @@ class Storage
*/
function allow_account_edit($user=null)
{
- return $GLOBALS['egw_info']['server']['allow_account_edit'] &&
+ return !empty($GLOBALS['egw_info']['server']['allow_account_edit']) &&
array_intersect($GLOBALS['egw_info']['server']['allow_account_edit'],
- $GLOBALS['egw']->accounts->memberships($user ? $user : $this->user, true));
+ $GLOBALS['egw']->accounts->memberships($user ?: $this->user, true));
}
/**
diff --git a/api/src/Db.php b/api/src/Db.php
index cb42718df4..c2160cc0a8 100644
--- a/api/src/Db.php
+++ b/api/src/Db.php
@@ -591,7 +591,7 @@ class Db
$this->setupType = $this->Type;
$this->Type = 'mysql';
}
- if ($new_connection)
+ if (!empty($new_connection))
{
foreach(get_included_files() as $file)
{
@@ -1599,7 +1599,7 @@ class Db
{
return $array;
}
- if (!$column_definitions)
+ if (empty($column_definitions))
{
$column_definitions = $this->column_definitions;
}
diff --git a/api/src/Db/Pdo.php b/api/src/Db/Pdo.php
index cd038c6f15..353409d523 100644
--- a/api/src/Db/Pdo.php
+++ b/api/src/Db/Pdo.php
@@ -125,7 +125,7 @@ class Pdo
// Exception reveals password, so we ignore the exception and connect again without pw, to get the right exception without pw
self::$pdo = new \PDO($dsn,$egw_db->User,'$egw_db->Password');
}
- if ($query)
+ if (!empty($query))
{
self::$pdo->exec($query);
}
diff --git a/api/src/Etemplate.php b/api/src/Etemplate.php
index 0631d9e3b7..45e88ae271 100644
--- a/api/src/Etemplate.php
+++ b/api/src/Etemplate.php
@@ -117,22 +117,22 @@ class Etemplate extends Etemplate\Widget\Template
foreach(count(array_filter(array_keys($extras), 'is_int')) ? $extras : array($extras) as $extra)
{
- if ($extra['data'] && is_array($extra['data']))
+ if (!empty($extra['data']) && is_array($extra['data']))
{
$content = array_merge($content, $extra['data']);
}
- if ($extra['preserve'] && is_array($extra['preserve']))
+ if (!empty($extra['preserve']) && is_array($extra['preserve']))
{
$preserv = array_merge($preserv, $extra['preserve']);
}
- if ($extra['readonlys'] && is_array($extra['readonlys']))
+ if (!empty($extra['readonlys']) && is_array($extra['readonlys']))
{
$readonlys = array_merge($readonlys, $extra['readonlys']);
}
- if ($extra['sel_options'] && is_array($extra['sel_options']))
+ if (!empty($extra['sel_options']) && is_array($extra['sel_options']))
{
$sel_options = array_merge($sel_options, $extra['sel_options']);
}
@@ -177,7 +177,7 @@ class Etemplate extends Etemplate\Widget\Template
}
// some apps (eg. InfoLog) set app_header only in get_rows depending on filter settings
- self::$request->app_header = $GLOBALS['egw_info']['flags']['app_header'];
+ self::$request->app_header = $GLOBALS['egw_info']['flags']['app_header'] ?? null;
// compile required translations translations
$currentapp = $GLOBALS['egw_info']['flags']['currentapp'];
@@ -209,7 +209,7 @@ class Etemplate extends Etemplate\Widget\Template
'currentapp' => $currentapp,
);
- if($data['content']['nm']['rows'] && is_array($data['content']['nm']['rows']))
+ if (!empty($data['content']['nm']['rows']) && is_array($data['content']['nm']['rows']))
{
// Deep copy rows so we don't lose them when request is set to null
// (some content by reference)
@@ -420,7 +420,7 @@ class Etemplate extends Etemplate\Widget\Template
}
$tcontent = is_array($content) ? $content :
- self::complete_array_merge(self::$request->preserv, $validated);
+ self::complete_array_merge(self::$request->preserv ?? [], $validated);
$hook_data = Hooks::process(
array(
diff --git a/api/src/Etemplate/Request.php b/api/src/Etemplate/Request.php
index f4823645b9..4843c9503d 100644
--- a/api/src/Etemplate/Request.php
+++ b/api/src/Etemplate/Request.php
@@ -428,9 +428,9 @@ class Request
* @param string $var
* @param mixed $val
*/
- public function __set($var,$val)
+ public function __set($var, $val)
{
- if ($this->data[$var] !== $val)
+ if (!isset($this->data[$var]) || $this->data[$var] !== $val)
{
$this->data[$var] = $val;
//error_log(__METHOD__."('$var', ...) data of id=$this->id changed ...");
diff --git a/api/src/Etemplate/Request/Files.php b/api/src/Etemplate/Request/Files.php
index b15054d320..613bd5be30 100644
--- a/api/src/Etemplate/Request/Files.php
+++ b/api/src/Etemplate/Request/Files.php
@@ -97,9 +97,10 @@ class Files extends Etemplate\Request
* Factory method to get a new request object or the one for an existing request
*
* @param string $id =null
- * @return ?Etemplate\Request|false the object or false if $id is not found
+ * @param bool $handle_not_found =true true: handle not found by trying to redirect, false: just return null
+ * @return Request|null null if Request not found and $handle_not_found === false
*/
- static function read($id=null)
+ public static function read($id=null, $handle_not_found=true)
{
$request = new Files($id);
diff --git a/api/src/Etemplate/Request/Session.php b/api/src/Etemplate/Request/Session.php
index 7bad1420fe..339c09307d 100644
--- a/api/src/Etemplate/Request/Session.php
+++ b/api/src/Etemplate/Request/Session.php
@@ -83,9 +83,10 @@ class Session extends Etemplate\Request
* Factory method to get a new request object or the one for an existing request
*
* @param string $id =null
- * @return ?Etemplate\request|false the object or false if $id is not found
+ * @param bool $handle_not_found =true true: handle not found by trying to redirect, false: just return null
+ * @return Request|null null if Request not found and $handle_not_found === false
*/
- static function read($id=null)
+ public static function read($id=null, $handle_not_found=true)
{
$request = new Session($id);
diff --git a/api/src/Etemplate/Widget.php b/api/src/Etemplate/Widget.php
index 00a591f000..a3f41e0f23 100644
--- a/api/src/Etemplate/Widget.php
+++ b/api/src/Etemplate/Widget.php
@@ -553,12 +553,21 @@ class Widget
$method = new ReflectionMethod($this, $method_name);
foreach($method->getParameters() as $index => $param)
{
- if(!$param->isOptional() && !array_key_exists($index,$params))
+ if(!$param->isOptional() && !array_key_exists($index, $params))
{
error_log("Missing required parameter {$param->getPosition()}: {$param->getName()}");
$call = false;
}
- if($param->isArray() && !is_array($params[$index]))
+ // Check to see if method wants an array, and we're providing it
+ $paramType = $param->getType();
+ if(!$paramType)
+ {
+ continue;
+ }
+ $types = $paramType instanceof \ReflectionUnionType
+ ? $paramType->getTypes()
+ : [$paramType];
+ if(in_array('array', array_map(fn(\ReflectionNamedType $t) => $t->getName(), $types)) && !is_array($params[$index]))
{
error_log("$method_name expects an array for {$param->getPosition()}: {$param->getName()}");
$params[$index] = (array)$params[$index];
@@ -1044,6 +1053,10 @@ class Widget
*/
public static function &setElementAttribute($name,$attr,$val)
{
+ if (!isset(self::$request))
+ {
+ throw new \Exception(__METHOD__."('$name', '$attr', ".json_encode($val)." called before instanciating Api\Etemplate!");
+ }
//error_log(__METHOD__."('$name', '$attr', ...) request=".get_class(self::$request).", response=".get_class(self::$response).function_backtrace());
$ref =& self::$request->modifications[$name][$attr];
if(self::$request && self::$response)
diff --git a/api/src/Etemplate/Widget/Box.php b/api/src/Etemplate/Widget/Box.php
index de3a379091..74a198d239 100644
--- a/api/src/Etemplate/Widget/Box.php
+++ b/api/src/Etemplate/Widget/Box.php
@@ -50,7 +50,7 @@ class Box extends Etemplate\Widget
$old_expand = $params[1];
if ($this->id && $this->type != 'groupbox') $cname = self::form_name($cname, $this->id, $params[1]);
- if (!empty($expand['cname']) && $expand['cname'] !== $cname && trim($cname))
+ if (($expand['cname'] ?? null) !== $cname && trim($cname))
{
$expand['cont'] =& self::get_array(self::$request->content, $cname);
$expand['cname'] = $cname;
diff --git a/api/src/Etemplate/Widget/Customfields.php b/api/src/Etemplate/Widget/Customfields.php
index 0964a7fd9b..466ff5f5bc 100644
--- a/api/src/Etemplate/Widget/Customfields.php
+++ b/api/src/Etemplate/Widget/Customfields.php
@@ -98,7 +98,7 @@ class Customfields extends Transformer
$form_name = self::form_name($cname, $this->id, $expand);
// Store properties at top level, so all customfield widgets can share
- if($this->attrs['app'])
+ if (!empty($this->attrs['app']))
{
$app = $this->attrs['app'];
}
@@ -141,12 +141,12 @@ class Customfields extends Transformer
// app changed
$customfields = Api\Storage\Customfields::get($app);
}
- if($this->attrs['customfields'])
+ if (!empty($this->attrs['customfields']))
{
$customfields = $this->attrs['customfields'];
}
// Filter fields
- if($this->attrs['field-names'])
+ if (!empty($this->attrs['field-names']))
{
$fields_name = explode(',', $this->attrs['field-names']);
foreach($fields_name as &$f)
@@ -162,8 +162,8 @@ class Customfields extends Transformer
$fields = $customfields;
- $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);
+ $use_private = self::expand_name($this->attrs['use-private'] ?? null,0,0,'','',self::$cont);
+ $this->attrs['sub-type'] = self::expand_name($this->attrs['sub-type'] ?? null,0,0,'','',self::$cont);
foreach((array)$fields as $key => $field)
{
@@ -174,7 +174,7 @@ class Customfields extends Transformer
}
// Remove filtered fields
- if($field_filters && in_array($key, $negate_fields) && in_array($key, $field_filters))
+ if (!empty($field_filters) && in_array($key, $negate_fields) && in_array($key, $field_filters))
{
unset($fields[$key]);
}
@@ -284,7 +284,7 @@ class Customfields extends Transformer
$type = $field['type'];
// Link-tos needs to change from appname to link-to
- if($link_types[$field['type']])
+ if (!empty($link_types[$field['type']]))
{
if($type == 'filemanager')
{
@@ -314,8 +314,8 @@ class Customfields extends Transformer
{
$widget->attrs['data_format'] = $type == 'date' ? 'Y-m-d' : 'Y-m-d H:i:s';
}
- if($field['values']['min']) $widget->attrs['min'] = $field['values']['min'];
- if($field['values']['max']) $widget->attrs['min'] = $field['values']['max'];
+ if (isset($field['values']['min'])) $widget->attrs['min'] = $field['values']['min'];
+ if (isset($field['values']['max'])) $widget->attrs['min'] = $field['values']['max'];
break;
case 'vfs-upload':
@@ -355,7 +355,7 @@ class Customfields extends Transformer
$field['values'] = Api\Storage\Customfields::get_options_from_file($field['values']['@']);
}
// keep extra values set by app code, eg. addressbook advanced search
- if (is_array(self::$request->sel_options[self::$prefix.$fname]))
+ if (!empty(self::$request->sel_options[self::$prefix.$fname]) && is_array(self::$request->sel_options[self::$prefix.$fname]))
{
self::$request->sel_options[self::$prefix.$fname] += (array)$field['values'];
}
diff --git a/api/src/Etemplate/Widget/Description.php b/api/src/Etemplate/Widget/Description.php
index 338e80f15d..e69bcdfd19 100644
--- a/api/src/Etemplate/Widget/Description.php
+++ b/api/src/Etemplate/Widget/Description.php
@@ -42,7 +42,7 @@ class Description extends Etemplate\Widget
*/
public function beforeSendToClient($cname, array $expand=null)
{
- if ($this->attrs['activate_links'])
+ if (!empty($this->attrs['activate_links']))
{
$form_name = self::form_name($cname, $this->id, $expand);
$value =& self::get_array(self::$request->content, $form_name);
diff --git a/api/src/Etemplate/Widget/Grid.php b/api/src/Etemplate/Widget/Grid.php
index 17433ba3e1..a26d76a73b 100644
--- a/api/src/Etemplate/Widget/Grid.php
+++ b/api/src/Etemplate/Widget/Grid.php
@@ -88,8 +88,11 @@ class Grid extends Box
return false; // return
}
- if ($this->id && $this->type !== 'row') $cname = self::form_name($cname, $this->id, $expand);
- if (!empty($expand['cname']) && $expand['cname'] !== $cname && $cname)
+ if($this->id && $this->type !== 'row')
+ {
+ $cname = self::form_name($cname, $this->id, $expand);
+ }
+ if($cname && (!empty($expand['cname']) && $expand['cname'] !== $cname || !$expand['cname']))
{
$expand['cont'] =& self::get_array(self::$request->content, $cname);
$expand['cname'] = $cname;
diff --git a/api/src/Etemplate/Widget/Image.php b/api/src/Etemplate/Widget/Image.php
index 7969ab83dc..f77067f082 100644
--- a/api/src/Etemplate/Widget/Image.php
+++ b/api/src/Etemplate/Widget/Image.php
@@ -36,17 +36,17 @@ class Image extends Etemplate\Widget
$image = $value != '' ? $value : $this->attrs['src'];
- if (is_string($image)) list($app,$img) = explode('/',$image,2);
- if (!$app || !$img || !is_dir(EGW_SERVER_ROOT.'/'.$app) || strpos($img,'/')!==false)
+ if (is_string($image)) list($app,$img) = explode('/',$image,2)+[null,null];
+ if (empty($app) || empty($img) || !is_dir(EGW_SERVER_ROOT.'/'.$app) || strpos($img,'/')!==false)
{
$img = $image;
list($app) = explode('.',$form_name);
}
$src = Api\Image::find($app, $img);
- if(!$this->id)
+ /*if(!$this->id)
{
// self::setElementAttribute($this->attrs['src'], 'id', $this->attrs['src']);
- }
+ }*/
self::setElementAttribute($this->attrs['src'], 'src', $src);
}
}
diff --git a/api/src/Etemplate/Widget/Nextmatch.php b/api/src/Etemplate/Widget/Nextmatch.php
index d6ccd128c7..10004d276e 100644
--- a/api/src/Etemplate/Widget/Nextmatch.php
+++ b/api/src/Etemplate/Widget/Nextmatch.php
@@ -130,13 +130,13 @@ class Nextmatch extends Etemplate\Widget
$send_value = $value;
list($app) = explode('.',$value['get_rows']);
- if(!$GLOBALS['egw_info']['apps'][$app])
+ if (empty($GLOBALS['egw_info']['apps'][$app]))
{
list($app) = explode('.',$this->attrs['template']);
}
// Check for a favorite in URL
- if($_GET['favorite'] && $value['favorites'])
+ if (!empty($_GET['favorite']) && !empty($value['favorites']))
{
$safe_name = preg_replace('/[^A-Za-z0-9-_]/','_',strip_tags($_GET['favorite']));
$pref_name = "favorite_" .$safe_name;
@@ -210,7 +210,7 @@ class Nextmatch extends Etemplate\Widget
}
// Favorite group for admins
- if($GLOBALS['egw_info']['apps']['admin'] && $value['favorites'])
+ if (!empty($GLOBALS['egw_info']['apps']['admin']) && !empty($value['favorites']))
{
self::$request->sel_options[$form_name]['favorite']['group'] = array('all' => lang('All users')) +
Select::typeOptions('select-account',',groups');
@@ -894,7 +894,7 @@ class Nextmatch extends Etemplate\Widget
if ($default_attrs) $action += $default_attrs;
// Add 'Select All' after first group
- if ($first_level && $group !== false && $action['group'] != $group && empty($egw_actions[$prefix.'select_all']))
+ if ($first_level && $group !== false && ($action['group']??null) != $group && empty($egw_actions[$prefix.'select_all']))
{
$egw_actions[$prefix.'select_all'] = array(
diff --git a/api/src/Etemplate/Widget/Password.php b/api/src/Etemplate/Widget/Password.php
index ae4d5ef7f3..3e7cbe9997 100644
--- a/api/src/Etemplate/Widget/Password.php
+++ b/api/src/Etemplate/Widget/Password.php
@@ -49,7 +49,8 @@ class Password extends Etemplate\Widget\Textbox
{
$form_name = self::form_name($cname, $this->id, $expand);
$value =& self::get_array(self::$request->content, $form_name);
- $plaintext = !in_array(self::expand_name($this->attrs['plaintext'],$expand['c'], $expand['row'], $expand['c_'], $expand['row_'], $expand['cont']),
+ $plaintext = !empty($this->attrs['plaintext']) && !in_array(
+ self::expand_name($this->attrs['plaintext'], $expand['c'] ?? null, $expand['row'] ?? null, $expand['c_'] ?? null, $expand['row_'] ?? null, $expand['cont']),
['false', '0']);
if (!empty($value))
diff --git a/api/src/Etemplate/Widget/Placeholder.php b/api/src/Etemplate/Widget/Placeholder.php
index a31d88c49d..c2f933c6c8 100644
--- a/api/src/Etemplate/Widget/Placeholder.php
+++ b/api/src/Etemplate/Widget/Placeholder.php
@@ -64,9 +64,13 @@ class Placeholder extends Etemplate\Widget
if(is_null($apps))
{
- $apps = ['addressbook', 'user', 'general'] +
+ $apps = array_merge(
+ ['addressbook', 'user', 'general'],
// We use linking for preview, so limit to apps that support links
- array_keys(Api\Link::app_list('query'));
+ array_keys(Api\Link::app_list('query')),
+ // Filemanager doesn't support links, but add it anyway
+ ['filemanager']
+ );
}
foreach($apps as $appname)
@@ -86,6 +90,8 @@ class Placeholder extends Etemplate\Widget
// Looks like app doesn't support merging
continue 2;
}
+
+ Api\Translation::load_app($appname, $GLOBALS['egw_info']['user']['preferences']['common']['lang']);
$list = method_exists($merge, 'get_placeholder_list') ? $merge->get_placeholder_list() : [];
break;
}
diff --git a/api/src/Etemplate/Widget/Select.php b/api/src/Etemplate/Widget/Select.php
index 84817c9aa5..e8c8844cff 100644
--- a/api/src/Etemplate/Widget/Select.php
+++ b/api/src/Etemplate/Widget/Select.php
@@ -109,14 +109,14 @@ class Select extends Etemplate\Widget
{
parent::set_attrs($xml, $cloned);
- if ($this->attrs['multiple'] !== 'dynamic')
+ if (!isset($this->attrs['multiple']) || $this->attrs['multiple'] !== 'dynamic')
{
$this->attrs['multiple'] = !isset($this->attrs['multiple']) ? false :
!(!$this->attrs['multiple'] || $this->attrs['multiple'] === 'false');
}
// set attrs[multiple] from attrs[options], unset options only if it just contains number or rows
- if ($this->attrs['options'] > 1)
+ if (isset($this->attrs['options']) && $this->attrs['options'] > 1)
{
$this->attrs['multiple'] = (int)$this->attrs['options'];
if ((string)$this->attrs['multiple'] == $this->attrs['options'])
@@ -124,7 +124,7 @@ class Select extends Etemplate\Widget
unset($this->attrs['options']);
}
}
- elseif($this->attrs['rows'] > 1)
+ elseif(isset($this->attrs['rows']) && $this->attrs['rows'] > 1)
{
$this->attrs['multiple'] = true;
}
@@ -311,8 +311,8 @@ class Select extends Etemplate\Widget
{
$form_name = self::form_name($cname, $this->id, $expand);
}
- if (!is_array(self::$request->sel_options[$form_name])) self::$request->sel_options[$form_name] = array();
- $type = $this->attrs['type'] ? $this->attrs['type'] : $this->type;
+ if (empty(self::$request->sel_options[$form_name]) || !is_array(self::$request->sel_options[$form_name])) self::$request->sel_options[$form_name] = [];
+ $type = $this->attrs['type'] ?? $this->type;
if ($type != 'select' && $type != 'menupopup')
{
// Check selection preference, we may be able to skip reading some data
@@ -335,8 +335,8 @@ class Select extends Etemplate\Widget
if (!isset($form_names_done[$form_name]) &&
($type_options = self::typeOptions($this,
// typeOptions thinks # of rows is the first thing in options
- ($this->attrs['rows'] && strpos($this->attrs['options'], $this->attrs['rows']) !== 0 ? $this->attrs['rows'].','.$this->attrs['options'] : $this->attrs['options']),
- $no_lang, $this->attrs['readonly'], self::get_array(self::$request->content, $form_name), $form_name)))
+ (!empty($this->attrs['rows']) && !empty($this->attrs['options']) && strpos($this->attrs['options'], $this->attrs['rows']) !== 0 ? $this->attrs['rows'].','.$this->attrs['options'] : $this->attrs['options']),
+ $no_lang, $this->attrs['readonly'] ?? false, self::get_array(self::$request->content, $form_name), $form_name)))
{
self::fix_encoded_options($type_options);
@@ -356,7 +356,7 @@ class Select extends Etemplate\Widget
$options = (isset(self::$request->sel_options[$form_name]) ? $form_name : $this->id);
if(is_array(self::$request->sel_options[$options]))
{
- if(in_array($this->attrs['type'], self::$cached_types) && !isset($form_names_done[$options]))
+ if (isset($this->attrs['type']) && in_array($this->attrs['type'], self::$cached_types) && !isset($form_names_done[$options]))
{
// Fix any custom options from application
self::fix_encoded_options(self::$request->sel_options[$options],true);
@@ -561,7 +561,7 @@ class Select extends Etemplate\Widget
$field = self::expand_name($field, 0, 0,'','',self::$cont);
}
- list($rows,$type,$type2,$type3,$type4,$type5) = $legacy_options;
+ list($rows,$type,$type2,$type3,$type4,$type5) = $legacy_options+[null,null,null,null,null,null];
$no_lang = false;
$options = array();
switch ($widget_type)
@@ -644,7 +644,7 @@ class Select extends Etemplate\Widget
// These are extra info for easy dealing with categories
// client side, without extra loading
'main' => (int)$cat['main'],
- 'children' => $cat['children'],
+ 'children' => $cat['children'] ?? null,
//add different class per level to allow different styling for each category level:
'class' => "cat_level". $cat['level']
);
@@ -839,7 +839,7 @@ class Select extends Etemplate\Widget
}
foreach((array)$options as $right => $name)
{
- if(!!($value & $right))
+ if (!!((int)$value & (int)$right))
{
$new_value[] = $right;
}
diff --git a/api/src/Etemplate/Widget/Template.php b/api/src/Etemplate/Widget/Template.php
index b83255e7e9..f256e78272 100644
--- a/api/src/Etemplate/Widget/Template.php
+++ b/api/src/Etemplate/Widget/Template.php
@@ -68,7 +68,7 @@ class Template extends Etemplate\Widget
list($name) = explode('?', $_name); // remove optional cache-buster
if (isset(self::$cache[$name]) || !($path = self::relPath($name, $template_set, $version, $load_via)))
{
- if ((!$path || self::read($load_via, $template_set)) && isset(self::$cache[$name]))
+ if ((empty($path) || self::read($load_via, $template_set)) && isset(self::$cache[$name]))
{
//error_log(__METHOD__."('$name', '$template_set', '$version', '$load_via') read from cache");
return self::$cache[$name];
@@ -146,7 +146,7 @@ class Template extends Etemplate\Widget
{
static $prefixes = null;
unset($version); // not used currently
- list($app, $rest) = explode('.', $load_via ?: $name, 2);
+ list($app, $rest) = explode('.', $load_via ?: $name, 2)+[null,null];
if (empty($template_set))
{
@@ -184,7 +184,7 @@ class Template extends Etemplate\Widget
$path = $prefix.$path;
}
//error_log(__METHOD__."('$name', '$template_set') returning ".array2string($path));
- return $path;
+ return $path ?? null;
}
/**
@@ -230,16 +230,16 @@ class Template extends Etemplate\Widget
{
$cname =& $params[0];
$old_cname = $params[0];
- if ($this->attrs['content']) $cname = self::form_name($cname, $this->attrs['content'], $params[1]);
+ if (!empty($this->attrs['content'])) $cname = self::form_name($cname, $this->attrs['content'], $params[1]);
// Check for template from content, and run over it
// templates included via template tag have their name to load them from in attribute "template"
- $expand_name = self::expand_name($this->id ? $this->id : $this->attrs['template'], '','','','',self::$request->content);
+ $expand_name = self::expand_name($this->id ?: $this->attrs['template'], '','','','',self::$request->content);
if(!$expand_name && $this->id && $this->attrs['template'])
{
$expand_name = $this->attrs['template'];
}
- if($this->original_name)
+ if (!empty($this->original_name))
{
$expand_name = self::expand_name($this->original_name, '','','','',self::$request->content);
}
diff --git a/api/src/Etemplate/Widget/Textbox.php b/api/src/Etemplate/Widget/Textbox.php
index 74717982ac..26a32a3897 100644
--- a/api/src/Etemplate/Widget/Textbox.php
+++ b/api/src/Etemplate/Widget/Textbox.php
@@ -62,14 +62,14 @@ class Textbox extends Etemplate\Widget
parent::set_attrs($xml, $cloned);
// Legacy handling only
- // A negative size triggered the HTML readonly attibute, but not etemplate readonly,
+ // A negative size triggered the HTML readonly attribute, but not etemplate readonly,
// so you got an input element, but it was not editable.
- if ($this->attrs['size'] < 0)
+ if (isset($this->attrs['size']) && $this->attrs['size'] < 0)
{
self::setElementAttribute($this->id, 'size', abs($this->attrs['size']));
self::$request->readonlys[$this->id] = false;
self::setElementAttribute($this->id, 'readonly', true);
- trigger_error("Using a negative size to set textbox readonly. " .$this, E_USER_DEPRECATED);
+ //trigger_error("Using a negative size to set textbox readonly. " .$this, E_USER_DEPRECATED);
}
return $this;
}
diff --git a/api/src/Etemplate/Widget/Tree.php b/api/src/Etemplate/Widget/Tree.php
index 1fa12c56d0..b05deaac1c 100644
--- a/api/src/Etemplate/Widget/Tree.php
+++ b/api/src/Etemplate/Widget/Tree.php
@@ -143,7 +143,7 @@ class Tree extends Etemplate\Widget
parent::set_attrs($xml, $cloned);
// set attrs[multiple] from attrs[options]
- if ($this->attrs['options'] > 1)
+ if (isset($this->attrs['options']) && (int)$this->attrs['options'] > 1)
{
self::setElementAttribute($this->id, 'multiple', true);
}
@@ -297,21 +297,21 @@ class Tree extends Etemplate\Widget
{
$form_name = self::form_name($cname, $this->id);
- if (($templated_path = self::templateImagePath($this->attrs['image_path'])) != $this->attrs['image_path'])
+ if (($templated_path = self::templateImagePath($this->attrs['image_path'] ?? null)) !== ($this->attrs['image_path'] ?? null))
{
self::setElementAttribute($form_name, 'image_path', $this->attrs['image_path'] = $templated_path);
//error_log(__METHOD__."() setting templated image-path for $form_name: $templated_path");
}
- if (!is_array(self::$request->sel_options[$form_name])) self::$request->sel_options[$form_name] = array();
- if ($this->attrs['type'])
+ if (empty(self::$request->sel_options[$form_name])) self::$request->sel_options[$form_name] = [];
+ if (!empty($this->attrs['type']))
{
// += to keep further options set by app code
- self::$request->sel_options[$form_name] += self::typeOptions($this->attrs['type'], $this->attrs['options'],
- $no_lang, $this->attrs['readonly'], self::get_array(self::$request->content, $form_name), $form_name);
+ self::$request->sel_options[$form_name] += self::typeOptions($this->attrs['type'], $this->attrs['options'] ?? null,
+ $no_lang, $this->attrs['readonly'] ?? null, self::get_array(self::$request->content, $form_name), $form_name);
// if no_lang was modified, forward modification to the client
- if ($no_lang != $this->attr['no_lang'])
+ if (!isset($this->attr['no_lang']) || $no_lang != $this->attr['no_lang'])
{
self::setElementAttribute($form_name, 'no_lang', $no_lang);
}
@@ -440,7 +440,7 @@ class Tree extends Etemplate\Widget
*/
public static function typeOptions($widget_type, $legacy_options, &$no_lang=false, $readonly=false, $value=null, $form_name=null)
{
- list($rows,$type,$type2,$type3) = explode(',',$legacy_options);
+ list($rows,$type,$type2,$type3) = explode(',', $legacy_options)+[null,null,null,null];
$no_lang = false;
$options = array();
diff --git a/api/src/Etemplate/Widget/Vfs.php b/api/src/Etemplate/Widget/Vfs.php
index 9781da9ad7..d04e8b96cc 100644
--- a/api/src/Etemplate/Widget/Vfs.php
+++ b/api/src/Etemplate/Widget/Vfs.php
@@ -37,10 +37,10 @@ class Vfs extends File
*/
public function beforeSendToClient($cname, $expand = array())
{
- if($this->type == 'vfs-upload' || $this->attrs['type'] == 'vfs-upload')
+ if ($this->type === 'vfs-upload' || !empty($this->attrs['type']) && $this->attrs['type'] === 'vfs-upload')
{
$form_name = self::form_name($cname, $this->id, $expand ? $expand : array('cont'=>self::$request->content));
- if($this->attrs['path'])
+ if (!empty($this->attrs['path']))
{
$path = self::expand_name($this->attrs['path'],$expand['c'], $expand['row'], $expand['c_'], $expand['row_'], $expand['cont']);
}
@@ -226,7 +226,7 @@ class Vfs extends File
foreach($links as $link)
{
$matches = null;
- if (is_array($link) && preg_match('|^'.preg_quote(Api\Vfs::PREFIX,'|').'('.preg_quote(self::get_temp_dir($app, ''), '|').'[^/]+)/|', $link['id']['tmp_name'], $matches))
+ if (is_array($link) && !empty($link['id']['tmp_name']) && preg_match('|^'.preg_quote(Api\Vfs::PREFIX,'|').'('.preg_quote(self::get_temp_dir($app, ''), '|').'[^/]+)/|', $link['id']['tmp_name'], $matches))
{
$replace[substr($link['id']['tmp_name'], strlen(Api\Vfs::PREFIX))] =
Api\Link::vfs_path($app, $id, Api\Vfs::basename($link['id']['tmp_name']), true);
diff --git a/api/src/Framework/Ajax.php b/api/src/Framework/Ajax.php
index 77f0e67530..e10618fa2c 100755
--- a/api/src/Framework/Ajax.php
+++ b/api/src/Framework/Ajax.php
@@ -2,12 +2,12 @@
/**
* EGroupware - Framework for Ajax based templates: jdots & Pixelegg
*
- * @link http://www.stylite.de
+ * @link https://www.egroupware.org
* @package api
* @subpackage framework
- * @author Andreas Stöckel
- * @author Ralf Becker
- * @author Nathan Gray
+ * @author Andreas Stöckel
+ * @author Ralf Becker
+ * @author Nathan Gray
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
*/
@@ -16,7 +16,7 @@ namespace EGroupware\Api\Framework;
use EGroupware\Api;
/**
-* Stylite jdots template
+* Framework for Ajax based templates
*/
abstract class Ajax extends Api\Framework
{
@@ -88,13 +88,13 @@ abstract class Ajax extends Api\Framework
$width = self::DEFAULT_SIDEBAR_WIDTH;
//Check whether the width had been stored explicitly for the jdots template, use that value
- if ($GLOBALS['egw_info']['user']['preferences'][$app]['jdotssideboxwidth'])
+ if (!empty($GLOBALS['egw_info']['user']['preferences'][$app]['jdotssideboxwidth']))
{
$width = (int)$GLOBALS['egw_info']['user']['preferences'][$app]['jdotssideboxwidth'];
// error_log(__METHOD__.__LINE__."($app):$width --> reading jdotssideboxwidth");
}
//Otherwise use the legacy "idotssideboxwidth" value
- else if ($GLOBALS['egw_info']['user']['preferences'][$app]['idotssideboxwidth'])
+ elseif (!empty($GLOBALS['egw_info']['user']['preferences'][$app]['idotssideboxwidth']))
{
$width = (int)$GLOBALS['egw_info']['user']['preferences'][$app]['idotssideboxwidth'];
// error_log(__METHOD__.__LINE__."($app):$width --> reading idotssideboxwidth");
@@ -249,7 +249,7 @@ abstract class Ajax extends Api\Framework
{
if (empty($GLOBALS['egw_info']['flags']['java_script'])) $GLOBALS['egw_info']['flags']['java_script']='';
// eT2 sets $GLOBALS['egw_info']['flags']['nonavbar'] === 'popup' for popups, Etemplate::exec($outputmode === 2)
- $extra['check-framework'] = $_GET['cd'] !== 'no' && $GLOBALS['egw_info']['flags']['nonavbar'] !== 'popup';
+ $extra['check-framework'] = (!isset($_GET['cd']) || $_GET['cd'] !== 'no') && $GLOBALS['egw_info']['flags']['nonavbar'] !== 'popup';
}
}
@@ -1047,16 +1047,16 @@ abstract class Ajax extends Api\Framework
if (self::$footer_done) return; // prevent (multiple) footers
self::$footer_done = true;
- if (!isset($GLOBALS['egw_info']['flags']['nofooter']) || !$GLOBALS['egw_info']['flags']['nofooter'])
+ if (empty($GLOBALS['egw_info']['flags']['nofooter']))
{
- if ($no_framework && $GLOBALS['egw_info']['user']['preferences']['common']['show_generation_time'])
+ if ($no_framework && !empty($GLOBALS['egw_info']['user']['preferences']['common']['show_generation_time']))
{
$vars = $this->_get_footer();
$footer = "\n".$vars['page_generation_time']."\n";
}
}
- return $footer.
- $GLOBALS['egw_info']['flags']['need_footer']."\n". // eg. javascript, which need to be at the end of the page
+ return ($footer??'').
+ ($GLOBALS['egw_info']['flags']['need_footer']??'')."\n". // eg. javascript, which need to be at the end of the page
"