Skip to content

Commit bffcb5b

Browse files
committed
feat(ldapselectfield): lazy loading
1 parent d170c79 commit bffcb5b

File tree

5 files changed

+255
-89
lines changed

5 files changed

+255
-89
lines changed

ajax/getldapvalues.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
/**
3+
* ---------------------------------------------------------------------
4+
* Formcreator is a plugin which allows creation of custom forms of
5+
* easy access.
6+
* ---------------------------------------------------------------------
7+
* LICENSE
8+
*
9+
* This file is part of Formcreator.
10+
*
11+
* Formcreator is free software; you can redistribute it and/or modify
12+
* it under the terms of the GNU General Public License as published by
13+
* the Free Software Foundation; either version 2 of the License, or
14+
* (at your option) any later version.
15+
*
16+
* Formcreator is distributed in the hope that it will be useful,
17+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+
* GNU General Public License for more details.
20+
*
21+
* You should have received a copy of the GNU General Public License
22+
* along with Formcreator. If not, see <http://www.gnu.org/licenses/>.
23+
* ---------------------------------------------------------------------
24+
* @copyright Copyright © 2011 - 2021 Teclib'
25+
* @license http://www.gnu.org/licenses/gpl.txt GPLv3+
26+
* @link https://github.com/pluginsGLPI/formcreator/
27+
* @link https://pluginsglpi.github.io/formcreator/
28+
* @link http://plugins.glpi-project.org/#/plugin/formcreator
29+
* ---------------------------------------------------------------------
30+
*/
31+
32+
include ('../../../inc/includes.php');
33+
34+
if (!defined('GLPI_ROOT')) {
35+
die("Sorry. You can't access this file directly");
36+
}
37+
38+
header('Content-Type: application/json; charset=UTF-8');
39+
Html::header_nocache();
40+
41+
// Check if plugin is activated...
42+
if (!Plugin::isPluginActive('formcreator')) {
43+
Html::displayNotFoundError();
44+
}
45+
46+
Session::checkLoginUser();
47+
echo PluginFormcreatorLdapDropdown::getDropdownValue($_POST);

ajax/gettranslationsvalues.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333

