Commit 20ffcffb authored by Elias Villiger's avatar Elias Villiger
Browse files

Bug #5444 - Add feature typeAheadSqlPrefetch

parent 414539db
......@@ -1563,12 +1563,13 @@ Prefetch
^^^^^^^^
After 'form load' with an existing record, the user epects to see the previous saved data. In case there is an *id* to
*value* translation, the *value* does not exist in the database, instead it has to be fetched again dynamically from the
LDAP server. A precise LDAP query has to be defined to force this:
*value* translation, the *value* does not exist in the database, instead it has to be fetched again dynamically.
A precise LDAP or SQL query has to be defined to force this:
* *Form.parameter* or *FormElement.parameter*:
* *typeAheadLdapSearchPrefetch* = `(mail=?)`
* *typeAheadSqlPrefetch* = `SELECT firstName, ' ', lastName FROM person WHERE id = ?`
This situation also applies in *pedantic* mode to verify the user input after each change.
......@@ -2488,6 +2489,7 @@ See also at specific *FormElement* definitions.
| typeAheadLimit | string | See `input-typeahead`_ |
| typeAheadMinLength | string | |
| typeAheadSql | string | |
| typeAheadSqlPrefetch | string | |
+------------------------+--------+----------------------------------------------------------------------------------------------------------+
| editor-plugins | string | See `input-editor`_ |
| editor-toolbar | string | |
......@@ -2856,6 +2858,11 @@ SQL
* The value, typed by the user, will be replaced on all places where a `?` appears.
* All `?` will be automatically surrounded by '%'. Therefore wildcard search is implemented: `... LIKE '%<?>%' ...`
* *typeAheadSqlPrefetch* = `SELECT firstName, ' ', lastName FROM person WHERE id = ?`
* If the query returns several results, only the first one is returned and displayed.
* If the query selects multiple columns, the columns are concatenated.
LDAP
;;;;
......
......@@ -685,7 +685,6 @@ abstract class AbstractBuildForm {
* @throws UserFormException
*/
private function prepareFillStoreFireLdap(array $formElement) {
$config = array();
if (isset($formElement[FE_FILL_STORE_LDAP]) || isset($formElement[FE_TYPEAHEAD_LDAP])) {
$keyNames = [F_LDAP_SERVER, F_LDAP_BASE_DN, F_LDAP_ATTRIBUTES,
......@@ -1192,14 +1191,19 @@ abstract class AbstractBuildForm {
*/
private function typeAheadBuildParam(array &$formElement) {
$urlParam = '';
$arr = [];
$formElement[FE_TYPEAHEAD_LIMIT] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_LIMIT, TYPEAHEAD_DEFAULT_LIMIT);
$formElement[FE_TYPEAHEAD_MINLENGTH] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_MINLENGTH, 2);
if (isset($formElement[FE_TYPEAHEAD_SQL])) {
$sql = $this->checkSqlAppendLimit($formElement[FE_TYPEAHEAD_SQL], $formElement[FE_TYPEAHEAD_LIMIT]);
$urlParam = FE_TYPEAHEAD_SQL . '=' . $sql;
$formElement[FE_TYPEAHEAD_SQL_PREFETCH] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_SQL_PREFETCH);
$arr = [
FE_TYPEAHEAD_SQL => $sql,
FE_TYPEAHEAD_SQL_PREFETCH => $formElement[FE_TYPEAHEAD_SQL_PREFETCH]
];
} elseif (isset($formElement[FE_TYPEAHEAD_LDAP])) {
$formElement[FE_LDAP_SERVER] = Support::setIfNotSet($formElement, FE_LDAP_SERVER);
$formElement[FE_LDAP_BASE_DN] = Support::setIfNotSet($formElement, FE_LDAP_BASE_DN);
......@@ -1238,11 +1242,9 @@ abstract class AbstractBuildForm {
$arr[SYSTEM_LDAP_1_PASSWORD] = $this->store->getVar(SYSTEM_LDAP_1_PASSWORD, STORE_SYSTEM);
}
$urlParam = OnArray::toString($arr);
}
return $urlParam;
return OnArray::toString($arr);
}
/**
......
......@@ -233,11 +233,12 @@ const ERROR_UPLOAD_GET_MIME_TYPE = 1503;
const ERROR_UPLOAD_UNKNOWN_ACTION = 1504;
const ERROR_NO_TARGET_PATH_FILE_NAME = 1505;
// LDAP
// LDAP / typeahead
const ERROR_LDAP_CONNECT = 1600;
const ERROR_MISSING_TYPE_AHEAD_LDAP_SEARCH = 1601;
const ERROR_MISSING_TYPE_AHEAD_LDAP_SEARCH_PREFETCH = 1602;
const ERROR_LDAP_BIND = 1603;
const ERROR_MISSING_TYPE_AHEAD_SQL_PREFETCH = 1604;
// Download
const ERROR_DOWNLOAD_CREATE_NEW_FILE = 1700;
......@@ -951,6 +952,7 @@ const FE_TYPEAHEAD_LIMIT = F_TYPEAHEAD_LIMIT;
const FE_TYPEAHEAD_MINLENGTH = F_TYPEAHEAD_MINLENGTH;
const FE_TYPEAHEAD_PEDANTIC = F_TYPEAHEAD_PEDANTIC;
const FE_TYPEAHEAD_SQL = 'typeAheadSql';
const FE_TYPEAHEAD_SQL_PREFETCH = 'typeAheadSqlPrefetch';
const FE_TYPEAHEAD_LDAP_VALUE_PRINTF = F_TYPEAHEAD_LDAP_VALUE_PRINTF;
const FE_TYPEAHEAD_LDAP_ID_PRINTF = F_TYPEAHEAD_LDAP_ID_PRINTF;
const FE_TYPEAHEAD_LDAP = 'typeAheadLdap';
......
......@@ -61,14 +61,17 @@ class TypeAhead {
public function process() {
$arr = array();
$values = array();
$sipClass = new Sip();
$sipVars = $sipClass->getVarsFromSip($this->vars[TYPEAHEAD_API_SIP]);
if (isset($sipVars[FE_TYPEAHEAD_SQL])) {
$arr = $this->typeAheadSql($sipVars, $this->vars[TYPEAHEAD_API_QUERY]);
if($this->vars[TYPEAHEAD_API_PREFETCH] == '') {
$arr = $this->typeAheadSql($sipVars, $this->vars[TYPEAHEAD_API_QUERY]);
} else {
$arr = $this->typeAheadSqlPrefetch($sipVars, $this->vars[TYPEAHEAD_API_PREFETCH]);
}
} elseif (isset($sipVars[FE_LDAP_SERVER])) {
$ldap = new Ldap();
......@@ -87,7 +90,7 @@ class TypeAhead {
}
/**
* Do a wildcard serach on the prepared statement $config[FE_TYPEAHEAD_SQL].
* Do a wildcard search on the prepared statement $config[FE_TYPEAHEAD_SQL].
* All '?' will be replaced by '%$value%'.
* If there is no 'LIMIT x' defined, append it.
* Returns an dict array [ API_TYPEAHEAD_KEY => key, API_TYPEAHEAD_VALUE => value ]
......@@ -126,6 +129,44 @@ class TypeAhead {
return $this->db->makeArrayDict($arr, TYPEAHEAD_SQL_KEY_NAME, API_TYPEAHEAD_VALUE, API_TYPEAHEAD_KEY, API_TYPEAHEAD_VALUE);
}
/**
* Returns a dict array [ API_TYPEAHEAD_KEY => key, API_TYPEAHEAD_VALUE => value ] with the prefetch result
*
* @param array $config
* @param string $key
*
* @return array
* @throws UserFormException
*/
private function typeAheadSqlPrefetch(array $config, $key) {
$keys = array();
$sql = $config[FE_TYPEAHEAD_SQL_PREFETCH];
if ($config[FE_TYPEAHEAD_SQL_PREFETCH] == '') {
throw new UserFormException("Missing definition for `" . FE_TYPEAHEAD_SQL_PREFETCH . "`", ERROR_MISSING_TYPE_AHEAD_SQL_PREFETCH);
}
$cnt = substr_count($sql, '?');
if ($cnt == 0) {
throw new UserFormException("Missing at least one '?' in " . FE_TYPEAHEAD_SQL_PREFETCH);
}
for ($ii = 0; $ii < $cnt; $ii++) {
$keys[] = $key;
}
$arr = $this->db->sql($sql, ROW_REGULAR, $keys);
if ($arr == false || count($arr) == 0) {
return array();
}
// return first result as key-value pair (concatenate columns)
$value = '';
foreach($arr[0] AS $name => $column) {
$value .= $column;
}
return [ [ API_TYPEAHEAD_KEY => $key, API_TYPEAHEAD_VALUE => $value ] ];
}
}
\ No newline at end of file
......@@ -34,6 +34,10 @@ class OnArray {
* @return string
*/
public static function toString(array $dataArray, $keyValueGlue = '=', $rowGlue = '&', $encloseValue = '') {
if (count($dataArray) === 0) {
return '';
}
$dataString = '';
foreach ($dataArray as $key => $value) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment