diff --git a/ajax_dataload.php b/ajax_dataload.php
index b53ae590f..e85d193f3 100644
--- a/ajax_dataload.php
+++ b/ajax_dataload.php
@@ -2,6 +2,8 @@
include_once __DIR__.'/core.php';
+use Util\Query;
+
// Informazioni fondamentali
$columns = filter('columns');
$order = filter('order')[0];
@@ -32,27 +34,23 @@ $results = [
'summable' => [],
];
-$query = Util\Query::getQuery($structure);
+$query = Query::getQuery($structure);
if (!empty($query)) {
// CONTEGGIO TOTALE
$results['recordsTotal'] = $dbo->fetchNum($query);
// RISULTATI VISIBILI
- $query = Util\Query::getQuery($structure, $search, $order, $limit);
+ $query = Query::getQuery($structure, $search, $order, $limit);
// Filtri derivanti dai permessi (eventuali)
if (empty($id_plugin)) {
$query = Modules::replaceAdditionals($id_module, $query);
}
- $query = str_replace_once('SELECT', 'SELECT SQL_CALC_FOUND_ROWS', $query);
- $rows = $dbo->fetchArray($query);
-
// Conteggio dei record filtrati
- $count = $dbo->fetchArray('SELECT FOUND_ROWS()');
- if (!empty($count)) {
- $results['recordsFiltered'] = $count[0]['FOUND_ROWS()'];
- }
+ $data = Query::executeAndCount($query);
+ $rows = $data['results'];
+ $results['recordsFiltered'] = $data['count'];
// SOMME
$results['summable'] = Util\Query::getSums($structure, $search);
diff --git a/ajax_select.php b/ajax_select.php
index 6ef1bf4f5..473f522a4 100644
--- a/ajax_select.php
+++ b/ajax_select.php
@@ -4,14 +4,16 @@ include_once __DIR__.'/core.php';
if (!isset($resource)) {
$op = empty($op) ? filter('op') : $op;
- $search = filter('q');
+ $search = filter('search');
+ $page = filter('page') ?: 0;
+ $length = filter('length') ?: 100;
if (!isset($elements)) {
$elements = [];
}
$elements = (!is_array($elements)) ? explode(',', $elements) : $elements;
- $results = AJAX::select($op, $elements, $search);
+ $results = AJAX::select($op, $elements, $search, $page, $length);
echo json_encode($results);
}
diff --git a/lib/functions.js b/lib/functions.js
index bbcc2c911..80f34ad78 100644
--- a/lib/functions.js
+++ b/lib/functions.js
@@ -972,13 +972,23 @@ function start_superselect() {
delay: 250,
data: function (params) {
return {
- q: params.term // search term
+ search: params.term,
+ page: params.page || 0,
+ length: params.length || 100,
}
},
- processResults: function (data) {
- return {
- results: data
- }
+ processResults: function (data, params) {
+ params.page = params.page || 0;
+ params.length = params.length || 100;
+
+ var response = {
+ results: data.results,
+ pagination: {
+ more: (params.page + 1) * params.length < data.recordsFiltered,
+ }
+ };
+
+ return response;
},
cache: false
},
diff --git a/lib/helpers.php b/lib/helpers.php
index d4569f87e..00579de71 100644
--- a/lib/helpers.php
+++ b/lib/helpers.php
@@ -175,3 +175,60 @@ function logger()
{
return Monolog\Registry::getInstance('logs');
}
+
+/**
+ * Restituisce il numero indicato formattato secondo la configurazione del sistema.
+ *
+ * @param float $number
+ * @param int $decimals
+ *
+ * @return string
+ *
+ * @since 2.4.8
+ */
+function numberFormat($number, $decimals)
+{
+ return Translator::numberToLocale($number, $decimals);
+}
+
+/**
+ * Restituisce il timestamp indicato formattato secondo la configurazione del sistema.
+ *
+ * @param string $timestamp
++ *
+ * @return string
+ *
+ * @since 2.4.8
+ */
+function timestampFormat($timestamp)
+{
+ return Translator::timestampToLocale($timestamp);
+}
+
+/**
+ * Restituisce la data indicata formattato secondo la configurazione del sistema.
+ *
+ * @param string $date
+ *
+ * @return string
+ *
+ * @since 2.4.8
+ */
+function dateFormat($date)
+{
+ return Translator::dateToLocale($date);
+}
+
+/**
+ * Restituisce l'orario indicato formattato secondo la configurazione del sistema.
+ *
+ * @param string $time
+ *
+ * @return string
+ *
+ * @since 2.4.8
+ */
+function timeFormat($time)
+{
+ return Translator::timeToLocale($time);
+}
diff --git a/lib/util.php b/lib/util.php
index 49055a533..74a355441 100644
--- a/lib/util.php
+++ b/lib/util.php
@@ -77,30 +77,6 @@ if (!function_exists('ends_with')) {
}
}
-if (!function_exists('str_replace_once')) {
- /**
- * Sostituisce la prima occorenza di una determinata stringa.
- *
- * @param string $str_pattern
- * @param string $str_replacement
- * @param string $string
- *
- * @since 2.3
- *
- * @return string
- */
- function str_replace_once($str_pattern, $str_replacement, $string)
- {
- if (strpos($string, $str_pattern) !== false) {
- $occurrence = strpos($string, $str_pattern);
-
- return substr_replace($string, $str_replacement, strpos($string, $str_pattern), strlen($str_pattern));
- }
-
- return $string;
- }
-}
-
if (!function_exists('str_contains')) {
/**
* Check if a string contains the given string.
diff --git a/modules/anagrafiche/ajax/select.php b/modules/anagrafiche/ajax/select.php
index d2b85fd24..a37bee004 100644
--- a/modules/anagrafiche/ajax/select.php
+++ b/modules/anagrafiche/ajax/select.php
@@ -87,7 +87,7 @@ switch ($resource) {
$search_fields[] = 'provincia LIKE '.prepare('%'.$search.'%');
}
- $results = AJAX::completeResults($query, $where, $filter, $search, $custom);
+ $results = AJAX::selectResults($query, $where, $filter, $search, $limit, $custom);
// Evidenzia l'agente di default
if ($superselect['idanagrafica']) {
diff --git a/modules/articoli/ajax/select.php b/modules/articoli/ajax/select.php
index adbae2920..e70fa2e9f 100644
--- a/modules/articoli/ajax/select.php
+++ b/modules/articoli/ajax/select.php
@@ -4,7 +4,62 @@ include_once __DIR__.'/../../../core.php';
switch ($resource) {
case 'articoli':
- $query = 'SELECT mg_articoli.*, (SELECT CONCAT(co_pianodeiconti2.numero, ".", co_pianodeiconti3.numero, " ", co_pianodeiconti3.descrizione) FROM co_pianodeiconti3 INNER JOIN co_pianodeiconti2 ON co_pianodeiconti3.idpianodeiconti2=co_pianodeiconti2.id WHERE co_pianodeiconti3.id = idconto_vendita) AS idconto_vendita_title, (SELECT CONCAT(co_pianodeiconti2.numero, ".", co_pianodeiconti3.numero, " ", co_pianodeiconti3.descrizione) FROM co_pianodeiconti3 INNER JOIN co_pianodeiconti2 ON co_pianodeiconti3.idpianodeiconti2=co_pianodeiconti2.id WHERE co_pianodeiconti3.id = idconto_acquisto) AS idconto_acquisto_title, co_iva.descrizione AS iva_vendita FROM mg_articoli LEFT OUTER JOIN co_iva ON mg_articoli.idiva_vendita=co_iva.id |where| ORDER BY mg_articoli.id_categoria ASC, mg_articoli.id_sottocategoria ASC';
+ $query = 'SELECT
+ mg_articoli.id,
+ mg_articoli.codice,
+ mg_articoli.descrizione,
+ mg_articoli.um,
+ mg_articoli.idiva_vendita,
+ mg_articoli.idconto_vendita,
+ mg_articoli.idconto_acquisto,
+ mg_articoli.prezzo_vendita,
+ mg_articoli.prezzo_acquisto,
+ categoria.`nome` AS categoria,
+ sottocategoria.`nome` AS sottocategoria,
+ co_iva.descrizione AS iva_vendita,
+ CONCAT(conto_vendita_categoria .numero, ".", conto_vendita_sottocategoria.numero, " ", conto_vendita_sottocategoria.descrizione) AS idconto_vendita_title,
+ CONCAT(conto_acquisto_categoria .numero, ".", conto_acquisto_sottocategoria.numero, " ", conto_acquisto_sottocategoria.descrizione) AS idconto_acquisto_title
+ FROM mg_articoli
+ LEFT JOIN co_iva ON mg_articoli.idiva_vendita = co_iva.id
+ LEFT JOIN `mg_categorie` AS categoria ON `categoria`.`id` = `mg_articoli`.`id_categoria`
+ LEFT JOIN `mg_categorie` AS sottocategoria ON `sottocategoria`.`id` = `mg_articoli`.`id_sottocategoria`
+ LEFT JOIN co_pianodeiconti3 AS conto_vendita_sottocategoria ON conto_vendita_sottocategoria.id=mg_articoli.idconto_vendita
+ LEFT JOIN co_pianodeiconti2 AS conto_vendita_categoria ON conto_vendita_sottocategoria.idpianodeiconti2=conto_vendita_categoria.id
+ LEFT JOIN co_pianodeiconti3 AS conto_acquisto_sottocategoria ON conto_acquisto_sottocategoria.id=mg_articoli.idconto_acquisto
+ LEFT JOIN co_pianodeiconti2 AS conto_acquisto_categoria ON conto_acquisto_sottocategoria.idpianodeiconti2=conto_acquisto_categoria.id
+ |where| ORDER BY mg_articoli.id_categoria ASC, mg_articoli.id_sottocategoria ASC';
+
+ foreach ($elements as $element) {
+ $filter[] = 'mg_articoli.id='.prepare($element);
+ }
+
+ $where[] = 'attivo = 1';
+ if (!empty($superselect['dir']) && $superselect['dir'] == 'entrata') {
+ //$where[] = '(qta > 0 OR servizio = 1)';
+ }
+
+ if (!empty($search)) {
+ $search_fields[] = 'mg_articoli.descrizione LIKE '.prepare('%'.$search.'%');
+ $search_fields[] = 'mg_articoli.codice LIKE '.prepare('%'.$search.'%');
+ }
+
+ $custom = [
+ 'id' => 'id',
+ 'codice' => 'codice',
+ 'descrizione' => 'descrizione',
+ 'um' => 'um',
+ 'idiva_vendita' => 'idiva_vendita',
+ 'iva_vendita' => 'iva_vendita',
+ 'idconto_vendita' => 'idconto_vendita',
+ 'idconto_vendita_title' => 'idconto_vendita_title',
+ 'idconto_acquisto' => 'idconto_acquisto',
+ 'idconto_acquisto_title' => 'idconto_acquisto_title',
+ 'prezzo_acquisto' => 'prezzo_acquisto',
+ 'prezzo_vendita' => 'prezzo_vendita',
+ ];
+
+ $data = AJAX::selectResults($query, $where, $filter, $search_fields, $limit, $custom);
+ $rs = $data['results'];
// Individuazione di eventuali listini
if (!empty($superselect['dir']) && !empty($superselect['idanagrafica'])) {
@@ -21,45 +76,22 @@ switch ($resource) {
$idiva_predefinita = get_var('Iva predefinita');
$iva_predefinita = $dbo->fetchOne('SELECT descrizione FROM co_iva WHERE id='.prepare($idiva_predefinita))['descrizione'];
- foreach ($elements as $element) {
- $filter[] = 'mg_articoli.id='.prepare($element);
- }
-
- $where[] = 'attivo = 1';
- if (!empty($superselect['dir']) && $superselect['dir'] == 'entrata') {
- //$where[] = '(qta > 0 OR servizio = 1)';
- }
-
- if (!empty($search)) {
- $search_fields[] = 'mg_articoli.descrizione LIKE '.prepare('%'.$search.'%');
- $search_fields[] = 'mg_articoli.codice LIKE '.prepare('%'.$search.'%');
- }
-
- if (!empty($search_fields)) {
- $where[] = '('.implode(' OR ', $search_fields).')';
- }
-
- if (!empty($filter)) {
- $where[] = '('.implode(' OR ', $filter).')';
- }
-
- $wh = '';
- if (count($where) != 0) {
- $wh = 'WHERE '.implode(' AND ', $where);
- }
- $query = str_replace('|where|', $wh, $query);
-
- $prev = -1;
- $rs = $dbo->fetchArray($query);
+ $previous_category = -1;
+ $previous_subcategory = -1;
foreach ($rs as $r) {
- if ($prev != $r['id_sottocategoria']) {
- $categoria = $dbo->fetchOne('SELECT `nome` FROM `mg_categorie` WHERE `id`='.prepare($r['id_categoria']))['nome'];
+ if ($previous_category != $r['categoria'] || $previous_subcategory != $r['sottocategoria']) {
+ $previous_category = $r['categoria'];
+ $previous_subcategory = $r['sottocategoria'];
- $sottocategoria = $dbo->fetchOne('SELECT `nome` FROM `mg_categorie` WHERE `id`='.prepare($r['id_sottocategoria']));
- $sottocategoria = isset($sottocategoria['nome']) ? $sottocategoria['nome'] : null;
+ $text = ''.tr('Nessuna categoria').'';
+ if (!empty($r['categoria'])) {
+ $text = $r['categoria'].' ('.(!empty($r['sottocategoria']) ? $r['sottocategoria'] : '-').')';
+ }
- $prev = $r['id_sottocategoria'];
- $results[] = ['text' => $categoria.' ('.(!empty($r['id_sottocategoria']) ? $sottocategoria : '-').')', 'children' => []];
+ $results[] = [
+ 'text' => $text,
+ 'children' => [],
+ ];
}
// Iva dell'articolo
@@ -101,6 +133,11 @@ switch ($resource) {
];
}
+ $results = [
+ 'results' => $results,
+ 'recordsFiltered' => $data['recordsFiltered'],
+ ];
+
break;
case 'prodotti_lotti':
diff --git a/modules/gestione_componenti/ajax/select.php b/modules/gestione_componenti/ajax/select.php
index 0a1833c20..483805bd8 100644
--- a/modules/gestione_componenti/ajax/select.php
+++ b/modules/gestione_componenti/ajax/select.php
@@ -24,7 +24,7 @@ switch ($resource) {
$custom['contenuto'] = 'contenuto';
- $results = AJAX::completeResults($query, $where, $filter, $search, $custom);
+ $results = AJAX::selectResults($query, $where, $filter, $search, $limit, $custom);
foreach ($results as $key => $value) {
$matricola = \Util\Ini::getValue($r['contenuto'], 'Matricola');
diff --git a/src/AJAX.php b/src/AJAX.php
index 4e0aee995..7a0684da5 100644
--- a/src/AJAX.php
+++ b/src/AJAX.php
@@ -23,10 +23,12 @@ class AJAX
* @param string $resource
* @param array $elements
* @param mixed $search
+ * @param int $page
+ * @param int $length
*
* @return array
*/
- public static function select($resource, $elements = [], $search = null)
+ public static function select($resource, $elements = [], $search = null, $page = 0, $length = 100)
{
if (!isset($elements)) {
$elements = [];
@@ -39,13 +41,23 @@ class AJAX
array_unshift($files, DOCROOT.'/ajax_select.php');
foreach ($files as $file) {
- $results = self::getSelectResults($file, $resource, $elements, $search);
+ $results = self::getSelectResults($file, $resource, $elements, [
+ 'offset' => $page * $length,
+ 'length' => $length,
+ ], $search);
+
if (isset($results)) {
break;
}
}
- return $results;
+ $total = $results['recordsFiltered'] ?: count($results);
+ $list = $results['results'] ? $results['results'] : $results;
+
+ return [
+ 'results' => $list,
+ 'recordsFiltered' => $total,
+ ];
}
/**
@@ -55,11 +67,12 @@ class AJAX
* @param array $where
* @param array $filter
* @param array $search
+ * @param array $limit
* @param array $custom
*
* @return array
*/
- public static function completeResults($query, $where, $filter = [], $search = [], $custom = [])
+ public static function selectResults($query, $where, $filter = [], $search = [], $limit = [], $custom = [])
{
if (str_contains($query, '|filter|')) {
$query = str_replace('|filter|', !empty($filter) ? 'WHERE '.implode(' OR ', $filter) : '', $query);
@@ -72,21 +85,25 @@ class AJAX
}
$query = str_replace('|where|', !empty($where) ? 'WHERE '.implode(' AND ', $where) : '', $query);
+ $query .= ' LIMIT '.$limit['offset'].', '.$limit['length'];
- $database = database();
- $rs = $database->fetchArray($query);
+ $data = \Util\Query::executeAndCount($query);
+ $rows = $data['results'];
$results = [];
- foreach ($rs as $r) {
+ foreach ($rows as $row) {
$result = [];
foreach ($custom as $key => $value) {
- $result[$key] = $r[$value];
+ $result[$key] = $row[$value];
}
$results[] = $result;
}
- return $results;
+ return [
+ 'results' => $results,
+ 'recordsFiltered' => $data['count'],
+ ];
}
/**
@@ -196,11 +213,12 @@ class AJAX
* @param string $file
* @param string $resource
* @param array $elements
+ * @param array $limit
* @param mixed $search
*
* @return array|null
*/
- protected static function getSelectResults($file, $resource, $elements = [], $search = null)
+ protected static function getSelectResults($file, $resource, $elements = [], $limit = [], $search = null)
{
$superselect = self::getSelectInfo();
@@ -219,7 +237,7 @@ class AJAX
require $file;
if (!isset($results) && !empty($query)) {
- $results = self::completeResults($query, $where, $filter, $search_fields, $custom);
+ $results = self::selectResults($query, $where, $filter, $search_fields, $limit, $custom);
}
return isset($results) ? $results : null;
diff --git a/src/HTMLBuilder/Handler/SelectHandler.php b/src/HTMLBuilder/Handler/SelectHandler.php
index feafa081b..66aba5d09 100644
--- a/src/HTMLBuilder/Handler/SelectHandler.php
+++ b/src/HTMLBuilder/Handler/SelectHandler.php
@@ -98,8 +98,8 @@ class SelectHandler implements HandlerInterface
* Gestione dell'input di tipo "select" con richieste AJAX (nome della richiesta indicato tramite attributo "ajax-source").
* Esempio: {[ "type": "select", "label": "Select di test", "name": "test", "ajax-source": "test" ]}.
*
- * @param array $values
- * @param array $extras
+ * @param string $op
+ * @param array $elements
*
* @return string
*/
@@ -111,10 +111,11 @@ class SelectHandler implements HandlerInterface
include DOCROOT.'/ajax_select.php';
$text = ob_get_clean();
- $result = '';
+ $html = '';
- $array = (array) json_decode($text, true);
- foreach ($array as $element) {
+ $response = (array) json_decode($text, true);
+ $results = $response['results'];
+ foreach ($results as $element) {
$element = (array) $element;
if (isset($element['children'][0])) {
$element = (array) $element['children'][0];
@@ -137,11 +138,11 @@ class SelectHandler implements HandlerInterface
}
}
- $result .= '
+ $html .= '
';
}
- return $result;
+ return $html;
}
/**
diff --git a/src/Util/Query.php b/src/Util/Query.php
index 8d91148aa..d0d0be8b3 100644
--- a/src/Util/Query.php
+++ b/src/Util/Query.php
@@ -181,6 +181,23 @@ class Query
return $query;
}
+ public static function executeAndCount($query)
+ {
+ $database = database();
+
+ // Esecuzione della query
+ $query = self::str_replace_once('SELECT', 'SELECT SQL_CALC_FOUND_ROWS', $query);
+ $results = $database->fetchArray($query);
+
+ // Conteggio dei record filtrati
+ $count = $database->fetchOne('SELECT FOUND_ROWS() AS count');
+
+ return [
+ 'results' => $results,
+ 'count' => $count['count'],
+ ];
+ }
+
/**
* Restituisce le somme richieste dalla query prevista dalla struttura.
*
@@ -202,7 +219,7 @@ class Query
$result_query = self::getQuery($structure, $search);
- $query = str_replace_once('SELECT', 'SELECT '.implode(', ', $total['summable']).' FROM(SELECT ', $result_query).') AS `z`';
+ $query = self::str_replace_once('SELECT', 'SELECT '.implode(', ', $total['summable']).' FROM(SELECT ', $result_query).') AS `z`';
$sums = database()->fetchOne($query);
$results = [];
@@ -217,6 +234,28 @@ class Query
return $results;
}
+ /**
+ * Sostituisce la prima occorenza di una determinata stringa.
+ *
+ * @param string $str_pattern
+ * @param string $str_replacement
+ * @param string $string
+ *
+ * @since 2.3
+ *
+ * @return string
+ */
+ protected static function str_replace_once($str_pattern, $str_replacement, $string)
+ {
+ if (strpos($string, $str_pattern) !== false) {
+ $occurrence = strpos($string, $str_pattern);
+
+ return substr_replace($string, $str_replacement, strpos($string, $str_pattern), strlen($str_pattern));
+ }
+
+ return $string;
+ }
+
/**
* Interpreta lo standard modulare per l'individuazione delle query di un modulo/plugin del progetto.
*