3434
// Direct access to file
3535
if (strpos($_SERVER['PHP_SELF'], 'gettranslationsvalues.php')) {
36-
include ('../../../inc/includes.php');
3736
header('Content-Type: application/json; charset=UTF-8');
3837
Html::header_nocache();
3938
} else if (!defined('GLPI_ROOT')) {

inc/field/ldapselectfield.class.php

Lines changed: 9 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,13 @@
3333
namespace GlpiPlugin\Formcreator\Field;
3434

3535
use AuthLDAP;
36-
use Exception;
3736
use Html;
3837
use Session;
3938
use RuleRightParameter;
39+
use PluginFormcreatorQuestion;
4040
use Glpi\Application\View\TemplateRenderer;
4141
use PluginFormcreatorAbstractField;
42+
use PluginFormcreatorLdapDropdown;
4243

4344
class LdapselectField extends SelectField
4445
{
@@ -67,17 +68,19 @@ public function getRenderedHtml($domain, $canEdit = true): string {
6768
$id = $this->question->getID();
6869
$rand = mt_rand();
6970
$fieldName = 'formcreator_field_' . $id;
70-
$values = $this->getAvailableValues();
7171

7272
if (!empty($this->question->fields['values'])) {
73-
$html .= Dropdown::showFromArray($fieldName, $values, [
74-
'display_emptychoice' => $this->question->fields['show_empty'] == 1,
73+
$options = [
74+
'name' => $fieldName,
7575
'value' => $this->value,
76-
'values' => [],
7776
'rand' => $rand,
7877
'multiple' => false,
7978
'display' => false,
80-
]);
79+
'condition' => [
80+
PluginFormcreatorQuestion::getForeignKeyField() => $this->question->getID()
81+
]
82+
];
83+
$html .= PluginFormcreatorLdapDropdown::dropdown($options);
8184
}
8285
$html .= PHP_EOL;
8386
$html .= Html::scriptBlock("$(function() {
@@ -87,77 +90,6 @@ public function getRenderedHtml($domain, $canEdit = true): string {
8790
return $html;
8891
}
8992

90-
public function getAvailableValues() {
91-
if (empty($this->question->fields['values'])) {
92-
return [];
93-
}
94-
95-
$ldap_values = json_decode($this->question->fields['values'], JSON_OBJECT_AS_ARRAY);
96-
$ldap_dropdown = new RuleRightParameter();
97-
if (!$ldap_dropdown->getFromDB($ldap_values['ldap_attribute'])) {
98-
return [];
99-
}
100-
$attribute = [$ldap_dropdown->fields['value']];
101-
102-
$config_ldap = new AuthLDAP();
103-
if (!$config_ldap->getFromDB($ldap_values['ldap_auth'])) {
104-
return [];
105-
}
106-
107-
set_error_handler([self::class, 'ldapErrorHandler'], E_WARNING);
108-
109-
$tab_values = [];
110-
try {
111-
$cookie = '';
112-
$ds = $config_ldap->connect();
113-
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
114-
do {
115-
if (AuthLDAP::isLdapPageSizeAvailable($config_ldap)) {
116-
$controls = [
117-
[
118-
'oid' => LDAP_CONTROL_PAGEDRESULTS,
119-
'iscritical' => true,
120-
'value' => [
121-
'size' => $config_ldap->fields['pagesize'],
122-
'cookie' => $cookie
123-
]
124-
]
125-
];
126-
$result = ldap_search($ds, $config_ldap->fields['basedn'], $ldap_values['ldap_filter'], $attribute, 0, -1, -1, LDAP_DEREF_NEVER, $controls);
127-
ldap_parse_result($ds, $result, $errcode, $matcheddn, $errmsg, $referrals, $controls);
128-
$cookie = $controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'] ?? '';
129-
} else {
130-
$result = ldap_search($ds, $config_ldap->fields['basedn'], $ldap_values['ldap_filter'], $attribute);
131-
}
132-
133-
$entries = ldap_get_entries($ds, $result);
134-
// openldap return 4 for Size limit exceeded
135-
$limitexceeded = in_array(ldap_errno($ds), [4, 11]);
136-
137-
if ($limitexceeded) {
138-
Session::addMessageAfterRedirect(__('LDAP size limit exceeded', 'formcreator'), true, WARNING);
139-
}
140-
array_shift($entries);
141-
142-
$id = 0;
143-
foreach ($entries as $attr) {
144-
if (!isset($attr[$attribute[0]]) || in_array($attr[$attribute[0]][0], $tab_values)) {
145-
continue;
146-
}
147-
$tab_values[$id] = $attr[$attribute[0]][0];
148-
$id++;
149-
}
150-
} while ($cookie !== null && $cookie != '');
151-
} catch (Exception $e) {
152-
restore_error_handler();
153-
trigger_error($e->getMessage(), E_USER_WARNING);
154-
}
155-
156-
restore_error_handler();
157-
asort($tab_values);
158-
return $tab_values;
159-
}
160-
16193
public static function getName(): string {
16294
return __('LDAP Select', 'formcreator');
16395
}
@@ -305,11 +237,4 @@ public function isVisibleField(): bool {
305237
public function isEditableField(): bool {
306238
return true;
307239
}
308-
309-
public static function ldapErrorHandler($errno, $errstr, $errfile, $errline) {
310-
if (0 === error_reporting()) {
311-
return false;
312-
}
313-
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
314-
}
315240
}

inc/ldapdropdown.class.php

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
<?php
2+
/**
3+
* ---------------------------------------------------------------------
4+
* Formcreator is a plugin which allows creation of custom forms of
5+
* easy access.
6+
* ---------------------------------------------------------------------
7+
* LICENSE
8+
*
9+
* This file is part of Formcreator.
10+
*
11+
* Formcreator is free software; you can redistribute it and/or modify
12+
* it under the terms of the GNU General Public License as published by
13+
* the Free Software Foundation; either version 2 of the License, or
14+
* (at your option) any later version.
15+
*
16+
* Formcreator is distributed in the hope that it will be useful,
17+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+
* GNU General Public License for more details.
20+
*
21+
* You should have received a copy of the GNU General Public License
22+
* along with Formcreator. If not, see <http://www.gnu.org/licenses/>.
23+
* ---------------------------------------------------------------------
24+
* @copyright Copyright © 2011 - 2020 Teclib'
25+
* @license http://www.gnu.org/licenses/gpl.txt GPLv3+
26+
* @link https://github.com/pluginsGLPI/formcreator/
27+
* @link https://pluginsglpi.github.io/formcreator/
28+
* @link http://plugins.glpi-project.org/#/plugin/formcreator
29+
* ---------------------------------------------------------------------
30+
*/
31+
32+
use Glpi\Toolbox\Sanitizer;
33+
34+
if (!defined('GLPI_ROOT')) {
35+
die("Sorry. You can't access this file directly");
36+
}
37+
38+
class PluginFormcreatorLdapDropdown extends CommonGLPI
39+
{
40+
public static function getTable() {
41+
return '';
42+
}
43+
44+
public function getForeignKeyField() {
45+
return '';
46+
}
47+
48+
public function isField() {
49+
return false;
50+
}
51+
52+
public static function dropdown($options = []) {
53+
$options['display'] = $options['display'] ?? false;
54+
$options['url'] = Plugin::getWebDir('formcreator') . '/ajax/getldapvalues.php';
55+
56+
$out = Dropdown::show(self::class, $options);
57+
if (!$options['display']) {
58+
return $out;
59+
}
60+
echo $out;
61+
}
62+
63+
public static function getDropdownValue($post, $json = true) {
64+
// Count real items returned
65+
$count = 0;
66+
67+
if (isset($post['condition']) && !empty($post['condition']) && !is_array($post['condition'])) {
68+
// Retreive conditions from SESSION using its key
69+
$key = $post['condition'];
70+
$post['condition'] = [];
71+
if (isset($_SESSION['glpicondition']) && isset($_SESSION['glpicondition'][$key])) {
72+
$post['condition'] = $_SESSION['glpicondition'][$key];
73+
}
74+
}
75+
76+
$questionId = $post['condition'][PluginFormcreatorQuestion::getForeignKeyField()];
77+
$question = PluginFormcreatorQuestion::getById($questionId);
78+
if (!is_object($question)) {
79+
return [];
80+
}
81+
82+
$form = PluginFormcreatorCommon::getForm();
83+
$form = $form::getByItem($question);
84+
if (!$form->canViewForRequest()) {
85+
return [];
86+
}
87+
$post['searchText'] = $post['searchText'] ?? '';
88+
89+
// Search values
90+
$ldap_values = json_decode($question->fields['values'], JSON_OBJECT_AS_ARRAY);
91+
$ldap_dropdown = new RuleRightParameter();
92+
if (!$ldap_dropdown->getFromDB($ldap_values['ldap_attribute'])) {
93+
return [];
94+
}
95+
$attribute = [$ldap_dropdown->fields['value']];
96+
97+
$config_ldap = new AuthLDAP();
98+
if (!$config_ldap->getFromDB($ldap_values['ldap_auth'])) {
99+
return [];
100+
}
101+
102+
set_error_handler([self::class, 'ldapErrorHandler'], E_WARNING);
103+
104+
if ($post['searchText'] != '') {
105+
$ldap_values['ldap_filter'] = sprintf(
106+
"(& %s (%s))",
107+
$ldap_values['ldap_filter'],
108+
$attribute[0] . '=*' . $post['searchText'] . '*'
109+
);
110+
}
111+
112+
$tab_values = [];
113+
try {
114+
$cookie = '';
115+
$ds = $config_ldap->connect();
116+
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
117+
$foundCount = 0;
118+
do {
119+
if (AuthLDAP::isLdapPageSizeAvailable($config_ldap)) {
120+
$controls = [
121+
[
122+
'oid' => LDAP_CONTROL_PAGEDRESULTS,
123+
'iscritical' => true,
124+
'value' => [
125+
'size' => $config_ldap->fields['pagesize'],
126+
'cookie' => $cookie
127+
]
128+
]
129+
];
130+
$result = ldap_search($ds, $config_ldap->fields['basedn'], $ldap_values['ldap_filter'], $attribute, 0, -1, -1, LDAP_DEREF_NEVER, $controls);
131+
ldap_parse_result($ds, $result, $errcode, $matcheddn, $errmsg, $referrals, $controls);
132+
$cookie = $controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'] ?? '';
133+
} else {
134+
$result = ldap_search($ds, $config_ldap->fields['basedn'], $ldap_values['ldap_filter'], $attribute);
135+
}
136+
137+
$entries = ldap_get_entries($ds, $result);
138+
// openldap return 4 for Size limit exceeded
139+
$limitexceeded = in_array(ldap_errno($ds), [4, 11]);
140+
141+
if ($limitexceeded) {
142+
Session::addMessageAfterRedirect(__('LDAP size limit exceeded', 'formcreator'), true, WARNING);
143+
}
144+
145+
unset($entries['count']);
146+
147+
foreach ($entries as $attr) {
148+
if (!isset($attr[$attribute[0]]) || in_array($attr[$attribute[0]][0], $tab_values)) {
149+
continue;
150+
}
151+
152+
$foundCount++;
153+
if ($foundCount < ((int) $post['page'] - 1) * (int) $post['page_limit'] + 1) {
154+
// before the requested page
155+
continue;
156+
}
157+
if ($foundCount > ((int) $post['page']) * (int) $post['page_limit']) {
158+
// after the requested page
159+
break;
160+
}
161+
162+
$tab_values[] = [
163+
'id' => $attr[$attribute[0]][0],
164+
'text' => $attr[$attribute[0]][0],
165+
];
166+
$count++;
167+
if ($count >= $post['page_limit']) {
168+
break;
169+
}
170+
}
171+
} while ($cookie !== null && $cookie != '' && $count < $post['page_limit']);
172+
} catch (Exception $e) {
173+
restore_error_handler();
174+
trigger_error($e->getMessage(), E_USER_WARNING);
175+
}
176+
177+
restore_error_handler();
178+
179+
$tab_values = Sanitizer::unsanitize($tab_values);
180+
usort($tab_values, function($a, $b) {
181+
return strnatcmp($a['text'], $b['text']);
182+
});
183+
$ret['results'] = $tab_values;
184+
$ret['count'] = $count;
185+
186+
return ($json === true) ? json_encode($ret) : $ret;
187+
}
188+
189+
public static function ldapErrorHandler($errno, $errstr, $errfile, $errline) {
190+
if (0 === error_reporting()) {
191+
return false;
192+
}
193+
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
194+
}
195+
}

0 commit comments

Comments
 (0)