diff --git a/COPYRIGHT b/COPYRIGHT
index b4cc9752426..cb1dc3e0d29 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -15,8 +15,9 @@ PHP libraries:
AdoDb-Date 0.36 Modified BSD License Yes Date convertion (not into rpm package)
ChromePHP 4.1.0 Apache Software License 2.0 Yes Return server log to chrome browser console
CKEditor 4.6.2 LGPL-2.1+ Yes Editor WYSIWYG
+PHPDebugBar 1.15.0 MIT License Yes Used only by the module "debugbar" for developers
EvalMath 1.0 BSD Yes Safe math expressions evaluation
-Escpos-php MIT License Yes Thermal receipt printer library, for use with ESC/POS compatible printers
+Escpos-php ? MIT License Yes Thermal receipt printer library, for use with ESC/POS compatible printers
GeoIP 1.4 LGPL-2.1+ Yes Sample code to make geoip convert (not into deb package)
Mobiledetect 2.8.17 MIT License Yes Detect mobile devices browsers
NuSoap 0.9.5 LGPL 2.1+ Yes Library to develop SOAP Web services (not into rpm and deb package)
@@ -24,9 +25,12 @@ PEAR Mail_MIME 1.8.9 BSD Yes
odtPHP 1.0.1 GPL-2+ Yes Library to build/edit ODT files
ParseDown 1.6 MIT License Yes Markdown parser
PHPExcel 1.8.1 LGPL-2.1+ Yes Read/Write XLS files, read ODS files
+PHPSpreadSheet ? LGPL-2.1+ Yes Read/Write XLS files, read ODS files
php-iban 1.4.7 LGPL-3+ Yes Parse and validate IBAN (and IIBAN) bank account information in PHP
PHPoAuthLib 0.8.2 MIT License Yes Library to provide oauth1 and oauth2 to different service
PHPPrintIPP 1.3 GPL-2+ Yes Library to send print IPP requests
+PSR/Logs 1.0 Library for logs (used by DebugBar)
+PSR/simple-cache Library for cache (used by PHPSpreadSheet)
Restler 3.0.0RC6 LGPL-3+ Yes Library to develop REST Web services (+ swagger-ui js lib into dir explorer)
TCPDF 6.2.25 LGPL-3+ Yes PDF generation
TCPDI 1.0.0 LGPL-3+ / Apache 2.0 Yes FPDI replacement
diff --git a/ChangeLog b/ChangeLog
index c931f9ea865..08aaaa4b6f2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -18,6 +18,8 @@ Following changes may create regressions for some external modules, but were nec
* Deprecated function img_phone as been removed. You can use img_picto(..., 'call|call_out') instead.;
* Files for variables of themes were renamed from graph-color.php into theme_vars.inc.php to match naming
convention of extension .inc.php for files to be included.
+* All methods set_draft() were renamed into setDraft().
+* Removed deprecated function function test_sql_and_script_inject that was replaced with testSqlAndScriptInject.
***** ChangeLog for 9.0.1 compared to 9.0.0 *****
diff --git a/dev/initdemo/mysqldump_dolibarr_4.0.0.sql b/dev/initdemo/mysqldump_dolibarr_4.0.0.sql
index e8580cdff28..6363873d7c0 100644
--- a/dev/initdemo/mysqldump_dolibarr_4.0.0.sql
+++ b/dev/initdemo/mysqldump_dolibarr_4.0.0.sql
@@ -7853,7 +7853,7 @@ CREATE TABLE `llx_socpeople` (
LOCK TABLES `llx_socpeople` WRITE;
/*!40000 ALTER TABLE `llx_socpeople` DISABLE KEYS */;
-INSERT INTO `llx_socpeople` VALUES (1,'2010-07-08 14:26:14','2016-01-16 15:07:51',1,1,NULL,'MR','Indra','Mahala','','','',297,117,'2010-07-08','Project leader','','','','','','','',NULL,0,0,1,12,'Met during a congress at Dubai','',NULL,NULL,NULL,1),(2,'2010-07-08 22:44:50','2010-07-08 20:59:57',NULL,1,NULL,'MR','Freeman','Public','','','',200,11,NULL,'','','','','','','',NULL,NULL,0,0,1,1,'A friend that is a free contact not linked to any company',NULL,NULL,NULL,NULL,1),(3,'2010-07-08 22:59:02','2016-01-22 17:30:07',NULL,1,NULL,'MR','Mywife','Nicy','','','',NULL,11,'1980-10-03','','','','','','','','',NULL,1,0,1,12,'This is a private contact','',NULL,NULL,NULL,1),(4,'2010-07-09 00:16:58','2010-07-08 22:16:58',6,1,NULL,'MR','Rotchield','Evan','','','',NULL,6,NULL,'Bank director','','','','','','',NULL,NULL,0,0,1,1,'The bank director',NULL,NULL,NULL,NULL,1),(6,'2011-08-01 02:41:26','2016-01-22 17:29:53',17,1,NULL,'','Bookkeeper','Bob','99 account street','123456','BigTown',NULL,4,NULL,'book keeper','','','','','','','',NULL,0,0,1,12,'','',NULL,NULL,NULL,1),(7,'2016-07-30 16:11:06','2016-07-30 12:16:07',NULL,1,'','MR','Dad','','','','',NULL,14,'1967-09-04','','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(8,'2016-07-30 16:13:03','2016-07-30 12:15:58',NULL,1,'','MLE','Mom','','','','',NULL,14,NULL,'','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(9,'2016-07-30 16:14:41','2016-07-30 12:15:51',NULL,1,'','MR','Francky','','','89455','Virigia',NULL,205,'1980-07-09','Baker','555-98989898','','','','francky@example.com','','','',0,0,12,12,'','',NULL,NULL,NULL,1),(10,'2016-07-30 16:26:22','2016-07-30 12:52:38',10,1,'','MR','Eldy','','','33600','Pessac',NULL,1,'1972-10-10','Dolibarr project leader','','','','','eldy@example.com','','','ldestailleur_200x200.jpg',0,0,NULL,12,'','',NULL,NULL,NULL,1);
+INSERT INTO `llx_socpeople` VALUES (1,'2010-07-08 14:26:14','2016-01-16 15:07:51',1,1,NULL,'MR','Indra','Mahala','','','',297,117,'2010-07-08','Project leader','','','','','','','',NULL,0,0,1,12,'Met during a congress at Dubai','',NULL,NULL,NULL,1),(2,'2010-07-08 22:44:50','2010-07-08 20:59:57',NULL,1,NULL,'MR','Freeman','Public','','','',200,11,NULL,'','','','','','','',NULL,NULL,0,0,1,1,'A friend that is a free contact not linked to any company',NULL,NULL,NULL,NULL,1),(3,'2010-07-08 22:59:02','2016-01-22 17:30:07',NULL,1,NULL,'MR','Mywife','Nicy','','','',NULL,11,'1980-10-03','','','','','','','','',NULL,1,0,1,12,'This is a private contact','',NULL,NULL,NULL,1),(4,'2010-07-09 00:16:58','2010-07-08 22:16:58',6,1,NULL,'MR','Rotchield','Evan','','','',NULL,6,NULL,'Bank director','','','','','','',NULL,NULL,0,0,1,1,'The bank director',NULL,NULL,NULL,NULL,1),(6,'2011-08-01 02:41:26','2016-01-22 17:29:53',17,1,NULL,'','Bookkeeper','Bob','99 account street','123456','BigTown',NULL,4,NULL,'book keeper','','','','','','','',NULL,0,0,1,12,'','',NULL,NULL,NULL,1),(7,'2016-07-30 16:11:06','2016-07-30 12:16:07',NULL,1,'','MR','Dad','','','','',NULL,14,'1967-09-04','','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(8,'2016-07-30 16:13:03','2016-07-30 12:15:58',NULL,1,'','MLE','Mom','','','','',NULL,14,NULL,'','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(9,'2016-07-30 16:14:41','2016-07-30 12:15:51',NULL,1,'','MR','Francky','','','89455','Virigia',NULL,205,'1980-07-09','Baker','555-98989898','','','','francky@example.com','','','',0,0,12,12,'','',NULL,NULL,NULL,1),(10,'2016-07-30 16:26:22','2016-07-30 12:52:38',10,1,'','MR','Eldy','','','33600','Pessac',NULL,1,'1972-10-10','Dolibarr project leader','','','','','demo@example.com','','','ldestailleur_200x200.jpg',0,0,NULL,12,'','',NULL,NULL,NULL,1);
/*!40000 ALTER TABLE `llx_socpeople` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/dev/initdemo/mysqldump_dolibarr_5.0.0.sql b/dev/initdemo/mysqldump_dolibarr_5.0.0.sql
index 4c31fd25e8a..a66bd427499 100644
--- a/dev/initdemo/mysqldump_dolibarr_5.0.0.sql
+++ b/dev/initdemo/mysqldump_dolibarr_5.0.0.sql
@@ -8260,7 +8260,7 @@ CREATE TABLE `llx_socpeople` (
LOCK TABLES `llx_socpeople` WRITE;
/*!40000 ALTER TABLE `llx_socpeople` DISABLE KEYS */;
-INSERT INTO `llx_socpeople` VALUES (1,'2010-07-08 14:26:14','2016-01-16 15:07:51',1,1,NULL,'MR','Indra','Mahala','','','',297,117,'2010-07-08','Project leader','','','','','','','',NULL,0,0,1,12,'Met during a congress at Dubai','',NULL,NULL,NULL,1),(2,'2010-07-08 22:44:50','2010-07-08 20:59:57',NULL,1,NULL,'MR','Freeman','Public','','','',200,11,NULL,'','','','','','','',NULL,NULL,0,0,1,1,'A friend that is a free contact not linked to any company',NULL,NULL,NULL,NULL,1),(3,'2010-07-08 22:59:02','2016-01-22 17:30:07',NULL,1,NULL,'MR','Mywife','Nicy','','','',NULL,11,'1980-10-03','','','','','','','','',NULL,1,0,1,12,'This is a private contact','',NULL,NULL,NULL,1),(4,'2010-07-09 00:16:58','2010-07-08 22:16:58',6,1,NULL,'MR','Rotchield','Evan','','','',NULL,6,NULL,'Bank director','','','','','','',NULL,NULL,0,0,1,1,'The bank director',NULL,NULL,NULL,NULL,1),(6,'2011-08-01 02:41:26','2016-01-22 17:29:53',17,1,NULL,'','Bookkeeper','Bob','99 account street','123456','BigTown',NULL,4,NULL,'book keeper','','','','','','','',NULL,0,0,1,12,'','',NULL,NULL,NULL,1),(7,'2016-07-30 16:11:06','2016-07-30 12:16:07',NULL,1,'','MR','Dad','','','','',NULL,14,'1967-09-04','','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(8,'2016-07-30 16:13:03','2016-07-30 12:15:58',NULL,1,'','MLE','Mom','','','','',NULL,14,NULL,'','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(9,'2016-07-30 16:14:41','2016-07-30 12:15:51',NULL,1,'','MR','Francky','','','89455','Virigia',NULL,205,'1980-07-09','Baker','555-98989898','','','','francky@example.com','','','',0,0,12,12,'','',NULL,NULL,NULL,1),(10,'2016-07-30 16:26:22','2016-07-30 12:52:38',10,1,'','MR','Eldy','','','33600','Pessac',NULL,1,'1972-10-10','Dolibarr project leader','','','','','eldy@example.com','','','ldestailleur_200x200.jpg',0,0,NULL,12,'','',NULL,NULL,NULL,1),(11,'2017-05-12 13:16:36','2017-05-12 09:18:20',11,1,'','MR','Smith','Laurent','45 Big road','897','Seattle',NULL,11,NULL,'Director','','','','','','','','ldestailleur_200x200.png',0,0,12,12,'','',NULL,NULL,NULL,1),(12,'2017-05-12 13:19:31','2017-05-12 09:19:42',11,1,'','MR','Einstein','','','','',NULL,11,NULL,'Genius','333444555','','','','genius@example.com','','','Einstein.jpg',0,0,12,12,'','',NULL,NULL,NULL,1);
+INSERT INTO `llx_socpeople` VALUES (1,'2010-07-08 14:26:14','2016-01-16 15:07:51',1,1,NULL,'MR','Indra','Mahala','','','',297,117,'2010-07-08','Project leader','','','','','','','',NULL,0,0,1,12,'Met during a congress at Dubai','',NULL,NULL,NULL,1),(2,'2010-07-08 22:44:50','2010-07-08 20:59:57',NULL,1,NULL,'MR','Freeman','Public','','','',200,11,NULL,'','','','','','','',NULL,NULL,0,0,1,1,'A friend that is a free contact not linked to any company',NULL,NULL,NULL,NULL,1),(3,'2010-07-08 22:59:02','2016-01-22 17:30:07',NULL,1,NULL,'MR','Mywife','Nicy','','','',NULL,11,'1980-10-03','','','','','','','','',NULL,1,0,1,12,'This is a private contact','',NULL,NULL,NULL,1),(4,'2010-07-09 00:16:58','2010-07-08 22:16:58',6,1,NULL,'MR','Rotchield','Evan','','','',NULL,6,NULL,'Bank director','','','','','','',NULL,NULL,0,0,1,1,'The bank director',NULL,NULL,NULL,NULL,1),(6,'2011-08-01 02:41:26','2016-01-22 17:29:53',17,1,NULL,'','Bookkeeper','Bob','99 account street','123456','BigTown',NULL,4,NULL,'book keeper','','','','','','','',NULL,0,0,1,12,'','',NULL,NULL,NULL,1),(7,'2016-07-30 16:11:06','2016-07-30 12:16:07',NULL,1,'','MR','Dad','','','','',NULL,14,'1967-09-04','','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(8,'2016-07-30 16:13:03','2016-07-30 12:15:58',NULL,1,'','MLE','Mom','','','','',NULL,14,NULL,'','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(9,'2016-07-30 16:14:41','2016-07-30 12:15:51',NULL,1,'','MR','Francky','','','89455','Virigia',NULL,205,'1980-07-09','Baker','555-98989898','','','','francky@example.com','','','',0,0,12,12,'','',NULL,NULL,NULL,1),(10,'2016-07-30 16:26:22','2016-07-30 12:52:38',10,1,'','MR','Eldy','','','33600','Pessac',NULL,1,'1972-10-10','Dolibarr project leader','','','','','demo@example.com','','','ldestailleur_200x200.jpg',0,0,NULL,12,'','',NULL,NULL,NULL,1),(11,'2017-05-12 13:16:36','2017-05-12 09:18:20',11,1,'','MR','Smith','Laurent','45 Big road','897','Seattle',NULL,11,NULL,'Director','','','','','','','','ldestailleur_200x200.png',0,0,12,12,'','',NULL,NULL,NULL,1),(12,'2017-05-12 13:19:31','2017-05-12 09:19:42',11,1,'','MR','Einstein','','','','',NULL,11,NULL,'Genius','333444555','','','','genius@example.com','','','Einstein.jpg',0,0,12,12,'','',NULL,NULL,NULL,1);
/*!40000 ALTER TABLE `llx_socpeople` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/dev/initdemo/mysqldump_dolibarr_6.0.0.sql b/dev/initdemo/mysqldump_dolibarr_6.0.0.sql
index f0375a4b407..19cb46d0237 100644
--- a/dev/initdemo/mysqldump_dolibarr_6.0.0.sql
+++ b/dev/initdemo/mysqldump_dolibarr_6.0.0.sql
@@ -8612,7 +8612,7 @@ CREATE TABLE `llx_socpeople` (
LOCK TABLES `llx_socpeople` WRITE;
/*!40000 ALTER TABLE `llx_socpeople` DISABLE KEYS */;
-INSERT INTO `llx_socpeople` VALUES (1,'2010-07-08 14:26:14','2016-01-16 15:07:51',1,1,NULL,'MR','Indra','Mahala','','','',297,117,'2010-07-08','Project leader','','','','','','','',NULL,0,0,1,12,'Met during a congress at Dubai','',NULL,NULL,NULL,1),(2,'2010-07-08 22:44:50','2010-07-08 20:59:57',NULL,1,NULL,'MR','Freeman','Public','','','',200,11,NULL,'','','','','','','',NULL,NULL,0,0,1,1,'A friend that is a free contact not linked to any company',NULL,NULL,NULL,NULL,1),(3,'2010-07-08 22:59:02','2016-01-22 17:30:07',NULL,1,NULL,'MR','Mywife','Nicy','','','',NULL,11,'1980-10-03','','','','','','','','',NULL,1,0,1,12,'This is a private contact','',NULL,NULL,NULL,1),(4,'2010-07-09 00:16:58','2010-07-08 22:16:58',6,1,NULL,'MR','Rotchield','Evan','','','',NULL,6,NULL,'Bank director','','','','','','',NULL,NULL,0,0,1,1,'The bank director',NULL,NULL,NULL,NULL,1),(6,'2011-08-01 02:41:26','2016-01-22 17:29:53',17,1,NULL,'','Bookkeeper','Bob','99 account street','123456','BigTown',NULL,4,NULL,'book keeper','','','','','','','',NULL,0,0,1,12,'','',NULL,NULL,NULL,1),(7,'2016-07-30 16:11:06','2016-07-30 12:16:07',NULL,1,'','MR','Dad','','','','',NULL,14,'1967-09-04','','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(8,'2016-07-30 16:13:03','2016-07-30 12:15:58',NULL,1,'','MLE','Mom','','','','',NULL,14,NULL,'','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(9,'2016-07-30 16:14:41','2016-07-30 12:15:51',NULL,1,'','MR','Francky','','','89455','Virigia',NULL,205,'1980-07-09','Baker','555-98989898','','','','francky@example.com','','','',0,0,12,12,'','',NULL,NULL,NULL,1),(10,'2016-07-30 16:26:22','2016-07-30 12:52:38',10,1,'','MR','Eldy','','','33600','Pessac',NULL,1,'1972-10-10','Dolibarr project leader','','','','','eldy@example.com','','','ldestailleur_200x200.jpg',0,0,NULL,12,'','',NULL,NULL,NULL,1),(11,'2017-05-12 13:16:36','2017-05-12 09:18:20',11,1,'','MR','Smith','Laurent','45 Big road','897','Seattle',NULL,11,NULL,'Director','','','','','','','','ldestailleur_200x200.png',0,0,12,12,'','',NULL,NULL,NULL,1),(12,'2017-05-12 13:19:31','2017-05-12 09:19:42',11,1,'','MR','Einstein','','','','',NULL,11,NULL,'Genius','333444555','','','','genius@example.com','','','Einstein.jpg',0,0,12,12,'','',NULL,NULL,NULL,1);
+INSERT INTO `llx_socpeople` VALUES (1,'2010-07-08 14:26:14','2016-01-16 15:07:51',1,1,NULL,'MR','Indra','Mahala','','','',297,117,'2010-07-08','Project leader','','','','','','','',NULL,0,0,1,12,'Met during a congress at Dubai','',NULL,NULL,NULL,1),(2,'2010-07-08 22:44:50','2010-07-08 20:59:57',NULL,1,NULL,'MR','Freeman','Public','','','',200,11,NULL,'','','','','','','',NULL,NULL,0,0,1,1,'A friend that is a free contact not linked to any company',NULL,NULL,NULL,NULL,1),(3,'2010-07-08 22:59:02','2016-01-22 17:30:07',NULL,1,NULL,'MR','Mywife','Nicy','','','',NULL,11,'1980-10-03','','','','','','','','',NULL,1,0,1,12,'This is a private contact','',NULL,NULL,NULL,1),(4,'2010-07-09 00:16:58','2010-07-08 22:16:58',6,1,NULL,'MR','Rotchield','Evan','','','',NULL,6,NULL,'Bank director','','','','','','',NULL,NULL,0,0,1,1,'The bank director',NULL,NULL,NULL,NULL,1),(6,'2011-08-01 02:41:26','2016-01-22 17:29:53',17,1,NULL,'','Bookkeeper','Bob','99 account street','123456','BigTown',NULL,4,NULL,'book keeper','','','','','','','',NULL,0,0,1,12,'','',NULL,NULL,NULL,1),(7,'2016-07-30 16:11:06','2016-07-30 12:16:07',NULL,1,'','MR','Dad','','','','',NULL,14,'1967-09-04','','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(8,'2016-07-30 16:13:03','2016-07-30 12:15:58',NULL,1,'','MLE','Mom','','','','',NULL,14,NULL,'','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(9,'2016-07-30 16:14:41','2016-07-30 12:15:51',NULL,1,'','MR','Francky','','','89455','Virigia',NULL,205,'1980-07-09','Baker','555-98989898','','','','francky@example.com','','','',0,0,12,12,'','',NULL,NULL,NULL,1),(10,'2016-07-30 16:26:22','2016-07-30 12:52:38',10,1,'','MR','Eldy','','','33600','Pessac',NULL,1,'1972-10-10','Dolibarr project leader','','','','','demo@example.com','','','ldestailleur_200x200.jpg',0,0,NULL,12,'','',NULL,NULL,NULL,1),(11,'2017-05-12 13:16:36','2017-05-12 09:18:20',11,1,'','MR','Smith','Laurent','45 Big road','897','Seattle',NULL,11,NULL,'Director','','','','','','','','ldestailleur_200x200.png',0,0,12,12,'','',NULL,NULL,NULL,1),(12,'2017-05-12 13:19:31','2017-05-12 09:19:42',11,1,'','MR','Einstein','','','','',NULL,11,NULL,'Genius','333444555','','','','genius@example.com','','','Einstein.jpg',0,0,12,12,'','',NULL,NULL,NULL,1);
/*!40000 ALTER TABLE `llx_socpeople` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/dev/initdemo/mysqldump_dolibarr_7.0.0.sql b/dev/initdemo/mysqldump_dolibarr_7.0.0.sql
index bd5789f0a6b..363cc32670d 100644
--- a/dev/initdemo/mysqldump_dolibarr_7.0.0.sql
+++ b/dev/initdemo/mysqldump_dolibarr_7.0.0.sql
@@ -9181,7 +9181,7 @@ CREATE TABLE `llx_socpeople` (
LOCK TABLES `llx_socpeople` WRITE;
/*!40000 ALTER TABLE `llx_socpeople` DISABLE KEYS */;
-INSERT INTO `llx_socpeople` VALUES (1,'2010-07-08 14:26:14','2016-01-16 15:07:51',1,1,NULL,'MR','Indra','Mahala','','','',297,117,'2010-07-08','Project leader','','','','','','','',NULL,0,0,1,12,'Met during a congress at Dubai','',NULL,NULL,NULL,1),(2,'2010-07-08 22:44:50','2010-07-08 20:59:57',NULL,1,NULL,'MR','Freeman','Public','','','',200,11,NULL,'','','','','','','',NULL,NULL,0,0,1,1,'A friend that is a free contact not linked to any company',NULL,NULL,NULL,NULL,1),(3,'2010-07-08 22:59:02','2016-01-22 17:30:07',NULL,1,NULL,'MR','Mywife','Nicy','','','',NULL,11,'1980-10-03','','','','','','','','',NULL,1,0,1,12,'This is a private contact','',NULL,NULL,NULL,1),(4,'2010-07-09 00:16:58','2010-07-08 22:16:58',6,1,NULL,'MR','Rotchield','Evan','','','',NULL,6,NULL,'Bank director','','','','','','',NULL,NULL,0,0,1,1,'The bank director',NULL,NULL,NULL,NULL,1),(6,'2011-08-01 02:41:26','2016-01-22 17:29:53',17,1,NULL,'','Bookkeeper','Bob','99 account street','123456','BigTown',NULL,4,NULL,'book keeper','','','','','','','',NULL,0,0,1,12,'','',NULL,NULL,NULL,1),(7,'2016-07-30 16:11:06','2016-07-30 12:16:07',NULL,1,'','MR','Dad','','','','',NULL,14,'1967-09-04','','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(8,'2016-07-30 16:13:03','2016-07-30 12:15:58',NULL,1,'','MLE','Mom','','','','',NULL,14,NULL,'','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(9,'2016-07-30 16:14:41','2016-07-30 12:15:51',NULL,1,'','MR','Francky','','','89455','Virigia',NULL,205,'1980-07-09','Baker','555-98989898','','','','francky@example.com','','','',0,0,12,12,'','',NULL,NULL,NULL,1),(10,'2016-07-30 16:26:22','2016-07-30 12:52:38',10,1,'','MR','Eldy','','','33600','Pessac',NULL,1,'1972-10-10','Dolibarr project leader','','','','','eldy@example.com','','','ldestailleur_200x200.jpg',0,0,NULL,12,'','',NULL,NULL,NULL,1),(11,'2017-05-12 13:16:36','2017-05-12 09:18:20',11,1,'','MR','Smith','Laurent','45 Big road','897','Seattle',NULL,11,NULL,'Director','','','','','','','','ldestailleur_200x200.png',0,0,12,12,'','',NULL,NULL,NULL,1),(12,'2017-05-12 13:19:31','2017-05-12 09:19:42',11,1,'','MR','Einstein','','','','',NULL,11,NULL,'Genius','333444555','','','','genius@example.com','','','Einstein.jpg',0,0,12,12,'','',NULL,NULL,NULL,1);
+INSERT INTO `llx_socpeople` VALUES (1,'2010-07-08 14:26:14','2016-01-16 15:07:51',1,1,NULL,'MR','Indra','Mahala','','','',297,117,'2010-07-08','Project leader','','','','','','','',NULL,0,0,1,12,'Met during a congress at Dubai','',NULL,NULL,NULL,1),(2,'2010-07-08 22:44:50','2010-07-08 20:59:57',NULL,1,NULL,'MR','Freeman','Public','','','',200,11,NULL,'','','','','','','',NULL,NULL,0,0,1,1,'A friend that is a free contact not linked to any company',NULL,NULL,NULL,NULL,1),(3,'2010-07-08 22:59:02','2016-01-22 17:30:07',NULL,1,NULL,'MR','Mywife','Nicy','','','',NULL,11,'1980-10-03','','','','','','','','',NULL,1,0,1,12,'This is a private contact','',NULL,NULL,NULL,1),(4,'2010-07-09 00:16:58','2010-07-08 22:16:58',6,1,NULL,'MR','Rotchield','Evan','','','',NULL,6,NULL,'Bank director','','','','','','',NULL,NULL,0,0,1,1,'The bank director',NULL,NULL,NULL,NULL,1),(6,'2011-08-01 02:41:26','2016-01-22 17:29:53',17,1,NULL,'','Bookkeeper','Bob','99 account street','123456','BigTown',NULL,4,NULL,'book keeper','','','','','','','',NULL,0,0,1,12,'','',NULL,NULL,NULL,1),(7,'2016-07-30 16:11:06','2016-07-30 12:16:07',NULL,1,'','MR','Dad','','','','',NULL,14,'1967-09-04','','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(8,'2016-07-30 16:13:03','2016-07-30 12:15:58',NULL,1,'','MLE','Mom','','','','',NULL,14,NULL,'','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(9,'2016-07-30 16:14:41','2016-07-30 12:15:51',NULL,1,'','MR','Francky','','','89455','Virigia',NULL,205,'1980-07-09','Baker','555-98989898','','','','francky@example.com','','','',0,0,12,12,'','',NULL,NULL,NULL,1),(10,'2016-07-30 16:26:22','2016-07-30 12:52:38',10,1,'','MR','Eldy','','','33600','Pessac',NULL,1,'1972-10-10','Dolibarr project leader','','','','','demo@example.com','','','ldestailleur_200x200.jpg',0,0,NULL,12,'','',NULL,NULL,NULL,1),(11,'2017-05-12 13:16:36','2017-05-12 09:18:20',11,1,'','MR','Smith','Laurent','45 Big road','897','Seattle',NULL,11,NULL,'Director','','','','','','','','ldestailleur_200x200.png',0,0,12,12,'','',NULL,NULL,NULL,1),(12,'2017-05-12 13:19:31','2017-05-12 09:19:42',11,1,'','MR','Einstein','','','','',NULL,11,NULL,'Genius','333444555','','','','genius@example.com','','','Einstein.jpg',0,0,12,12,'','',NULL,NULL,NULL,1);
/*!40000 ALTER TABLE `llx_socpeople` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/dev/initdemo/mysqldump_dolibarr_8.0.0.sql b/dev/initdemo/mysqldump_dolibarr_8.0.0.sql
index 05a4814a7ef..b000b807930 100644
--- a/dev/initdemo/mysqldump_dolibarr_8.0.0.sql
+++ b/dev/initdemo/mysqldump_dolibarr_8.0.0.sql
@@ -6360,7 +6360,7 @@ CREATE TABLE `llx_emailcollector_emailcollector` (
LOCK TABLES `llx_emailcollector_emailcollector` WRITE;
/*!40000 ALTER TABLE `llx_emailcollector_emailcollector` DISABLE KEYS */;
-INSERT INTO `llx_emailcollector_emailcollector` VALUES (1,1,'MyEmailCollector1','My email collector 1','aaa','imap.gmail.com','testldr10@gmail.com','testldr10-10','INBOX','','','aftercollect','2018-11-19 15:21:07','1 emails analyzed, 1 emails successfuly processed (for 3 record/actions done) by collector',NULL,NULL,'2018-10-31 18:08:05','2018-10-31 17:08:05',12,12,NULL,1,'OK',0);
+INSERT INTO `llx_emailcollector_emailcollector` VALUES (1,1,'MyEmailCollector1','My email collector 1','aaa','imap.gmail.com','testldr10@example.com','testldr10-10','INBOX','','','aftercollect','2018-11-19 15:21:07','1 emails analyzed, 1 emails successfuly processed (for 3 record/actions done) by collector',NULL,NULL,'2018-10-31 18:08:05','2018-10-31 17:08:05',12,12,NULL,1,'OK',0);
/*!40000 ALTER TABLE `llx_emailcollector_emailcollector` ENABLE KEYS */;
UNLOCK TABLES;
@@ -12450,7 +12450,7 @@ CREATE TABLE `llx_socpeople` (
LOCK TABLES `llx_socpeople` WRITE;
/*!40000 ALTER TABLE `llx_socpeople` DISABLE KEYS */;
-INSERT INTO `llx_socpeople` VALUES (1,'2010-07-08 14:26:14','2016-01-16 15:07:51',1,1,NULL,'MR','Indra','Mahala','','','',297,117,'2010-07-08','Project leader','','','','','','','',NULL,0,0,1,12,'Met during a congress at Dubai','',NULL,NULL,NULL,1),(2,'2010-07-08 22:44:50','2010-07-08 20:59:57',NULL,1,NULL,'MR','Freeman','Public','','','',200,11,NULL,'','','','','','','',NULL,NULL,0,0,1,1,'A friend that is a free contact not linked to any company',NULL,NULL,NULL,NULL,1),(3,'2010-07-08 22:59:02','2016-01-22 17:30:07',NULL,1,NULL,'MR','Mywife','Nicy','','','',NULL,11,'1980-10-03','','','','','','','','',NULL,1,0,1,12,'This is a private contact','',NULL,NULL,NULL,1),(4,'2010-07-09 00:16:58','2010-07-08 22:16:58',6,1,NULL,'MR','Rotchield','Evan','','','',NULL,6,NULL,'Bank director','','','','','','',NULL,NULL,0,0,1,1,'The bank director',NULL,NULL,NULL,NULL,1),(6,'2011-08-01 02:41:26','2016-01-22 17:29:53',17,1,NULL,'','Bookkeeper','Bob','99 account street','123456','BigTown',NULL,4,NULL,'book keeper','','','','','','','',NULL,0,0,1,12,'','',NULL,NULL,NULL,1),(7,'2016-07-30 16:11:06','2016-07-30 12:16:07',NULL,1,'','MR','Dad','','','','',NULL,14,'1967-09-04','','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(8,'2016-07-30 16:13:03','2016-07-30 12:15:58',NULL,1,'','MLE','Mom','','','','',NULL,14,NULL,'','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(9,'2016-07-30 16:14:41','2016-07-30 12:15:51',NULL,1,'','MR','Francky','','','89455','Virigia',NULL,205,'1980-07-09','Baker','555-98989898','','','','francky@example.com','','','',0,0,12,12,'','',NULL,NULL,NULL,1),(10,'2016-07-30 16:26:22','2016-07-30 12:52:38',10,1,'','MR','Eldy','','','33600','Pessac',NULL,1,'1972-10-10','Dolibarr project leader','','','','','eldy@example.com','','','ldestailleur_200x200.jpg',0,0,NULL,12,'','',NULL,NULL,NULL,1),(11,'2017-05-12 13:16:36','2017-05-12 09:18:20',11,1,'','MR','Smith','Laurent','45 Big road','897','Seattle',NULL,11,NULL,'Director','','','','','','','','ldestailleur_200x200.png',0,0,12,12,'','',NULL,NULL,NULL,1),(12,'2017-05-12 13:19:31','2017-05-12 09:19:42',11,1,'','MR','Einstein','','','','',NULL,11,NULL,'Genius','333444555','','','','genius@example.com','','','Einstein.jpg',0,0,12,12,'','',NULL,NULL,NULL,1);
+INSERT INTO `llx_socpeople` VALUES (1,'2010-07-08 14:26:14','2016-01-16 15:07:51',1,1,NULL,'MR','Indra','Mahala','','','',297,117,'2010-07-08','Project leader','','','','','','','',NULL,0,0,1,12,'Met during a congress at Dubai','',NULL,NULL,NULL,1),(2,'2010-07-08 22:44:50','2010-07-08 20:59:57',NULL,1,NULL,'MR','Freeman','Public','','','',200,11,NULL,'','','','','','','',NULL,NULL,0,0,1,1,'A friend that is a free contact not linked to any company',NULL,NULL,NULL,NULL,1),(3,'2010-07-08 22:59:02','2016-01-22 17:30:07',NULL,1,NULL,'MR','Mywife','Nicy','','','',NULL,11,'1980-10-03','','','','','','','','',NULL,1,0,1,12,'This is a private contact','',NULL,NULL,NULL,1),(4,'2010-07-09 00:16:58','2010-07-08 22:16:58',6,1,NULL,'MR','Rotchield','Evan','','','',NULL,6,NULL,'Bank director','','','','','','',NULL,NULL,0,0,1,1,'The bank director',NULL,NULL,NULL,NULL,1),(6,'2011-08-01 02:41:26','2016-01-22 17:29:53',17,1,NULL,'','Bookkeeper','Bob','99 account street','123456','BigTown',NULL,4,NULL,'book keeper','','','','','','','',NULL,0,0,1,12,'','',NULL,NULL,NULL,1),(7,'2016-07-30 16:11:06','2016-07-30 12:16:07',NULL,1,'','MR','Dad','','','','',NULL,14,'1967-09-04','','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(8,'2016-07-30 16:13:03','2016-07-30 12:15:58',NULL,1,'','MLE','Mom','','','','',NULL,14,NULL,'','','','','','','','','',1,0,12,12,'','',NULL,NULL,NULL,1),(9,'2016-07-30 16:14:41','2016-07-30 12:15:51',NULL,1,'','MR','Francky','','','89455','Virigia',NULL,205,'1980-07-09','Baker','555-98989898','','','','francky@example.com','','','',0,0,12,12,'','',NULL,NULL,NULL,1),(10,'2016-07-30 16:26:22','2016-07-30 12:52:38',10,1,'','MR','Eldy','','','33600','Pessac',NULL,1,'1972-10-10','Dolibarr project leader','','','','','demo@example.com','','','ldestailleur_200x200.jpg',0,0,NULL,12,'','',NULL,NULL,NULL,1),(11,'2017-05-12 13:16:36','2017-05-12 09:18:20',11,1,'','MR','Smith','Laurent','45 Big road','897','Seattle',NULL,11,NULL,'Director','','','','','','','','ldestailleur_200x200.png',0,0,12,12,'','',NULL,NULL,NULL,1),(12,'2017-05-12 13:19:31','2017-05-12 09:19:42',11,1,'','MR','Einstein','','','','',NULL,11,NULL,'Genius','333444555','','','','genius@example.com','','','Einstein.jpg',0,0,12,12,'','',NULL,NULL,NULL,1);
/*!40000 ALTER TABLE `llx_socpeople` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/dev/initdemo/mysqldump_dolibarr_9.0.0.sql b/dev/initdemo/mysqldump_dolibarr_9.0.0.sql
index 61201d931e3..c3d5fcd9e73 100644
--- a/dev/initdemo/mysqldump_dolibarr_9.0.0.sql
+++ b/dev/initdemo/mysqldump_dolibarr_9.0.0.sql
@@ -6275,7 +6275,7 @@ CREATE TABLE `llx_emailcollector_emailcollector` (
LOCK TABLES `llx_emailcollector_emailcollector` WRITE;
/*!40000 ALTER TABLE `llx_emailcollector_emailcollector` DISABLE KEYS */;
-INSERT INTO `llx_emailcollector_emailcollector` VALUES (1,1,'MyEmailCollector1','My email collector 1','aaa','imap.gmail.com','testldr10@gmail.com','testldr10-10','INBOX','','','aftercollect','2018-11-19 15:21:07','1 emails analyzed, 1 emails successfuly processed (for 3 record/actions done) by collector',NULL,NULL,'2018-10-31 18:08:05','2018-10-31 17:08:05',12,12,NULL,1,'OK',0);
+INSERT INTO `llx_emailcollector_emailcollector` VALUES (1,1,'MyEmailCollector1','My email collector 1','aaa','imap.gmail.com','testldr10@example.com','testldr10-10','INBOX','','','aftercollect','2018-11-19 15:21:07','1 emails analyzed, 1 emails successfuly processed (for 3 record/actions done) by collector',NULL,NULL,'2018-10-31 18:08:05','2018-10-31 17:08:05',12,12,NULL,1,'OK',0);
/*!40000 ALTER TABLE `llx_emailcollector_emailcollector` ENABLE KEYS */;
UNLOCK TABLES;
@@ -12388,7 +12388,7 @@ CREATE TABLE `llx_socpeople` (
LOCK TABLES `llx_socpeople` WRITE;
/*!40000 ALTER TABLE `llx_socpeople` DISABLE KEYS */;
-INSERT INTO `llx_socpeople` VALUES (1,'2012-07-08 14:26:14','2018-01-16 15:07:51',1,1,NULL,'MR','Indra','Mahala','','','',297,117,'2012-07-08','Project leader','','','','','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,12,'Met during a congress at Dubai','',NULL,NULL,NULL,1),(2,'2012-07-08 22:44:50','2012-07-08 20:59:57',NULL,1,NULL,'MR','Freeman','Public','','','',200,11,NULL,'','','','','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,1,'A friend that is a free contact not linked to any company',NULL,NULL,NULL,NULL,1),(3,'2012-07-08 22:59:02','2018-01-22 17:30:07',NULL,1,NULL,'MR','Mywife','Nicy','','','',NULL,11,'1980-10-03','','','','','','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,0,1,12,'This is a private contact','',NULL,NULL,NULL,1),(4,'2012-07-09 00:16:58','2012-07-08 22:16:58',6,1,NULL,'MR','Rotchield','Evan','','','',NULL,6,NULL,'Bank director','','','','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,1,'The bank director',NULL,NULL,NULL,NULL,1),(6,'2013-08-01 02:41:26','2018-01-22 17:29:53',17,1,NULL,'','Bookkeeper','Bob','99 account street','123456','BigTown',NULL,4,NULL,'book keeper','','','','','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,12,'','',NULL,NULL,NULL,1),(7,'2018-07-30 16:11:06','2018-07-30 12:16:07',NULL,1,'','MR','Dad','','','','',NULL,14,'1967-09-04','','','','','','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'',1,0,12,12,'','',NULL,NULL,NULL,1),(8,'2018-07-30 16:13:03','2018-07-30 12:15:58',NULL,1,'','MLE','Mom','','','','',NULL,14,NULL,'','','','','','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'',1,0,12,12,'','',NULL,NULL,NULL,1),(9,'2018-07-30 16:14:41','2018-07-30 12:15:51',NULL,1,'','MR','Francky','','','89455','Virigia',NULL,205,'1980-07-09','Baker','555-98989898','','','','francky@example.com','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'',0,0,12,12,'','',NULL,NULL,NULL,1),(10,'2018-07-30 16:26:22','2018-07-30 12:52:38',10,1,'','MR','Eldy','','','33600','Pessac',NULL,1,'1972-10-10','Dolibarr project leader','','','','','eldy@example.com','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'ldestailleur_200x200.jpg',0,0,NULL,12,'','',NULL,NULL,NULL,1),(11,'2017-05-12 13:16:36','2017-05-12 09:18:20',11,1,'','MR','Smith','Laurent','45 Big road','897','Seattle',NULL,11,NULL,'Director','','','','','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'ldestailleur_200x200.png',0,0,12,12,'','',NULL,NULL,NULL,1),(12,'2017-05-12 13:19:31','2017-05-12 09:19:42',11,1,'','MR','Einstein','','','','',NULL,11,NULL,'Genius','333444555','','','','genius@example.com','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'Einstein.jpg',0,0,12,12,'','',NULL,NULL,NULL,1);
+INSERT INTO `llx_socpeople` VALUES (1,'2012-07-08 14:26:14','2018-01-16 15:07:51',1,1,NULL,'MR','Indra','Mahala','','','',297,117,'2012-07-08','Project leader','','','','','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,12,'Met during a congress at Dubai','',NULL,NULL,NULL,1),(2,'2012-07-08 22:44:50','2012-07-08 20:59:57',NULL,1,NULL,'MR','Freeman','Public','','','',200,11,NULL,'','','','','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,1,'A friend that is a free contact not linked to any company',NULL,NULL,NULL,NULL,1),(3,'2012-07-08 22:59:02','2018-01-22 17:30:07',NULL,1,NULL,'MR','Mywife','Nicy','','','',NULL,11,'1980-10-03','','','','','','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,0,1,12,'This is a private contact','',NULL,NULL,NULL,1),(4,'2012-07-09 00:16:58','2012-07-08 22:16:58',6,1,NULL,'MR','Rotchield','Evan','','','',NULL,6,NULL,'Bank director','','','','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,1,'The bank director',NULL,NULL,NULL,NULL,1),(6,'2013-08-01 02:41:26','2018-01-22 17:29:53',17,1,NULL,'','Bookkeeper','Bob','99 account street','123456','BigTown',NULL,4,NULL,'book keeper','','','','','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,12,'','',NULL,NULL,NULL,1),(7,'2018-07-30 16:11:06','2018-07-30 12:16:07',NULL,1,'','MR','Dad','','','','',NULL,14,'1967-09-04','','','','','','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'',1,0,12,12,'','',NULL,NULL,NULL,1),(8,'2018-07-30 16:13:03','2018-07-30 12:15:58',NULL,1,'','MLE','Mom','','','','',NULL,14,NULL,'','','','','','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'',1,0,12,12,'','',NULL,NULL,NULL,1),(9,'2018-07-30 16:14:41','2018-07-30 12:15:51',NULL,1,'','MR','Francky','','','89455','Virigia',NULL,205,'1980-07-09','Baker','555-98989898','','','','francky@example.com','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'',0,0,12,12,'','',NULL,NULL,NULL,1),(10,'2018-07-30 16:26:22','2018-07-30 12:52:38',10,1,'','MR','Eldy','','','33600','Pessac',NULL,1,'1972-10-10','Dolibarr project leader','','','','','demo@example.com','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'ldestailleur_200x200.jpg',0,0,NULL,12,'','',NULL,NULL,NULL,1),(11,'2017-05-12 13:16:36','2017-05-12 09:18:20',11,1,'','MR','Smith','Laurent','45 Big road','897','Seattle',NULL,11,NULL,'Director','','','','','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'ldestailleur_200x200.png',0,0,12,12,'','',NULL,NULL,NULL,1),(12,'2017-05-12 13:19:31','2017-05-12 09:19:42',11,1,'','MR','Einstein','','','','',NULL,11,NULL,'Genius','333444555','','','','genius@example.com','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'Einstein.jpg',0,0,12,12,'','',NULL,NULL,NULL,1);
/*!40000 ALTER TABLE `llx_socpeople` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/htdocs/accountancy/admin/categories.php b/htdocs/accountancy/admin/categories.php
index decae324ac5..faba7fb1c62 100644
--- a/htdocs/accountancy/admin/categories.php
+++ b/htdocs/accountancy/admin/categories.php
@@ -60,7 +60,7 @@ $accountingcategory = new AccountancyCategory($db);
// si ajout de comptes
if (! empty($selectcpt)) {
- $cpts = array ();
+ $cpts = array();
foreach ($selectcpt as $selectedoption) {
if (! array_key_exists($selectedoption, $cpts))
$cpts[$selectedoption] = "'" . $selectedoption . "'";
@@ -71,13 +71,13 @@ if (! empty($selectcpt)) {
if ($return<0) {
setEventMessages($langs->trans('errors'), $accountingcategory->errors, 'errors');
} else {
- setEventMessages($langs->trans('SetupSaved'), null, 'mesgs');
+ setEventMessages($langs->trans('RecordModifiedSuccessfully'), null, 'mesgs');
}
}
if ($action == 'delete') {
if ($cpt_id) {
if ($accountingcategory->deleteCptCat($cpt_id)) {
- setEventMessages($langs->trans('CategoryDeleted'), null, 'mesgs');
+ setEventMessages($langs->trans('AccountRemovedFromGroup'), null, 'mesgs');
} else {
setEventMessages($langs->trans('errors'), null, 'errors');
}
@@ -173,8 +173,9 @@ if ($action == 'display' || $action == 'delete') {
print '
' . $cpt->label . ' ';
print '';
print "rowid."'>";
- print img_delete($langs->trans("DeleteFromCat")).' ';
- print $langs->trans("DeleteFromCat")." ";
+ print $langs->trans("DeleteFromCat");
+ print img_picto($langs->trans("DeleteFromCat"), 'unlink');
+ print "";
print " ";
print "\n";
}
diff --git a/htdocs/accountancy/admin/productaccount.php b/htdocs/accountancy/admin/productaccount.php
index df8ce99fa10..07df2a91872 100644
--- a/htdocs/accountancy/admin/productaccount.php
+++ b/htdocs/accountancy/admin/productaccount.php
@@ -65,6 +65,8 @@ $accounting_product_mode = GETPOST('accounting_product_mode', 'alpha');
$btn_changeaccount = GETPOST('changeaccount', 'alpha');
$btn_changetype = GETPOST('changetype', 'alpha');
+if (empty($accounting_product_mode)) $accounting_product_mode='ACCOUNTANCY_SELL';
+
$limit = GETPOST('limit', 'int')?GETPOST('limit', 'int'):(empty($conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION)?$conf->liste_limit:$conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION);
$sortfield = GETPOST("sortfield", 'alpha');
$sortorder = GETPOST("sortorder", 'alpha');
@@ -112,8 +114,6 @@ if ($action == 'update') {
'ACCOUNTANCY_BUY'
);
- $accounting_product_mode = GETPOST('accounting_product_mode', 'alpha');
-
if (in_array($accounting_product_mode, $accounting_product_modes)) {
if (! dolibarr_set_const($db, 'ACCOUNTING_PRODUCT_MODE', $accounting_product_mode, 'chaine', 0, '', $conf->entity)) {
diff --git a/htdocs/accountancy/class/accountancycategory.class.php b/htdocs/accountancy/class/accountancycategory.class.php
index 73cccdfd721..523fba7acda 100644
--- a/htdocs/accountancy/class/accountancycategory.class.php
+++ b/htdocs/accountancy/class/accountancycategory.class.php
@@ -38,7 +38,7 @@ class AccountancyCategory // extends CommonObject
/**
* @var string Error string
- * @see errors
+ * @see $errors
*/
public $error;
@@ -63,7 +63,7 @@ class AccountancyCategory // extends CommonObject
public $id;
/**
- * @var mixed Sample property 1
+ * @var string Accountancy code
*/
public $code;
@@ -73,7 +73,7 @@ class AccountancyCategory // extends CommonObject
public $label;
/**
- * @var mixed Sample property 1
+ * @var string Accountancy range account
*/
public $range_account;
@@ -83,37 +83,37 @@ class AccountancyCategory // extends CommonObject
public $sens;
/**
- * @var mixed Sample property 1
+ * @var int Category type of accountancy
*/
public $category_type;
/**
- * @var mixed Sample property 1
+ * @var string Formula
*/
public $formula;
/**
- * @var mixed Sample property 1
+ * @var int Position
*/
public $position;
/**
- * @var mixed Sample property 1
+ * @var int country id
*/
public $fk_country;
/**
- * @var mixed Sample property 1
+ * @var int Is active
*/
public $active;
/**
- * @var mixed Sample property 1
+ * @var array Lines cptbk
*/
public $lines_cptbk;
/**
- * @var mixed Sample property 1
+ * @var array Lines display
*/
public $lines_display;
@@ -151,12 +151,12 @@ class AccountancyCategory // extends CommonObject
if (isset($this->code)) $this->code=trim($this->code);
if (isset($this->label)) $this->label=trim($this->label);
if (isset($this->range_account)) $this->range_account=trim($this->range_account);
- if (isset($this->sens)) $this->sens=trim($this->sens);
- if (isset($this->category_type)) $this->category_type=trim($this->category_type);
+ if (isset($this->sens)) $this->sens = (int) $this->sens;
+ if (isset($this->category_type)) $this->category_type = (int) $this->category_type;
if (isset($this->formula)) $this->formula=trim($this->formula);
- if (isset($this->position)) $this->position=trim($this->position);
- if (isset($this->fk_country)) $this->fk_country=trim($this->fk_country);
- if (isset($this->active)) $this->active=trim($this->active);
+ if (isset($this->position)) $this->position = (int) $this->position;
+ if (isset($this->fk_country)) $this->fk_country = (int) $this->fk_country;
+ if (isset($this->active)) $this->active = (int) $this->active;
// Check parameters
// Put here code to add control on parameters values
@@ -308,12 +308,12 @@ class AccountancyCategory // extends CommonObject
if (isset($this->code)) $this->code=trim($this->code);
if (isset($this->label)) $this->label=trim($this->label);
if (isset($this->range_account)) $this->range_account=trim($this->range_account);
- if (isset($this->sens)) $this->sens=trim($this->sens);
- if (isset($this->category_type)) $this->category_type=trim($this->category_type);
+ if (isset($this->sens)) $this->sens = (int) $this->sens;
+ if (isset($this->category_type)) $this->category_type = (int) $this->category_type;
if (isset($this->formula)) $this->formula=trim($this->formula);
- if (isset($this->position)) $this->position=trim($this->position);
- if (isset($this->fk_country)) $this->fk_country=trim($this->fk_country);
- if (isset($this->active)) $this->active=trim($this->active);
+ if (isset($this->position)) $this->position = (int) $this->position;
+ if (isset($this->fk_country)) $this->fk_country = (int) $this->fk_country;
+ if (isset($this->active)) $this->active = (int) $this->active;
// Check parameters
@@ -338,8 +338,8 @@ class AccountancyCategory // extends CommonObject
$resql = $this->db->query($sql);
if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
- if (! $error)
- {
+ //if (! $error)
+ //{
// Uncomment this and change MYOBJECT to your own tag if you
// want this action call a trigger.
//if (! $notrigger)
@@ -351,7 +351,7 @@ class AccountancyCategory // extends CommonObject
// if ($result < 0) { $error++; $this->errors=$interface->errors; }
// // End call triggers
//}
- }
+ //}
// Commit or rollback
if ($error)
@@ -393,8 +393,8 @@ class AccountancyCategory // extends CommonObject
$resql = $this->db->query($sql);
if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
- if (! $error)
- {
+ //if (! $error)
+ //{
// Uncomment this and change MYOBJECT to your own tag if you
// want this action call a trigger.
//if (! $notrigger)
@@ -406,7 +406,7 @@ class AccountancyCategory // extends CommonObject
// if ($result < 0) { $error++; $this->errors=$interface->errors; }
// // End call triggers
//}
- }
+ //}
// Commit or rollback
if ($error)
@@ -514,7 +514,7 @@ class AccountancyCategory // extends CommonObject
/**
* Function to select accounting category of an accounting account present in chart of accounts
*
- * @param int $id Id category
+ * @param int $id Id of category to know which account to exclude
*
* @return int <0 if KO, 0 if not found, >0 if OK
*/
@@ -569,12 +569,13 @@ class AccountancyCategory // extends CommonObject
require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
- $sql = "SELECT aa.rowid,aa.account_number ";
+ $sql = "SELECT aa.rowid, aa.account_number";
$sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as aa";
$sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
$sql .= " AND asy.rowid = " . $conf->global->CHARTOFACCOUNTS;
$sql .= " AND aa.active = 1";
$sql .= " AND aa.entity = " . $conf->entity;
+ $sql .= " ORDER BY LENGTH(aa.account_number) DESC;"; // LENGTH is ok with mysql and postgresql
$this->db->begin();
@@ -587,10 +588,16 @@ class AccountancyCategory // extends CommonObject
return -1;
}
- while ( $obj = $this->db->fetch_object($resql))
+ $accountincptsadded=array();
+ while ($obj = $this->db->fetch_object($resql))
{
- if (array_key_exists(length_accountg($obj->account_number), $cpts))
+ $account_number_formated=length_accountg($obj->account_number);
+ if (! empty($accountincptsadded[$account_number_formated])) continue;
+
+ if (array_key_exists($account_number_formated, $cpts))
{
+ $accountincptsadded[$account_number_formated]=1;
+ // We found an account number that is in list $cpts of account to add
$sql = "UPDATE " . MAIN_DB_PREFIX . "accounting_account";
$sql .= " SET fk_accounting_category=" . $id_cat;
$sql .= " WHERE rowid=".$obj->rowid;
diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php
index 90b722d7959..a641ccb4db5 100644
--- a/htdocs/accountancy/class/accountancyexport.class.php
+++ b/htdocs/accountancy/class/accountancyexport.class.php
@@ -31,20 +31,15 @@
* \brief Class accountancy export
*/
-/**
- * Class AccountancyExport
- *
- * Manage the different format accountancy export
- */
-
require_once DOL_DOCUMENT_ROOT . '/core/lib/functions.lib.php';
+/**
+ * Manage the different format accountancy export
+ */
class AccountancyExport
{
- /**
- * Type of export. Defined by $conf->global->ACCOUNTING_EXPORT_MODELCSV
- */
- public static $EXPORT_TYPE_NORMAL = 1; // CSV
+ // Type of export. Used into $conf->global->ACCOUNTING_EXPORT_MODELCSV
+ public static $EXPORT_TYPE_NORMAL = 1; // CSV
public static $EXPORT_TYPE_CONFIGURABLE = 10; // CSV
public static $EXPORT_TYPE_CEGID = 2;
public static $EXPORT_TYPE_COALA = 3;
diff --git a/htdocs/accountancy/index.php b/htdocs/accountancy/index.php
index ca66201dac7..b34efe5ea04 100644
--- a/htdocs/accountancy/index.php
+++ b/htdocs/accountancy/index.php
@@ -64,13 +64,13 @@ if ($conf->accounting->enabled)
// STEPS
$step++;
- print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescJournalSetup", $step, ''.''.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("AccountingJournals").' '.' ');
+ print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescJournalSetup", $step, ''.''.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("AccountingJournals").' '.' ');
print " \n";
$step++;
- print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescChartModel", $step, ''.''.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("Pcg_version").' '.' ');
+ print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescChartModel", $step, ''.''.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("Pcg_version").' '.' ');
print " \n";
$step++;
- print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescChart", $step, ''.''.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("Chartofaccounts").' '.' ');
+ print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescChart", $step, ''.''.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("Chartofaccounts").' '.' ');
print " \n";
print " \n";
@@ -79,20 +79,20 @@ if ($conf->accounting->enabled)
print " \n";
$step++;
- print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescDefault", $step, ''.''.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").' '.' ');
+ print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescDefault", $step, ''.''.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("MenuDefaultAccounts").' '.' ');
print " \n";
$step++;
- print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescBank", $step, ''.''.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuBankAccounts").' '.' ')."\n";
+ print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescBank", $step, ''.''.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("MenuBankAccounts").' '.' ')."\n";
print " \n";
$step++;
- $textlink = ''.''.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup").'-'.$langs->transnoentitiesnoconv("MenuVatAccounts").' '.' ';
+ $textlink = ''.''.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("MenuVatAccounts").' '.' ';
print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescVat", $step, $textlink);
print " \n";
if (! empty($conf->tax->enabled))
{
- $textlink = ''.''.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup").'-'.$langs->transnoentitiesnoconv("MenuTaxAccounts").' '.' ';
+ $textlink = ''.''.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("MenuTaxAccounts").' '.' ';
$step++;
print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescContrib", $step, $textlink);
print " \n";
@@ -100,7 +100,7 @@ if ($conf->accounting->enabled)
/*if (! empty($conf->salaries->enabled))
{
$step++;
- print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescSal", $step, ''.$langs->transnoentitiesnoconv("MenuFinancial").'-'.$langs->transnoentitiesnoconv("MenuAccountancy")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").' ');
+ print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescSal", $step, ''.$langs->transnoentitiesnoconv("MenuFinancial").'-'.$langs->transnoentitiesnoconv("MenuAccountancy").' - '.$langs->transnoentitiesnoconv("MenuDefaultAccounts").' ');
// htdocs/admin/salaries.php
print " \n";
print " \n";
@@ -108,36 +108,37 @@ if ($conf->accounting->enabled)
if (! empty($conf->expensereport->enabled)) // TODO Move this in the default account page because this is only one accounting account per purpose, not several.
{
$step++;
- print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescExpenseReport", $step, ''.''.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuExpenseReportAccounts").' '.' ');
+ print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescExpenseReport", $step, ''.''.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("MenuExpenseReportAccounts").' '.' ');
print " \n";
}
/*
if (! empty($conf->loan->enabled))
{
$step++;
- print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescLoan", $step, ''.$langs->transnoentitiesnoconv("MenuSpecialExpenses").'-'.$langs->transnoentitiesnoconv("Loans").' '.$langs->transnoentitiesnoconv("or").' '.$langs->transnoentitiesnoconv("MenuFinancial").'-'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").' ');
+ print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescLoan", $step, ''.$langs->transnoentitiesnoconv("MenuSpecialExpenses").' - '.$langs->transnoentitiesnoconv("Loans").' '.$langs->transnoentitiesnoconv("or").' '.$langs->transnoentitiesnoconv("MenuFinancial").'-'.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("MenuDefaultAccounts").' ');
print " \n";
}
if (! empty($conf->don->enabled))
{
$step++;
- print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescDonation", $step, ''.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").' ');
+ print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescDonation", $step, ''.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("MenuDefaultAccounts").' ');
print " \n";
}
if (! empty($conf->adherents->enabled))
{
$step++;
- print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescSubscription", $step, ''.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").' ');
+ print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescSubscription", $step, ''.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("MenuDefaultAccounts").' ');
print " \n";
}*/
$step++;
- print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescProd", $step, ''.''.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("ProductsBinding").' '.' ');
+ print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescProd", $step, ''.''.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("ProductsBinding").' '.' ');
print " \n";
print ' ';
+ // Step A - E
print " \n";
print load_fiche_titre(' '.$langs->trans("AccountancyAreaDescActionFreq"), '', '');
@@ -148,22 +149,22 @@ if ($conf->accounting->enabled)
$langs->loadLangs(array('bills', 'trips'));
$step++;
- print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescBind", chr(64+$step), $langs->transnoentitiesnoconv("BillsCustomers"), ''.''.$langs->transnoentitiesnoconv("MenuAccountancy")."-".$langs->transnoentitiesnoconv("CustomersVentilation").' '.' ')."\n";
+ print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescBind", chr(64+$step), $langs->transnoentitiesnoconv("BillsCustomers"), ''.''.$langs->transnoentitiesnoconv("TransferInAccounting").' - '.$langs->transnoentitiesnoconv("CustomersVentilation").' '.' ')."\n";
print " \n";
$step++;
- print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescBind", chr(64+$step), $langs->transnoentitiesnoconv("BillsSuppliers"), ''.''.$langs->transnoentitiesnoconv("MenuAccountancy")."-".$langs->transnoentitiesnoconv("SuppliersVentilation").' '.' ')."\n";
+ print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescBind", chr(64+$step), $langs->transnoentitiesnoconv("BillsSuppliers"), ''.''.$langs->transnoentitiesnoconv("TransferInAccounting").' - '.$langs->transnoentitiesnoconv("SuppliersVentilation").' '.' ')."\n";
print " \n";
if (! empty($conf->expensereport->enabled) || ! empty($conf->deplacement->enabled))
{
$step++;
- print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescBind", chr(64+$step), $langs->transnoentitiesnoconv("ExpenseReports"), ''.''.$langs->transnoentitiesnoconv("MenuAccountancy")."-".$langs->transnoentitiesnoconv("ExpenseReportsVentilation").' '.' ')."\n";
+ print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescBind", chr(64+$step), $langs->transnoentitiesnoconv("ExpenseReports"), ''.''.$langs->transnoentitiesnoconv("TransferInAccounting").' - '.$langs->transnoentitiesnoconv("ExpenseReportsVentilation").' '.' ')."\n";
print " \n";
}
$step++;
- print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescWriteRecords", chr(64+$step), $langs->transnoentitiesnoconv("Journalization"), $langs->transnoentitiesnoconv("WriteBookKeeping"))."\n";
+ print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescWriteRecords", chr(64+$step), $langs->transnoentitiesnoconv("TransferInAccounting").' - '.$langs->transnoentitiesnoconv("RegistrationInAccounting"), $langs->transnoentitiesnoconv("WriteBookKeeping"))."\n";
print " \n";
$step++;
diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php
index d4b77342c84..9a84782e920 100644
--- a/htdocs/adherents/class/adherent.class.php
+++ b/htdocs/adherents/class/adherent.class.php
@@ -587,7 +587,7 @@ class Adherent extends CommonObject
}
}
}
-
+
dol_syslog(get_class($this)."::update update member", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql)
@@ -1866,7 +1866,7 @@ class Adherent extends CommonObject
$error=0;
- // Check paramaters
+ // Check parameters
if ($this->statut == 0)
{
dol_syslog(get_class($this)."::resiliate statut of member does not allow this", LOG_WARNING);
@@ -2149,7 +2149,7 @@ class Adherent extends CommonObject
* @param int $statut Id statut
* @param int $need_subscription 1 if member type need subscription, 0 otherwise
* @param int $date_end_subscription Date fin adhesion
- * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
+ * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
* @return string Label
*/
public function LibStatut($statut, $need_subscription, $date_end_subscription, $mode = 0)
@@ -2209,7 +2209,7 @@ class Adherent extends CommonObject
}
elseif ($mode == 5)
{
- if ($statut == -1) return $langs->trans("MemberStatusDraft").' '.img_picto($langs->trans('MemberStatusDraft'), 'statut0');
+ if ($statut == -1) return ''.$langs->trans("MemberStatusDraftShort").' '.img_picto($langs->trans('MemberStatusDraft'), 'statut0');
elseif ($statut >= 1) {
if (! $date_end_subscription) return ''.$langs->trans("MemberStatusActiveShort").' '.img_picto($langs->trans('MemberStatusActive'), 'statut1');
elseif ($date_end_subscription < time()) return ''.$langs->trans("MemberStatusActiveLateShort").' '.img_picto($langs->trans('MemberStatusActiveLate'), 'statut3');
@@ -2219,13 +2219,13 @@ class Adherent extends CommonObject
}
elseif ($mode == 6)
{
- if ($statut == -1) return $langs->trans("MemberStatusDraft").' '.img_picto($langs->trans('MemberStatusDraft'), 'statut0');
+ if ($statut == -1) return $langs->trans("MemberStatusDraft").' '.img_picto($langs->trans('MemberStatusDraft'), 'statut0');
if ($statut >= 1) {
- if (! $date_end_subscription) return ''.$langs->trans("MemberStatusActive").' '.img_picto($langs->trans('MemberStatusActive'), 'statut1');
- elseif ($date_end_subscription < time()) return ''.$langs->trans("MemberStatusActiveLate").' '.img_picto($langs->trans('MemberStatusActiveLate'), 'statut3');
- else return ''.$langs->trans("MemberStatusPaid").' '.img_picto($langs->trans('MemberStatusPaid'), 'statut4');
+ if (! $date_end_subscription) return $langs->trans("MemberStatusActive").' '.img_picto($langs->trans('MemberStatusActive'), 'statut1');
+ elseif ($date_end_subscription < time()) return $langs->trans("MemberStatusActiveLate").' '.img_picto($langs->trans('MemberStatusActiveLate'), 'statut3');
+ else return $langs->trans("MemberStatusPaid").' '.img_picto($langs->trans('MemberStatusPaid'), 'statut4');
}
- if ($statut == 0) return ''.$langs->trans("MemberStatusResiliated").' '.img_picto($langs->trans('MemberStatusResiliated'), 'statut5');
+ if ($statut == 0) return $langs->trans("MemberStatusResiliated").' '.img_picto($langs->trans('MemberStatusResiliated'), 'statut5');
}
}
diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php
index bd5f70d0973..35e1fd1553f 100644
--- a/htdocs/adherents/list.php
+++ b/htdocs/adherents/list.php
@@ -436,23 +436,23 @@ if (! empty($conf->global->MAIN_SHOW_TECHNICAL_ID))
if (! empty($arrayfields['d.ref']['checked']))
{
print '';
- print ' ';
+ print ' ';
print ' ';
}
if (! empty($arrayfields['d.civility']['checked']))
{
print '';
- print ' ';
+ print ' ';
}
if (! empty($arrayfields['d.firstname']['checked']))
{
print '';
- print ' ';
+ print ' ';
}
if (! empty($arrayfields['d.lastname']['checked']))
{
print '';
- print ' ';
+ print ' ';
}
if (! empty($arrayfields['d.gender']['checked']))
{
@@ -464,12 +464,12 @@ if (! empty($arrayfields['d.gender']['checked']))
if (! empty($arrayfields['d.company']['checked']))
{
print '';
- print ' ';
+ print ' ';
}
if (! empty($arrayfields['d.login']['checked']))
{
print '';
- print ' ';
+ print ' ';
}
if (! empty($arrayfields['d.morphy']['checked']))
{
@@ -487,24 +487,24 @@ if (! empty($arrayfields['t.libelle']['checked']))
if (! empty($arrayfields['d.address']['checked']))
{
print '';
- print ' ';
+ print ' ';
}
if (! empty($arrayfields['d.zip']['checked']))
{
print '';
- print ' ';
+ print ' ';
}
if (! empty($arrayfields['d.town']['checked']))
{
print '';
- print ' ';
+ print ' ';
}
// State
if (! empty($arrayfields['state.nom']['checked']))
{
print '';
- print ' ';
+ print ' ';
print ' ';
}
// Country
@@ -518,7 +518,7 @@ if (! empty($arrayfields['country.code_iso']['checked']))
if (! empty($arrayfields['d.phone']['checked']))
{
print '';
- print ' ';
+ print ' ';
}
// Phone perso
if (! empty($arrayfields['d.phone_perso']['checked']))
@@ -530,13 +530,13 @@ if (! empty($arrayfields['d.phone_perso']['checked']))
if (! empty($arrayfields['d.phone_mobile']['checked']))
{
print '';
- print ' ';
+ print ' ';
}
// Email
if (! empty($arrayfields['d.email']['checked']))
{
print '';
- print ' ';
+ print ' ';
}
if (! empty($arrayfields['d.datefin']['checked']))
diff --git a/htdocs/admin/debugbar.php b/htdocs/admin/debugbar.php
new file mode 100644
index 00000000000..34cc06c5f08
--- /dev/null
+++ b/htdocs/admin/debugbar.php
@@ -0,0 +1,104 @@
+
+ * Copyright (C) 2005-2009 Regis Houssin
+ * Copyright (C) 2007 Rodolphe Quiedeville
+ * Copyright (C) 2013 Juanjo Menent
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/**
+ * \file htdocs/admin/debugbar.php
+ * \ingroup debugbar
+ * \brief Setup page for debugbar module
+ */
+
+require '../main.inc.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
+
+global $conf;
+
+if (!$user->admin) accessforbidden();
+
+// Load translation files required by the page
+$langs->loadLangs(array("admin","other"));
+
+$error=0;
+$action = GETPOST('action', 'aZ09');
+
+
+/*
+ * Actions
+ */
+
+// Set modes
+if ($action == 'set')
+{
+ $db->begin();
+
+ $result = dolibarr_set_const($db, "DEBUGBAR_LOGS_LINES_NUMBER", GETPOST('DEBUGBAR_LOGS_LINES_NUMBER', 'int'), 'chaine', 0, '', 0);
+ if ($result < 0)
+ {
+ $error++;
+ }
+
+ if (! $error)
+ {
+ $db->commit();
+ setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
+ }
+ else
+ {
+ $db->rollback();
+ setEventMessages($error, $errors, 'errors');
+ }
+}
+
+
+/*
+ * View
+ */
+
+llxHeader();
+
+$form=new Form($db);
+
+$linkback=''.$langs->trans("BackToModuleList").' ';
+print load_fiche_titre($langs->trans("DebugBarSetup"), $linkback, 'title_setup');
+print ' ';
+
+//print load_fiche_titre($langs->trans("DebugBar"));
+
+// Level
+print '\n";
+
+// End of page
+llxFooter();
+$db->close();
diff --git a/htdocs/admin/facture.php b/htdocs/admin/facture.php
index e1d65250b6d..b1c9df224ea 100644
--- a/htdocs/admin/facture.php
+++ b/htdocs/admin/facture.php
@@ -77,8 +77,7 @@ if ($action == 'updateMask')
setEventMessages($langs->trans("Error"), null, 'errors');
}
}
-
-else if ($action == 'specimen')
+elseif ($action == 'specimen')
{
$modele=GETPOST('module', 'alpha');
@@ -122,7 +121,6 @@ else if ($action == 'specimen')
dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR);
}
}
-
// Activate a model
elseif ($action == 'set')
{
@@ -137,7 +135,6 @@ elseif ($action == 'del')
if ($conf->global->FACTURE_ADDON_PDF == "$value") dolibarr_del_const($db, 'FACTURE_ADDON_PDF', $conf->entity);
}
}
-
// Set default model
elseif ($action == 'setdoc')
{
@@ -155,7 +152,6 @@ elseif ($action == 'setdoc')
$ret = addDocumentModel($value, $type, $label, $scandir);
}
}
-
elseif ($action == 'setmod')
{
// TODO Verifier si module numerotation choisi peut etre active
@@ -163,8 +159,7 @@ elseif ($action == 'setmod')
dolibarr_set_const($db, "FACTURE_ADDON", $value, 'chaine', 0, '', $conf->entity);
}
-
-else if ($action == 'setribchq')
+elseif ($action == 'setribchq')
{
$rib = GETPOST('rib', 'alpha');
$chq = GETPOST('chq', 'alpha');
@@ -183,8 +178,7 @@ else if ($action == 'setribchq')
setEventMessages($langs->trans("Error"), null, 'errors');
}
}
-
-else if ($action == 'set_FACTURE_DRAFT_WATERMARK')
+elseif ($action == 'set_FACTURE_DRAFT_WATERMARK')
{
$draft = GETPOST('FACTURE_DRAFT_WATERMARK', 'alpha');
@@ -202,7 +196,7 @@ else if ($action == 'set_FACTURE_DRAFT_WATERMARK')
}
}
-else if ($action == 'set_INVOICE_FREE_TEXT')
+elseif ($action == 'set_INVOICE_FREE_TEXT')
{
$freetext = GETPOST('INVOICE_FREE_TEXT', 'none'); // No alpha here, we want exact string
@@ -219,8 +213,7 @@ else if ($action == 'set_INVOICE_FREE_TEXT')
setEventMessages($langs->trans("Error"), null, 'errors');
}
}
-
-else if ($action == 'setforcedate')
+elseif ($action == 'setforcedate')
{
$forcedate = GETPOST('forcedate', 'alpha');
@@ -237,8 +230,7 @@ else if ($action == 'setforcedate')
setEventMessages($langs->trans("Error"), null, 'errors');
}
}
-
-else if ($action == 'setDefaultPDFModulesByType')
+elseif ($action == 'setDefaultPDFModulesByType')
{
$invoicetypemodels = GETPOST('invoicetypemodels');
diff --git a/htdocs/admin/ihm.php b/htdocs/admin/ihm.php
index d903c592bfe..612883dac38 100644
--- a/htdocs/admin/ihm.php
+++ b/htdocs/admin/ihm.php
@@ -139,7 +139,7 @@ if ($action == 'update')
dolibarr_set_const($db, "MAIN_SIZE_LISTE_LIMIT", $_POST["main_size_liste_limit"], 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, "MAIN_SIZE_SHORTLIST_LIMIT", $_POST["main_size_shortliste_limit"], 'chaine', 0, '', $conf->entity);
- dolibarr_set_const($db, "MAIN_DISABLE_JAVASCRIPT", $_POST["main_disable_javascript"], 'chaine', 0, '', $conf->entity);
+ dolibarr_set_const($db, "MAIN_DISABLE_JAVASCRIPT", $_POST["MAIN_DISABLE_JAVASCRIPT"], 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, "MAIN_BUTTON_HIDE_UNAUTHORIZED", $_POST["MAIN_BUTTON_HIDE_UNAUTHORIZED"], 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, "MAIN_START_WEEK", $_POST["MAIN_START_WEEK"], 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, "MAIN_DEFAULT_WORKING_DAYS", $_POST["MAIN_DEFAULT_WORKING_DAYS"], 'chaine', 0, '', $conf->entity);
@@ -259,11 +259,18 @@ if ($action == 'edit') // Edit
print ' ';
// Other
- print '';
+ print '';
print ''.$langs->trans("Parameters").' '.$langs->trans("Value").' ';
print ' ';
print ' ';
+ // Disable javascript and ajax
+ print ''.$langs->trans("DisableJavascript").' ';
+ print $form->selectyesno('MAIN_DISABLE_JAVASCRIPT', isset($conf->global->MAIN_DISABLE_JAVASCRIPT)?$conf->global->MAIN_DISABLE_JAVASCRIPT:0, 1);
+ print ' ';
+ print ' ';
+ print ' ';
+
// Max size of lists
print ''.$langs->trans("DefaultMaxSizeList").' ';
print ' ';
@@ -283,13 +290,6 @@ if ($action == 'edit') // Edit
print ' ';
*/
- // Disable javascript and ajax
- print ''.$langs->trans("DisableJavascript").' ';
- print $form->selectyesno('main_disable_javascript', isset($conf->global->MAIN_DISABLE_JAVASCRIPT)?$conf->global->MAIN_DISABLE_JAVASCRIPT:0, 1);
- print ' ';
- print ' ';
- print ' ';
-
// First day for weeks
print ''.$langs->trans("WeekStartOnDay").' ';
print $formother->select_dayofweek((isset($conf->global->MAIN_START_WEEK)?$conf->global->MAIN_START_WEEK:'1'), 'MAIN_START_WEEK', 0);
@@ -468,17 +468,21 @@ else // Show
print '';
print ''.$langs->trans("Parameters").' '.$langs->trans("Value").' ';
+ // Disable javascript/ajax
+ print ''.$langs->trans("DisableJavascript").' ';
+ print yn($conf->global->MAIN_DISABLE_JAVASCRIPT);
+ print ' - '.$langs->trans("DisableJavascriptNote").' ';
+ print " ";
+ print " ";
+
+ // Max size of lists
print ''.$langs->trans("DefaultMaxSizeList").' ' . $conf->global->MAIN_SIZE_LISTE_LIMIT . ' ';
print " ";
+ // Max size of short lists
print ''.$langs->trans("DefaultMaxSizeShortList").' ' . $conf->global->MAIN_SIZE_SHORTLIST_LIMIT . ' ';
print " ";
- // Disable javascript/ajax
- print ''.$langs->trans("DisableJavascript").' ';
- print yn($conf->global->MAIN_DISABLE_JAVASCRIPT)." ";
- print " ";
-
// First day for weeks
print ''.$langs->trans("WeekStartOnDay").' ';
print $langs->trans("Day".(isset($conf->global->MAIN_START_WEEK)?$conf->global->MAIN_START_WEEK:'1'));
diff --git a/htdocs/admin/prelevement.php b/htdocs/admin/prelevement.php
index 34e407bd863..144ec744d41 100644
--- a/htdocs/admin/prelevement.php
+++ b/htdocs/admin/prelevement.php
@@ -173,7 +173,7 @@ if ($action == 'specimen')
}
// Set default model
-else if ($action == 'setdoc')
+elseif ($action == 'setdoc')
{
if (dolibarr_set_const($db, "PAYMENTORDER_ADDON_PDF",$value,'chaine',0,'',$conf->entity))
{
diff --git a/htdocs/admin/propal.php b/htdocs/admin/propal.php
index e9a037b98c9..db41876b02c 100644
--- a/htdocs/admin/propal.php
+++ b/htdocs/admin/propal.php
@@ -69,8 +69,7 @@ if ($action == 'updateMask')
setEventMessages($langs->trans("Error"), null, 'errors');
}
}
-
-else if ($action == 'specimen')
+elseif ($action == 'specimen')
{
$modele=GETPOST('module', 'alpha');
@@ -114,14 +113,13 @@ else if ($action == 'specimen')
dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR);
}
}
-
-else if ($action == 'setribchq')
+elseif ($action == 'setribchq')
{
- $rib = GETPOST('rib','alpha');
- $chq = GETPOST('chq','alpha');
+ $rib = GETPOST('rib', 'alpha');
+ $chq = GETPOST('chq', 'alpha');
- $res = dolibarr_set_const($db, "FACTURE_RIB_NUMBER",$rib,'chaine',0,'',$conf->entity);
- $res = dolibarr_set_const($db, "FACTURE_CHQ_NUMBER",$chq,'chaine',0,'',$conf->entity);
+ $res = dolibarr_set_const($db, "FACTURE_RIB_NUMBER", $rib, 'chaine', 0, '', $conf->entity);
+ $res = dolibarr_set_const($db, "FACTURE_CHQ_NUMBER", $chq, 'chaine', 0, '', $conf->entity);
if (! $res > 0) $error++;
@@ -134,8 +132,7 @@ else if ($action == 'setribchq')
setEventMessages($langs->trans("Error"), null, 'errors');
}
}
-
-else if ($action == 'set_PROPALE_DRAFT_WATERMARK')
+elseif ($action == 'set_PROPALE_DRAFT_WATERMARK')
{
$draft = GETPOST('PROPALE_DRAFT_WATERMARK', 'alpha');
@@ -151,8 +148,7 @@ else if ($action == 'set_PROPALE_DRAFT_WATERMARK')
setEventMessages($langs->trans("Error"), null, 'errors');
}
}
-
-else if ($action == 'set_PROPOSAL_FREE_TEXT')
+elseif ($action == 'set_PROPOSAL_FREE_TEXT')
{
$freetext = GETPOST('PROPOSAL_FREE_TEXT', 'none'); // No alpha here, we want exact string
@@ -169,8 +165,7 @@ else if ($action == 'set_PROPOSAL_FREE_TEXT')
setEventMessages($langs->trans("Error"), null, 'errors');
}
}
-
-else if ($action == 'setdefaultduration')
+elseif ($action == 'setdefaultduration')
{
$res = dolibarr_set_const($db, "PROPALE_VALIDITY_DURATION", $value, 'chaine', 0, '', $conf->entity);
@@ -186,7 +181,7 @@ else if ($action == 'setdefaultduration')
}
}
-else if ($action == 'set_BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL')
+elseif ($action == 'set_BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL')
{
$res = dolibarr_set_const($db, "BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL", $value, 'chaine', 0, '', $conf->entity);
@@ -201,13 +196,11 @@ else if ($action == 'set_BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL')
setEventMessages($langs->trans("Error"), null, 'errors');
}
}
-
// Activate a model
-else if ($action == 'set')
+elseif ($action == 'set')
{
$ret = addDocumentModel($value, $type, $label, $scandir);
}
-
elseif ($action == 'del')
{
$ret = delDocumentModel($value, $type);
@@ -476,7 +469,7 @@ foreach ($dirmodels as $reldir)
print ' ';
// Info
- $htmltooltip = ''.$langs->trans("Name").': '.$module->name;
+ $htmltooltip = $langs->trans("Name").': '.$module->name;
$htmltooltip.=' '.$langs->trans("Type").': '.($module->type?$module->type:$langs->trans("Unknown"));
if ($module->type == 'pdf')
{
@@ -526,7 +519,7 @@ print '
';
if (empty($conf->facture->enabled))
{
print ' ';
- print load_fiche_titre($langs->trans("SuggestedPaymentModesIfNotDefinedInProposal"),'','');
+ print load_fiche_titre($langs->trans("SuggestedPaymentModesIfNotDefinedInProposal"), '', '');
print '
';
diff --git a/htdocs/core/modules/supplier_invoice/mod_facture_fournisseur_tulip.php b/htdocs/core/modules/supplier_invoice/mod_facture_fournisseur_tulip.php
index 7f85cbe5bb6..8ab95ab3336 100644
--- a/htdocs/core/modules/supplier_invoice/mod_facture_fournisseur_tulip.php
+++ b/htdocs/core/modules/supplier_invoice/mod_facture_fournisseur_tulip.php
@@ -93,28 +93,28 @@ class mod_facture_fournisseur_tulip extends ModeleNumRefSuppliersInvoices
// Parametrage du prefix
$texte.= ''.$langs->trans("Mask").' ('.$langs->trans("InvoiceStandard").')';
$texte.= ': ';
- $texte.= ''.$form->textwithpicto(' ', $tooltip, 1, 1).' ';
+ $texte.= ''.$form->textwithpicto(' ', $tooltip, 1, 1).' ';
- $texte.= ' ';
+ $texte.= ' ';
$texte.= ' ';
// Parametrage du prefix des avoirs
$texte.= ''.$langs->trans("Mask").' ('.$langs->trans("InvoiceAvoir").'): ';
- $texte.= ''.$form->textwithpicto(' ', $tooltip, 1, 1).' ';
+ $texte.= ''.$form->textwithpicto(' ', $tooltip, 1, 1).' ';
$texte.= ' ';
if ($conf->global->MAIN_FEATURE_LEVEL >= 2)
{
// Parametrage du prefix des replacement
$texte.= ''.$langs->trans("Mask").' ('.$langs->trans("InvoiceReplacement").'): ';
- $texte.= ''.$form->textwithpicto(' ', $tooltip, 1, 1).' ';
+ $texte.= ''.$form->textwithpicto(' ', $tooltip, 1, 1).' ';
$texte.= ' ';
// Parametrage du prefix des acomptes
$texte.= ''.$langs->trans("Mask").' ('.$langs->trans("InvoiceDeposit").'): ';
- $texte.= ''.$form->textwithpicto(' ', $tooltip, 1, 1).' ';
+ $texte.= ''.$form->textwithpicto(' ', $tooltip, 1, 1).' ';
$texte.= ' ';
}
diff --git a/htdocs/core/modules/supplier_order/mod_commande_fournisseur_orchidee.php b/htdocs/core/modules/supplier_order/mod_commande_fournisseur_orchidee.php
index 320c33dce7d..1d1bc920237 100644
--- a/htdocs/core/modules/supplier_order/mod_commande_fournisseur_orchidee.php
+++ b/htdocs/core/modules/supplier_order/mod_commande_fournisseur_orchidee.php
@@ -85,9 +85,9 @@ class mod_commande_fournisseur_orchidee extends ModeleNumRefSuppliersOrders
// Parametrage du prefix
$texte.= ''.$langs->trans("Mask").': ';
- $texte.= ''.$form->textwithpicto(' ', $tooltip, 1, 1).' ';
+ $texte.= ''.$form->textwithpicto(' ', $tooltip, 1, 1).' ';
- $texte.= ' ';
+ $texte.= ' ';
$texte.= ' ';
diff --git a/htdocs/core/modules/supplier_payment/mod_supplier_payment_brodator.php b/htdocs/core/modules/supplier_payment/mod_supplier_payment_brodator.php
index c1f6e003d6d..2b29a18e2f0 100644
--- a/htdocs/core/modules/supplier_payment/mod_supplier_payment_brodator.php
+++ b/htdocs/core/modules/supplier_payment/mod_supplier_payment_brodator.php
@@ -82,9 +82,9 @@ class mod_supplier_payment_brodator extends ModeleNumRefSupplierPayments
// Parametrage du prefix
$texte.= ''.$langs->trans("Mask").': ';
- $texte.= ''.$form->textwithpicto(' ', $tooltip, 1, 1).' ';
+ $texte.= ''.$form->textwithpicto(' ', $tooltip, 1, 1).' ';
- $texte.= ' ';
+ $texte.= ' ';
$texte.= ' ';
diff --git a/htdocs/core/modules/supplier_proposal/mod_supplier_proposal_saphir.php b/htdocs/core/modules/supplier_proposal/mod_supplier_proposal_saphir.php
index f8cd365d5a7..d3a9de6c72b 100644
--- a/htdocs/core/modules/supplier_proposal/mod_supplier_proposal_saphir.php
+++ b/htdocs/core/modules/supplier_proposal/mod_supplier_proposal_saphir.php
@@ -85,9 +85,9 @@ class mod_supplier_proposal_saphir extends ModeleNumRefSupplierProposal
// Parametrage du prefix
$texte.= ''.$langs->trans("Mask").': ';
- $texte.= ''.$form->textwithpicto(' ', $tooltip, 1, 1).' ';
+ $texte.= ''.$form->textwithpicto(' ', $tooltip, 1, 1).' ';
- $texte.= ' ';
+ $texte.= ' ';
$texte.= ' ';
diff --git a/htdocs/core/modules/ticket/mod_ticket_universal.php b/htdocs/core/modules/ticket/mod_ticket_universal.php
index f33042aca67..deb7c4481cc 100644
--- a/htdocs/core/modules/ticket/mod_ticket_universal.php
+++ b/htdocs/core/modules/ticket/mod_ticket_universal.php
@@ -81,9 +81,9 @@ class mod_ticket_universal extends ModeleNumRefTicket
// Parametrage du prefix
$texte .= '' . $langs->trans("Mask") . ': ';
- $texte .= '' . $form->textwithpicto(' ', $tooltip, 1, 1) . ' ';
+ $texte .= '' . $form->textwithpicto(' ', $tooltip, 1, 1) . ' ';
- $texte .= ' ';
+ $texte .= ' ';
$texte .= ' ';
diff --git a/htdocs/core/tpl/commonfields_edit.tpl.php b/htdocs/core/tpl/commonfields_edit.tpl.php
index d6b70d86a2d..fce35ff9202 100644
--- a/htdocs/core/tpl/commonfields_edit.tpl.php
+++ b/htdocs/core/tpl/commonfields_edit.tpl.php
@@ -1,5 +1,5 @@
+/* Copyright (C) 2017-2019 Laurent Destailleur
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -55,7 +55,8 @@ foreach($object->fields as $key => $val)
elseif ($val['type'] == 'text' || $val['type'] == 'html') $value = GETPOSTISSET($key)?GETPOST($key, 'none'):$object->$key;
else $value = GETPOSTISSET($key)?GETPOST($key, 'alpha'):$object->$key;
//var_dump($val.' '.$key.' '.$value);
- print $object->showInputField($val, $key, $value, '', '', '', 0);
+ if ($val['noteditable']) print $object->showOutputField($val, $key, $value, '', '', '', 0);
+ else print $object->showInputField($val, $key, $value, '', '', '', 0);
print '';
print '';
}
diff --git a/htdocs/core/tpl/document_actions_post_headers.tpl.php b/htdocs/core/tpl/document_actions_post_headers.tpl.php
index e7f36bd358f..782385106db 100644
--- a/htdocs/core/tpl/document_actions_post_headers.tpl.php
+++ b/htdocs/core/tpl/document_actions_post_headers.tpl.php
@@ -52,7 +52,7 @@ if (in_array($modulepart, array('product', 'produit', 'societe', 'user', 'ticket
if ($action == 'delete')
{
$langs->load("companies"); // Need for string DeleteFile+ConfirmDeleteFiles
-print $form->formconfirm(
+ print $form->formconfirm(
$_SERVER["PHP_SELF"] . '?id=' . $object->id . '&urlfile=' . urlencode(GETPOST("urlfile")) . '&linkid=' . GETPOST('linkid', 'int') . (empty($param)?'':$param),
$langs->trans('DeleteFile'),
$langs->trans('ConfirmDeleteFile'),
diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php
index 6eaba659de0..388a9228024 100644
--- a/htdocs/core/tpl/objectline_create.tpl.php
+++ b/htdocs/core/tpl/objectline_create.tpl.php
@@ -278,6 +278,21 @@ else {
}
$form->select_produits_fournisseurs($object->socid, GETPOST('idprodfournprice'), 'idprodfournprice', '', '', $ajaxoptions, 1, $alsoproductwithnosupplierprice, 'maxwidth300');
+ ?>
+
+ ';
echo '';
diff --git a/htdocs/cron/class/cronjob.class.php b/htdocs/cron/class/cronjob.class.php
index c223f3c76ff..dafe772a0eb 100644
--- a/htdocs/cron/class/cronjob.class.php
+++ b/htdocs/cron/class/cronjob.class.php
@@ -67,7 +67,13 @@ class Cronjob extends CommonObject
public $md5params;
public $module_name;
public $priority;
+ /**
+ * @var string|int Date for last job execution
+ */
public $datelastrun='';
+ /**
+ * @var string|int Date for next job execution
+ */
public $datenextrun='';
public $dateend='';
public $datestart='';
@@ -1220,7 +1226,7 @@ class Cronjob extends CommonObject
$result=$user->fetch('', $userlogin);
if ($result<0)
{
- $this->error="User Error:".$user->error;
+ $this->error="User Error : ".$user->error;
dol_syslog(get_class($this)."::reprogram_jobs ".$this->error, LOG_ERR);
return -1;
}
diff --git a/htdocs/cron/list.php b/htdocs/cron/list.php
index 11d2b3acd35..ab905f745de 100644
--- a/htdocs/cron/list.php
+++ b/htdocs/cron/list.php
@@ -394,7 +394,7 @@ print ' ';
print ' ';
print '';
print $form->selectarray('search_status', array('0'=>$langs->trans("Disabled"), '1'=>$langs->trans("Enabled"), '-2'=>$langs->trans("EnabledAndDisabled"), '2'=>$langs->trans("Archived")), $search_status, 1);
-print ' ';
+print ' ';
$searchpicto=$form->showFilterButtons();
print $searchpicto;
print ' ';
@@ -505,11 +505,11 @@ if ($num > 0)
if(!empty($obj->dateend)) {print dol_print_date($db->jdate($obj->dateend), 'dayhour');}
print '';
- print '';
+ print ' ';
if (!empty($obj->maxrun)) {print $obj->maxrun;}
print ' ';
- print '';
+ print ' ';
if (!empty($obj->nbrun)) {print $obj->nbrun;} else {print '0';}
print ' ';
@@ -554,11 +554,11 @@ if ($num > 0)
print '';
// Status
- print '';
+ print ' ';
print $object->getLibStatut(3);
print ' ';
- print '';
+ print ' ';
$backtourl = urlencode($_SERVER["PHP_SELF"].'?'.$param.($sortfield?'&sortfield='.$sortfield:'').($sortorder?'&sortorder='.$sortorder:''));
if ($user->rights->cron->create)
diff --git a/htdocs/debugbar/class/DataCollector/DolConfigCollector.php b/htdocs/debugbar/class/DataCollector/DolConfigCollector.php
new file mode 100644
index 00000000000..a3fa8b84a92
--- /dev/null
+++ b/htdocs/debugbar/class/DataCollector/DolConfigCollector.php
@@ -0,0 +1,88 @@
+transnoentities('Config') => array(
+ "icon" => "gear",
+ "widget" => "PhpDebugBar.Widgets.VariableListWidget",
+ "map" => $this->getName(),
+ "default" => "{}"
+ )
+ );
+ }
+
+ /**
+ * Return collected data
+ *
+ * @return array Array
+ */
+ public function collect()
+ {
+ $this->data = $this->getConfig();
+
+ return parent::collect();
+ }
+
+ /**
+ * Returns an array with config data
+ *
+ * @return array Array of config
+ */
+ protected function getConfig()
+ {
+ global $conf, $user;
+
+ // Get constants
+ $const = get_defined_constants(true);
+
+ $config = array(
+ 'Dolibarr' => array(
+ 'const' => $const['user'],
+ '$conf' => $this->objectToArray($conf),
+ '$user' => $this->objectToArray($user)
+ ),
+ 'PHP' => array(
+ 'version' => PHP_VERSION,
+ 'interface' => PHP_SAPI,
+ 'os' => PHP_OS
+ )
+ );
+
+ return $config;
+ }
+
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ /**
+ * Convert an object to array
+ *
+ * @param mixed $obj Object
+ * @return array Array
+ */
+ protected function objectToArray($obj)
+ {
+ // phpcs:enable
+ $_arr = is_object($obj) ? get_object_vars($obj) : $obj;
+ foreach ($_arr as $key => $val) {
+ $val = (is_array($val) || is_object($val)) ? $this->objectToArray($val) : $val;
+ $arr[$key] = $val;
+ }
+
+ return $arr;
+ }
+}
diff --git a/htdocs/debugbar/class/DataCollector/DolExceptionsCollector.php b/htdocs/debugbar/class/DataCollector/DolExceptionsCollector.php
new file mode 100644
index 00000000000..15d433fd050
--- /dev/null
+++ b/htdocs/debugbar/class/DataCollector/DolExceptionsCollector.php
@@ -0,0 +1,35 @@
+transnoentities('Exceptions');
+
+ return array(
+ "$title" => array(
+ 'icon' => 'bug',
+ 'widget' => 'PhpDebugBar.Widgets.ExceptionsWidget',
+ 'map' => 'exceptions.exceptions',
+ 'default' => '[]'
+ ),
+ "$title:badge" => array(
+ 'map' => 'exceptions.count',
+ 'default' => 'null'
+ )
+ );
+ }
+}
diff --git a/htdocs/debugbar/class/DataCollector/DolLogsCollector.php b/htdocs/debugbar/class/DataCollector/DolLogsCollector.php
new file mode 100644
index 00000000000..8c03bdc2830
--- /dev/null
+++ b/htdocs/debugbar/class/DataCollector/DolLogsCollector.php
@@ -0,0 +1,184 @@
+path = $path ?: $this->getLogsFile();
+ $this->lines = empty($conf->global->DEBUGBAR_LOGS_LINES_NUMBER) ? 250 : $conf->global->DEBUGBAR_LOGS_LINES_NUMBER; // This slow seriously output
+ }
+
+ /**
+ * Return widget settings
+ *
+ * @return array Array
+ */
+ public function getWidgets()
+ {
+ global $langs;
+
+ $title = $langs->transnoentities('Logs');
+ $name = $this->getName();
+
+ return array(
+ "$title" => array(
+ "icon" => "list-alt",
+ "widget" => "PhpDebugBar.Widgets.MessagesWidget",
+ "map" => "$name.messages",
+ "default" => "[]"
+ ),
+ "$title:badge" => array(
+ "map" => "$name.count",
+ "default" => "null"
+ )
+ );
+ }
+
+ /**
+ * Return collected data
+ *
+ * @return array Array
+ */
+ public function collect()
+ {
+ $this->getStorageLogs($this->path);
+
+ return parent::collect();
+ }
+
+ /**
+ * Get the path to the logs file
+ *
+ * @return string Path of log file
+ */
+ public function getLogsFile()
+ {
+ // default dolibarr log file
+ $path = DOL_DATA_ROOT . '/dolibarr.log';
+
+ return $path;
+ }
+
+ /**
+ * Get logs
+ *
+ * @param string $path Path
+ * @return array
+ */
+ public function getStorageLogs($path)
+ {
+ if (! file_exists($path)) {
+ return;
+ }
+
+ // Load the latest lines
+ $file = implode("", $this->tailFile($path, $this->lines));
+
+ foreach ($this->getLogs($file) as $log) {
+ $this->addMessage($log['line'], $log['level'], false);
+ }
+ }
+
+ /**
+ * Get latest file lines
+ *
+ * @param string $file File
+ * @param int $lines Lines
+ * @return array Array
+ */
+ protected function tailFile($file, $lines)
+ {
+ $handle = fopen($file, "r");
+ $linecounter = $lines;
+ $pos = -2;
+ $beginning = false;
+ $text = [];
+ while ($linecounter > 0) {
+ $t = " ";
+ while ($t != "\n") {
+ if (fseek($handle, $pos, SEEK_END) == -1) {
+ $beginning = true;
+ break;
+ }
+ $t = fgetc($handle);
+ $pos--;
+ }
+ $linecounter--;
+ if ($beginning) {
+ rewind($handle);
+ }
+ $text[$lines - $linecounter - 1] = fgets($handle);
+ if ($beginning) {
+ break;
+ }
+ }
+ fclose($handle);
+ return array_reverse($text);
+ }
+
+ /**
+ * Search a string for log entries
+ *
+ * @param string $file File
+ * @return array Lines of logs
+ */
+ public function getLogs($file)
+ {
+ $pattern = "/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.*/";
+ $log_levels = $this->getLevels();
+ preg_match_all($pattern, $file, $matches);
+ $log = [];
+ foreach ($matches as $lines) {
+ foreach ($lines as $line) {
+ foreach ($log_levels as $level_key => $level) {
+ if (strpos(strtolower($line), strtolower($level_key)) == 20) {
+ $log[] = ['level' => $level, 'line' => $line];
+ }
+ }
+ }
+ }
+ $log = array_reverse($log);
+ return $log;
+ }
+
+ /**
+ * Get the log levels from psr/log.
+ *
+ * @return array Array of log level
+ */
+ public function getLevels()
+ {
+ $class = new ReflectionClass(new LogLevel());
+ $levels = $class->getConstants();
+ $levels['ERR'] = 'error';
+
+ return $levels;
+ }
+}
diff --git a/htdocs/debugbar/class/DataCollector/DolMemoryCollector.php b/htdocs/debugbar/class/DataCollector/DolMemoryCollector.php
new file mode 100644
index 00000000000..b6525633481
--- /dev/null
+++ b/htdocs/debugbar/class/DataCollector/DolMemoryCollector.php
@@ -0,0 +1,48 @@
+updatePeakUsage();
+ return array(
+ 'peak_usage' => $this->peakUsage,
+ //'peak_usage_str' => $this->getDataFormatter()->formatBytes($this->peakUsage, 2)
+ 'peak_usage_str' => $this->peakUsage.' '.$langs->trans("bytes")
+ );
+ }
+
+ /**
+ * Return widget settings
+ *
+ * @return void
+ */
+ public function getWidgets()
+ {
+ global $langs;
+
+ $langs->load("other");
+
+ return array(
+ "memory" => array(
+ "icon" => "cogs",
+ "tooltip" => $langs->transnoentities('MemoryUsage'),
+ "map" => "memory.peak_usage_str",
+ "default" => "'0B'"
+ )
+ );
+ }
+}
diff --git a/htdocs/debugbar/class/DataCollector/DolMessagesCollector.php b/htdocs/debugbar/class/DataCollector/DolMessagesCollector.php
new file mode 100644
index 00000000000..1fcf60c8ba6
--- /dev/null
+++ b/htdocs/debugbar/class/DataCollector/DolMessagesCollector.php
@@ -0,0 +1,36 @@
+transnoentities('Messages');
+ $name = $this->getName();
+
+ return array(
+ "$title" => array(
+ "icon" => "list-alt",
+ "widget" => "PhpDebugBar.Widgets.MessagesWidget",
+ "map" => "$name.messages",
+ "default" => "[]"
+ ),
+ "$title:badge" => array(
+ "map" => "$name.count",
+ "default" => "null"
+ )
+ );
+ }
+}
diff --git a/htdocs/debugbar/class/DataCollector/DolQueryCollector.php b/htdocs/debugbar/class/DataCollector/DolQueryCollector.php
new file mode 100644
index 00000000000..694112bf2f1
--- /dev/null
+++ b/htdocs/debugbar/class/DataCollector/DolQueryCollector.php
@@ -0,0 +1,119 @@
+db = $db;
+ }
+
+ /**
+ * Return collected data
+ *
+ * @return array Array
+ */
+ public function collect()
+ {
+ $queries = array();
+ $totalExecTime = 0;
+ $totalMemoryUsage = 0;
+ $totalFailed = 0;
+ foreach ($this->db->queries as $query) {
+ $queries[] = array(
+ 'sql' => $query['sql'],
+ 'duration' => $query['duration'],
+ 'duration_str' => $this->formatDuration($query['duration']),
+ 'memory' => $query['memory_usage'],
+ 'memory_str' => $this->formatBytes($query['memory_usage']),
+ 'is_success' => $query['is_success'],
+ 'error_code' => $query['error_code'],
+ 'error_message' => $query['error_message']
+ );
+ $totalExecTime += $query['duration'];
+ $totalMemoryUsage += $query['memory_usage'];
+ if (! $query['is_success']) {
+ $totalFailed += 1;
+ }
+ }
+
+ return array(
+ 'nb_statements' => count($queries),
+ 'nb_failed_statements' => $totalFailed,
+ 'accumulated_duration' => $totalExecTime,
+ 'accumulated_duration_str' => $this->formatDuration($totalExecTime),
+ 'memory_usage' => $totalMemoryUsage,
+ 'memory_usage_str' => $this->formatBytes($totalMemoryUsage),
+ 'statements' => $queries
+ );
+ }
+
+ /**
+ * Return collector name
+ *
+ * @return string Name
+ */
+ public function getName()
+ {
+ return 'query';
+ }
+
+ /**
+ * Return widget settings
+ *
+ * @return array Array
+ */
+ public function getWidgets()
+ {
+ global $langs;
+
+ $title = $langs->transnoentities('Database');
+
+ return array(
+ "$title" => array(
+ "icon" => "arrow-right",
+ "widget" => "PhpDebugBar.Widgets.SQLQueriesWidget",
+ "map" => "query",
+ "default" => "[]"
+ ),
+ "$title:badge" => array(
+ "map" => "query.nb_statements",
+ "default" => 0
+ )
+ );
+ }
+
+ /**
+ * Return assets
+ *
+ * @return array Array
+ */
+ public function getAssets()
+ {
+ return array(
+ 'css' => 'widgets/sqlqueries/widget.css',
+ 'js' => 'widgets/sqlqueries/widget.js'
+ );
+ }
+}
diff --git a/htdocs/debugbar/class/DataCollector/DolRequestDataCollector.php b/htdocs/debugbar/class/DataCollector/DolRequestDataCollector.php
new file mode 100644
index 00000000000..e4d8e89159a
--- /dev/null
+++ b/htdocs/debugbar/class/DataCollector/DolRequestDataCollector.php
@@ -0,0 +1,31 @@
+load("other");
+
+ return array(
+ $langs->transnoentities('Request') => array(
+ "icon" => "tags",
+ "widget" => "PhpDebugBar.Widgets.VariableListWidget",
+ "map" => "request",
+ "default" => "{}"
+ )
+ );
+ }
+}
diff --git a/htdocs/debugbar/class/DataCollector/DolTimeDataCollector.php b/htdocs/debugbar/class/DataCollector/DolTimeDataCollector.php
new file mode 100644
index 00000000000..ae69b16eba7
--- /dev/null
+++ b/htdocs/debugbar/class/DataCollector/DolTimeDataCollector.php
@@ -0,0 +1,35 @@
+ array(
+ "icon" => "clock-o",
+ "tooltip" => $langs->transnoentities('RequestDuration'),
+ "map" => "time.duration_str",
+ "default" => "'0ms'"
+ ),
+ $langs->transnoentities('Timeline') => array(
+ "icon" => "tasks",
+ "widget" => "PhpDebugBar.Widgets.TimelineWidget",
+ "map" => "time",
+ "default" => "{}"
+ )
+ );
+ }
+}
diff --git a/htdocs/debugbar/class/DataCollector/DolibarrCollector.php b/htdocs/debugbar/class/DataCollector/DolibarrCollector.php
new file mode 100644
index 00000000000..8bcd639ec7f
--- /dev/null
+++ b/htdocs/debugbar/class/DataCollector/DolibarrCollector.php
@@ -0,0 +1,147 @@
+trans('Host') . ': ' . $conf->db->host . ' ';
+ $info .= $langs->trans('Port') . ': ' . $conf->db->port . ' ';
+ $info .= $langs->trans('Name') . ': ' . $conf->db->name . ' ';
+ $info .= $langs->trans('User') . ': ' . $conf->db->user . ' ';
+ $info .= $langs->trans('Type') . ': ' . $conf->db->type . ' ';
+ $info .= $langs->trans('Prefix') . ': ' . $conf->db->prefix . ' ';
+ $info .= $langs->trans('Charset') . ': ' . $conf->db->character_set . ' ';
+
+ return $info;
+ }
+
+ /**
+ * Return dolibarr info as an HTML string
+ *
+ * @return string HTML string
+ */
+ protected function getDolibarrInfo()
+ {
+ global $conf, $langs;
+
+ $info = $langs->trans('Version') . ': ' . DOL_VERSION . ' ';
+ $info .= $langs->trans('Theme') . ': ' . $conf->theme . ' ';
+ $info .= $langs->trans('Locale') . ': ' . $conf->global->MAIN_LANG_DEFAULT . ' ';
+ $info .= $langs->trans('Currency') . ': ' . $conf->currency . ' ';
+ $info .= $langs->trans('DolEntity') . ': ' . $conf->entity . ' ';
+ $info .= $langs->trans('ListLimit') . ': ' . ($conf->liste_limit ?: $conf->global->MAIN_SIZE_LISTE_LIMIT) . ' ';
+ $info .= $langs->trans('UploadSize') . ': ' . $conf->global->MAIN_UPLOAD_DOC . ' ';
+
+ return $info;
+ }
+
+ /**
+ * Return mail info as an HTML string
+ *
+ * @return string HTML string
+ */
+ protected function getMailInfo()
+ {
+ global $conf, $langs;
+
+ $info = $langs->trans('Method') . ': ' . $conf->global->MAIN_MAIL_SENDMODE . ' ';
+ $info .= $langs->trans('Server') . ': ' . $conf->global->MAIN_MAIL_SMTP_SERVER . ' ';
+ $info .= $langs->trans('Port') . ': ' . $conf->global->MAIN_MAIL_SMTP_PORT . ' ';
+ $info .= $langs->trans('ID') . ': ' . $conf->global->MAIN_MAIL_SMTPS_ID . ' ';
+ $info .= $langs->trans('Pwd') . ': ' . $conf->global->MAIN_MAIL_SMTPS_PW . ' ';
+ $info .= $langs->trans('TLS/STARTTLS') . ': ' . $conf->global->MAIN_MAIL_EMAIL_TLS . ' / ' . $conf->global->MAIN_MAIL_EMAIL_STARTTLS . ' ';
+ $info .= $langs->trans('Status') . ': ' . ($conf->global->MAIN_DISABLE_ALL_MAILS ? $langs->trans('StatusDisabled') : $langs->trans('StatusEnabled')) . ' ';
+
+ return $info;
+ }
+
+ /**
+ * Return widget settings
+ *
+ * @return array Array
+ */
+ public function getWidgets()
+ {
+ return array(
+ "database_info" => array(
+ "icon" => "database",
+ "indicator" => "PhpDebugBar.DebugBar.TooltipIndicator",
+ "tooltip" => array(
+ "html" => $this->getDatabaseInfo(),
+ "class" => "tooltip-wide"
+ ),
+ "map" => "",
+ "default" => ""
+ ),
+ "dolibarr_info" => array(
+ "icon" => "desktop",
+ "indicator" => "PhpDebugBar.DebugBar.TooltipIndicator",
+ "tooltip" => array(
+ "html" => $this->getDolibarrInfo(),
+ "class" => "tooltip-wide"
+ ),
+ "map" => "",
+ "default" => ""
+ ),
+ "mail_info" => array(
+ "icon" => "envelope",
+ "indicator" => "PhpDebugBar.DebugBar.TooltipIndicator",
+ "tooltip" => array(
+ "html" => $this->getMailInfo(),
+ "class" => "tooltip-extra-wide"
+ ),
+ "map" => "",
+ "default" => ""
+ )
+ );
+ }
+
+ /**
+ * Return collector assests
+ *
+ * @return array Array
+ */
+ public function getAssets()
+ {
+ return array(
+ 'base_url' => dol_buildpath('/debugbar', 1),
+ 'js' => 'js/widgets.js'
+ );
+ }
+}
diff --git a/htdocs/debugbar/class/DebugBar.php b/htdocs/debugbar/class/DebugBar.php
new file mode 100644
index 00000000000..d3cc545e1b3
--- /dev/null
+++ b/htdocs/debugbar/class/DebugBar.php
@@ -0,0 +1,56 @@
+addCollector(new PhpInfoCollector());
+ $this->addCollector(new DolMessagesCollector());
+ $this->addCollector(new DolRequestDataCollector());
+ $this->addCollector(new DolConfigCollector());
+ $this->addCollector(new DolTimeDataCollector());
+ $this->addCollector(new DolMemoryCollector());
+ $this->addCollector(new DolExceptionsCollector());
+ $this->addCollector(new DolQueryCollector());
+ $this->addCollector(new DolibarrCollector());
+ if ($conf->syslog->enabled) {
+ $this->addCollector(new DolLogsCollector());
+ }
+ }
+
+ /**
+ * Returns a JavascriptRenderer for this instance
+ *
+ * @return string String content
+ */
+ public function getRenderer()
+ {
+ return parent::getJavascriptRenderer(DOL_URL_ROOT.'/includes/DebugBar/Resources');
+ }
+}
diff --git a/htdocs/debugbar/class/TraceableDB.php b/htdocs/debugbar/class/TraceableDB.php
new file mode 100644
index 00000000000..0caf6c2489f
--- /dev/null
+++ b/htdocs/debugbar/class/TraceableDB.php
@@ -0,0 +1,698 @@
+db::LABEL (but this is a constant? o_O)
+ /**
+ * @const Version min database
+ */
+ const VERSIONMIN = ''; // TODO: the same thing here, $this->db::VERSIONMIN is the right value
+
+ /**
+ * Constructor
+ *
+ * @param DoliDB $db Database handler
+ */
+ public function __construct($db)
+ {
+ $this->db = $db;
+ $this->type = $db->type;
+ $this->queries = array();
+ }
+
+ /**
+ * Format a SQL IF
+ *
+ * @param string $test Test string (example: 'cd.statut=0', 'field IS NULL')
+ * @param string $resok resultat si test egal
+ * @param string $resko resultat si test non egal
+ * @return string SQL string
+ */
+ public function ifsql($test, $resok, $resko)
+ {
+ return $this->db->ifsql($test, $resok, $resko);
+ }
+
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ /**
+ * Return datas as an array
+ *
+ * @param resource $resultset Resultset of request
+ * @return array Array
+ */
+ public function fetch_row($resultset)
+ {
+ // phpcs:enable
+ return $this->db->fetch_row($resultset);
+ }
+
+ /**
+ * Convert (by PHP) a GM Timestamp date into a string date with PHP server TZ to insert into a date field.
+ * Function to use to build INSERT, UPDATE or WHERE predica
+ *
+ * @param int $param Date TMS to convert
+ * @return string Date in a string YYYYMMDDHHMMSS
+ */
+ public function idate($param)
+ {
+ return $this->db->idate($param);
+ }
+
+ /**
+ * Return last error code
+ *
+ * @return string lasterrno
+ */
+ public function lasterrno()
+ {
+ return $this->db->lasterrno();
+ }
+
+ /**
+ * Start transaction
+ *
+ * @return int 1 if transaction successfuly opened or already opened, 0 if error
+ */
+ public function begin()
+ {
+ return $this->db->begin();
+ }
+
+ /**
+ * Create a new database
+ * Do not use function xxx_create_db (xxx=mysql, ...) as they are deprecated
+ * We force to create database with charset this->forcecharset and collate this->forcecollate
+ *
+ * @param string $database Database name to create
+ * @param string $charset Charset used to store data
+ * @param string $collation Charset used to sort data
+ * @param string $owner Username of database owner
+ * @return resource resource defined if OK, null if KO
+ */
+ public function DDLCreateDb($database, $charset = '', $collation = '', $owner = '')
+ {
+ return $this->db->DDLCreateDb($database, $charset, $collation, $owner);
+ }
+
+ /**
+ * Return version of database server into an array
+ *
+ * @return array Version array
+ */
+ public function getVersionArray()
+ {
+ return $this->db->getVersionArray();
+ }
+
+ /**
+ * Convert a SQL request in Mysql syntax to native syntax
+ *
+ * @param string $line SQL request line to convert
+ * @param string $type Type of SQL order ('ddl' for insert, update, select, delete or 'dml' for create, alter...)
+ * @return string SQL request line converted
+ */
+ public static function convertSQLFromMysql($line, $type = 'ddl')
+ {
+ return $this->db->convertSQLFromMysql($line);
+ }
+
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ /**
+ * Renvoie le nombre de lignes dans le resultat d'une requete INSERT, DELETE ou UPDATE
+ *
+ * @param resource $resultset Curseur de la requete voulue
+ * @return int Nombre de lignes
+ * @see num_rows()
+ */
+ public function affected_rows($resultset)
+ {
+ // phpcs:enable
+ return $this->db->affected_rows($resultset);
+ }
+
+ /**
+ * Return description of last error
+ *
+ * @return string Error text
+ */
+ public function error()
+ {
+ return $this->db->error();
+ }
+
+ /**
+ * List tables into a database
+ *
+ * @param string $database Name of database
+ * @param string $table Nmae of table filter ('xxx%')
+ * @return array List of tables in an array
+ */
+ public function DDLListTables($database, $table = '')
+ {
+ return $this->db->DDLListTables($database, $table);
+ }
+
+ /**
+ * Return last request executed with query()
+ *
+ * @return string Last query
+ */
+ public function lastquery()
+ {
+ return $this->db->lastquery();
+ }
+
+ /**
+ * Define sort criteria of request
+ *
+ * @param string $sortfield List of sort fields
+ * @param string $sortorder Sort order
+ * @return string String to provide syntax of a sort sql string
+ */
+ public function order($sortfield = null, $sortorder = null)
+ {
+ return $this->db->order($sortfield, $sortorder);
+ }
+
+ /**
+ * Decrypt sensitive data in database
+ *
+ * @param string $value Value to decrypt
+ * @return string Decrypted value if used
+ */
+ public function decrypt($value)
+ {
+ return $this->db->decrypt($value);
+ }
+
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ /**
+ * Return datas as an array
+ *
+ * @param resource $resultset Resultset of request
+ * @return array Array
+ */
+ public function fetch_array($resultset)
+ {
+ // phpcs:enable
+ return $this->db->fetch_array($resultset);
+ }
+
+ /**
+ * Return last error label
+ *
+ * @return string lasterror
+ */
+ public function lasterror()
+ {
+ return $this->db->lasterror();
+ }
+
+ /**
+ * Escape a string to insert data
+ *
+ * @param string $stringtoencode String to escape
+ * @return string String escaped
+ */
+ public function escape($stringtoencode)
+ {
+ return $this->db->escape($stringtoencode);
+ }
+
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ /**
+ * Get last ID after an insert INSERT
+ *
+ * @param string $tab Table name concerned by insert. Ne sert pas sous MySql mais requis pour compatibilite avec Postgresql
+ * @param string $fieldid Field name
+ * @return int Id of row
+ */
+ public function last_insert_id($tab, $fieldid = 'rowid')
+ {
+ // phpcs:enable
+ return $this->db->last_insert_id($tab, $fieldid);
+ }
+
+ /**
+ * Return full path of restore program
+ *
+ * @return string Full path of restore program
+ */
+ public function getPathOfRestore()
+ {
+ return $this->db->getPathOfRestore();
+ }
+
+ /**
+ * Annulation d'une transaction et retour aux anciennes valeurs
+ *
+ * @param string $log Add more log to default log line
+ * @return int 1 si annulation ok ou transaction non ouverte, 0 en cas d'erreur
+ */
+ public function rollback($log = '')
+ {
+ return $this->db->rollback($log);
+ }
+
+ /**
+ * Execute a SQL request and return the resultset
+ *
+ * @param string $query SQL query string
+ * @param int $usesavepoint 0=Default mode, 1=Run a savepoint before and a rollback to savepoint if error (this allow to have some request with errors inside global transactions).
+ * Note that with Mysql, this parameter is not used as Myssql can already commit a transaction even if one request is in error, without using savepoints.
+ * @param string $type Type of SQL order ('ddl' for insert, update, select, delete or 'dml' for create, alter...)
+ * @return resource Resultset of answer
+ */
+ public function query($query, $usesavepoint = 0, $type = 'auto')
+ {
+ $this->startTracing();
+
+ $resql = $this->db->query($query, $usesavepoint, $type);
+
+ $this->endTracing($query, $resql);
+
+ return $resql;
+ }
+
+ /**
+ * Start query tracing
+ *
+ * @return void
+ */
+ protected function startTracing()
+ {
+ $this->startTime = microtime(true);
+ $this->startMemory = memory_get_usage(true);
+ }
+
+ /**
+ * End query tracing
+ *
+ * @param string $sql query string
+ * @param string $resql query result
+ * @return void
+ */
+ protected function endTracing($sql, $resql)
+ {
+ $endTime = microtime(true);
+ $duration = $endTime - $this->startTime;
+ $endMemory = memory_get_usage(true);
+ $memoryDelta = $endMemory - $this->startMemory;
+
+ $this->queries[] = array(
+ 'sql' => $sql,
+ 'duration' => $duration,
+ 'memory_usage' => $memoryDelta,
+ 'is_success' => $resql,
+ 'error_code' => ! $resql ? $this->db->lasterrno() : null,
+ 'error_message' => ! $resql ? $this->db->lasterror() : null
+ );
+ }
+
+ /**
+ * Connexion to server
+ *
+ * @param string $host database server host
+ * @param string $login login
+ * @param string $passwd password
+ * @param string $name name of database (not used for mysql, used for pgsql)
+ * @param int $port Port of database server
+ * @return resource Database access handler
+ * @see close()
+ */
+ public function connect($host, $login, $passwd, $name, $port = 0)
+ {
+ return $this->db->connect($host, $login, $passwd, $name, $port);
+ }
+
+ /**
+ * Define limits and offset of request
+ *
+ * @param int $limit Maximum number of lines returned (-1=conf->liste_limit, 0=no limit)
+ * @param int $offset Numero of line from where starting fetch
+ * @return string String with SQL syntax to add a limit and offset
+ */
+ public function plimit($limit = 0, $offset = 0)
+ {
+ return $this->db->plimit($limit, $offset);
+ }
+
+ /**
+ * Return value of server parameters
+ *
+ * @param string $filter Filter list on a particular value
+ * @return array Array of key-values (key=>value)
+ */
+ public function getServerParametersValues($filter = '')
+ {
+ return $this->db->getServerParametersValues($filter);
+ }
+
+ /**
+ * Return value of server status
+ *
+ * @param string $filter Filter list on a particular value
+ * @return array Array of key-values (key=>value)
+ */
+ public function getServerStatusValues($filter = '')
+ {
+ return $this->db->getServerStatusValues($filter);
+ }
+
+ /**
+ * Return collation used in database
+ *
+ * @return string Collation value
+ */
+ public function getDefaultCollationDatabase()
+ {
+ return $this->db->getDefaultCollationDatabase();
+ }
+
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ /**
+ * Return number of lines for result of a SELECT
+ *
+ * @param resource $resultset Resulset of requests
+ * @return int Nb of lines
+ * @see affected_rows()
+ */
+ public function num_rows($resultset)
+ {
+ // phpcs:enable
+ return $this->db->num_rows($resultset);
+ }
+
+ /**
+ * Return full path of dump program
+ *
+ * @return string Full path of dump program
+ */
+ public function getPathOfDump()
+ {
+ return $this->db->getPathOfDump();
+ }
+
+ /**
+ * Return version of database client driver
+ *
+ * @return string Version string
+ */
+ public function getDriverInfo()
+ {
+ return $this->db->getDriverInfo();
+ }
+
+ /**
+ * Return generic error code of last operation.
+ *
+ * @return string Error code (Exemples: DB_ERROR_TABLE_ALREADY_EXISTS, DB_ERROR_RECORD_ALREADY_EXISTS...)
+ */
+ public function errno()
+ {
+ return $this->db->errno();
+ }
+
+ /**
+ * Create a table into database
+ *
+ * @param string $table Name of table
+ * @param array $fields Tableau associatif [nom champ][tableau des descriptions]
+ * @param string $primary_key Nom du champ qui sera la clef primaire
+ * @param string $type Type de la table
+ * @param array $unique_keys Tableau associatifs Nom de champs qui seront clef unique => valeur
+ * @param array $fulltext_keys Tableau des Nom de champs qui seront indexes en fulltext
+ * @param array $keys Tableau des champs cles noms => valeur
+ * @return int <0 if KO, >=0 if OK
+ */
+ public function DDLCreateTable($table, $fields, $primary_key, $type, $unique_keys = null, $fulltext_keys = null, $keys = null)
+ {
+ return $this->db->DDLCreateTable($table, $fields, $primary_key, $type, $unique_keys, $fulltext_keys, $keys);
+ }
+
+ /**
+ * Drop a table into database
+ *
+ * @param string $table Name of table
+ * @return int <0 if KO, >=0 if OK
+ */
+ public function DDLDropTable($table)
+ {
+ return $this->db->DDLDropTable($table);
+ }
+
+ /**
+ * Return list of available charset that can be used to store data in database
+ *
+ * @return array List of Charset
+ */
+ public function getListOfCharacterSet()
+ {
+ return $this->db->getListOfCharacterSet();
+ }
+
+ /**
+ * Create a new field into table
+ *
+ * @param string $table Name of table
+ * @param string $field_name Name of field to add
+ * @param string $field_desc Tableau associatif de description du champ a inserer[nom du parametre][valeur du parametre]
+ * @param string $field_position Optionnel ex.: "after champtruc"
+ * @return int <0 if KO, >0 if OK
+ */
+ public function DDLAddField($table, $field_name, $field_desc, $field_position = "")
+ {
+ return $this->db->DDLAddField($table, $field_name, $field_desc, $field_position);
+ }
+
+ /**
+ * Drop a field from table
+ *
+ * @param string $table Name of table
+ * @param string $field_name Name of field to drop
+ * @return int <0 if KO, >0 if OK
+ */
+ public function DDLDropField($table, $field_name)
+ {
+ return $this->db->DDLDropField($table, $field_name);
+ }
+
+ /**
+ * Update format of a field into a table
+ *
+ * @param string $table Name of table
+ * @param string $field_name Name of field to modify
+ * @param string $field_desc Array with description of field format
+ * @return int <0 if KO, >0 if OK
+ */
+ public function DDLUpdateField($table, $field_name, $field_desc)
+ {
+ return $this->db->DDLUpdateField($table, $field_name, $field_desc);
+ }
+
+ /**
+ * Return list of available collation that can be used for database
+ *
+ * @return array List of Collation
+ */
+ public function getListOfCollation()
+ {
+ return $this->db->getListOfCollation();
+ }
+
+ /**
+ * Return a pointer of line with description of a table or field
+ *
+ * @param string $table Name of table
+ * @param string $field Optionnel : Name of field if we want description of field
+ * @return resource Resource
+ */
+ public function DDLDescTable($table, $field = "")
+ {
+ return $this->db->DDLDescTable($table, $field);
+ }
+
+ /**
+ * Return version of database server
+ *
+ * @return string Version string
+ */
+ public function getVersion()
+ {
+ return $this->db->getVersion();
+ }
+
+ /**
+ * Return charset used to store data in database
+ *
+ * @return string Charset
+ */
+ public function getDefaultCharacterSetDatabase()
+ {
+ return $this->db->getDefaultCharacterSetDatabase();
+ }
+
+ /**
+ * Create a user and privileges to connect to database (even if database does not exists yet)
+ *
+ * @param string $dolibarr_main_db_host Ip serveur
+ * @param string $dolibarr_main_db_user Nom user a creer
+ * @param string $dolibarr_main_db_pass Mot de passe user a creer
+ * @param string $dolibarr_main_db_name Database name where user must be granted
+ * @return int <0 if KO, >=0 if OK
+ */
+ public function DDLCreateUser($dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name)
+ {
+ return $this->db->DDLCreateUser($dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name);
+ }
+
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ /**
+ * Convert (by PHP) a PHP server TZ string date into a Timestamps date (GMT if gm=true)
+ * 19700101020000 -> 3600 with TZ+1 and gmt=0
+ * 19700101020000 -> 7200 whaterver is TZ if gmt=1
+ *
+ * @param string $string Date in a string (YYYYMMDDHHMMSS, YYYYMMDD, YYYY-MM-DD HH:MM:SS)
+ * @param bool $gm 1=Input informations are GMT values, otherwise local to server TZ
+ * @return int|string Date TMS or ''
+ */
+ public function jdate($string, $gm = false)
+ {
+ // phpcs:enable
+ return $this->db->jdate($string, $gm);
+ }
+
+ /**
+ * Encrypt sensitive data in database
+ * Warning: This function includes the escape, so it must use direct value
+ *
+ * @param string $fieldorvalue Field name or value to encrypt
+ * @param int $withQuotes Return string with quotes
+ * @return string XXX(field) or XXX('value') or field or 'value'
+ */
+ public function encrypt($fieldorvalue, $withQuotes = 0)
+ {
+ return $this->db->encrypt($fieldorvalue, $withQuotes);
+ }
+
+ /**
+ * Validate a database transaction
+ *
+ * @param string $log Add more log to default log line
+ * @return int 1 if validation is OK or transaction level no started, 0 if ERROR
+ */
+ public function commit($log = '')
+ {
+ return $this->db->commit($log);
+ }
+
+ /**
+ * List information of columns into a table.
+ *
+ * @param string $table Name of table
+ * @return array Array with inforation on table
+ */
+ public function DDLInfoTable($table)
+ {
+ return $this->db->DDLInfoTable($table);
+ }
+
+ /**
+ * Free last resultset used.
+ *
+ * @param resource $resultset Fre cursor
+ * @return void
+ */
+ public function free($resultset = null)
+ {
+ return $this->db->free($resultset);
+ }
+
+ /**
+ * Close database connexion
+ *
+ * @return boolean True if disconnect successfull, false otherwise
+ * @see connect()
+ */
+ public function close()
+ {
+ return $this->db->close();
+ }
+
+ /**
+ * Return last query in error
+ *
+ * @return string lastqueryerror
+ */
+ public function lastqueryerror()
+ {
+ return $this->db->lastqueryerror();
+ }
+
+ /**
+ * Return connexion ID
+ *
+ * @return string Id connexion
+ */
+ public function DDLGetConnectId()
+ {
+ return $this->db->DDLGetConnectId();
+ }
+
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ /**
+ * Renvoie la ligne courante (comme un objet) pour le curseur resultset
+ *
+ * @param resource $resultset Curseur de la requete voulue
+ * @return Object Object result line or false if KO or end of cursor
+ */
+ public function fetch_object($resultset)
+ {
+ // phpcs:enable
+ return $this->db->fetch_object($resultset);
+ }
+
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ /**
+ * Select a database
+ *
+ * @param string $database Name of database
+ * @return boolean true if OK, false if KO
+ */
+ public function select_db($database)
+ {
+ // phpcs:enable
+ return $this->db->select_db($database);
+ }
+}
diff --git a/htdocs/debugbar/class/actions_debugbar.class.php b/htdocs/debugbar/class/actions_debugbar.class.php
new file mode 100644
index 00000000000..08790ca1cd3
--- /dev/null
+++ b/htdocs/debugbar/class/actions_debugbar.class.php
@@ -0,0 +1,113 @@
+getRenderer();
+ $conf->global->MAIN_HTML_HEADER .= $renderer->renderHead();
+ }
+
+ /**
+ * Overloading the afterLogin function
+ *
+ * @param array $parameters Hook metadatas (context, etc...)
+ * @param CommonObject $object The object to process (an invoice if you are in invoice module, a propale in propale's module, etc...)
+ * @param string $action Current action (if set). Generally create or edit or null
+ * @param HookManager $hookmanager Hook manager propagated to allow calling another hook
+ * @return int < 0 on error, 0 on success, 1 to replace standard code
+ */
+ public function afterLogin($parameters, &$object, &$action, $hookmanager)
+ {
+ $error = 0; // Error counter
+
+ if (in_array('login', explode(':', $parameters['context'])))
+ {
+ $this->loadDebugBar();
+ }
+
+ if (! $error)
+ {
+ return 0; // or return 1 to replace standard code
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ /**
+ * Overloading the updateSession function
+ *
+ * @param array $parameters Hook metadatas (context, etc...)
+ * @param CommonObject $object The object to process (an invoice if you are in invoice module, a propale in propale's module, etc...)
+ * @param string $action Current action (if set). Generally create or edit or null
+ * @param HookManager $hookmanager Hook manager propagated to allow calling another hook
+ * @return int < 0 on error, 0 on success, 1 to replace standard code
+ */
+ public function updateSession($parameters, &$object, &$action, $hookmanager)
+ {
+ $error = 0; // Error counter
+
+ if (in_array('main', explode(':', $parameters['context'])))
+ {
+ $this->loadDebugBar();
+ }
+
+ if (! $error)
+ {
+ return 0; // or return 1 to replace standard code
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ /**
+ * Overloading the printCommonFooter function
+ *
+ * @param array $parameters Hook metadatas (context, etc...)
+ * @param CommonObject $object The object to process (an invoice if you are in invoice module, a propale in propale's module, etc...)
+ * @param string $action Current action (if set). Generally create or edit or null
+ * @param HookManager $hookmanager Hook manager propagated to allow calling another hook
+ * @return int <0 on error, 0 on success, 1 to replace standard code
+ */
+ public function printCommonFooter($parameters, &$object, &$action, $hookmanager)
+ {
+ global $user, $debugbar, $langs;
+
+ $error = 0; // Error counter
+ $context = explode(':', $parameters['context']);
+
+ if (in_array('main', $context) || in_array('login', $context))
+ {
+ if ($user->rights->debugbar->read && is_object($debugbar)) {
+ $renderer = $debugbar->getRenderer();
+ echo $renderer->render();
+ }
+ }
+
+ if (! $error)
+ {
+ return 0; // or return 1 to replace standard code
+ }
+ else
+ {
+ return -1;
+ }
+ }
+}
diff --git a/htdocs/debugbar/class/autoloader.php b/htdocs/debugbar/class/autoloader.php
new file mode 100644
index 00000000000..1d5c85c975d
--- /dev/null
+++ b/htdocs/debugbar/class/autoloader.php
@@ -0,0 +1,18 @@
+ '', 'class' => '')
+ * - data: alias of title
+ */
+ var TooltipIndicator = PhpDebugBar.DebugBar.TooltipIndicator = PhpDebugBar.DebugBar.Indicator.extend({
+
+ render: function() {
+ this.$icon = $(' ').appendTo(this.$el);
+ this.bindAttr('icon', function(icon) {
+ if (icon) {
+ this.$icon.attr('class', 'fa fa-' + icon);
+ } else {
+ this.$icon.attr('class', '');
+ }
+ });
+
+ this.bindAttr(['title', 'data'], $(' ').addClass(csscls('text')).appendTo(this.$el));
+
+ this.$tooltip = $(' ').addClass(csscls('tooltip disabled')).appendTo(this.$el);
+ this.bindAttr('tooltip', function(tooltip) {
+ if (tooltip['html']) {
+ tooltipHTML = $(' ').html(tooltip['html']).addClass(csscls('tooltip-html'));
+ this.$tooltip.html(tooltipHTML).removeClass(csscls('disabled'));
+ if (tooltip['class']) {
+ this.$tooltip.addClass(csscls(tooltip['class']));
+ }
+ } else {
+ this.$tooltip.addClass(csscls('disabled'));
+ }
+ });
+ }
+
+ });
+
+ /**
+ * LinkIndicator
+ *
+ * A customised indicator class that will allow "click" behaviour.
+ *
+ * Options:
+ * - icon
+ * - title
+ * - tooltip
+ * - data: alias of title
+ * - href
+ * - target
+ */
+ var LinkIndicator = PhpDebugBar.DebugBar.LinkIndicator = PhpDebugBar.DebugBar.Indicator.extend({
+
+ tagName: 'a',
+
+ render: function() {
+ LinkIndicator.__super__.render.apply(this);
+ this.bindAttr('href', function(href) {
+ this.$el.attr('href', href);
+ });
+ this.bindAttr('target', function(target) {
+ this.$el.attr('target', target);
+ });
+ }
+
+ });
+
+})(PhpDebugBar.$);
\ No newline at end of file
diff --git a/htdocs/don/card.php b/htdocs/don/card.php
index d88017e52ea..08eb9efb094 100644
--- a/htdocs/don/card.php
+++ b/htdocs/don/card.php
@@ -397,7 +397,7 @@ if ($action == 'create')
print " ".''.$langs->trans("Lastname").' ';
print "".''.$langs->trans("Firstname").' ';
print "".''.$langs->trans("Address").' ';
- print ''.dol_escape_htmltag(GETPOST("address")).' ';
+ print ''.dol_escape_htmltag(GETPOST("address", "none"), 0, 1).' ';
// Zip / Town
print ''.$langs->trans("Zip").' / '.$langs->trans("Town").' ';
@@ -544,7 +544,7 @@ if ( $object->socid && ! empty($conf->societe->enabled) && ! empty($conf->global
print ' '.$langs->trans("Lastname").' ';
print ''.$langs->trans("Firstname").' ';
print ''.$langs->trans("Address").' ';
- print ''.dol_escape_htmltag($object->address).' ';
+ print ''.dol_escape_htmltag($object->address, 0, 1).' ';
// Zip / Town
print ''.$langs->trans("Zip").' / '.$langs->trans("Town").' ';
diff --git a/htdocs/ecm/search.php b/htdocs/ecm/search.php
index 951c2586346..a5e296ae1e6 100644
--- a/htdocs/ecm/search.php
+++ b/htdocs/ecm/search.php
@@ -137,10 +137,10 @@ print ' ';
print '";
//print $langs->trans("ECMSectionManualDesc");
@@ -162,7 +162,7 @@ foreach($sectionauto as $sectioncur)
print " ".$sectioncur['label'].': ';
print '';
print ' ';
print ' ';
@@ -173,7 +173,7 @@ foreach($sectionauto as $sectioncur)
//if ($butshown % 2 == 1)
// print ' ';
-print ' ';
+print ' ';
print "
";
//print $langs->trans("ECMSectionAutoDesc");
diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php
index 5a063fcbf4a..181e8b89a59 100644
--- a/htdocs/expedition/card.php
+++ b/htdocs/expedition/card.php
@@ -54,7 +54,7 @@ if (! empty($conf->projet->enabled)) {
}
// Load translation files required by the page
-$langs->loadLangs(array("sendings","companies","bills",'deliveries','orders','stocks','other','propal'));
+$langs->loadLangs(array("sendings", "companies", "bills", 'deliveries', 'orders', 'stocks', 'other', 'propal'));
if (!empty($conf->incoterm->enabled)) $langs->load('incoterm');
if (! empty($conf->productbatch->enabled)) $langs->load('productbatch');
@@ -101,7 +101,7 @@ $extralabelslines=$extrafieldsline->fetch_name_optionals_label($object->table_el
include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once
// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
-$hookmanager->initHooks(array('expeditioncard','globalcard'));
+$hookmanager->initHooks(array('expeditioncard', 'globalcard'));
$permissiondellink=$user->rights->expedition->livraison->creer; // Used by the include of actions_dellink.inc.php
//var_dump($object->lines[0]->detail_batch);
@@ -479,7 +479,7 @@ if (empty($reshook))
}
}
// TODO add alternative status
- /*else if ($action == 'reopen' && (! empty($user->rights->expedition->creer) || ! empty($user->rights->expedition->shipping_advance->validate)))
+ /*elseif ($action == 'reopen' && (! empty($user->rights->expedition->creer) || ! empty($user->rights->expedition->shipping_advance->validate)))
{
$result = $object->setStatut(0);
if ($result < 0)
@@ -784,7 +784,8 @@ if (empty($reshook))
$stockLocation="entl".$detail_entrepot->line_id;
$qty = "qtyl".$detail_entrepot->line_id;
$warehouse = GETPOST($stockLocation, 'int');
- if (!empty($warehouse)) {
+ if (!empty($warehouse))
+ {
$line->id = $detail_entrepot->line_id;
$line->entrepot_id = $warehouse;
$line->qty = GETPOST($qty, 'int');
@@ -968,7 +969,7 @@ if ($action == 'create')
// Date delivery planned
print ''.$langs->trans("DateDeliveryPlanned").' ';
print '';
- //print dol_print_date($object->date_livraison,"day"); // date_livraison come from order and will be stored into date_delivery planed.
+ //print dol_print_date($object->date_livraison, "day"); // date_livraison come from order and will be stored into date_delivery planed.
$date_delivery = ($date_delivery?$date_delivery:$object->date_livraison); // $date_delivery comes from GETPOST
print $form->selectDate($date_delivery?$date_delivery:-1, 'date_delivery', 1, 1, 1);
print " \n";
@@ -1136,449 +1137,455 @@ if ($action == 'create')
$line = $object->lines[$indiceAsked];
+ $parameters = array('i' => $indiceAsked, 'line' => $line, 'num' => $numAsked);
+ $reshook = $hookmanager->executeHooks('printObjectLine', $parameters, $object, $action);
+ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
- // Show product and description
- $type=$line->product_type?$line->product_type:$line->fk_product_type;
- // Try to enhance type detection using date_start and date_end for free lines where type
- // was not saved.
- if (! empty($line->date_start)) $type=1;
- if (! empty($line->date_end)) $type=1;
-
- print ''."\n";
- print ''."\n";
-
- // Product label
- if ($line->fk_product > 0) // If predefined product
+ if (empty($reshook))
{
- $product->fetch($line->fk_product);
- $product->load_stock('warehouseopen'); // Load all $product->stock_warehouse[idwarehouse]->detail_batch
- //var_dump($product->stock_warehouse[1]);
+ // Show product and description
+ $type=$line->product_type?$line->product_type:$line->fk_product_type;
+ // Try to enhance type detection using date_start and date_end for free lines where type
+ // was not saved.
+ if (! empty($line->date_start)) $type=1;
+ if (! empty($line->date_end)) $type=1;
- print '';
- print ' '; // ancre pour retourner sur la ligne
+ print ''."\n";
+ print ' '."\n";
- // Show product and description
- $product_static->type=$line->fk_product_type;
- $product_static->id=$line->fk_product;
- $product_static->ref=$line->ref;
- $product_static->status_batch=$line->product_tobatch;
- $text=$product_static->getNomUrl(1);
- $text.= ' - '.(! empty($line->label)?$line->label:$line->product_label);
- $description=($conf->global->PRODUIT_DESC_IN_FORM?'':dol_htmlentitiesbr($line->desc));
- print $form->textwithtooltip($text, $description, 3, '', '', $i);
+ // Product label
+ if ($line->fk_product > 0) // If predefined product
+ {
+ $product->fetch($line->fk_product);
+ $product->load_stock('warehouseopen'); // Load all $product->stock_warehouse[idwarehouse]->detail_batch
+ //var_dump($product->stock_warehouse[1]);
- // Show range
- print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
+ print '';
+ print ' '; // ancre pour retourner sur la ligne
- // Add description in form
- if (! empty($conf->global->PRODUIT_DESC_IN_FORM))
- {
- print ($line->desc && $line->desc!=$line->product_label)?' '.dol_htmlentitiesbr($line->desc):'';
- }
+ // Show product and description
+ $product_static->type=$line->fk_product_type;
+ $product_static->id=$line->fk_product;
+ $product_static->ref=$line->ref;
+ $product_static->status_batch=$line->product_tobatch;
+ $text=$product_static->getNomUrl(1);
+ $text.= ' - '.(! empty($line->label)?$line->label:$line->product_label);
+ $description=($conf->global->PRODUIT_DESC_IN_FORM?'':dol_htmlentitiesbr($line->desc));
+ print $form->textwithtooltip($text, $description, 3, '', '', $i);
- print ' ';
- }
- else
- {
- print "";
- if ($type==1) $text = img_object($langs->trans('Service'), 'service');
- else $text = img_object($langs->trans('Product'), 'product');
+ // Show range
+ print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
- if (! empty($line->label)) {
- $text.= ' '.$line->label.' ';
- print $form->textwithtooltip($text, $line->desc, 3, '', '', $i);
- } else {
- print $text.' '.nl2br($line->desc);
- }
+ // Add description in form
+ if (! empty($conf->global->PRODUIT_DESC_IN_FORM))
+ {
+ print ($line->desc && $line->desc!=$line->product_label)?' '.dol_htmlentitiesbr($line->desc):'';
+ }
- // Show range
- print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
- print " \n";
- }
-
- // Qty
- print ''.$line->qty;
- print ' ';
- print ' ';
- $qtyProdCom=$line->qty;
-
- // Qty already shipped
- print '';
- $quantityDelivered = $object->expeditions[$line->id];
- print $quantityDelivered;
- print ' ';
- print ' ';
-
- // Qty to ship
- $quantityAsked = $line->qty;
- if ($line->product_type == 1 && empty($conf->global->STOCK_SUPPORTS_SERVICES))
- {
- $quantityToBeDelivered = 0;
- }
- else
- {
- $quantityToBeDelivered = $quantityAsked - $quantityDelivered;
- }
- $warehouse_id = GETPOST('entrepot_id', 'int');
-
- $warehouseObject = null;
- if ($warehouse_id > 0 || ! ($line->fk_product > 0) || empty($conf->stock->enabled)) // If warehouse was already selected or if product is not a predefined, we go into this part with no multiwarehouse selection
- {
- print '';
- //ship from preselected location
- $stock = + $product->stock_warehouse[$warehouse_id]->real; // Convert to number
- $deliverableQty=min($quantityToBeDelivered, $stock);
- if ($deliverableQty < 0) $deliverableQty = 0;
- if (empty($conf->productbatch->enabled) || ! $product->hasbatch())
+ print '';
+ }
+ else
{
- // Quantity to send
- print '';
- if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
- {
- if (GETPOST('qtyl'.$indiceAsked, 'int')) $deliverableQty=GETPOST('qtyl'.$indiceAsked, 'int');
- print ' ';
- print ' ';
- }
- else print $langs->trans("NA");
- print ' ';
+ print "";
+ if ($type==1) $text = img_object($langs->trans('Service'), 'service');
+ else $text = img_object($langs->trans('Product'), 'product');
- // Stock
- if (! empty($conf->stock->enabled))
- {
- print ' ';
- if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES)) // Type of product need stock change ?
- {
- // Show warehouse combo list
- $ent = "entl".$indiceAsked;
- $idl = "idl".$indiceAsked;
- $tmpentrepot_id = is_numeric(GETPOST($ent, 'int'))?GETPOST($ent, 'int'):$warehouse_id;
- if ($line->fk_product > 0)
- {
- print '';
- print $formproduct->selectWarehouses($tmpentrepot_id, 'entl'.$indiceAsked, '', 1, 0, $line->fk_product, '', 1);
- if ($tmpentrepot_id > 0 && $tmpentrepot_id == $warehouse_id)
- {
- //print $stock.' '.$quantityToBeDelivered;
- if ($stock < $quantityToBeDelivered)
- {
- print ' '.img_warning($langs->trans("StockTooLow")); // Stock too low for this $warehouse_id but you can change warehouse
- }
- }
- }
- }
- else
- {
- print $langs->trans("Service");
- }
- print ' ';
- }
+ if (! empty($line->label)) {
+ $text.= ' '.$line->label.' ';
+ print $form->textwithtooltip($text, $line->desc, 3, '', '', $i);
+ } else {
+ print $text.' '.nl2br($line->desc);
+ }
- print " \n";
+ // Show range
+ print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
+ print "\n";
+ }
- // Show subproducts of product
- if (! empty($conf->global->PRODUIT_SOUSPRODUITS) && $line->fk_product > 0)
- {
- $product->get_sousproduits_arbo();
- $prods_arbo = $product->get_arbo_each_prod($qtyProdCom);
- if(count($prods_arbo) > 0)
- {
- foreach($prods_arbo as $key => $value)
- {
- //print $value[0];
- $img='';
- if ($value['stock'] < $value['stock_alert'])
- {
- $img=img_warning($langs->trans("StockTooLow"));
- }
- print " ->
- ".$value['fullpath']."
- (".$value['nb'].") ".$value['nb_total']."    
- ".$value['stock']." ".$img." ";
- }
- }
- }
+ // Qty
+ print ''.$line->qty;
+ print ' ';
+ print ' ';
+ $qtyProdCom=$line->qty;
+
+ // Qty already shipped
+ print '';
+ $quantityDelivered = $object->expeditions[$line->id];
+ print $quantityDelivered;
+ print ' ';
+ print ' ';
+
+ // Qty to ship
+ $quantityAsked = $line->qty;
+ if ($line->product_type == 1 && empty($conf->global->STOCK_SUPPORTS_SERVICES))
+ {
+ $quantityToBeDelivered = 0;
}
else
{
- // Product need lot
- print ' '; // end line and start a new one for lot/serial
- print '';
+ $quantityToBeDelivered = $quantityAsked - $quantityDelivered;
+ }
+ $warehouse_id = GETPOST('entrepot_id', 'int');
- $staticwarehouse=new Entrepot($db);
- if ($warehouse_id > 0) $staticwarehouse->fetch($warehouse_id);
-
- $subj=0;
- // Define nb of lines suggested for this order line
- $nbofsuggested=0;
- if (is_object($product->stock_warehouse[$warehouse_id]) && count($product->stock_warehouse[$warehouse_id]->detail_batch))
+ $warehouseObject = null;
+ if ($warehouse_id > 0 || ! ($line->fk_product > 0) || empty($conf->stock->enabled)) // If warehouse was already selected or if product is not a predefined, we go into this part with no multiwarehouse selection
+ {
+ print '';
+ //ship from preselected location
+ $stock = + $product->stock_warehouse[$warehouse_id]->real; // Convert to number
+ $deliverableQty=min($quantityToBeDelivered, $stock);
+ if ($deliverableQty < 0) $deliverableQty = 0;
+ if (empty($conf->productbatch->enabled) || ! $product->hasbatch())
{
- foreach ($product->stock_warehouse[$warehouse_id]->detail_batch as $dbatch)
- {
- $nbofsuggested++;
- }
- }
- print ' ';
- if (is_object($product->stock_warehouse[$warehouse_id]) && count($product->stock_warehouse[$warehouse_id]->detail_batch))
- {
- foreach ($product->stock_warehouse[$warehouse_id]->detail_batch as $dbatch) // $dbatch is instance of Productbatch
+ // Quantity to send
+ print '';
+ if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
{
- //var_dump($dbatch);
- $batchStock = + $dbatch->qty; // To get a numeric
- $deliverableQty = min($quantityToBeDelivered, $batchStock);
- print ' ';
- print '';
- print ' ';
- print ' ';
+ if (GETPOST('qtyl'.$indiceAsked, 'int')) $deliverableQty=GETPOST('qtyl'.$indiceAsked, 'int');
+ print ' ';
+ print ' ';
+ }
+ else print $langs->trans("NA");
+ print '';
- print '';
+ // Stock
+ if (! empty($conf->stock->enabled))
+ {
print '';
-
- print $staticwarehouse->getNomUrl(0).' / ';
-
- print ' ';
-
- $detail='';
- $detail.= $langs->trans("Batch").': '.$dbatch->batch;
- $detail.= ' - '.$langs->trans("SellByDate").': '.dol_print_date($dbatch->sellby, "day");
- $detail.= ' - '.$langs->trans("EatByDate").': '.dol_print_date($dbatch->eatby, "day");
- $detail.= ' - '.$langs->trans("Qty").': '.$dbatch->qty;
- $detail.= ' ';
- print $detail;
-
- $quantityToBeDelivered -= $deliverableQty;
- if ($quantityToBeDelivered < 0)
+ if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES)) // Type of product need stock change ?
{
- $quantityToBeDelivered = 0;
+ // Show warehouse combo list
+ $ent = "entl".$indiceAsked;
+ $idl = "idl".$indiceAsked;
+ $tmpentrepot_id = is_numeric(GETPOST($ent, 'int'))?GETPOST($ent, 'int'):$warehouse_id;
+ if ($line->fk_product > 0)
+ {
+ print '';
+ print $formproduct->selectWarehouses($tmpentrepot_id, 'entl'.$indiceAsked, '', 1, 0, $line->fk_product, '', 1);
+ if ($tmpentrepot_id > 0 && $tmpentrepot_id == $warehouse_id)
+ {
+ //print $stock.' '.$quantityToBeDelivered;
+ if ($stock < $quantityToBeDelivered)
+ {
+ print ' '.img_warning($langs->trans("StockTooLow")); // Stock too low for this $warehouse_id but you can change warehouse
+ }
+ }
+ }
+ }
+ else
+ {
+ print $langs->trans("Service");
+ }
+ print ' ';
+ }
+
+ print " \n";
+
+ // Show subproducts of product
+ if (! empty($conf->global->PRODUIT_SOUSPRODUITS) && $line->fk_product > 0)
+ {
+ $product->get_sousproduits_arbo();
+ $prods_arbo = $product->get_arbo_each_prod($qtyProdCom);
+ if(count($prods_arbo) > 0)
+ {
+ foreach($prods_arbo as $key => $value)
+ {
+ //print $value[0];
+ $img='';
+ if ($value['stock'] < $value['stock_alert'])
+ {
+ $img=img_warning($langs->trans("StockTooLow"));
+ }
+ print " ->
+ ".$value['fullpath']."
+ (".$value['nb'].") ".$value['nb_total']."    
+ ".$value['stock']." ".$img." ";
+ }
}
- $subj++;
- print '';
}
}
else
{
- print '';
- print '';
- print ' ';
- print ' ';
+ // Product need lot
+ print ' '; // end line and start a new one for lot/serial
+ print '';
- print '';
- print img_warning().' '.$langs->trans("NoProductToShipFoundIntoStock", $staticwarehouse->libelle);
- print ' ';
- }
- }
- }
- else
- {
- // ship from multiple locations
- if (empty($conf->productbatch->enabled) || ! $product->hasbatch())
- {
- print '';
- print ' '."\n"; // end line and start a new one for each warehouse
+ $staticwarehouse=new Entrepot($db);
+ if ($warehouse_id > 0) $staticwarehouse->fetch($warehouse_id);
- print ' ';
- $subj=0;
- // Define nb of lines suggested for this order line
- $nbofsuggested=0;
- foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse)
- {
- if ($stock_warehouse->real > 0)
+ $subj=0;
+ // Define nb of lines suggested for this order line
+ $nbofsuggested=0;
+ if (is_object($product->stock_warehouse[$warehouse_id]) && count($product->stock_warehouse[$warehouse_id]->detail_batch))
{
- $nbofsuggested++;
+ foreach ($product->stock_warehouse[$warehouse_id]->detail_batch as $dbatch)
+ {
+ $nbofsuggested++;
+ }
}
- }
- $tmpwarehouseObject=new Entrepot($db);
- foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse) // $stock_warehouse is product_stock
- {
- $tmpwarehouseObject->fetch($warehouse_id);
- if ($stock_warehouse->real > 0)
+ print ' ';
+ if (is_object($product->stock_warehouse[$warehouse_id]) && count($product->stock_warehouse[$warehouse_id]->detail_batch))
{
- $stock = + $stock_warehouse->real; // Convert it to number
- $deliverableQty = min($quantityToBeDelivered, $stock);
- $deliverableQty = max(0, $deliverableQty);
- // Quantity to send
- print '';
- print '';
- if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
- {
- print ' ';
- print ' ';
- }
- else print $langs->trans("NA");
- print ' ';
-
- // Stock
- if (! empty($conf->stock->enabled))
- {
- print '';
- if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
- {
- print $tmpwarehouseObject->getNomUrl(0).' ';
-
- print '';
- print '('.$stock.')';
- }
- else
- {
- print $langs->trans("Service");
- }
- print ' ';
- }
- $quantityToBeDelivered -= $deliverableQty;
- if ($quantityToBeDelivered < 0)
- {
- $quantityToBeDelivered = 0;
- }
- $subj++;
- print " \n";
- }
- }
- // Show subproducts of product (not recommanded)
- if (! empty($conf->global->PRODUIT_SOUSPRODUITS) && $line->fk_product > 0)
- {
- $product->get_sousproduits_arbo();
- $prods_arbo = $product->get_arbo_each_prod($qtyProdCom);
- if (count($prods_arbo) > 0)
- {
- foreach($prods_arbo as $key => $value)
- {
- //print $value[0];
- $img='';
- if ($value['stock'] < $value['stock_alert'])
- {
- $img=img_warning($langs->trans("StockTooLow"));
- }
- print '';
- print " ->
- ".$value['fullpath']."
- (".$value['nb'].") ".$value['nb_total']."    
- ".$value['stock']." ".$img." ";
- print " ";
- }
- }
- }
- }
- else
- {
- print '';
- print ' '; // end line and start a new one for lot/serial
-
- $subj=0;
- print ' ';
-
- $tmpwarehouseObject=new Entrepot($db);
- $productlotObject=new Productlot($db);
- // Define nb of lines suggested for this order line
- $nbofsuggested=0;
- foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse)
- {
- if (($stock_warehouse->real > 0) && (count($stock_warehouse->detail_batch))) {
- foreach ($stock_warehouse->detail_batch as $dbatch)
- {
- $nbofsuggested++;
- }
- }
- }
- foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse)
- {
- $tmpwarehouseObject->fetch($warehouse_id);
- if (($stock_warehouse->real > 0) && (count($stock_warehouse->detail_batch))) {
- foreach ($stock_warehouse->detail_batch as $dbatch)
+ foreach ($product->stock_warehouse[$warehouse_id]->detail_batch as $dbatch) // $dbatch is instance of Productbatch
{
//var_dump($dbatch);
$batchStock = + $dbatch->qty; // To get a numeric
$deliverableQty = min($quantityToBeDelivered, $batchStock);
- if ($deliverableQty < 0) $deliverableQty = 0;
- print '';
+ print ' ';
+ print '';
print ' ';
print ' ';
+ print '';
print '';
- print $tmpwarehouseObject->getNomUrl(0).' / ';
+ print $staticwarehouse->getNomUrl(0).' / ';
- print '';
print ' ';
- //print '|'.$line->fk_product.'|'.$dbatch->batch.'| ';
- print $langs->trans("Batch").': ';
- $result = $productlotObject->fetch(0, $line->fk_product, $dbatch->batch);
- if ($result > 0) print $productlotObject->getNomUrl(1);
- else print 'TableLotIncompleteRunRepairWithParamStandardEqualConfirmed';
- print ' ('.$dbatch->qty.')';
+ $detail='';
+ $detail.= $langs->trans("Batch").': '.$dbatch->batch;
+ $detail.= ' - '.$langs->trans("SellByDate").': '.dol_print_date($dbatch->sellby, "day");
+ $detail.= ' - '.$langs->trans("EatByDate").': '.dol_print_date($dbatch->eatby, "day");
+ $detail.= ' - '.$langs->trans("Qty").': '.$dbatch->qty;
+ $detail.= ' ';
+ print $detail;
+
$quantityToBeDelivered -= $deliverableQty;
if ($quantityToBeDelivered < 0)
{
$quantityToBeDelivered = 0;
}
- //dol_syslog('deliverableQty = '.$deliverableQty.' batchStock = '.$batchStock);
$subj++;
print ' ';
}
}
+ else
+ {
+ print '';
+ print '';
+ print ' ';
+ print ' ';
+
+ print '';
+ print img_warning().' '.$langs->trans("NoProductToShipFoundIntoStock", $staticwarehouse->libelle);
+ print ' ';
+ }
}
}
- if ($subj == 0) // Line not shown yet, we show it
+ else
{
- print '';
- print '';
- if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
+ // ship from multiple locations
+ if (empty($conf->productbatch->enabled) || ! $product->hasbatch())
{
- $disabled='';
- if (! empty($conf->productbatch->enabled) && $product->hasbatch())
- {
- $disabled='disabled="disabled"';
- }
- print ' ';
- }
- else
- {
- print $langs->trans("NA");
- }
- print ' ';
+ print '';
+ print ' '."\n"; // end line and start a new one for each warehouse
- print '';
- if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
- {
- $warehouse_selected_id = GETPOST('entrepot_id', 'int');
- if ($warehouse_selected_id > 0)
- {
- $warehouseObject=new Entrepot($db);
- $warehouseObject->fetch($warehouse_selected_id);
- print img_warning().' '.$langs->trans("NoProductToShipFoundIntoStock", $warehouseObject->libelle);
- }
- else
- {
- if ($line->fk_product) print img_warning().' '.$langs->trans("StockTooLow");
- else print '';
- }
+ print ' ';
+ $subj=0;
+ // Define nb of lines suggested for this order line
+ $nbofsuggested=0;
+ foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse)
+ {
+ if ($stock_warehouse->real > 0)
+ {
+ $nbofsuggested++;
+ }
+ }
+ $tmpwarehouseObject=new Entrepot($db);
+ foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse) // $stock_warehouse is product_stock
+ {
+ $tmpwarehouseObject->fetch($warehouse_id);
+ if ($stock_warehouse->real > 0)
+ {
+ $stock = + $stock_warehouse->real; // Convert it to number
+ $deliverableQty = min($quantityToBeDelivered, $stock);
+ $deliverableQty = max(0, $deliverableQty);
+ // Quantity to send
+ print ' ';
+ print '';
+ if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
+ {
+ print ' ';
+ print ' ';
+ }
+ else print $langs->trans("NA");
+ print ' ';
+
+ // Stock
+ if (! empty($conf->stock->enabled))
+ {
+ print '';
+ if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
+ {
+ print $tmpwarehouseObject->getNomUrl(0).' ';
+
+ print '';
+ print '('.$stock.')';
+ }
+ else
+ {
+ print $langs->trans("Service");
+ }
+ print ' ';
+ }
+ $quantityToBeDelivered -= $deliverableQty;
+ if ($quantityToBeDelivered < 0)
+ {
+ $quantityToBeDelivered = 0;
+ }
+ $subj++;
+ print " \n";
+ }
+ }
+ // Show subproducts of product (not recommanded)
+ if (! empty($conf->global->PRODUIT_SOUSPRODUITS) && $line->fk_product > 0)
+ {
+ $product->get_sousproduits_arbo();
+ $prods_arbo = $product->get_arbo_each_prod($qtyProdCom);
+ if (count($prods_arbo) > 0)
+ {
+ foreach($prods_arbo as $key => $value)
+ {
+ //print $value[0];
+ $img='';
+ if ($value['stock'] < $value['stock_alert'])
+ {
+ $img=img_warning($langs->trans("StockTooLow"));
+ }
+ print '';
+ print " ->
+ ".$value['fullpath']."
+ (".$value['nb'].") ".$value['nb_total']."    
+ ".$value['stock']." ".$img." ";
+ print " ";
+ }
+ }
+ }
}
else
{
- print $langs->trans("Service");
+ print '';
+ print ' '; // end line and start a new one for lot/serial
+
+ $subj=0;
+ print ' ';
+
+ $tmpwarehouseObject=new Entrepot($db);
+ $productlotObject=new Productlot($db);
+ // Define nb of lines suggested for this order line
+ $nbofsuggested=0;
+ foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse)
+ {
+ if (($stock_warehouse->real > 0) && (count($stock_warehouse->detail_batch))) {
+ foreach ($stock_warehouse->detail_batch as $dbatch)
+ {
+ $nbofsuggested++;
+ }
+ }
+ }
+ foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse)
+ {
+ $tmpwarehouseObject->fetch($warehouse_id);
+ if (($stock_warehouse->real > 0) && (count($stock_warehouse->detail_batch))) {
+ foreach ($stock_warehouse->detail_batch as $dbatch)
+ {
+ //var_dump($dbatch);
+ $batchStock = + $dbatch->qty; // To get a numeric
+ $deliverableQty = min($quantityToBeDelivered, $batchStock);
+ if ($deliverableQty < 0) $deliverableQty = 0;
+ print '';
+ print ' ';
+ print ' ';
+
+ print '';
+
+ print $tmpwarehouseObject->getNomUrl(0).' / ';
+
+ print '';
+ print ' ';
+
+ //print '|'.$line->fk_product.'|'.$dbatch->batch.'| ';
+ print $langs->trans("Batch").': ';
+ $result = $productlotObject->fetch(0, $line->fk_product, $dbatch->batch);
+ if ($result > 0) print $productlotObject->getNomUrl(1);
+ else print 'TableLotIncompleteRunRepairWithParamStandardEqualConfirmed';
+ print ' ('.$dbatch->qty.')';
+ $quantityToBeDelivered -= $deliverableQty;
+ if ($quantityToBeDelivered < 0)
+ {
+ $quantityToBeDelivered = 0;
+ }
+ //dol_syslog('deliverableQty = '.$deliverableQty.' batchStock = '.$batchStock);
+ $subj++;
+ print ' ';
+ }
+ }
+ }
}
- print '';
+ if ($subj == 0) // Line not shown yet, we show it
+ {
+ print '';
+ print '';
+ if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
+ {
+ $disabled='';
+ if (! empty($conf->productbatch->enabled) && $product->hasbatch())
+ {
+ $disabled='disabled="disabled"';
+ }
+ print ' ';
+ }
+ else
+ {
+ print $langs->trans("NA");
+ }
+ print ' ';
+
+ print '';
+ if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
+ {
+ $warehouse_selected_id = GETPOST('entrepot_id', 'int');
+ if ($warehouse_selected_id > 0)
+ {
+ $warehouseObject=new Entrepot($db);
+ $warehouseObject->fetch($warehouse_selected_id);
+ print img_warning().' '.$langs->trans("NoProductToShipFoundIntoStock", $warehouseObject->libelle);
+ }
+ else
+ {
+ if ($line->fk_product) print img_warning().' '.$langs->trans("StockTooLow");
+ else print '';
+ }
+ }
+ else
+ {
+ print $langs->trans("Service");
+ }
+ print ' ';
+ print ' ';
+ }
+ }
+
+
+ //Display lines extrafields
+ if (is_array($extralabelslines) && count($extralabelslines)>0)
+ {
+ $colspan=5;
+ $orderLineExtrafields = new Extrafields($db);
+ $orderLineExtrafieldLabels = $orderLineExtrafields->fetch_name_optionals_label($object->table_element_line);
+ $srcLine = new OrderLine($db);
+ $srcLine->fetch_optionals($line->id); // fetch extrafields also available in orderline
+ $line = new ExpeditionLigne($db);
+ //$line->fetch_optionals($line->id);
+ $line->array_options = array_merge($line->array_options, $srcLine->array_options);
+ print '';
+ print $line->showOptionals($extrafieldsline, 'edit', array('style'=>$bc[$var], 'colspan'=>$colspan), $indiceAsked);
print ' ';
}
- }
-
- //Display lines extrafields
- if (is_array($extralabelslines) && count($extralabelslines)>0)
- {
- $colspan=5;
- $orderLineExtrafields = new Extrafields($db);
- $orderLineExtrafieldLabels = $orderLineExtrafields->fetch_name_optionals_label($object->table_element_line);
- $srcLine = new OrderLine($db);
- $srcLine->fetch_optionals($line->id); // fetch extrafields also available in orderline
- $line = new ExpeditionLigne($db);
- //$line->fetch_optionals($line->id);
- $line->array_options = array_merge($line->array_options, $srcLine->array_options);
- print '';
- print $line->showOptionals($extrafieldsline, 'edit', array('style'=>$bc[$var], 'colspan'=>$colspan), $indiceAsked);
- print ' ';
- }
-
- $indiceAsked++;
+ $indiceAsked++;
+ }
}
print "";
@@ -1828,7 +1835,7 @@ elseif ($id || $ref)
if ($totalWeight > 0)
{
if (!empty($object->trueWeight)) print ' ('.$langs->trans("SumOfProductWeights").': ';
- //print $totalWeight.' '.measuring_units_string(0,"weight");
+ //print $totalWeight.' '.measuring_units_string(0, "weight");
print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, isset($conf->global->MAIN_WEIGHT_DEFAULT_ROUND)?$conf->global->MAIN_WEIGHT_DEFAULT_ROUND:-1, isset($conf->global->MAIN_WEIGHT_DEFAULT_UNIT)?$conf->global->MAIN_WEIGHT_DEFAULT_UNIT:'no');
//if (empty($object->trueWeight)) print ' ('.$langs->trans("Calculated").')';
if (!empty($object->trueWeight)) print ')';
@@ -1886,7 +1893,7 @@ elseif ($id || $ref)
{
if ($volumeUnit < 50)
{
- //print $calculatedVolume.' '.measuring_units_string($volumeUnit,"volume");
+ //print $calculatedVolume.' '.measuring_units_string($volumeUnit, "volume");
print showDimensionInBestUnit($calculatedVolume, $volumeUnit, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND)?$conf->global->MAIN_VOLUME_DEFAULT_ROUND:-1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT)?$conf->global->MAIN_VOLUME_DEFAULT_UNIT:'no');
}
else print $calculatedVolume.' '.measuring_units_string($volumeUnit, "volume");
@@ -1894,7 +1901,7 @@ elseif ($id || $ref)
if ($totalVolume > 0)
{
if ($calculatedVolume) print ' ('.$langs->trans("SumOfProductVolumes").': ';
- //print $totalVolume.' '.measuring_units_string(0,"volume");
+ //print $totalVolume.' '.measuring_units_string(0, "volume");
print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND)?$conf->global->MAIN_VOLUME_DEFAULT_ROUND:-1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT)?$conf->global->MAIN_VOLUME_DEFAULT_UNIT:'no');
//if (empty($calculatedVolume)) print ' ('.$langs->trans("Calculated").')';
if ($calculatedVolume) print ')';
@@ -1975,6 +1982,11 @@ elseif ($id || $ref)
print '';
}
+ // Other attributes
+ $parameters = array('colspan' => ' colspan="3"');
+ $reshook=$hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
+ print $hookmanager->resPrint;
+
print "";
print '';
@@ -2129,298 +2141,306 @@ elseif ($id || $ref)
// Loop on each product to send/sent
for ($i = 0 ; $i < $num_prod ; $i++)
{
- print ''; // id of order line
- print '';
+ $parameters = array('i' => $i, 'line' => $lines[$i], 'line_id' => $line_id, 'num' => $num_prod, 'alreadysent' => $alreadysent, 'editColspan' => $editColspan, 'outputlangs' => $outputlangs);
+ $reshook = $hookmanager->executeHooks('printObjectLine', $parameters, $object, $action);
+ if($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
- // Adds a line numbering column
- if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER))
+ if(empty($reshook))
{
- print ''.($i+1).' ';
- }
+ print ''; // id of order line
+ print ' ';
- // Predefined product or service
- if ($lines[$i]->fk_product > 0)
- {
- // Define output language
- if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE))
+ // #
+ if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER))
{
- $prod = new Product($db);
- $prod->fetch($lines[$i]->fk_product);
- $label = ( ! empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $lines[$i]->product_label;
+ print ''.($i+1).' ';
+ }
+
+ // Predefined product or service
+ if ($lines[$i]->fk_product > 0)
+ {
+ // Define output language
+ if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE))
+ {
+ $prod = new Product($db);
+ $prod->fetch($lines[$i]->fk_product);
+ $label = ( ! empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $lines[$i]->product_label;
+ }
+ else
+ $label = (! empty($lines[$i]->label)?$lines[$i]->label:$lines[$i]->product_label);
+
+ print '';
+
+ // Show product and description
+ $product_static->type=$lines[$i]->fk_product_type;
+ $product_static->id=$lines[$i]->fk_product;
+ $product_static->ref=$lines[$i]->ref;
+ $product_static->status_batch=$lines[$i]->product_tobatch;
+ $text=$product_static->getNomUrl(1);
+ $text.= ' - '.$label;
+ $description=(! empty($conf->global->PRODUIT_DESC_IN_FORM)?'':dol_htmlentitiesbr($lines[$i]->description));
+ print $form->textwithtooltip($text, $description, 3, '', '', $i);
+ print_date_range($lines[$i]->date_start, $lines[$i]->date_end);
+ if (! empty($conf->global->PRODUIT_DESC_IN_FORM))
+ {
+ print (! empty($lines[$i]->description) && $lines[$i]->description!=$lines[$i]->product)?' '.dol_htmlentitiesbr($lines[$i]->description):'';
+ }
+ print " \n";
}
else
- $label = (! empty($lines[$i]->label)?$lines[$i]->label:$lines[$i]->product_label);
-
- print '';
-
- // Show product and description
- $product_static->type=$lines[$i]->fk_product_type;
- $product_static->id=$lines[$i]->fk_product;
- $product_static->ref=$lines[$i]->ref;
- $product_static->status_batch=$lines[$i]->product_tobatch;
- $text=$product_static->getNomUrl(1);
- $text.= ' - '.$label;
- $description=(! empty($conf->global->PRODUIT_DESC_IN_FORM)?'':dol_htmlentitiesbr($lines[$i]->description));
- print $form->textwithtooltip($text, $description, 3, '', '', $i);
- print_date_range($lines[$i]->date_start, $lines[$i]->date_end);
- if (! empty($conf->global->PRODUIT_DESC_IN_FORM))
{
- print (! empty($lines[$i]->description) && $lines[$i]->description!=$lines[$i]->product)?' '.dol_htmlentitiesbr($lines[$i]->description):'';
- }
- print " \n";
- }
- else
- {
- print "";
- if ($lines[$i]->product_type == Product::TYPE_SERVICE) $text = img_object($langs->trans('Service'), 'service');
- else $text = img_object($langs->trans('Product'), 'product');
+ print " ";
+ if ($lines[$i]->product_type == Product::TYPE_SERVICE) $text = img_object($langs->trans('Service'), 'service');
+ else $text = img_object($langs->trans('Product'), 'product');
- if (! empty($lines[$i]->label)) {
- $text.= ' '.$lines[$i]->label.' ';
- print $form->textwithtooltip($text, $lines[$i]->description, 3, '', '', $i);
- } else {
- print $text.' '.nl2br($lines[$i]->description);
- }
-
- print_date_range($lines[$i]->date_start, $lines[$i]->date_end);
- print " \n";
- }
-
- // Qty ordered
- print ''.$lines[$i]->qty_asked.' ';
-
- // Qty in other shipments (with shipment and warehouse used)
- if ($origin && $origin_id > 0)
- {
- print '';
- foreach ($alreadysent as $key => $val)
- {
- if ($lines[$i]->fk_origin_line == $key)
- {
- $j = 0;
- foreach($val as $shipmentline_id=> $shipmentline_var)
- {
- if ($shipmentline_var['shipment_id'] == $lines[$i]->fk_expedition) continue; // We want to show only "other shipments"
-
- $j++;
- if ($j > 1) print ' ';
- $shipment_static->fetch($shipmentline_var['shipment_id']);
- print $shipment_static->getNomUrl(1);
- print ' - '.$shipmentline_var['qty_shipped'];
- $htmltext=$langs->trans("DateValidation").' : '.(empty($shipmentline_var['date_valid'])?$langs->trans("Draft"):dol_print_date($shipmentline_var['date_valid'], 'dayhour'));
- if (! empty($conf->stock->enabled) && $shipmentline_var['warehouse'] > 0)
- {
- $warehousestatic->fetch($shipmentline_var['warehouse']);
- $htmltext .= ' '.$langs->trans("From").' : '.$warehousestatic->getNomUrl(1);
- }
- print ' '.$form->textwithpicto('', $htmltext, 1);
- }
- }
- }
- }
- print ' ';
-
- if ($action == 'editline' && $lines[$i]->id == $line_id)
- {
- // edit mode
- print '';
- if (is_array($lines[$i]->detail_batch) && count($lines[$i]->detail_batch) > 0)
- {
- print '';
- $line = new ExpeditionLigne($db);
- foreach ($lines[$i]->detail_batch as $detail_batch)
- {
- print '';
- // Qty to ship or shipped
- print '' . ' ' . ' ';
- // Batch number managment
- if ($lines[$i]->entrepot_id == 0)
- {
- // only show lot numbers from src warehouse when shipping from multiple warehouses
- $line->fetch($detail_batch->fk_expeditiondet);
- }
- print '' . $formproduct->selectLotStock($detail_batch->fk_origin_stock, 'batchl'.$detail_batch->fk_expeditiondet.'_'.$detail_batch->fk_origin_stock, '', 1, 0, $lines[$i]->fk_product, $line->entrepot_id). ' ';
- print ' ';
+ if (! empty($lines[$i]->label)) {
+ $text.= ' '.$lines[$i]->label.' ';
+ print $form->textwithtooltip($text, $lines[$i]->description, 3, '', '', $i);
+ } else {
+ print $text.' '.nl2br($lines[$i]->description);
}
- // add a 0 qty lot row to be able to add a lot
- print '';
- // Qty to ship or shipped
- print '' . ' ' . ' ';
- // Batch number managment
- print '' . $formproduct->selectLotStock('', 'batchl'.$line_id.'_0', '', 1, 0, $lines[$i]->fk_product). ' ';
- print ' ';
+
+ print_date_range($lines[$i]->date_start, $lines[$i]->date_end);
+ print "\n";
}
- elseif (! empty($conf->stock->enabled))
+
+ // Qty ordered
+ print ''.$lines[$i]->qty_asked.' ';
+
+ // Qty in other shipments (with shipment and warehouse used)
+ if ($origin && $origin_id > 0)
+ {
+ print '';
+ foreach ($alreadysent as $key => $val)
+ {
+ if ($lines[$i]->fk_origin_line == $key)
+ {
+ $j = 0;
+ foreach($val as $shipmentline_id=> $shipmentline_var)
+ {
+ if ($shipmentline_var['shipment_id'] == $lines[$i]->fk_expedition) continue; // We want to show only "other shipments"
+
+ $j++;
+ if ($j > 1) print ' ';
+ $shipment_static->fetch($shipmentline_var['shipment_id']);
+ print $shipment_static->getNomUrl(1);
+ print ' - '.$shipmentline_var['qty_shipped'];
+ $htmltext=$langs->trans("DateValidation").' : '.(empty($shipmentline_var['date_valid'])?$langs->trans("Draft"):dol_print_date($shipmentline_var['date_valid'], 'dayhour'));
+ if (! empty($conf->stock->enabled) && $shipmentline_var['warehouse'] > 0)
+ {
+ $warehousestatic->fetch($shipmentline_var['warehouse']);
+ $htmltext .= ' '.$langs->trans("From").' : '.$warehousestatic->getNomUrl(1);
+ }
+ print ' '.$form->textwithpicto('', $htmltext, 1);
+ }
+ }
+ }
+ }
+ print ' ';
+
+ if ($action == 'editline' && $lines[$i]->id == $line_id)
{
- if ($lines[$i]->fk_product > 0)
+ // edit mode
+ print '';
+ if (is_array($lines[$i]->detail_batch) && count($lines[$i]->detail_batch) > 0)
{
- if ($lines[$i]->entrepot_id > 0)
+ print '';
+ $line = new ExpeditionLigne($db);
+ foreach ($lines[$i]->detail_batch as $detail_batch)
{
- print '';
print '';
// Qty to ship or shipped
- print '' . ' ' . ' ';
- // Warehouse source
- print '' . $formproduct->selectWarehouses($lines[$i]->entrepot_id, 'entl'.$line_id, '', 1, 0, $lines[$i]->fk_product, '', 1). ' ';
+ print '' . ' ' . ' ';
// Batch number managment
- print ' - ' . $langs->trans("NA") . ' ';
+ if ($lines[$i]->entrepot_id == 0)
+ {
+ // only show lot numbers from src warehouse when shipping from multiple warehouses
+ $line->fetch($detail_batch->fk_expeditiondet);
+ }
+ print '' . $formproduct->selectLotStock($detail_batch->fk_origin_stock, 'batchl'.$detail_batch->fk_expeditiondet.'_'.$detail_batch->fk_origin_stock, '', 1, 0, $lines[$i]->fk_product, $line->entrepot_id). ' ';
print ' ';
}
- elseif (count($lines[$i]->details_entrepot) > 1)
+ // add a 0 qty lot row to be able to add a lot
+ print '';
+ // Qty to ship or shipped
+ print '' . ' ' . ' ';
+ // Batch number managment
+ print '' . $formproduct->selectLotStock('', 'batchl'.$line_id.'_0', '', 1, 0, $lines[$i]->fk_product). ' ';
+ print ' ';
+ }
+ elseif (! empty($conf->stock->enabled))
+ {
+ if ($lines[$i]->fk_product > 0)
{
- print '';
- foreach ($lines[$i]->details_entrepot as $detail_entrepot)
+ if ($lines[$i]->entrepot_id > 0)
{
+ print '';
print '';
// Qty to ship or shipped
- print '' . ' ' . ' ';
+ print '' . ' ' . ' ';
// Warehouse source
- print '' . $formproduct->selectWarehouses($detail_entrepot->entrepot_id, 'entl'.$detail_entrepot->line_id, '', 1, 0, $lines[$i]->fk_product, '', 1) . ' ';
+ print '' . $formproduct->selectWarehouses($lines[$i]->entrepot_id, 'entl'.$line_id, '', 1, 0, $lines[$i]->fk_product, '', 1). ' ';
// Batch number managment
print ' - ' . $langs->trans("NA") . ' ';
print ' ';
}
+ elseif (count($lines[$i]->details_entrepot) > 1)
+ {
+ print '';
+ foreach ($lines[$i]->details_entrepot as $detail_entrepot)
+ {
+ print '';
+ // Qty to ship or shipped
+ print '' . ' ' . ' ';
+ // Warehouse source
+ print '' . $formproduct->selectWarehouses($detail_entrepot->entrepot_id, 'entl'.$detail_entrepot->line_id, '', 1, 0, $lines[$i]->fk_product, '', 1) . ' ';
+ // Batch number managment
+ print ' - ' . $langs->trans("NA") . ' ';
+ print ' ';
+ }
+ }
+ else
+ {
+ print '';
+ print ''.$langs->trans("NotEnoughStock").' ';
+ }
}
else
{
- print '';
- print ''.$langs->trans("NotEnoughStock").' ';
+ print '';
+ print '';
+ // Qty to ship or shipped
+ print '' . ' ' . ' ';
+ // Warehouse source
+ print '' . ' ';
+ // Batch number managment
+ print '' . ' ';
+ print ' ';
}
}
- else
- {
- print '';
- print '';
- // Qty to ship or shipped
- print '' . ' ' . ' ';
- // Warehouse source
- print '' . ' ';
- // Batch number managment
- print '' . ' ';
- print ' ';
- }
- }
- print '
';
- }
- else
- {
- // Qty to ship or shipped
- print ''.$lines[$i]->qty_shipped.' ';
- // Warehouse source
- if (! empty($conf->stock->enabled))
- {
- print '';
- if ($lines[$i]->entrepot_id > 0)
- {
- $entrepot = new Entrepot($db);
- $entrepot->fetch($lines[$i]->entrepot_id);
- print $entrepot->getNomUrl(1);
- }
- elseif (count($lines[$i]->details_entrepot) > 1)
- {
- $detail = '';
- foreach ($lines[$i]->details_entrepot as $detail_entrepot)
- {
- if ($detail_entrepot->entrepot_id > 0)
- {
- $entrepot = new Entrepot($db);
- $entrepot->fetch($detail_entrepot->entrepot_id);
- $detail.= $langs->trans("DetailWarehouseFormat", $entrepot->libelle, $detail_entrepot->qty_shipped).' ';
- }
- }
- print $form->textwithtooltip(img_picto('', 'object_stock').' '.$langs->trans("DetailWarehouseNumber"), $detail);
- }
- print ' ';
- }
-
- // Batch number managment
- if (! empty($conf->productbatch->enabled))
- {
- if (isset($lines[$i]->detail_batch))
- {
- print '';
- print '';
- if ($lines[$i]->product_tobatch)
- {
- $detail = '';
- foreach ($lines[$i]->detail_batch as $dbatch) // $dbatch is instance of ExpeditionLineBatch
- {
- $detail.= $langs->trans("Batch").': '.$dbatch->batch;
- $detail.= ' - '.$langs->trans("SellByDate").': '.dol_print_date($dbatch->sellby, "day");
- $detail.= ' - '.$langs->trans("EatByDate").': '.dol_print_date($dbatch->eatby, "day");
- $detail.= ' - '.$langs->trans("Qty").': '.$dbatch->qty;
- $detail.= ' ';
- }
- print $form->textwithtooltip(img_picto('', 'object_barcode').' '.$langs->trans("DetailBatchNumber"), $detail);
- }
- else
- {
- print $langs->trans("NA");
- }
- print ' ';
- } else {
- print ' ';
- }
- }
- }
-
- // Weight
- print '';
- if ($lines[$i]->fk_product_type == Product::TYPE_PRODUCT) print $lines[$i]->weight*$lines[$i]->qty_shipped.' '.measuring_units_string($lines[$i]->weight_units, "weight");
- else print ' ';
- print ' ';
-
- // Volume
- print '';
- if ($lines[$i]->fk_product_type == Product::TYPE_PRODUCT) print $lines[$i]->volume*$lines[$i]->qty_shipped.' '.measuring_units_string($lines[$i]->volume_units, "volume");
- else print ' ';
- print ' ';
-
- // Size
- //print ''.$lines[$i]->volume*$lines[$i]->qty_shipped.' '.measuring_units_string($lines[$i]->volume_units,"volume").' ';
-
- if ($action == 'editline' && $lines[$i]->id == $line_id)
- {
- print '';
- print ' ';
- print ' ';
- }
- elseif ($object->statut == 0)
- {
- // edit-delete buttons
- print ' ';
- print 'id . '&action=editline&lineid=' . $lines[$i]->id . '">' . img_edit() . ' ';
- print ' ';
- print '';
- print 'id . '&action=deleteline&lineid=' . $lines[$i]->id . '">' . img_delete() . ' ';
- print ' ';
-
- // Display lines extrafields
- if (! empty($rowExtrafieldsStart))
- {
- print $rowExtrafieldsStart;
- print $rowExtrafieldsView;
- print $rowEnd;
- }
- }
- print "";
-
- // Display lines extrafields
- if (is_array($extralabelslines) && count($extralabelslines)>0) {
- $colspan= empty($conf->productbatch->enabled) ? 5 : 6;
- $line = new ExpeditionLigne($db);
- $line->fetch_optionals($lines[$i]->id);
- print '';
- if ($action == 'editline' && $lines[$i]->id == $line_id)
- {
- print $line->showOptionals($extrafieldsline, 'edit', array('style'=>$bc[$var], 'colspan'=>$colspan), $indiceAsked);
+ print '
';
}
else
{
- print $line->showOptionals($extrafieldsline, 'view', array('style'=>$bc[$var], 'colspan'=>$colspan), $indiceAsked);
+ // Qty to ship or shipped
+ print ''.$lines[$i]->qty_shipped.' ';
+
+ // Warehouse source
+ if (! empty($conf->stock->enabled))
+ {
+ print '';
+ if ($lines[$i]->entrepot_id > 0)
+ {
+ $entrepot = new Entrepot($db);
+ $entrepot->fetch($lines[$i]->entrepot_id);
+ print $entrepot->getNomUrl(1);
+ }
+ elseif (count($lines[$i]->details_entrepot) > 1)
+ {
+ $detail = '';
+ foreach ($lines[$i]->details_entrepot as $detail_entrepot)
+ {
+ if ($detail_entrepot->entrepot_id > 0)
+ {
+ $entrepot = new Entrepot($db);
+ $entrepot->fetch($detail_entrepot->entrepot_id);
+ $detail.= $langs->trans("DetailWarehouseFormat", $entrepot->libelle, $detail_entrepot->qty_shipped).' ';
+ }
+ }
+ print $form->textwithtooltip(img_picto('', 'object_stock').' '.$langs->trans("DetailWarehouseNumber"), $detail);
+ }
+ print ' ';
+ }
+
+ // Batch number managment
+ if (! empty($conf->productbatch->enabled))
+ {
+ if (isset($lines[$i]->detail_batch))
+ {
+ print '';
+ print '';
+ if ($lines[$i]->product_tobatch)
+ {
+ $detail = '';
+ foreach ($lines[$i]->detail_batch as $dbatch) // $dbatch is instance of ExpeditionLineBatch
+ {
+ $detail.= $langs->trans("Batch").': '.$dbatch->batch;
+ $detail.= ' - '.$langs->trans("SellByDate").': '.dol_print_date($dbatch->sellby, "day");
+ $detail.= ' - '.$langs->trans("EatByDate").': '.dol_print_date($dbatch->eatby, "day");
+ $detail.= ' - '.$langs->trans("Qty").': '.$dbatch->qty;
+ $detail.= ' ';
+ }
+ print $form->textwithtooltip(img_picto('', 'object_barcode').' '.$langs->trans("DetailBatchNumber"), $detail);
+ }
+ else
+ {
+ print $langs->trans("NA");
+ }
+ print ' ';
+ } else {
+ print ' ';
+ }
+ }
+ }
+
+ // Weight
+ print '';
+ if ($lines[$i]->fk_product_type == Product::TYPE_PRODUCT) print $lines[$i]->weight*$lines[$i]->qty_shipped.' '.measuring_units_string($lines[$i]->weight_units, "weight");
+ else print ' ';
+ print ' ';
+
+ // Volume
+ print '';
+ if ($lines[$i]->fk_product_type == Product::TYPE_PRODUCT) print $lines[$i]->volume*$lines[$i]->qty_shipped.' '.measuring_units_string($lines[$i]->volume_units, "volume");
+ else print ' ';
+ print ' ';
+
+ // Size
+ //print ''.$lines[$i]->volume*$lines[$i]->qty_shipped.' '.measuring_units_string($lines[$i]->volume_units, "volume").' ';
+
+ if ($action == 'editline' && $lines[$i]->id == $line_id)
+ {
+ print '';
+ print ' ';
+ print ' ';
+ }
+ elseif ($object->statut == 0)
+ {
+ // edit-delete buttons
+ print ' ';
+ print 'id . '&action=editline&lineid=' . $lines[$i]->id . '">' . img_edit() . ' ';
+ print ' ';
+ print '';
+ print 'id . '&action=deleteline&lineid=' . $lines[$i]->id . '">' . img_delete() . ' ';
+ print ' ';
+
+ // Display lines extrafields
+ if (! empty($rowExtrafieldsStart))
+ {
+ print $rowExtrafieldsStart;
+ print $rowExtrafieldsView;
+ print $rowEnd;
+ }
+ }
+ print " ";
+
+ // Display lines extrafields
+ if (is_array($extralabelslines) && count($extralabelslines)>0) {
+ $colspan= empty($conf->productbatch->enabled) ? 5 : 6;
+ $line = new ExpeditionLigne($db);
+ $line->fetch_optionals($lines[$i]->id);
+ print '';
+ if ($action == 'editline' && $lines[$i]->id == $line_id)
+ {
+ print $line->showOptionals($extrafieldsline, 'edit', array('style'=>$bc[$var], 'colspan'=>$colspan), $indiceAsked);
+ }
+ else
+ {
+ print $line->showOptionals($extrafieldsline, 'view', array('style'=>$bc[$var], 'colspan'=>$colspan), $indiceAsked);
+ }
+ print ' ';
}
- print '';
}
}
diff --git a/htdocs/expedition/contact.php b/htdocs/expedition/contact.php
index 202808d5d58..4acb2fce932 100644
--- a/htdocs/expedition/contact.php
+++ b/htdocs/expedition/contact.php
@@ -123,7 +123,7 @@ elseif ($action == 'deletecontact' && $user->rights->expedition->creer)
}
}
/*
-else if ($action == 'setaddress' && $user->rights->expedition->creer)
+elseif ($action == 'setaddress' && $user->rights->expedition->creer)
{
$object->fetch($id);
$result=$object->setDeliveryAddress($_POST['fk_address']);
diff --git a/htdocs/expedition/shipment.php b/htdocs/expedition/shipment.php
index 50c67354dde..d9b2537e4ba 100644
--- a/htdocs/expedition/shipment.php
+++ b/htdocs/expedition/shipment.php
@@ -44,9 +44,12 @@ if (! empty($conf->product->enabled) || ! empty($conf->service->enabled)) requi
// Load translation files required by the page
$langs->loadLangs(array('orders',"companies","bills",'propal','deliveries','stocks',"productbatch",'incoterm'));
-$id=GETPOST('id', 'int'); // id of order
-$ref= GETPOST('ref', 'alpha');
-$action=GETPOST('action', 'alpha');
+$id = GETPOST('id', 'int'); // id of order
+$ref = GETPOST('ref', 'alpha');
+$action = GETPOST('action', 'alpha');
+
+$hookmanager->initHooks(array('ordershipmentcard'));
+
// Security check
$socid=0;
@@ -612,6 +615,7 @@ if ($id > 0 || ! empty($ref))
$sql.= " cd.qty,";
$sql.= ' cd.date_start,';
$sql.= ' cd.date_end,';
+ $sql.= ' cd.special_code,';
$sql.= ' p.rowid as prodid, p.label as product_label, p.entity, p.ref, p.fk_product_type as product_type, p.description as product_desc';
$sql.= " FROM ".MAIN_DB_PREFIX."commandedet as cd";
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON cd.fk_product = p.rowid";
@@ -647,164 +651,169 @@ if ($id > 0 || ! empty($ref))
{
$objp = $db->fetch_object($resql);
+ $parameters = array('i' => $i, 'line' => $objp, 'num' => $num);
+ $reshook = $hookmanager->executeHooks('printObjectLine', $parameters, $object, $action);
+ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
- // Show product and description
- $type=isset($objp->type)?$objp->type:$objp->product_type;
-
- // Try to enhance type detection using date_start and date_end for free lines where type
- // was not saved.
- if (! empty($objp->date_start)) $type=1;
- if (! empty($objp->date_end)) $type=1;
-
- print '';
-
- // Product label
- if ($objp->fk_product > 0)
+ if (empty($reshook))
{
- // Define output language
- if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE))
+ // Show product and description
+ $type=isset($objp->type)?$objp->type:$objp->product_type;
+
+ // Try to enhance type detection using date_start and date_end for free lines where type
+ // was not saved.
+ if (! empty($objp->date_start)) $type=1;
+ if (! empty($objp->date_end)) $type=1;
+
+ print ' ';
+
+ // Product label
+ if ($objp->fk_product > 0)
{
- $object->fetch_thirdparty();
-
- $prod = new Product($db);
- $prod->id = $objp->fk_product;
- $prod->entity = $objp->entity;
- $prod->getMultiLangs();
-
- $outputlangs = $langs;
- $newlang='';
- if (empty($newlang) && ! empty($_REQUEST['lang_id'])) $newlang=$_REQUEST['lang_id'];
- if (empty($newlang)) $newlang=$object->thirdparty->default_lang;
- if (! empty($newlang))
+ // Define output language
+ if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE))
{
- $outputlangs = new Translate("", $conf);
- $outputlangs->setDefaultLang($newlang);
+ $object->fetch_thirdparty();
+
+ $prod = new Product($db);
+ $prod->id = $objp->fk_product;
+ $prod->entity = $objp->entity;
+ $prod->getMultiLangs();
+
+ $outputlangs = $langs;
+ $newlang='';
+ if (empty($newlang) && ! empty($_REQUEST['lang_id'])) $newlang=$_REQUEST['lang_id'];
+ if (empty($newlang)) $newlang=$object->thirdparty->default_lang;
+ if (! empty($newlang))
+ {
+ $outputlangs = new Translate("", $conf);
+ $outputlangs->setDefaultLang($newlang);
+ }
+
+ $label = (! empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $objp->product_label;
+ }
+ else
+ $label = (! empty($objp->label)?$objp->label:$objp->product_label);
+
+ print '';
+ print ' '; // ancre pour retourner sur la ligne
+
+ // Show product and description
+ $product_static->type=$type;
+ $product_static->id=$objp->fk_product;
+ $product_static->ref=$objp->ref;
+ $product_static->entity = $objp->entity;
+ $text=$product_static->getNomUrl(1);
+ $text.= ' - '.$label;
+ $description=($conf->global->PRODUIT_DESC_IN_FORM?'':dol_htmlentitiesbr($objp->description)).' ';
+ $description.= $product_static->show_photos('product', $conf->product->multidir_output[$product_static->entity], 1, 1, 0, 0, 0, 80);
+ print $form->textwithtooltip($text, $description, 3, '', '', $i);
+
+ // Show range
+ print_date_range($db->jdate($objp->date_start), $db->jdate($objp->date_end));
+
+ // Add description in form
+ if (! empty($conf->global->PRODUIT_DESC_IN_FORM))
+ {
+ print ($objp->description && $objp->description!=$objp->product_label)?' '.dol_htmlentitiesbr($objp->description):'';
}
- $label = (! empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $objp->product_label;
+ print ' ';
}
else
- $label = (! empty($objp->label)?$objp->label:$objp->product_label);
-
- print '';
- print ' '; // ancre pour retourner sur la ligne
-
- // Show product and description
- $product_static->type=$type;
- $product_static->id=$objp->fk_product;
- $product_static->ref=$objp->ref;
- $product_static->entity = $objp->entity;
- $text=$product_static->getNomUrl(1);
- $text.= ' - '.$label;
- $description=($conf->global->PRODUIT_DESC_IN_FORM?'':dol_htmlentitiesbr($objp->description)).' ';
- $description.= $product_static->show_photos('product', $conf->product->multidir_output[$product_static->entity], 1, 1, 0, 0, 0, 80);
- print $form->textwithtooltip($text, $description, 3, '', '', $i);
-
- // Show range
- print_date_range($db->jdate($objp->date_start), $db->jdate($objp->date_end));
-
- // Add description in form
- if (! empty($conf->global->PRODUIT_DESC_IN_FORM))
{
- print ($objp->description && $objp->description!=$objp->product_label)?' '.dol_htmlentitiesbr($objp->description):'';
+ print " ";
+ if ($type==1) $text = img_object($langs->trans('Service'), 'service');
+ else $text = img_object($langs->trans('Product'), 'product');
+
+ if (! empty($objp->label)) {
+ $text.= ' '.$objp->label.' ';
+ print $form->textwithtooltip($text, $objp->description, 3, '', '', $i);
+ } else {
+ print $text.' '.nl2br($objp->description);
+ }
+
+ // Show range
+ print_date_range($db->jdate($objp->date_start), $db->jdate($objp->date_end));
+ print " \n";
}
- print '';
- }
- else
- {
- print "";
- if ($type==1) $text = img_object($langs->trans('Service'), 'service');
- else $text = img_object($langs->trans('Product'), 'product');
+ // Qty ordered
+ print ' ' . $objp->qty . ' ';
- if (! empty($objp->label)) {
- $text.= ' '.$objp->label.' ';
- print $form->textwithtooltip($text, $objp->description, 3, '', '', $i);
- } else {
- print $text.' '.nl2br($objp->description);
- }
-
- // Show range
- print_date_range($db->jdate($objp->date_start), $db->jdate($objp->date_end));
- print "\n";
- }
-
- // Qty ordered
- print '' . $objp->qty . ' ';
-
- // Qty already shipped
- $qtyProdCom=$objp->qty;
- print '';
- // Nb of sending products for this line of order
- $qtyAlreadyShipped = (! empty($object->expeditions[$objp->rowid])?$object->expeditions[$objp->rowid]:0);
- print $qtyAlreadyShipped;
- print ' ';
-
- // Qty remains to ship
- print '';
- if ($type == 0 || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
- {
- $toBeShipped[$objp->fk_product] = $objp->qty - $qtyAlreadyShipped;
- $toBeShippedTotal += $toBeShipped[$objp->fk_product];
- print $toBeShipped[$objp->fk_product];
- }
- else
- {
- print '0 ('.$langs->trans("Service").')';
- }
- print ' ';
-
- if ($objp->fk_product > 0)
- {
- $product = new Product($db);
- $product->fetch($objp->fk_product);
- $product->load_stock('warehouseopen');
- }
-
- if ($objp->fk_product > 0 && ($type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES)) && ! empty($conf->stock->enabled))
- {
+ // Qty already shipped
+ $qtyProdCom=$objp->qty;
print '';
- print $product->stock_reel;
- if ($product->stock_reel < $toBeShipped[$objp->fk_product])
+ // Nb of sending products for this line of order
+ $qtyAlreadyShipped = (! empty($object->expeditions[$objp->rowid])?$object->expeditions[$objp->rowid]:0);
+ print $qtyAlreadyShipped;
+ print ' ';
+
+ // Qty remains to ship
+ print '';
+ if ($type == 0 || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
{
- print ' '.img_warning($langs->trans("StockTooLow"));
+ $toBeShipped[$objp->fk_product] = $objp->qty - $qtyAlreadyShipped;
+ $toBeShippedTotal += $toBeShipped[$objp->fk_product];
+ print $toBeShipped[$objp->fk_product];
+ }
+ else
+ {
+ print '0 ('.$langs->trans("Service").')';
}
print ' ';
- }
- else
- {
- print ' ';
- }
- print " \n";
- // Show subproducts lines
- if ($objp->fk_product > 0 && ! empty($conf->global->PRODUIT_SOUSPRODUITS))
- {
- // Set tree of subproducts in product->sousprods
- $product->get_sousproduits_arbo();
- //var_dump($product->sousprods);exit;
-
- // Define a new tree with quantiies recalculated
- $prods_arbo = $product->get_arbo_each_prod($qtyProdCom);
- //var_dump($prods_arbo);
- if (count($prods_arbo) > 0)
+ if ($objp->fk_product > 0)
{
- foreach($prods_arbo as $key => $value)
+ $product = new Product($db);
+ $product->fetch($objp->fk_product);
+ $product->load_stock('warehouseopen');
+ }
+
+ if ($objp->fk_product > 0 && ($type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES)) && ! empty($conf->stock->enabled))
+ {
+ print '';
+ print $product->stock_reel;
+ if ($product->stock_reel < $toBeShipped[$objp->fk_product])
{
- $img='';
- if ($value['stock'] < $value['stock_alert'])
+ print ' '.img_warning($langs->trans("StockTooLow"));
+ }
+ print ' ';
+ }
+ else
+ {
+ print ' ';
+ }
+ print "\n";
+
+ // Show subproducts lines
+ if ($objp->fk_product > 0 && ! empty($conf->global->PRODUIT_SOUSPRODUITS))
+ {
+ // Set tree of subproducts in product->sousprods
+ $product->get_sousproduits_arbo();
+ //var_dump($product->sousprods);exit;
+
+ // Define a new tree with quantiies recalculated
+ $prods_arbo = $product->get_arbo_each_prod($qtyProdCom);
+ //var_dump($prods_arbo);
+ if (count($prods_arbo) > 0)
+ {
+ foreach($prods_arbo as $key => $value)
{
- $img=img_warning($langs->trans("StockTooLow"));
+ $img='';
+ if ($value['stock'] < $value['stock_alert'])
+ {
+ $img=img_warning($langs->trans("StockTooLow"));
+ }
+ print ' -> '.$value['fullpath'].' ('.$value['nb'].') ';
+ print ' '.$value['nb_total'].' ';
+ print '  ';
+ print '  ';
+ print ''.$value['stock'].' '.$img.' '."\n";
}
- print ' -> '.$value['fullpath'].' ('.$value['nb'].') ';
- print ' '.$value['nb_total'].' ';
- print '  ';
- print '  ';
- print ''.$value['stock'].' '.$img.' '."\n";
}
}
}
-
$i++;
}
$db->free($resql);
diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php
index c6d87acef4d..c39b67a8680 100644
--- a/htdocs/expensereport/card.php
+++ b/htdocs/expensereport/card.php
@@ -66,7 +66,7 @@ $socid = GETPOST('socid', 'int')?GETPOST('socid', 'int'):GETPOST('socid_id', 'in
// Security check
$id=GETPOST("id", 'int');
if ($user->societe_id) $socid=$user->societe_id;
-$result = restrictedArea($user, 'expensereport', 0, 'expensereport');
+$result = restrictedArea($user, 'expensereport', $id, 'expensereport');
// Hack to use expensereport dir
@@ -1892,9 +1892,9 @@ else
print '' . $langs->trans('Date') . ' ';
print '' . $langs->trans('Type') . ' ';
if (! empty($conf->banque->enabled)) {
- print '' . $langs->trans('BankAccount') . ' ';
+ print '' . $langs->trans('BankAccount') . ' ';
}
- print '' . $langs->trans('Amount') . ' ';
+ print '' . $langs->trans('Amount') . ' ';
print ' ';
print '';
@@ -1948,12 +1948,12 @@ else
$bankaccountstatic->accountancy_journal = $accountingjournal->getNomUrl(0, 1, 1, '', 1);
}
- print '';
+ print ' ';
if ($bankaccountstatic->id)
print $bankaccountstatic->getNomUrl(1, 'transactions');
print ' ';
}
- print ''.price($objp->amount)." ";
+ print ''.price($objp->amount)." ";
print ' ';
print "";
$totalpaid += $objp->amount;
@@ -1975,10 +1975,10 @@ else
{
$cssforamountpaymentcomplete = 'amountpaymentneutral';
}
- print ''.$langs->trans("AlreadyPaid").': '.price($totalpaid).' ';
- print ''.$langs->trans("AmountExpected").': '.price($object->total_ttc).' ';
+ print ''.$langs->trans("AlreadyPaid").': '.price($totalpaid).' ';
+ print ''.$langs->trans("AmountExpected").': '.price($object->total_ttc).' ';
- print ''.$langs->trans("RemainderToPay").': ';
+ print ''.$langs->trans("RemainderToPay").': ';
print ''.price($resteapayeraffiche).' ';
$db->free($resql);
@@ -2014,26 +2014,26 @@ else
$i = 0;$total = 0;
print '';
- print ''.$langs->trans('LineNb').' ';
- //print ''.$langs->trans('Piece').' ';
- print ''.$langs->trans('Date').' ';
+ print ''.$langs->trans('LineNb').' ';
+ //print ''.$langs->trans('Piece').' ';
+ print ''.$langs->trans('Date').' ';
if (! empty($conf->projet->enabled)) print ''.$langs->trans('Project').' ';
if (!empty($conf->global->MAIN_USE_EXPENSE_IK)) print ''.$langs->trans('CarCategory').' ';
- print ''.$langs->trans('Type').' ';
- print ''.$langs->trans('Description').' ';
- print ''.$langs->trans('VAT').' ';
- print ''.$langs->trans('PriceUHT').' ';
- print ''.$langs->trans('PriceUTTC').' ';
- print ''.$langs->trans('Qty').' ';
+ print ''.$langs->trans('Type').' ';
+ print ''.$langs->trans('Description').' ';
+ print ''.$langs->trans('VAT').' ';
+ print ''.$langs->trans('PriceUHT').' ';
+ print ''.$langs->trans('PriceUTTC').' ';
+ print ''.$langs->trans('Qty').' ';
if ($action != 'editline')
{
- print ''.$langs->trans('AmountHT').' ';
- print ''.$langs->trans('AmountTTC').' ';
+ print ''.$langs->trans('AmountHT').' ';
+ print ''.$langs->trans('AmountTTC').' ';
}
// Ajout des boutons de modification/suppression
if (($object->fk_statut < 2 || $object->fk_statut == 99) && $user->rights->expensereport->creer)
{
- print ' ';
+ print ' ';
}
print ' ';
@@ -2045,22 +2045,22 @@ else
{
print '';
- print '';
+ print ' ';
print $numline;
print ' ';
- /*print '';
+ /*print ' ';
print img_picto($langs->trans("Document"), "object_generic");
print ' '.$piece_comptable.' ';
print ' ';*/
- print ''.dol_print_date($db->jdate($line->date), 'day').' ';
+ print ''.dol_print_date($db->jdate($line->date), 'day').' ';
if (! empty($conf->projet->enabled))
{
print '';
- if ($line->fk_projet > 0)
+ if ($line->fk_project > 0)
{
- $projecttmp->id=$line->fk_projet;
+ $projecttmp->id=$line->fk_project;
$projecttmp->ref=$line->projet_ref;
print $projecttmp->getNomUrl(1);
}
@@ -2076,10 +2076,10 @@ else
$labeltype = ($langs->trans(($line->type_fees_code)) == $line->type_fees_code ? $line->type_fees_libelle : $langs->trans($line->type_fees_code));
print $labeltype;
print ' ';
- print ''.dol_escape_htmltag($line->comments).' ';
- print ''.vatrate($line->vatrate, true).' ';
+ print ''.dol_nl2br($line->comments).' ';
+ print ''.vatrate($line->vatrate, true).' ';
// Unit price HT
- print '';
+ print ' ';
if (! empty($line->value_unit_ht))
{
print price($line->value_unit_ht);
@@ -2092,20 +2092,20 @@ else
}
print ' ';
- print ''.price($line->value_unit).' ';
+ print ''.price($line->value_unit).' ';
- print ''.dol_escape_htmltag($line->qty).' ';
+ print ''.dol_escape_htmltag($line->qty).' ';
if ($action != 'editline')
{
- print ''.price($line->total_ht).' ';
- print ''.price($line->total_ttc).' ';
+ print ''.price($line->total_ht).' ';
+ print ''.price($line->total_ttc).' ';
}
// Ajout des boutons de modification/suppression
if (($object->fk_statut < ExpenseReport::STATUS_VALIDATED || $object->fk_statut == ExpenseReport::STATUS_REFUSED) && $user->rights->expensereport->creer)
{
- print '';
+ print ' ';
print 'id.'&action=editline&rowid='.$line->rowid.'#'.$line->rowid.'">';
print img_edit();
@@ -2135,7 +2135,7 @@ else
if (! empty($conf->projet->enabled))
{
print ' ';
- $formproject->select_projects(-1, $line->fk_projet, 'fk_projet', 0, 0, 1, 1, 0, 0, 0, '', 0, 0, 'maxwidth300');
+ $formproject->select_projects(-1, $line->fk_project, 'fk_projet', 0, 0, 1, 1, 0, 0, 0, '', 0, 0, 'maxwidth300');
print ' ';
}
@@ -2154,36 +2154,36 @@ else
// Add comments
print '';
- print ''.dol_escape_htmltag($line->comments).' ';
+ print ''.dol_escape_htmltag($line->comments, 0, 1).' ';
print ' ';
// VAT
- print '';
+ print ' ';
print $form->load_tva('vatrate', (isset($_POST["vatrate"])?$_POST["vatrate"]:$line->vatrate), $mysoc, '', 0, 0, '', false, 1);
print ' ';
// Unit price
- print '';
+ print ' ';
print ' ';
print ' ';
// Unit price with tax
- print '';
+ print ' ';
print ' ';
print ' ';
// Quantity
- print '';
+ print ' ';
print ' ';
print ' ';
if ($action != 'editline')
{
- print ''.$langs->trans('AmountHT').' ';
- print ''.$langs->trans('AmountTTC').' ';
+ print ''.$langs->trans('AmountHT').' ';
+ print ''.$langs->trans('AmountTTC').' ';
}
- print '';
+ print ' ';
print ' ';
print ' ';
print ' ';
@@ -2202,12 +2202,54 @@ else
if (! empty($conf->projet->enabled)) $colspan++;
if ($action != 'editline') $colspan++;
+ $nbFiles = $nbLinks = 0;
+ $arrayoffiles = array();
+ if ($conf->global->MAIN_FEATURES_LEVEL >= 2)
+ {
+ require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
+ require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
+ require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
+ $upload_dir = $conf->expensereport->dir_output . "/" . dol_sanitizeFileName($object->ref);
+ $arrayoffiles=dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png|'.preg_quote(dol_sanitizeFileName($object->ref.'.pdf'), '/').')$');
+ $nbFiles = count($arrayoffiles);
+ $nbLinks=Link::count($db, $object->element, $object->id);
+ }
+
+ // Add line with link to add new file or attach to an existing file
print ' ';
print '';
- print $langs->trans("UploadANewFileNow");
+ print ''.$langs->trans("UploadANewFileNow");
+ print img_picto($langs->trans("UploadANewFileNow"), 'chevron-down', '', false, 0, 0, '', 'marginleftonly');
+ print ' ';
+ if ($conf->global->MAIN_FEATURES_LEVEL >= 2)
+ {
+ print ' - '.''.$langs->trans("AttachTheNewLineToTheDocument");
+ print img_picto($langs->trans("AttachTheNewLineToTheDocument"), 'chevron-down', '', false, 0, 0, '', 'marginleftonly');
+ print ' ';
+ }
+
+ print ''."\n";
print ' ';
- print '';
+ // Add line to upload new file
+ print ' global->MAIN_OPTIMIZEFORTEXTBROWSER)?' style="display: none"':'').'>';
print '';
$modulepart = 'expensereport';
@@ -2251,17 +2293,76 @@ else
print ' ';
+ // Add line to select existing file
+ if ($conf->global->MAIN_FEATURES_LEVEL >= 2)
+ {
+ require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
+ require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
+ require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
+ $upload_dir = $conf->expensereport->dir_output . "/" . dol_sanitizeFileName($object->ref);
+ $arrayoffiles=dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png|'.preg_quote(dol_sanitizeFileName($object->ref.'.pdf'), '/').')$');
+ $nbFiles = count($arrayoffiles);
+ $nbLinks=Link::count($db, $object->element, $object->id);
+ if ($nbFiles >= 0)
+ {
+ print 'global->MAIN_OPTIMIZEFORTEXTBROWSER)?' style="display: none"':'').'>';
+ print '';
+ //print ''.$langs->trans("AttachTheNewLineToTheDocument").' ';
+ $modulepart='expensereport';$maxheightmini=48;
+ $relativepath=(! empty($object->ref)?dol_sanitizeFileName($object->ref):'').'/';
+ foreach($arrayoffiles as $file)
+ {
+ print '';
+ $fileinfo = pathinfo($file['name']);
+ if (image_format_supported($file['name']) > 0)
+ {
+ $minifile=getImageFileNameForSize($file['name'], '_mini'); // For new thumbs using same ext (in lower case howerver) than original
+ //if (! dol_is_file($file['path'].'/'.$minifile)) $minifile=getImageFileNameForSize($file['name'], '_mini', '.png'); // For backward compatibility of old thumbs that were created with filename in lower case and with .png extension
+ //print $file['path'].'/'.$minifile.'
';
+ $urlforhref=getAdvancedPreviewUrl($modulepart, $fileinfo['relativename'].'.'.strtolower($fileinfo['extension']), 1, '&entity='.(!empty($object->entity)?$object->entity:$conf->entity));
+ if (empty($urlforhref)) {
+ $urlforhref=DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.(!empty($object->entity)?$object->entity:$conf->entity).'&file='.urlencode($fileinfo['relativename'].'.'.strtolower($fileinfo['extension']));
+ print '
';
+ } else {
+ print ' ';
+ }
+ print ' ';
+ print ' ';
+ }
+ else print ' ';
+ print '
';
+ $checked='';
+ //var_dump(GETPOST($file['relativename'])); var_dump($file['relativename']); var_dump($_FILES['userfile']['name']);
+ foreach($_FILES['userfile']['name'] as $tmpfile)
+ {
+ if ($file['relativename'] == (GETPOST('savingdocmask', 'alpha') ? dol_sanitizeFileName($object->ref.'-') : '').$tmpfile)
+ {
+ $checked=' checked';
+ break;
+ }
+ elseif ($file['relativename'] && in_array($file['relativename'], GETPOST('attachfile', 'array'))) {
+ $checked=' checked';
+ break;
+ }
+ }
+ print '
'.$file['relativename'];
+ print '
';
+ }
+ print ' ';
+ }
+ }
+
print '';
print ' ';
- print ''.$langs->trans('Date').' ';
+ print ''.$langs->trans('Date').' ';
if (! empty($conf->projet->enabled)) print ''.$langs->trans('Project').' ';
if (!empty($conf->global->MAIN_USE_EXPENSE_IK)) print ''.$langs->trans('CarCategory').' ';
- print ''.$langs->trans('Type').' ';
+ print ''.$langs->trans('Type').' ';
print ''.$langs->trans('Description').' ';
- print ''.$langs->trans('VAT').' ';
- print ''.$langs->trans('PriceUHT').' ';
- print ''.$langs->trans('PriceUTTC').' ';
- print ''.$langs->trans('Qty').' ';
+ print ''.$langs->trans('VAT').' ';
+ print ''.$langs->trans('PriceUHT').' ';
+ print ''.$langs->trans('PriceUTTC').' ';
+ print ''.$langs->trans('Qty').' ';
print ' ';
print ' ';
@@ -2271,7 +2372,7 @@ else
print ' ';
// Select date
- print '';
+ print ' ';
print $form->selectDate($date?$date:-1, 'date', 0, 0, 0, '', 1, 1);
print ' ';
@@ -2292,56 +2393,46 @@ else
}
// Select type
- print '';
+ print ' ';
select_type_fees_id($fk_c_type_fees, 'fk_c_type_fees', 1);
print ' ';
// Add comments
print '';
- print ''.dol_escape_htmltag($comments).' ';
+ print ''.dol_escape_htmltag($comments, 0, 1).' ';
print ' ';
// Select VAT
- print '';
+ print ' ';
$defaultvat=-1;
if (! empty($conf->global->EXPENSEREPORT_NO_DEFAULT_VAT)) $conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS = 'none';
print $form->load_tva('vatrate', ($vatrate!=''?$vatrate:$defaultvat), $mysoc, '', 0, 0, '', false, 1);
print ' ';
// Unit price net
- print '';
+ print ' ';
print ' ';
print ' ';
// Unit price with tax
- print '';
+ print ' ';
print ' ';
print ' ';
// Quantity
- print '';
+ print ' ';
print ' '; // We must be able to enter decimal qty
print ' ';
if ($action != 'editline')
{
- print ' ';
- print ' ';
+ print ' ';
+ print ' ';
}
- print ' ';
+ print ' ';
print '';
-
- if ($conf->global->MAIN_FEATURES_LEVEL >= 2)
- {
- print '';
- print $langs->trans("AttachTheNewLineToTheDocument");
-
- print '...';
-
- print ' ';
- }
} // Fin si c'est payé/validé
print '';
diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php
index 48902b45ca8..0bc5c533f9e 100644
--- a/htdocs/expensereport/class/expensereport.class.php
+++ b/htdocs/expensereport/class/expensereport.class.php
@@ -856,12 +856,12 @@ class ExpenseReport extends CommonObject
print '';
print ''.$objp->ref_num.' ';
- print ''.dol_print_date($objp->date, 'day').' ';
+ print ''.dol_print_date($objp->date, 'day').' ';
print ''.$author->getNomUrl(1).' ';
print ''.$objp->comments.' ';
- print ''.price($objp->total_ht).' ';
- print ''.price($objp->total_ttc).' ';
- print '';
+ print ' '.price($objp->total_ht).' ';
+ print ''.price($objp->total_ttc).' ';
+ print '';
switch($objp->fk_c_expensereport_status) {
case 4:
@@ -895,8 +895,8 @@ class ExpenseReport extends CommonObject
}
print ' '.$langs->trans("Number").': '.$i.' ';
- print ''.$langs->trans("TotalHT").' : '.price($total_HT).' ';
- print ''.$langs->trans("TotalTTC").' : '.price($total_TTC).' ';
+ print ''.$langs->trans("TotalHT").' : '.price($total_HT).' ';
+ print ''.$langs->trans("TotalTTC").' : '.price($total_TTC).' ';
print ' ';
print ' ';
}
@@ -971,7 +971,7 @@ class ExpenseReport extends CommonObject
$this->lines=array();
$sql = ' SELECT de.rowid, de.comments, de.qty, de.value_unit, de.date, de.rang,';
- $sql.= ' de.'.$this->fk_element.', de.fk_c_type_fees, de.fk_c_exp_tax_cat, de.fk_projet, de.tva_tx,';
+ $sql.= ' de.'.$this->fk_element.', de.fk_c_type_fees, de.fk_c_exp_tax_cat, de.fk_projet as fk_project, de.tva_tx,';
$sql.= ' de.total_ht, de.total_tva, de.total_ttc,';
$sql.= ' ctf.code as code_type_fees, ctf.label as libelle_type_fees,';
$sql.= ' p.ref as ref_projet, p.title as title_projet';
@@ -1010,7 +1010,8 @@ class ExpenseReport extends CommonObject
$deplig->fk_expensereport = $objp->fk_expensereport;
$deplig->fk_c_type_fees = $objp->fk_c_type_fees;
$deplig->fk_c_exp_tax_cat = $objp->fk_c_exp_tax_cat;
- $deplig->fk_projet = $objp->fk_projet;
+ $deplig->fk_projet = $objp->fk_project;
+ $deplig->fk_project = $objp->fk_project;
$deplig->total_ht = $objp->total_ht;
$deplig->total_tva = $objp->total_tva;
@@ -1994,7 +1995,8 @@ class ExpenseReport extends CommonObject
$this->line->fk_expensereport= $expensereport_id;
$this->line->fk_c_type_fees = $type_fees_id;
$this->line->fk_c_exp_tax_cat = $fk_c_exp_tax_cat;
- $this->line->fk_projet = $projet_id;
+ $this->line->fk_projet = $projet_id; // deprecated
+ $this->line->fk_project = $projet_id;
$this->line->vat_src_code = $vat_src_code;
$this->line->vatrate = price2num($vatrate);
@@ -2513,7 +2515,7 @@ class ExpenseReportLine
*/
public function fetch($rowid)
{
- $sql = 'SELECT fde.rowid, fde.fk_expensereport, fde.fk_c_type_fees, fde.fk_c_exp_tax_cat, fde.fk_projet, fde.date,';
+ $sql = 'SELECT fde.rowid, fde.fk_expensereport, fde.fk_c_type_fees, fde.fk_c_exp_tax_cat, fde.fk_projet as fk_project, fde.date,';
$sql.= ' fde.tva_tx as vatrate, fde.vat_src_code, fde.comments, fde.qty, fde.value_unit, fde.total_ht, fde.total_tva, fde.total_ttc,';
$sql.= ' ctf.code as type_fees_code, ctf.label as type_fees_libelle,';
$sql.= ' pjt.rowid as projet_id, pjt.title as projet_title, pjt.ref as projet_ref';
@@ -2539,7 +2541,8 @@ class ExpenseReportLine
$this->value_unit = $objp->value_unit;
$this->fk_c_type_fees = $objp->fk_c_type_fees;
$this->fk_c_exp_tax_cat = $objp->fk_c_exp_tax_cat;
- $this->fk_projet = $objp->fk_projet;
+ $this->fk_projet = $objp->fk_project; // deprecated
+ $this->fk_project = $objp->fk_project;
$this->type_fees_code = $objp->type_fees_code;
$this->type_fees_libelle = $objp->type_fees_libelle;
$this->projet_ref = $objp->projet_ref;
@@ -2585,7 +2588,7 @@ class ExpenseReportLine
$sql.= ' tva_tx, vat_src_code, comments, qty, value_unit, total_ht, total_tva, total_ttc, date, rule_warning_message, fk_c_exp_tax_cat)';
$sql.= " VALUES (".$this->db->escape($this->fk_expensereport).",";
$sql.= " ".$this->db->escape($this->fk_c_type_fees).",";
- $sql.= " ".$this->db->escape($this->fk_projet>0?$this->fk_projet:'null').",";
+ $sql.= " ".$this->db->escape($this->fk_project>0?$this->fk_project:($this->fk_projet>0?$this->fk_projet:'null')).",";
$sql.= " ".$this->db->escape($this->vatrate).",";
$sql.= " '".$this->db->escape($this->vat_src_code)."',";
$sql.= " '".$this->db->escape($this->comments)."',";
@@ -2713,7 +2716,7 @@ class ExpenseReportLine
$sql.= ",fk_c_exp_tax_cat=".$this->db->escape($this->fk_c_exp_tax_cat);
if ($this->fk_c_type_fees) $sql.= ",fk_c_type_fees=".$this->db->escape($this->fk_c_type_fees);
else $sql.= ",fk_c_type_fees=null";
- if ($this->fk_projet) $sql.= ",fk_projet=".$this->db->escape($this->fk_projet);
+ if ($this->fk_project > 0) $sql.= ",fk_projet=".$this->db->escape($this->fk_project);
else $sql.= ",fk_projet=null";
$sql.= " WHERE rowid = ".$this->db->escape($this->rowid);
diff --git a/htdocs/expensereport/index.php b/htdocs/expensereport/index.php
index bfe5bc59126..f7d4e2a8405 100644
--- a/htdocs/expensereport/index.php
+++ b/htdocs/expensereport/index.php
@@ -122,7 +122,7 @@ foreach ($listoftype as $code => $label)
if ($conf->use_javascript_ajax)
{
- print '';
+ print ' ';
include_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php';
$dolgraph = new DolGraph();
@@ -139,7 +139,7 @@ if ($conf->use_javascript_ajax)
print ' ';
print ''.$langs->trans("Total").' ';
-print ''.price($totalsum, 1, $langs, 0, 0, 0, $conf->currency).' ';
+print ''.price($totalsum, 1, $langs, 0, 0, 0, $conf->currency).' ';
print ' ';
print '';
@@ -183,9 +183,9 @@ if ($result)
print '';
print '';
print ''.$langs->trans("BoxTitleLastModifiedExpenses", min($max, $num)).' ';
- print ''.$langs->trans("AmountHT").' ';
- print ''.$langs->trans("AmountTTC").' ';
- print ''.$langs->trans("DateModificationShort").' ';
+ print ''.$langs->trans("AmountHT").' ';
+ print ''.$langs->trans("AmountTTC").' ';
+ print ''.$langs->trans("DateModificationShort").' ';
print ' ';
print ' ';
if ($num)
@@ -208,10 +208,10 @@ if ($result)
print '';
print ''.$expensereportstatic->getNomUrl(1).' ';
print ''.$userstatic->getNomUrl(-1).' ';
- print ''.price($obj->total_ht).' ';
- print ''.price($obj->total_ttc).' ';
- print ''.dol_print_date($db->jdate($obj->dm), 'day').' ';
- print '';
+ print ' '.price($obj->total_ht).' ';
+ print ''.price($obj->total_ttc).' ';
+ print ''.dol_print_date($db->jdate($obj->dm), 'day').' ';
+ print '';
//print $obj->libelle;
print $expensereportstatic->LibStatut($obj->fk_status, 3);
print ' ';
diff --git a/htdocs/expensereport/list.php b/htdocs/expensereport/list.php
index c59b6d70e0f..c221baf7d65 100644
--- a/htdocs/expensereport/list.php
+++ b/htdocs/expensereport/list.php
@@ -556,16 +556,16 @@ if ($resql)
// Amount with no tax
if (! empty($arrayfields['d.total_ht']['checked']))
{
- print ' ';
+ print ' ';
}
if (! empty($arrayfields['d.total_vat']['checked']))
{
- print ' ';
+ print ' ';
}
// Amount with all taxes
if (! empty($arrayfields['d.total_ttc']['checked']))
{
- print ' ';
+ print ' ';
}
// Extra fields
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
@@ -589,12 +589,12 @@ if ($resql)
// Status
if (! empty($arrayfields['d.fk_statut']['checked']))
{
- print '';
+ print ' ';
select_expensereport_statut($search_status, 'search_status', 1, 1);
print ' ';
}
// Action column
- print '';
+ print ' ';
$searchpicto=$form->showFilterButtons();
print $searchpicto;
print ' ';
@@ -670,7 +670,7 @@ if ($resql)
print '';
}
print '';
- print '';
+ print ' ';
$filename=dol_sanitizeFileName($obj->ref);
$filedir=$conf->expensereport->dir_output . '/' . dol_sanitizeFileName($obj->ref);
$urlsource=$_SERVER['PHP_SELF'].'?id='.$obj->rowid;
@@ -696,28 +696,28 @@ if ($resql)
}
// Start date
if (! empty($arrayfields['d.date_debut']['checked'])) {
- print ' '.($obj->date_debut > 0 ? dol_print_date($db->jdate($obj->date_debut), 'day') : '').' ';
+ print ''.($obj->date_debut > 0 ? dol_print_date($db->jdate($obj->date_debut), 'day') : '').' ';
if (! $i) $totalarray['nbfield']++;
}
// End date
if (! empty($arrayfields['d.date_fin']['checked'])) {
- print ''.($obj->date_fin > 0 ? dol_print_date($db->jdate($obj->date_fin), 'day') : '').' ';
+ print ''.($obj->date_fin > 0 ? dol_print_date($db->jdate($obj->date_fin), 'day') : '').' ';
if (! $i) $totalarray['nbfield']++;
}
// Date validation
if (! empty($arrayfields['d.date_valid']['checked'])) {
- print ''.($obj->date_valid > 0 ? dol_print_date($db->jdate($obj->date_valid), 'day') : '').' ';
+ print ''.($obj->date_valid > 0 ? dol_print_date($db->jdate($obj->date_valid), 'day') : '').' ';
if (! $i) $totalarray['nbfield']++;
}
// Date approval
if (! empty($arrayfields['d.date_approve']['checked'])) {
- print ''.($obj->date_approve > 0 ? dol_print_date($db->jdate($obj->date_approve), 'day') : '').' ';
+ print ''.($obj->date_approve > 0 ? dol_print_date($db->jdate($obj->date_approve), 'day') : '').' ';
if (! $i) $totalarray['nbfield']++;
}
// Amount HT
if (! empty($arrayfields['d.total_ht']['checked']))
{
- print ''.price($obj->total_ht)." \n";
+ print ''.price($obj->total_ht)." \n";
if (! $i) $totalarray['nbfield']++;
if (! $i) $totalarray['totalhtfield']=$totalarray['nbfield'];
$totalarray['totalht'] += $obj->total_ht;
@@ -725,7 +725,7 @@ if ($resql)
// Amount VAT
if (! empty($arrayfields['d.total_vat']['checked']))
{
- print ''.price($obj->total_tva)." \n";
+ print ''.price($obj->total_tva)." \n";
if (! $i) $totalarray['nbfield']++;
if (! $i) $totalarray['totalvatfield']=$totalarray['nbfield'];
$totalarray['totalvat'] += $obj->total_tva;
@@ -733,7 +733,7 @@ if ($resql)
// Amount TTC
if (! empty($arrayfields['d.total_ttc']['checked']))
{
- print ''.price($obj->total_ttc)." \n";
+ print ''.price($obj->total_ttc)." \n";
if (! $i) $totalarray['nbfield']++;
if (! $i) $totalarray['totalttcfield']=$totalarray['nbfield'];
$totalarray['totalttc'] += $obj->total_ttc;
@@ -748,7 +748,7 @@ if ($resql)
// Date creation
if (! empty($arrayfields['d.date_create']['checked']))
{
- print '';
+ print ' ';
print dol_print_date($db->jdate($obj->date_create), 'dayhour');
print ' ';
if (! $i) $totalarray['nbfield']++;
@@ -756,7 +756,7 @@ if ($resql)
// Date modification
if (! empty($arrayfields['d.tms']['checked']))
{
- print '';
+ print ' ';
print dol_print_date($db->jdate($obj->date_modif), 'dayhour');
print ' ';
if (! $i) $totalarray['nbfield']++;
@@ -764,11 +764,11 @@ if ($resql)
// Status
if (! empty($arrayfields['d.fk_statut']['checked']))
{
- print ''.$expensereportstatic->getLibStatut(5).' ';
+ print ''.$expensereportstatic->getLibStatut(5).' ';
if (! $i) $totalarray['nbfield']++;
}
// Action column
- print '';
+ print ' ';
if ($massactionbutton || $massaction) // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
{
$selected=0;
@@ -808,9 +808,9 @@ if ($resql)
if ($num < $limit && empty($offset)) print ' '.$langs->trans("Total").' ';
else print ''.$langs->trans("Totalforthispage").' ';
}
- elseif ($totalarray['totalhtfield'] == $i) print ''.price($totalarray['totalht']).' ';
- elseif ($totalarray['totalvatfield'] == $i) print ''.price($totalarray['totalvat']).' ';
- elseif ($totalarray['totalttcfield'] == $i) print ''.price($totalarray['totalttc']).' ';
+ elseif ($totalarray['totalhtfield'] == $i) print ''.price($totalarray['totalht']).' ';
+ elseif ($totalarray['totalvatfield'] == $i) print ''.price($totalarray['totalvat']).' ';
+ elseif ($totalarray['totalttcfield'] == $i) print ''.price($totalarray['totalttc']).' ';
else print ' ';
}
print ' ';
diff --git a/htdocs/expensereport/payment/card.php b/htdocs/expensereport/payment/card.php
index 83de49358bc..73da11f4619 100644
--- a/htdocs/expensereport/payment/card.php
+++ b/htdocs/expensereport/payment/card.php
@@ -229,10 +229,10 @@ if ($resql)
print '';
print ''.$langs->trans('ExpenseReport').' ';
- print ''.$langs->trans('ExpectedToPay').' ';
- print ''.$langs->trans('PayedByThisPayment').' ';
- print ''.$langs->trans('RemainderToPay').' ';
- print ''.$langs->trans('Status').' ';
+ print ''.$langs->trans('ExpectedToPay').' ';
+ print ''.$langs->trans('PayedByThisPayment').' ';
+ print ''.$langs->trans('RemainderToPay').' ';
+ print ''.$langs->trans('Status').' ';
print " \n";
if ($num > 0)
@@ -252,16 +252,16 @@ if ($resql)
print "\n";
// Expected to pay
- print ''.price($objp->total_ttc).' ';
+ print ''.price($objp->total_ttc).' ';
// Amount paid
- print ''.price($objp->amount).' ';
+ print ''.price($objp->amount).' ';
// Remain to pay
- print ''.price($remaintopay).' ';
+ print ''.price($remaintopay).' ';
// Status
- print ''.$expensereport->getLibStatut(4, $objp->amount).' ';
+ print ''.$expensereport->getLibStatut(4, $objp->amount).' ';
print "\n";
diff --git a/htdocs/expensereport/payment/payment.php b/htdocs/expensereport/payment/payment.php
index cda372317ab..d95edae6450 100644
--- a/htdocs/expensereport/payment/payment.php
+++ b/htdocs/expensereport/payment/payment.php
@@ -289,10 +289,10 @@ if ($action == 'create' || empty($action))
print '';
print '';
- print ''.$langs->trans("Amount").' ';
- print ''.$langs->trans("AlreadyPaid").' ';
- print ''.$langs->trans("RemainderToPay").' ';
- print ''.$langs->trans("Amount").' ';
+ print ''.$langs->trans("Amount").' ';
+ print ''.$langs->trans("AlreadyPaid").' ';
+ print ''.$langs->trans("RemainderToPay").' ';
+ print ''.$langs->trans("Amount").' ';
print " \n";
$total=0;
@@ -304,10 +304,10 @@ if ($action == 'create' || empty($action))
print '';
- print ''.price($objp->total_ttc)." ";
- print ''.price($sumpaid)." ";
- print ''.price($objp->total_ttc - $sumpaid)." ";
- print '';
+ print ' '.price($objp->total_ttc)." ";
+ print ''.price($sumpaid)." ";
+ print ''.price($objp->total_ttc - $sumpaid)." ";
+ print '';
if ($sumpaid < $objp->total_ttc)
{
$namef = "amount_".$objp->id;
@@ -335,11 +335,11 @@ if ($action == 'create' || empty($action))
{
// Print total
print ' ';
- print ''.$langs->trans("Total").': ';
- print "".price($total_ttc)." ";
- print "".price($totalrecu)." ";
- print "".price($total_ttc - $totalrecu)." ";
- print ' ';
+ print ''.$langs->trans("Total").': ';
+ print ''.price($total_ttc).' ';
+ print ''.price($totalrecu).' ';
+ print ''.price($total_ttc - $totalrecu).' ';
+ print ' ';
print " \n";
}
diff --git a/htdocs/expensereport/stats/index.php b/htdocs/expensereport/stats/index.php
index eb269d4f5f8..8980238c07b 100644
--- a/htdocs/expensereport/stats/index.php
+++ b/htdocs/expensereport/stats/index.php
@@ -242,7 +242,7 @@ if (! in_array($year, $arrayyears)) $arrayyears[$year]=$year;
arsort($arrayyears);
print $form->selectarray('year', $arrayyears, $year, 0);
print '';
-print ' ';
+print ' ';
print '
';
print '';
print ' ';
@@ -250,10 +250,10 @@ print ' ';
print '';
print '
';
print '';
-print ''.$langs->trans("Year").' ';
-print ''.$langs->trans("Number").' ';
-print ''.$langs->trans("AmountTotal").' ';
-print ''.$langs->trans("AmountAverage").' ';
+print ''.$langs->trans("Year").' ';
+print ''.$langs->trans("Number").' ';
+print ''.$langs->trans("AmountTotal").' ';
+print ''.$langs->trans("AmountAverage").' ';
print ' ';
$oldyear=0;
@@ -265,19 +265,19 @@ foreach ($data as $val)
$oldyear--;
print '';
- print ''.$oldyear.' ';
- print '0 ';
- print '0 ';
- print '0 ';
+ print ''.$oldyear.' ';
+ print '0 ';
+ print '0 ';
+ print '0 ';
print ' ';
}
print '';
- print ''.$year.' ';
- print ''.$val['nb'].' ';
- print ''.price(price2num($val['total'], 'MT'), 1).' ';
- print ''.price(price2num($val['avg'], 'MT'), 1).' ';
+ print ''.$year.' ';
+ print ''.$val['nb'].' ';
+ print ''.price(price2num($val['total'], 'MT'), 1).' ';
+ print ''.price(price2num($val['avg'], 'MT'), 1).' ';
print ' ';
$oldyear=$year;
}
@@ -289,7 +289,7 @@ print '';
// Show graphs
-print '
';
+print '';
if ($mesg) { print $mesg; }
else {
print $px1->show();
diff --git a/htdocs/expensereport/tpl/linkedobjectblock.tpl.php b/htdocs/expensereport/tpl/linkedobjectblock.tpl.php
index f206a4b4424..9c7a418a6cc 100644
--- a/htdocs/expensereport/tpl/linkedobjectblock.tpl.php
+++ b/htdocs/expensereport/tpl/linkedobjectblock.tpl.php
@@ -45,14 +45,14 @@ foreach($linkedObjectBlock as $key => $objectlink)
trans("ExpenseReport"); ?>
getNomUrl(1); ?>
- date_debut, 'day'); ?>
- date_debut, 'day'); ?>
+ rights->expensereport->lire) {
$total = $total + $objectlink->total_ht;
echo price($objectlink->total_ht);
} ?>
- getLibStatut(3); ?>
- id.'&action=dellink&dellinkid='.$key; ?>">transnoentitiesnoconv("RemoveLink"), 'unlink'); ?>
+ getLibStatut(3); ?>
+ id.'&action=dellink&dellinkid='.$key; ?>">transnoentitiesnoconv("RemoveLink"), 'unlink'); ?>
socid > 0) {
$newinter->socid=$object->socid;
$newinter->fk_projet=$object->fk_projet;
+ $newinter->fk_project=$object->fk_projet;
$newinter->fk_contrat=$object->fk_contrat;
} else
$newinter->socid=GETPOST("socid");
@@ -772,8 +773,8 @@ $date_next_execution = (GETPOST('remonth') ? dol_mktime(
/*
* List mode
*/
- $sql = "SELECT f.rowid as fich_rec, s.nom as name, s.rowid as socid, f.rowid as facid, f.titre, ";
- $sql.= " f.duree, f.fk_contrat, f.fk_projet, f.frequency, f.nb_gen_done, f.nb_gen_max,";
+ $sql = "SELECT f.rowid as fich_rec, s.nom as name, s.rowid as socid, f.rowid as facid, f.titre,";
+ $sql.= " f.duree, f.fk_contrat, f.fk_projet as fk_project, f.frequency, f.nb_gen_done, f.nb_gen_max,";
$sql.= " f.date_last_gen, f.date_when, f.datec";
$sql.= " FROM ".MAIN_DB_PREFIX."fichinter_rec as f";
@@ -863,7 +864,7 @@ $date_next_execution = (GETPOST('remonth') ? dol_mktime(
if (! empty($conf->projet->enabled)) {
print '';
if ($objp->fk_project > 0) {
- $projectstatic->fetch($objp->fk_projet);
+ $projectstatic->fetch($objp->fk_project);
print $projectstatic->getNomUrl(1);
}
print ' ';
diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php
index fbc53183ea1..5f7789e72f5 100644
--- a/htdocs/fourn/class/fournisseur.commande.class.php
+++ b/htdocs/fourn/class/fournisseur.commande.class.php
@@ -2310,6 +2310,7 @@ class CommandeFournisseur extends CommonOrder
{
$this->oldcopy= clone $this;
$this->fk_projet = $id_projet;
+ $this->fk_project = $id_projet;
}
if (! $notrigger && empty($error))
diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php
index 6b533ae2d21..aa914b54894 100644
--- a/htdocs/fourn/class/fournisseur.facture.class.php
+++ b/htdocs/fourn/class/fournisseur.facture.class.php
@@ -578,7 +578,7 @@ class FactureFournisseur extends CommonInvoice
$sql.= " t.fk_user_author,";
$sql.= " t.fk_user_valid,";
$sql.= " t.fk_facture_source,";
- $sql.= " t.fk_projet,";
+ $sql.= " t.fk_projet as fk_project,";
$sql.= " t.fk_cond_reglement,";
$sql.= " t.fk_account,";
$sql.= " t.fk_mode_reglement,";
@@ -641,8 +641,8 @@ class FactureFournisseur extends CommonInvoice
$this->author = $obj->fk_user_author;
$this->fk_user_valid = $obj->fk_user_valid;
$this->fk_facture_source = $obj->fk_facture_source;
- $this->fk_project = $obj->fk_projet;
- $this->cond_reglement_id = $obj->fk_cond_reglement;
+ $this->fk_project = $obj->fk_project;
+ $this->cond_reglement_id = $obj->fk_cond_reglement;
$this->cond_reglement_code = $obj->cond_reglement_code;
$this->cond_reglement = $obj->cond_reglement_libelle;
$this->cond_reglement_doc = $obj->cond_reglement_libelle;
@@ -1458,7 +1458,7 @@ class FactureFournisseur extends CommonInvoice
* @param int $idwarehouse Id warehouse to use for stock change.
* @return int <0 if KO, >0 if OK
*/
- public function set_draft($user, $idwarehouse = -1)
+ public function setDraft($user, $idwarehouse = -1)
{
// phpcs:enable
global $conf,$langs;
diff --git a/htdocs/fourn/class/fournisseur.product.class.php b/htdocs/fourn/class/fournisseur.product.class.php
index bbdea07270e..9eedea68335 100644
--- a/htdocs/fourn/class/fournisseur.product.class.php
+++ b/htdocs/fourn/class/fournisseur.product.class.php
@@ -227,9 +227,11 @@ class ProductFournisseur extends Product
* @param float $multicurrency_tx Rate currency
* @param string $multicurrency_code Currency code
* @param string $desc_fourn Custom description for product_fourn_price
+ * @param string $barcode Barcode
+ * @param int $fk_barcode_type Barcode type
* @return int <0 if KO, >=0 if OK
*/
- public function update_buyprice($qty, $buyprice, $user, $price_base_type, $fourn, $availability, $ref_fourn, $tva_tx, $charges = 0, $remise_percent = 0, $remise = 0, $newnpr = 0, $delivery_time_days = 0, $supplier_reputation = '', $localtaxes_array = array(), $newdefaultvatcode = '', $multicurrency_buyprice = 0, $multicurrency_price_base_type = 'HT', $multicurrency_tx = 1, $multicurrency_code = '', $desc_fourn = '')
+ public function update_buyprice($qty, $buyprice, $user, $price_base_type, $fourn, $availability, $ref_fourn, $tva_tx, $charges = 0, $remise_percent = 0, $remise = 0, $newnpr = 0, $delivery_time_days = 0, $supplier_reputation = '', $localtaxes_array = array(), $newdefaultvatcode = '', $multicurrency_buyprice = 0, $multicurrency_price_base_type = 'HT', $multicurrency_tx = 1, $multicurrency_code = '', $desc_fourn = '', $barcode = '', $fk_barcode_type = '')
{
// phpcs:enable
global $conf, $langs;
@@ -350,7 +352,9 @@ class ProductFournisseur extends Product
$sql.= " info_bits = ".$newnpr.",";
$sql.= " charges = ".$charges.","; // deprecated
$sql.= " delivery_time_days = ".($delivery_time_days != '' ? $delivery_time_days : 'null').",";
- $sql.= " supplier_reputation = ".(empty($supplier_reputation) ? 'NULL' : "'".$this->db->escape($supplier_reputation)."'");
+ $sql.= " supplier_reputation = ".(empty($supplier_reputation) ? 'NULL' : "'".$this->db->escape($supplier_reputation)."'").",";
+ $sql.= " barcode = ".(empty($barcode) ? 'NULL' : "'".$this->db->escape($barcode)."'").",";
+ $sql.= " fk_barcode_type = ".(empty($fk_barcode_type) ? 'NULL' : "'".$this->db->escape($fk_barcode_type)."'");
$sql.= " WHERE rowid = ".$this->product_fourn_price_id;
// TODO Add price_base_type and price_ttc
@@ -400,7 +404,7 @@ class ProductFournisseur extends Product
// Add price for this quantity to supplier
$sql = "INSERT INTO " . MAIN_DB_PREFIX . "product_fournisseur_price(";
$sql.= " multicurrency_price, multicurrency_unitprice, multicurrency_tx, fk_multicurrency, multicurrency_code,";
- $sql .= "datec, fk_product, fk_soc, ref_fourn, desc_fourn, fk_user, price, quantity, remise_percent, remise, unitprice, tva_tx, charges, fk_availability, default_vat_code, info_bits, entity, delivery_time_days, supplier_reputation)";
+ $sql .= "datec, fk_product, fk_soc, ref_fourn, desc_fourn, fk_user, price, quantity, remise_percent, remise, unitprice, tva_tx, charges, fk_availability, default_vat_code, info_bits, entity, delivery_time_days, supplier_reputation, barcode, fk_barcode_type)";
$sql .= " values(";
$sql.= (isset($multicurrency_buyprice)?"'".$this->db->escape(price2num($multicurrency_buyprice))."'":'null').",";
$sql.= (isset($multicurrency_unitBuyPrice)?"'".$this->db->escape(price2num($multicurrency_unitBuyPrice))."'":'null').",";
@@ -426,6 +430,8 @@ class ProductFournisseur extends Product
$sql .= $conf->entity . ",";
$sql .= $delivery_time_days . ",";
$sql .= (empty($supplier_reputation) ? 'NULL' : "'" . $this->db->escape($supplier_reputation) . "'");
+ $sql .= (empty($barcode) ? 'NULL' : "'" . $this->db->escape($barcode) . "'");
+ $sql .= (empty($fk_barcode_type) ? 'NULL' : "'" . $this->db->escape($fk_barcode_type) . "'");
$sql .= ")";
$idinserted = 0;
@@ -488,8 +494,9 @@ class ProductFournisseur extends Product
$sql = "SELECT pfp.rowid, pfp.price, pfp.quantity, pfp.unitprice, pfp.remise_percent, pfp.remise, pfp.tva_tx, pfp.default_vat_code, pfp.info_bits as fourn_tva_npr, pfp.fk_availability,";
$sql.= " pfp.fk_soc, pfp.ref_fourn, pfp.desc_fourn, pfp.fk_product, pfp.charges, pfp.fk_supplier_price_expression, pfp.delivery_time_days,";
- $sql.= " pfp.supplier_reputation, pfp.fk_user, pfp.datec";
- $sql.= " ,pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code";
+ $sql.= " pfp.supplier_reputation, pfp.fk_user, pfp.datec,";
+ $sql.= " pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code,";
+ $sql.=" pfp.barcode, pfp.fk_barcode_type";
$sql.= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price as pfp";
$sql.= " WHERE pfp.rowid = ".$rowid;
@@ -529,7 +536,10 @@ class ProductFournisseur extends Product
$this->fourn_multicurrency_tx = $obj->multicurrency_tx;
$this->fourn_multicurrency_id = $obj->fk_multicurrency;
$this->fourn_multicurrency_code = $obj->multicurrency_code;
-
+ if($conf->barcode->enabled) {
+ $this->fourn_barcode = $obj->barcode;
+ $this->fourn_fk_barcode_type = $obj->fk_barcode_type;
+ }
if (empty($ignore_expression) && !empty($this->fk_supplier_price_expression))
{
$priceparser = new PriceParser($this->db);
@@ -582,7 +592,8 @@ class ProductFournisseur extends Product
$sql = "SELECT s.nom as supplier_name, s.rowid as fourn_id,";
$sql.= " pfp.rowid as product_fourn_pri_id, pfp.ref_fourn, pfp.desc_fourn, pfp.fk_product as product_fourn_id, pfp.fk_supplier_price_expression,";
$sql.= " pfp.price, pfp.quantity, pfp.unitprice, pfp.remise_percent, pfp.remise, pfp.tva_tx, pfp.fk_availability, pfp.charges, pfp.info_bits, pfp.delivery_time_days, pfp.supplier_reputation,";
- $sql.= " pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code, pfp.datec, pfp.tms";
+ $sql.= " pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code, pfp.datec, pfp.tms,";
+ $sql.= " pfp.barcode, pfp.fk_barcode_type";
$sql.= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price as pfp, ".MAIN_DB_PREFIX."societe as s";
$sql.= " WHERE pfp.entity IN (".getEntity('productsupplierprice').")";
$sql.= " AND pfp.fk_soc = s.rowid";
@@ -623,8 +634,8 @@ class ProductFournisseur extends Product
$prodfourn->fourn_tva_npr = $record["info_bits"];
$prodfourn->fk_supplier_price_expression = $record["fk_supplier_price_expression"];
$prodfourn->supplier_reputation = $record["supplier_reputation"];
- $prodfourn->date_creation = $this->db->jdate($record['datec']);
- $prodfourn->date_modification = $this->db->jdate($record['tms']);
+ $prodfourn->fourn_date_creation = $this->db->jdate($record['datec']);
+ $prodfourn->fourn_date_modification = $this->db->jdate($record['tms']);
$prodfourn->fourn_multicurrency_price = $record["multicurrency_price"];
$prodfourn->fourn_multicurrency_unitprice = $record["multicurrency_unitprice"];
@@ -632,6 +643,11 @@ class ProductFournisseur extends Product
$prodfourn->fourn_multicurrency_id = $record["fk_multicurrency"];
$prodfourn->fourn_multicurrency_code = $record["multicurrency_code"];
+ if($conf->barcode->enabled){
+ $prodfourn->barcode = $record["barcode"];
+ $prodfourn->fk_barcode_type = $record["fk_barcode_type"];
+ }
+
if (!empty($conf->dynamicprices->enabled) && !empty($prodfourn->fk_supplier_price_expression)) {
$priceparser = new PriceParser($this->db);
$price_result = $priceparser->parseProductSupplier($prodfourn);
diff --git a/htdocs/fourn/class/paiementfourn.class.php b/htdocs/fourn/class/paiementfourn.class.php
index a5016822c66..45ad69f6c64 100644
--- a/htdocs/fourn/class/paiementfourn.class.php
+++ b/htdocs/fourn/class/paiementfourn.class.php
@@ -585,7 +585,7 @@ class PaiementFourn extends Paiement
$label = ''.$langs->trans("ShowPayment").' ';
$label.= ''.$langs->trans("Ref").': '.$text;
- $label.= ''.$langs->trans("Date").': '.dol_print_date($this->datepaye ? $this->datepaye : $this->date, 'dayhour');
+ if ($this->datepaye ? $this->datepaye : $this->date) $label.= ''.$langs->trans("Date").': '.dol_print_date($this->datepaye ? $this->datepaye : $this->date, 'dayhour');
$linkstart = '';
$linkend = ' ';
diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php
index 7c4b09a6f6c..bdf480ccfc4 100644
--- a/htdocs/fourn/commande/card.php
+++ b/htdocs/fourn/commande/card.php
@@ -2769,6 +2769,8 @@ elseif (! empty($object->id))
}
}
+
+
// End of page
llxFooter();
$db->close();
diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php
index 2fc36516bc6..c2a5552f15e 100644
--- a/htdocs/fourn/facture/card.php
+++ b/htdocs/fourn/facture/card.php
@@ -1446,7 +1446,7 @@ if (empty($reshook))
}
}
- $object->set_draft($user, $idwarehouse);
+ $object->setDraft($user, $idwarehouse);
// Define output language
if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
@@ -3235,6 +3235,7 @@ else
}
}
+
// End of page
llxFooter();
$db->close();
diff --git a/htdocs/fourn/facture/paiement.php b/htdocs/fourn/facture/paiement.php
index fa4500b8c31..22470bd4c81 100644
--- a/htdocs/fourn/facture/paiement.php
+++ b/htdocs/fourn/facture/paiement.php
@@ -69,7 +69,7 @@ if (! $sortorder) $sortorder="DESC";
if (! $sortfield) $sortfield="p.rowid";
$optioncss = GETPOST('optioncss', 'alpha');
-$amounts = array();array();
+$amounts = array();
$amountsresttopay=array();
$addwarning=0;
@@ -247,7 +247,23 @@ if (empty($reshook))
{
$error=0;
- $datepaye = dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear'));
+ $datepaye = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int'));
+
+ // Clean parameters amount if payment is for a credit note
+ if (GETPOST('type', 'int') == FactureFournisseur::TYPE_CREDIT_NOTE)
+ {
+ foreach ($amounts as $key => $value) // How payment is dispatch
+ {
+ $newvalue = price2num($value, 'MT');
+ $amounts[$key] = -$newvalue;
+ }
+
+ foreach ($multicurrency_amounts as $key => $value) // How payment is dispatch
+ {
+ $newvalue = price2num($value, 'MT');
+ $multicurrency_amounts[$key] = -$newvalue;
+ }
+ }
if (! $error)
{
@@ -432,6 +448,7 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie
print ' ';
print ' ';
print ' ';
+ print ' ';
print ' ';
dol_fiche_head(null);
@@ -620,14 +637,14 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie
print '';
}
- print ''.price($objp->total_ttc).' ';
+ print ''.price($sign * $objp->total_ttc).' ';
- print ''.price($objp->am);
+ print ' '.price($sign * $objp->am);
if ($creditnotes) print '+'.price($creditnotes);
if ($deposits) print '+'.price($deposits);
print ' ';
- print ''.price($remaintopay).' ';
+ print ''.price($sign * $remaintopay).' ';
// Amount
print '';
diff --git a/htdocs/fourn/facture/rapport.php b/htdocs/fourn/facture/rapport.php
index 26e0884bdd6..ccc92ad2cba 100644
--- a/htdocs/fourn/facture/rapport.php
+++ b/htdocs/fourn/facture/rapport.php
@@ -26,6 +26,8 @@ require_once DOL_DOCUMENT_ROOT.'/core/modules/rapport/pdf_paiement_fourn.class.p
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
+$langs->loadLangs(array('bills'));
+
// Security check
$socid='';
if (! empty($user->societe_id)) $socid=$user->societe_id;
diff --git a/htdocs/holiday/card.php b/htdocs/holiday/card.php
index 9bc181f66d9..1c92e558c41 100644
--- a/htdocs/holiday/card.php
+++ b/htdocs/holiday/card.php
@@ -45,7 +45,8 @@ $ref=GETPOST('ref', 'alpha');
$fuserid = (GETPOST('fuserid', 'int')?GETPOST('fuserid', 'int'):$user->id);
// Protection if external user
-if ($user->societe_id > 0) accessforbidden();
+if ($user->societe_id) $socid=$user->societe_id;
+$result = restrictedArea($user, 'holiday', $id, 'holiday');
$now=dol_now();
diff --git a/htdocs/holiday/class/holiday.class.php b/htdocs/holiday/class/holiday.class.php
index 45146324e32..b05e94cccfa 100644
--- a/htdocs/holiday/class/holiday.class.php
+++ b/htdocs/holiday/class/holiday.class.php
@@ -1023,12 +1023,12 @@ class Holiday extends CommonObject
* Warning: It consumes a lot of memory because it load in ->holiday all holiday of a dedicated user at each call.
*
* @param int $fk_user Id user
- * @param date $dateStart Start date of period to check
- * @param date $dateEnd End date of period to check
+ * @param integer $dateStart Start date of period to check
+ * @param integer $dateEnd End date of period to check
* @param int $halfday Tag to define how start and end the period to check:
* 0:Full days, 2:Start afternoon end morning, -1:Start afternoon end afternoon, 1:Start morning end morning
* @return boolean False = New range overlap an existing holiday, True = no overlapping (is never on holiday during checked period).
- * @see verifDateHolidayForTimestamp
+ * @see verifDateHolidayForTimestamp()
*/
public function verifDateHolidayCP($fk_user, $dateStart, $dateEnd, $halfday = 0)
{
@@ -1107,10 +1107,10 @@ class Holiday extends CommonObject
* Check that a user is not on holiday for a particular timestamp
*
* @param int $fk_user Id user
- * @param timestamp $timestamp Time stamp date for a day (YYYY-MM-DD) without hours (= 12:00AM in english and not 12:00PM that is 12:00)
+ * @param integer $timestamp Time stamp date for a day (YYYY-MM-DD) without hours (= 12:00AM in english and not 12:00PM that is 12:00)
* @param string $status Filter on holiday status. '-1' = no filter.
* @return array array('morning'=> ,'afternoon'=> ), Boolean is true if user is available for day timestamp.
- * @see verifDateHolidayCP
+ * @see verifDateHolidayCP()
*/
public function verifDateHolidayForTimestamp($fk_user, $timestamp, $status = '-1')
{
@@ -1222,7 +1222,7 @@ class Holiday extends CommonObject
*
* @param int $statut id statut
* @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
- * @param date $startdate Date holiday should start
+ * @param integer $startdate Date holiday should start
* @return string Label
*/
public function LibStatut($statut, $mode = 0, $startdate = '')
diff --git a/htdocs/holiday/document.php b/htdocs/holiday/document.php
index be948280eaf..942b6cb98fb 100644
--- a/htdocs/holiday/document.php
+++ b/htdocs/holiday/document.php
@@ -144,7 +144,7 @@ if ($object->id)
print ' '.$langs->trans('DateDebCP').' ('.$langs->trans("FirstDayOfHoliday").') ';
print ''.dol_print_date($object->date_debut, 'day');
print ' ';
- print $langs->trans($listhalfday[$starthalfday]);
+ print ''.$langs->trans($listhalfday[$starthalfday]).' ';
print ' ';
print '';
}
@@ -166,7 +166,7 @@ if ($object->id)
print ''.$langs->trans('DateFinCP').' ('.$langs->trans("LastDayOfHoliday").') ';
print ''.dol_print_date($object->date_fin, 'day');
print ' ';
- print $langs->trans($listhalfday[$endhalfday]);
+ print ''.$langs->trans($listhalfday[$endhalfday]).' ';
print ' ';
print '';
}
diff --git a/htdocs/hrm/index.php b/htdocs/hrm/index.php
index 2985386676f..066a21ebad0 100644
--- a/htdocs/hrm/index.php
+++ b/htdocs/hrm/index.php
@@ -322,7 +322,7 @@ if (! empty($conf->expensereport->enabled) && $user->rights->expensereport->lire
{
$sql = "SELECT u.rowid as uid, u.lastname, u.firstname, u.login, u.email, u.statut, u.photo, x.rowid, x.ref, x.date_debut as date, x.tms as dm, x.total_ttc, x.fk_statut as status";
$sql.= " FROM ".MAIN_DB_PREFIX."expensereport as x, ".MAIN_DB_PREFIX."user as u";
- if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= ", ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."societe_commerciaux as sc";
+ //if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= ", ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."societe_commerciaux as sc";
$sql.= " WHERE u.rowid = x.fk_user_author";
$sql.= " AND x.entity = ".$conf->entity;
if (empty($user->rights->expensereport->readall) && empty($user->rights->expensereport->lire_tous)) $sql.=' AND x.fk_user_author IN ('.join(',', $childids).')';
diff --git a/htdocs/includes/DebugBar/Bridge/CacheCacheCollector.php b/htdocs/includes/DebugBar/Bridge/CacheCacheCollector.php
new file mode 100644
index 00000000000..3d841c6784e
--- /dev/null
+++ b/htdocs/includes/DebugBar/Bridge/CacheCacheCollector.php
@@ -0,0 +1,62 @@
+
+ * $debugbar->addCollector(new CacheCacheCollector(CacheManager::get('default')));
+ * // or
+ * $debugbar->addCollector(new CacheCacheCollector());
+ * $debugbar['cache']->addCache(CacheManager::get('default'));
+ *
+ */
+class CacheCacheCollector extends MonologCollector
+{
+ protected $logger;
+
+ public function __construct(Cache $cache = null, Logger $logger = null, $level = Logger::DEBUG, $bubble = true)
+ {
+ parent::__construct(null, $level, $bubble);
+
+ if ($logger === null) {
+ $logger = new Logger('Cache');
+ }
+ $this->logger = $logger;
+
+ if ($cache !== null) {
+ $this->addCache($cache);
+ }
+ }
+
+ public function addCache(Cache $cache)
+ {
+ $backend = $cache->getBackend();
+ if (!($backend instanceof LoggingBackend)) {
+ $backend = new LoggingBackend($backend, $this->logger);
+ }
+ $cache->setBackend($backend);
+ $this->addLogger($backend->getLogger());
+ }
+
+ public function getName()
+ {
+ return 'cache';
+ }
+}
diff --git a/htdocs/includes/DebugBar/Bridge/DoctrineCollector.php b/htdocs/includes/DebugBar/Bridge/DoctrineCollector.php
new file mode 100644
index 00000000000..6fa358e29ab
--- /dev/null
+++ b/htdocs/includes/DebugBar/Bridge/DoctrineCollector.php
@@ -0,0 +1,98 @@
+
+ * $debugStack = new Doctrine\DBAL\Logging\DebugStack();
+ * $entityManager->getConnection()->getConfiguration()->setSQLLogger($debugStack);
+ * $debugbar->addCollector(new DoctrineCollector($debugStack));
+ *
+ */
+class DoctrineCollector extends DataCollector implements Renderable, AssetProvider
+{
+ protected $debugStack;
+
+ public function __construct($debugStackOrEntityManager)
+ {
+ if ($debugStackOrEntityManager instanceof EntityManager) {
+ $debugStackOrEntityManager = $debugStackOrEntityManager->getConnection()->getConfiguration()->getSQLLogger();
+ }
+ if (!($debugStackOrEntityManager instanceof DebugStack)) {
+ throw new DebugBarException("'DoctrineCollector' requires an 'EntityManager' or 'DebugStack' object");
+ }
+ $this->debugStack = $debugStackOrEntityManager;
+ }
+
+ public function collect()
+ {
+ $queries = array();
+ $totalExecTime = 0;
+ foreach ($this->debugStack->queries as $q) {
+ $queries[] = array(
+ 'sql' => $q['sql'],
+ 'params' => (object) $q['params'],
+ 'duration' => $q['executionMS'],
+ 'duration_str' => $this->formatDuration($q['executionMS'])
+ );
+ $totalExecTime += $q['executionMS'];
+ }
+
+ return array(
+ 'nb_statements' => count($queries),
+ 'accumulated_duration' => $totalExecTime,
+ 'accumulated_duration_str' => $this->formatDuration($totalExecTime),
+ 'statements' => $queries
+ );
+ }
+
+ public function getName()
+ {
+ return 'doctrine';
+ }
+
+ public function getWidgets()
+ {
+ return array(
+ "database" => array(
+ "icon" => "arrow-right",
+ "widget" => "PhpDebugBar.Widgets.SQLQueriesWidget",
+ "map" => "doctrine",
+ "default" => "[]"
+ ),
+ "database:badge" => array(
+ "map" => "doctrine.nb_statements",
+ "default" => 0
+ )
+ );
+ }
+
+ public function getAssets()
+ {
+ return array(
+ 'css' => 'widgets/sqlqueries/widget.css',
+ 'js' => 'widgets/sqlqueries/widget.js'
+ );
+ }
+}
diff --git a/htdocs/includes/DebugBar/Bridge/MonologCollector.php b/htdocs/includes/DebugBar/Bridge/MonologCollector.php
new file mode 100644
index 00000000000..609d5c5f837
--- /dev/null
+++ b/htdocs/includes/DebugBar/Bridge/MonologCollector.php
@@ -0,0 +1,103 @@
+
+ * $debugbar->addCollector(new MonologCollector($logger));
+ *
+ */
+class MonologCollector extends AbstractProcessingHandler implements DataCollectorInterface, Renderable, MessagesAggregateInterface
+{
+ protected $name;
+
+ protected $records = array();
+
+ /**
+ * @param Logger $logger
+ * @param int $level
+ * @param boolean $bubble
+ * @param string $name
+ */
+ public function __construct(Logger $logger = null, $level = Logger::DEBUG, $bubble = true, $name = 'monolog')
+ {
+ parent::__construct($level, $bubble);
+ $this->name = $name;
+ if ($logger !== null) {
+ $this->addLogger($logger);
+ }
+ }
+
+ /**
+ * Adds logger which messages you want to log
+ *
+ * @param Logger $logger
+ */
+ public function addLogger(Logger $logger)
+ {
+ $logger->pushHandler($this);
+ }
+
+ protected function write(array $record)
+ {
+ $this->records[] = array(
+ 'message' => $record['formatted'],
+ 'is_string' => true,
+ 'label' => strtolower($record['level_name']),
+ 'time' => $record['datetime']->format('U')
+ );
+ }
+
+ public function getMessages()
+ {
+ return $this->records;
+ }
+
+ public function collect()
+ {
+ return array(
+ 'count' => count($this->records),
+ 'records' => $this->records
+ );
+ }
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function getWidgets()
+ {
+ $name = $this->getName();
+ return array(
+ $name => array(
+ "icon" => "suitcase",
+ "widget" => "PhpDebugBar.Widgets.MessagesWidget",
+ "map" => "$name.records",
+ "default" => "[]"
+ ),
+ "$name:badge" => array(
+ "map" => "$name.count",
+ "default" => "null"
+ )
+ );
+ }
+}
diff --git a/htdocs/includes/DebugBar/Bridge/PropelCollector.php b/htdocs/includes/DebugBar/Bridge/PropelCollector.php
new file mode 100644
index 00000000000..93ad4ff82fd
--- /dev/null
+++ b/htdocs/includes/DebugBar/Bridge/PropelCollector.php
@@ -0,0 +1,253 @@
+
+ * $debugbar->addCollector(new PropelCollector($debugbar['messages']));
+ * PropelCollector::enablePropelProfiling();
+ *
+ */
+class PropelCollector extends DataCollector implements BasicLogger, Renderable, AssetProvider
+{
+ protected $logger;
+
+ protected $statements = array();
+
+ protected $accumulatedTime = 0;
+
+ protected $peakMemory = 0;
+
+ /**
+ * Sets the needed configuration option in propel to enable query logging
+ *
+ * @param PropelConfiguration $config Apply profiling on a specific config
+ */
+ public static function enablePropelProfiling(PropelConfiguration $config = null)
+ {
+ if ($config === null) {
+ $config = Propel::getConfiguration(PropelConfiguration::TYPE_OBJECT);
+ }
+ $config->setParameter('debugpdo.logging.details.method.enabled', true);
+ $config->setParameter('debugpdo.logging.details.time.enabled', true);
+ $config->setParameter('debugpdo.logging.details.mem.enabled', true);
+ $allMethods = array(
+ 'PropelPDO::__construct', // logs connection opening
+ 'PropelPDO::__destruct', // logs connection close
+ 'PropelPDO::exec', // logs a query
+ 'PropelPDO::query', // logs a query
+ 'PropelPDO::beginTransaction', // logs a transaction begin
+ 'PropelPDO::commit', // logs a transaction commit
+ 'PropelPDO::rollBack', // logs a transaction rollBack (watch out for the capital 'B')
+ 'DebugPDOStatement::execute', // logs a query from a prepared statement
+ );
+ $config->setParameter('debugpdo.logging.methods', $allMethods, false);
+ }
+
+ /**
+ * @param LoggerInterface $logger A logger to forward non-query log lines to
+ * @param PropelPDO $conn Bound this collector to a connection only
+ */
+ public function __construct(LoggerInterface $logger = null, PropelPDO $conn = null)
+ {
+ if ($conn) {
+ $conn->setLogger($this);
+ } else {
+ Propel::setLogger($this);
+ }
+ $this->logger = $logger;
+ $this->logQueriesToLogger = false;
+ }
+
+ public function setLogQueriesToLogger($enable = true)
+ {
+ $this->logQueriesToLogger = $enable;
+ return $this;
+ }
+
+ public function isLogQueriesToLogger()
+ {
+ return $this->logQueriesToLogger;
+ }
+
+ public function emergency($m)
+ {
+ $this->log($m, Propel::LOG_EMERG);
+ }
+
+ public function alert($m)
+ {
+ $this->log($m, Propel::LOG_ALERT);
+ }
+
+ public function crit($m)
+ {
+ $this->log($m, Propel::LOG_CRIT);
+ }
+
+ public function err($m)
+ {
+ $this->log($m, Propel::LOG_ERR);
+ }
+
+ public function warning($m)
+ {
+ $this->log($m, Propel::LOG_WARNING);
+ }
+
+ public function notice($m)
+ {
+ $this->log($m, Propel::LOG_NOTICE);
+ }
+
+ public function info($m)
+ {
+ $this->log($m, Propel::LOG_INFO);
+ }
+
+ public function debug($m)
+ {
+ $this->log($m, Propel::LOG_DEBUG);
+ }
+
+ public function log($message, $severity = null)
+ {
+ if (strpos($message, 'DebugPDOStatement::execute') !== false) {
+ list($sql, $duration_str) = $this->parseAndLogSqlQuery($message);
+ if (!$this->logQueriesToLogger) {
+ return;
+ }
+ $message = "$sql ($duration_str)";
+ }
+
+ if ($this->logger !== null) {
+ $this->logger->log($this->convertLogLevel($severity), $message);
+ }
+ }
+
+ /**
+ * Converts Propel log levels to PSR log levels
+ *
+ * @param int $level
+ * @return string
+ */
+ protected function convertLogLevel($level)
+ {
+ $map = array(
+ Propel::LOG_EMERG => LogLevel::EMERGENCY,
+ Propel::LOG_ALERT => LogLevel::ALERT,
+ Propel::LOG_CRIT => LogLevel::CRITICAL,
+ Propel::LOG_ERR => LogLevel::ERROR,
+ Propel::LOG_WARNING => LogLevel::WARNING,
+ Propel::LOG_NOTICE => LogLevel::NOTICE,
+ Propel::LOG_DEBUG => LogLevel::DEBUG
+ );
+ return $map[$level];
+ }
+
+ /**
+ * Parse a log line to extract query information
+ *
+ * @param string $message
+ */
+ protected function parseAndLogSqlQuery($message)
+ {
+ $parts = explode('|', $message, 4);
+ $sql = trim($parts[3]);
+
+ $duration = 0;
+ if (preg_match('/([0-9]+\.[0-9]+)/', $parts[1], $matches)) {
+ $duration = (float) $matches[1];
+ }
+
+ $memory = 0;
+ if (preg_match('/([0-9]+\.[0-9]+) ([A-Z]{1,2})/', $parts[2], $matches)) {
+ $memory = (float) $matches[1];
+ if ($matches[2] == 'KB') {
+ $memory *= 1024;
+ } elseif ($matches[2] == 'MB') {
+ $memory *= 1024 * 1024;
+ }
+ }
+
+ $this->statements[] = array(
+ 'sql' => $sql,
+ 'is_success' => true,
+ 'duration' => $duration,
+ 'duration_str' => $this->formatDuration($duration),
+ 'memory' => $memory,
+ 'memory_str' => $this->formatBytes($memory)
+ );
+ $this->accumulatedTime += $duration;
+ $this->peakMemory = max($this->peakMemory, $memory);
+ return array($sql, $this->formatDuration($duration));
+ }
+
+ public function collect()
+ {
+ return array(
+ 'nb_statements' => count($this->statements),
+ 'nb_failed_statements' => 0,
+ 'accumulated_duration' => $this->accumulatedTime,
+ 'accumulated_duration_str' => $this->formatDuration($this->accumulatedTime),
+ 'peak_memory_usage' => $this->peakMemory,
+ 'peak_memory_usage_str' => $this->formatBytes($this->peakMemory),
+ 'statements' => $this->statements
+ );
+ }
+
+ public function getName()
+ {
+ return 'propel';
+ }
+
+ public function getWidgets()
+ {
+ return array(
+ "propel" => array(
+ "icon" => "bolt",
+ "widget" => "PhpDebugBar.Widgets.SQLQueriesWidget",
+ "map" => "propel",
+ "default" => "[]"
+ ),
+ "propel:badge" => array(
+ "map" => "propel.nb_statements",
+ "default" => 0
+ )
+ );
+ }
+
+ public function getAssets()
+ {
+ return array(
+ 'css' => 'widgets/sqlqueries/widget.css',
+ 'js' => 'widgets/sqlqueries/widget.js'
+ );
+ }
+}
diff --git a/htdocs/includes/DebugBar/Bridge/SlimCollector.php b/htdocs/includes/DebugBar/Bridge/SlimCollector.php
new file mode 100644
index 00000000000..030a3baf624
--- /dev/null
+++ b/htdocs/includes/DebugBar/Bridge/SlimCollector.php
@@ -0,0 +1,66 @@
+slim = $slim;
+ if ($log = $slim->getLog()) {
+ $this->originalLogWriter = $log->getWriter();
+ $log->setWriter($this);
+ $log->setEnabled(true);
+ }
+ }
+
+ public function write($message, $level)
+ {
+ if ($this->originalLogWriter) {
+ $this->originalLogWriter->write($message, $level);
+ }
+ $this->addMessage($message, $this->getLevelName($level));
+ }
+
+ protected function getLevelName($level)
+ {
+ $map = array(
+ Log::EMERGENCY => LogLevel::EMERGENCY,
+ Log::ALERT => LogLevel::ALERT,
+ Log::CRITICAL => LogLevel::CRITICAL,
+ Log::ERROR => LogLevel::ERROR,
+ Log::WARN => LogLevel::WARNING,
+ Log::NOTICE => LogLevel::NOTICE,
+ Log::INFO => LogLevel::INFO,
+ Log::DEBUG => LogLevel::DEBUG
+ );
+ return $map[$level];
+ }
+
+ public function getName()
+ {
+ return 'slim';
+ }
+}
diff --git a/htdocs/includes/DebugBar/Bridge/SwiftMailer/SwiftLogCollector.php b/htdocs/includes/DebugBar/Bridge/SwiftMailer/SwiftLogCollector.php
new file mode 100644
index 00000000000..fdef79a0bdc
--- /dev/null
+++ b/htdocs/includes/DebugBar/Bridge/SwiftMailer/SwiftLogCollector.php
@@ -0,0 +1,44 @@
+registerPlugin(new Swift_Plugins_LoggerPlugin($this));
+ }
+
+ public function add($entry)
+ {
+ $this->addMessage($entry);
+ }
+
+ public function dump()
+ {
+ return implode(PHP_EOL, $this->_log);
+ }
+
+ public function getName()
+ {
+ return 'swiftmailer_logs';
+ }
+}
diff --git a/htdocs/includes/DebugBar/Bridge/SwiftMailer/SwiftMailCollector.php b/htdocs/includes/DebugBar/Bridge/SwiftMailer/SwiftMailCollector.php
new file mode 100644
index 00000000000..01a5e906c88
--- /dev/null
+++ b/htdocs/includes/DebugBar/Bridge/SwiftMailer/SwiftMailCollector.php
@@ -0,0 +1,92 @@
+messagesLogger = new Swift_Plugins_MessageLogger();
+ $mailer->registerPlugin($this->messagesLogger);
+ }
+
+ public function collect()
+ {
+ $mails = array();
+ foreach ($this->messagesLogger->getMessages() as $msg) {
+ $mails[] = array(
+ 'to' => $this->formatTo($msg->getTo()),
+ 'subject' => $msg->getSubject(),
+ 'headers' => $msg->getHeaders()->toString()
+ );
+ }
+ return array(
+ 'count' => count($mails),
+ 'mails' => $mails
+ );
+ }
+
+ protected function formatTo($to)
+ {
+ if (!$to) {
+ return '';
+ }
+
+ $f = array();
+ foreach ($to as $k => $v) {
+ $f[] = (empty($v) ? '' : "$v ") . "<$k>";
+ }
+ return implode(', ', $f);
+ }
+
+ public function getName()
+ {
+ return 'swiftmailer_mails';
+ }
+
+ public function getWidgets()
+ {
+ return array(
+ 'emails' => array(
+ 'icon' => 'inbox',
+ 'widget' => 'PhpDebugBar.Widgets.MailsWidget',
+ 'map' => 'swiftmailer_mails.mails',
+ 'default' => '[]',
+ 'title' => 'Mails'
+ ),
+ 'emails:badge' => array(
+ 'map' => 'swiftmailer_mails.count',
+ 'default' => 'null'
+ )
+ );
+ }
+
+ public function getAssets()
+ {
+ return array(
+ 'css' => 'widgets/mails/widget.css',
+ 'js' => 'widgets/mails/widget.js'
+ );
+ }
+}
diff --git a/htdocs/includes/DebugBar/Bridge/Twig/TraceableTwigEnvironment.php b/htdocs/includes/DebugBar/Bridge/Twig/TraceableTwigEnvironment.php
new file mode 100644
index 00000000000..0d4c957f5b2
--- /dev/null
+++ b/htdocs/includes/DebugBar/Bridge/Twig/TraceableTwigEnvironment.php
@@ -0,0 +1,417 @@
+twig = $twig;
+ $this->timeDataCollector = $timeDataCollector;
+ }
+
+ public function __call($name, $arguments)
+ {
+ return call_user_func_array(array($this->twig, $name), $arguments);
+ }
+
+ public function getRenderedTemplates()
+ {
+ return $this->renderedTemplates;
+ }
+
+ public function addRenderedTemplate(array $info)
+ {
+ $this->renderedTemplates[] = $info;
+ }
+
+ public function getTimeDataCollector()
+ {
+ return $this->timeDataCollector;
+ }
+
+ public function getBaseTemplateClass()
+ {
+ return $this->twig->getBaseTemplateClass();
+ }
+
+ public function setBaseTemplateClass($class)
+ {
+ $this->twig->setBaseTemplateClass($class);
+ }
+
+ public function enableDebug()
+ {
+ $this->twig->enableDebug();
+ }
+
+ public function disableDebug()
+ {
+ $this->twig->disableDebug();
+ }
+
+ public function isDebug()
+ {
+ return $this->twig->isDebug();
+ }
+
+ public function enableAutoReload()
+ {
+ $this->twig->enableAutoReload();
+ }
+
+ public function disableAutoReload()
+ {
+ $this->twig->disableAutoReload();
+ }
+
+ public function isAutoReload()
+ {
+ return $this->twig->isAutoReload();
+ }
+
+ public function enableStrictVariables()
+ {
+ $this->twig->enableStrictVariables();
+ }
+
+ public function disableStrictVariables()
+ {
+ $this->twig->disableStrictVariables();
+ }
+
+ public function isStrictVariables()
+ {
+ return $this->twig->isStrictVariables();
+ }
+
+ public function getCache()
+ {
+ return $this->twig->getCache();
+ }
+
+ public function setCache($cache)
+ {
+ $this->twig->setCache($cache);
+ }
+
+ public function getCacheFilename($name)
+ {
+ return $this->twig->getCacheFilename($name);
+ }
+
+ public function getTemplateClass($name, $index = null)
+ {
+ return $this->twig->getTemplateClass($name, $index);
+ }
+
+ public function getTemplateClassPrefix()
+ {
+ return $this->twig->getTemplateClassPrefix();
+ }
+
+ public function render($name, array $context = array())
+ {
+ return $this->loadTemplate($name)->render($context);
+ }
+
+ public function display($name, array $context = array())
+ {
+ $this->loadTemplate($name)->display($context);
+ }
+
+ public function loadTemplate($name, $index = null)
+ {
+ $cls = $this->twig->getTemplateClass($name, $index);
+
+ if (isset($this->twig->loadedTemplates[$cls])) {
+ return $this->twig->loadedTemplates[$cls];
+ }
+
+ if (!class_exists($cls, false)) {
+ if (false === $cache = $this->getCacheFilename($name)) {
+ eval('?>'.$this->compileSource($this->getLoader()->getSource($name), $name));
+ } else {
+ if (!is_file($cache) || ($this->isAutoReload() && !$this->isTemplateFresh($name, filemtime($cache)))) {
+ $this->writeCacheFile($cache, $this->compileSource($this->getLoader()->getSource($name), $name));
+ }
+
+ require_once $cache;
+ }
+ }
+
+ if (!$this->twig->runtimeInitialized) {
+ $this->initRuntime();
+ }
+
+ return $this->twig->loadedTemplates[$cls] = new TraceableTwigTemplate($this, new $cls($this));
+ }
+
+ public function isTemplateFresh($name, $time)
+ {
+ return $this->twig->isTemplateFresh($name, $time);
+ }
+
+ public function resolveTemplate($names)
+ {
+ return $this->twig->resolveTemplate($names);
+ }
+
+ public function clearTemplateCache()
+ {
+ $this->twig->clearTemplateCache();
+ }
+
+ public function clearCacheFiles()
+ {
+ $this->twig->clearCacheFiles();
+ }
+
+ public function getLexer()
+ {
+ return $this->twig->getLexer();
+ }
+
+ public function setLexer(Twig_LexerInterface $lexer)
+ {
+ $this->twig->setLexer($lexer);
+ }
+
+ public function tokenize($source, $name = null)
+ {
+ return $this->twig->tokenize($source, $name);
+ }
+
+ public function getParser()
+ {
+ return $this->twig->getParser();
+ }
+
+ public function setParser(Twig_ParserInterface $parser)
+ {
+ $this->twig->setParser($parser);
+ }
+
+ public function parse(Twig_TokenStream $tokens)
+ {
+ return $this->twig->parse($tokens);
+ }
+
+ public function getCompiler()
+ {
+ return $this->twig->getCompiler();
+ }
+
+ public function setCompiler(Twig_CompilerInterface $compiler)
+ {
+ $this->twig->setCompiler($compiler);
+ }
+
+ public function compile(Twig_NodeInterface $node)
+ {
+ return $this->twig->compile($node);
+ }
+
+ public function compileSource($source, $name = null)
+ {
+ return $this->twig->compileSource($source, $name);
+ }
+
+ public function setLoader(Twig_LoaderInterface $loader)
+ {
+ $this->twig->setLoader($loader);
+ }
+
+ public function getLoader()
+ {
+ return $this->twig->getLoader();
+ }
+
+ public function setCharset($charset)
+ {
+ $this->twig->setCharset($charset);
+ }
+
+ public function getCharset()
+ {
+ return $this->twig->getCharset();
+ }
+
+ public function initRuntime()
+ {
+ $this->twig->initRuntime();
+ }
+
+ public function hasExtension($name)
+ {
+ return $this->twig->hasExtension($name);
+ }
+
+ public function getExtension($name)
+ {
+ return $this->twig->getExtension($name);
+ }
+
+ public function addExtension(Twig_ExtensionInterface $extension)
+ {
+ $this->twig->addExtension($extension);
+ }
+
+ public function removeExtension($name)
+ {
+ $this->twig->removeExtension($name);
+ }
+
+ public function setExtensions(array $extensions)
+ {
+ $this->twig->setExtensions($extensions);
+ }
+
+ public function getExtensions()
+ {
+ return $this->twig->getExtensions();
+ }
+
+ public function addTokenParser(Twig_TokenParserInterface $parser)
+ {
+ $this->twig->addTokenParser($parser);
+ }
+
+ public function getTokenParsers()
+ {
+ return $this->twig->getTokenParsers();
+ }
+
+ public function getTags()
+ {
+ return $this->twig->getTags();
+ }
+
+ public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
+ {
+ $this->twig->addNodeVisitor($visitor);
+ }
+
+ public function getNodeVisitors()
+ {
+ return $this->twig->getNodeVisitors();
+ }
+
+ public function addFilter($name, $filter = null)
+ {
+ $this->twig->addFilter($name, $filter);
+ }
+
+ public function getFilter($name)
+ {
+ return $this->twig->getFilter($name);
+ }
+
+ public function registerUndefinedFilterCallback($callable)
+ {
+ $this->twig->registerUndefinedFilterCallback($callable);
+ }
+
+ public function getFilters()
+ {
+ return $this->twig->getFilters();
+ }
+
+ public function addTest($name, $test = null)
+ {
+ $this->twig->addTest($name, $test);
+ }
+
+ public function getTests()
+ {
+ return $this->twig->getTests();
+ }
+
+ public function getTest($name)
+ {
+ return $this->twig->getTest($name);
+ }
+
+ public function addFunction($name, $function = null)
+ {
+ $this->twig->addFunction($name, $function);
+ }
+
+ public function getFunction($name)
+ {
+ return $this->twig->getFunction($name);
+ }
+
+ public function registerUndefinedFunctionCallback($callable)
+ {
+ $this->twig->registerUndefinedFunctionCallback($callable);
+ }
+
+ public function getFunctions()
+ {
+ return $this->twig->getFunctions();
+ }
+
+ public function addGlobal($name, $value)
+ {
+ $this->twig->addGlobal($name, $value);
+ }
+
+ public function getGlobals()
+ {
+ return $this->twig->getGlobals();
+ }
+
+ public function mergeGlobals(array $context)
+ {
+ return $this->twig->mergeGlobals($context);
+ }
+
+ public function getUnaryOperators()
+ {
+ return $this->twig->getUnaryOperators();
+ }
+
+ public function getBinaryOperators()
+ {
+ return $this->twig->getBinaryOperators();
+ }
+
+ public function computeAlternatives($name, $items)
+ {
+ return $this->twig->computeAlternatives($name, $items);
+ }
+}
diff --git a/htdocs/includes/DebugBar/Bridge/Twig/TraceableTwigTemplate.php b/htdocs/includes/DebugBar/Bridge/Twig/TraceableTwigTemplate.php
new file mode 100644
index 00000000000..dab53d15e1f
--- /dev/null
+++ b/htdocs/includes/DebugBar/Bridge/Twig/TraceableTwigTemplate.php
@@ -0,0 +1,131 @@
+env = $env;
+ $this->template = $template;
+ }
+
+ public function __call($name, $arguments)
+ {
+ return call_user_func_array(array($this->template, $name), $arguments);
+ }
+
+ public function getTemplateName()
+ {
+ return $this->template->getTemplateName();
+ }
+
+ public function getEnvironment()
+ {
+ return $this->template->getEnvironment();
+ }
+
+ public function getParent(array $context)
+ {
+ return $this->template->getParent($context);
+ }
+
+ public function isTraitable()
+ {
+ return $this->template->isTraitable();
+ }
+
+ public function displayParentBlock($name, array $context, array $blocks = array())
+ {
+ $this->template->displayParentBlock($name, $context, $blocks);
+ }
+
+ public function displayBlock($name, array $context, array $blocks = array(), $useBlocks = true)
+ {
+ $this->template->displayBlock($name, $context, $blocks, $useBlocks);
+ }
+
+ public function renderParentBlock($name, array $context, array $blocks = array())
+ {
+ return $this->template->renderParentBlock($name, $context, $blocks);
+ }
+
+ public function renderBlock($name, array $context, array $blocks = array(), $useBlocks = true)
+ {
+ return $this->template->renderBlock($name, $context, $blocks, $useBlocks);
+ }
+
+ public function hasBlock($name)
+ {
+ return $this->template->hasBlock($name);
+ }
+
+ public function getBlockNames()
+ {
+ return $this->template->getBlockNames();
+ }
+
+ public function getBlocks()
+ {
+ return $this->template->getBlocks();
+ }
+
+ public function display(array $context, array $blocks = array())
+ {
+ $start = microtime(true);
+ $this->template->display($context, $blocks);
+ $end = microtime(true);
+
+ if ($timeDataCollector = $this->env->getTimeDataCollector()) {
+ $name = sprintf("twig.render(%s)", $this->template->getTemplateName());
+ $timeDataCollector->addMeasure($name, $start, $end);
+ }
+
+ $this->env->addRenderedTemplate(array(
+ 'name' => $this->template->getTemplateName(),
+ 'render_time' => $end - $start
+ ));
+ }
+
+ public function render(array $context)
+ {
+ $level = ob_get_level();
+ ob_start();
+ try {
+ $this->display($context);
+ } catch (Exception $e) {
+ while (ob_get_level() > $level) {
+ ob_end_clean();
+ }
+
+ throw $e;
+ }
+
+ return ob_get_clean();
+ }
+
+ public static function clearCache()
+ {
+ Twig_Template::clearCache();
+ }
+}
diff --git a/htdocs/includes/DebugBar/Bridge/Twig/TwigCollector.php b/htdocs/includes/DebugBar/Bridge/Twig/TwigCollector.php
new file mode 100644
index 00000000000..fde5a3f85ba
--- /dev/null
+++ b/htdocs/includes/DebugBar/Bridge/Twig/TwigCollector.php
@@ -0,0 +1,87 @@
+
+ * $env = new TraceableTwigEnvironment(new Twig_Environment($loader));
+ * $debugbar->addCollector(new TwigCollector($env));
+ *
+ */
+class TwigCollector extends DataCollector implements Renderable, AssetProvider
+{
+ public function __construct(TraceableTwigEnvironment $twig)
+ {
+ $this->twig = $twig;
+ }
+
+ public function collect()
+ {
+ $templates = array();
+ $accuRenderTime = 0;
+
+ foreach ($this->twig->getRenderedTemplates() as $tpl) {
+ $accuRenderTime += $tpl['render_time'];
+ $templates[] = array(
+ 'name' => $tpl['name'],
+ 'render_time' => $tpl['render_time'],
+ 'render_time_str' => $this->formatDuration($tpl['render_time'])
+ );
+ }
+
+ return array(
+ 'nb_templates' => count($templates),
+ 'templates' => $templates,
+ 'accumulated_render_time' => $accuRenderTime,
+ 'accumulated_render_time_str' => $this->formatDuration($accuRenderTime)
+ );
+ }
+
+ public function getName()
+ {
+ return 'twig';
+ }
+
+ public function getWidgets()
+ {
+ return array(
+ 'twig' => array(
+ 'icon' => 'leaf',
+ 'widget' => 'PhpDebugBar.Widgets.TemplatesWidget',
+ 'map' => 'twig',
+ 'default' => '[]'
+ ),
+ 'twig:badge' => array(
+ 'map' => 'twig.nb_templates',
+ 'default' => 0
+ )
+ );
+ }
+
+ public function getAssets()
+ {
+ return array(
+ 'css' => 'widgets/templates/widget.css',
+ 'js' => 'widgets/templates/widget.js'
+ );
+ }
+}
diff --git a/htdocs/includes/DebugBar/DataCollector/AggregatedCollector.php b/htdocs/includes/DebugBar/DataCollector/AggregatedCollector.php
new file mode 100644
index 00000000000..6c8e711ef76
--- /dev/null
+++ b/htdocs/includes/DebugBar/DataCollector/AggregatedCollector.php
@@ -0,0 +1,166 @@
+
+ * $aggcollector = new AggregateCollector('foobar');
+ * $aggcollector->addCollector(new MessagesCollector('msg1'));
+ * $aggcollector->addCollector(new MessagesCollector('msg2'));
+ * $aggcollector['msg1']->addMessage('hello world');
+ *
+ */
+class AggregatedCollector implements DataCollectorInterface, ArrayAccess
+{
+ protected $name;
+
+ protected $mergeProperty;
+
+ protected $sort;
+
+ protected $collectors = array();
+
+ /**
+ * @param string $name
+ * @param string $mergeProperty
+ * @param boolean $sort
+ */
+ public function __construct($name, $mergeProperty = null, $sort = false)
+ {
+ $this->name = $name;
+ $this->mergeProperty = $mergeProperty;
+ $this->sort = $sort;
+ }
+
+ /**
+ * @param DataCollectorInterface $collector
+ */
+ public function addCollector(DataCollectorInterface $collector)
+ {
+ $this->collectors[$collector->getName()] = $collector;
+ }
+
+ /**
+ * @return array
+ */
+ public function getCollectors()
+ {
+ return $this->collectors;
+ }
+
+ /**
+ * Merge data from one of the key/value pair of the collected data
+ *
+ * @param string $property
+ */
+ public function setMergeProperty($property)
+ {
+ $this->mergeProperty = $property;
+ }
+
+ /**
+ * @return string
+ */
+ public function getMergeProperty()
+ {
+ return $this->mergeProperty;
+ }
+
+ /**
+ * Sorts the collected data
+ *
+ * If true, sorts using sort()
+ * If it is a string, sorts the data using the value from a key/value pair of the array
+ *
+ * @param bool|string $sort
+ */
+ public function setSort($sort)
+ {
+ $this->sort = $sort;
+ }
+
+ /**
+ * @return bool|string
+ */
+ public function getSort()
+ {
+ return $this->sort;
+ }
+
+ public function collect()
+ {
+ $aggregate = array();
+ foreach ($this->collectors as $collector) {
+ $data = $collector->collect();
+ if ($this->mergeProperty !== null) {
+ $data = $data[$this->mergeProperty];
+ }
+ $aggregate = array_merge($aggregate, $data);
+ }
+
+ return $this->sort($aggregate);
+ }
+
+ /**
+ * Sorts the collected data
+ *
+ * @param array $data
+ * @return array
+ */
+ protected function sort($data)
+ {
+ if (is_string($this->sort)) {
+ $p = $this->sort;
+ usort($data, function ($a, $b) use ($p) {
+ if ($a[$p] == $b[$p]) {
+ return 0;
+ }
+ return $a[$p] < $b[$p] ? -1 : 1;
+ });
+ } elseif ($this->sort === true) {
+ sort($data);
+ }
+ return $data;
+ }
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ // --------------------------------------------
+ // ArrayAccess implementation
+
+ public function offsetSet($key, $value)
+ {
+ throw new DebugBarException("AggregatedCollector[] is read-only");
+ }
+
+ public function offsetGet($key)
+ {
+ return $this->collectors[$key];
+ }
+
+ public function offsetExists($key)
+ {
+ return isset($this->collectors[$key]);
+ }
+
+ public function offsetUnset($key)
+ {
+ throw new DebugBarException("AggregatedCollector[] is read-only");
+ }
+}
diff --git a/htdocs/includes/DebugBar/DataCollector/AssetProvider.php b/htdocs/includes/DebugBar/DataCollector/AssetProvider.php
new file mode 100644
index 00000000000..6910f737e17
--- /dev/null
+++ b/htdocs/includes/DebugBar/DataCollector/AssetProvider.php
@@ -0,0 +1,28 @@
+name = $name;
+ $this->data = $data;
+ }
+
+ /**
+ * Sets the data
+ *
+ * @param array $data
+ */
+ public function setData(array $data)
+ {
+ $this->data = $data;
+ }
+
+ public function collect()
+ {
+ $data = array();
+ foreach ($this->data as $k => $v) {
+ if (!is_string($v)) {
+ $v = $this->getDataFormatter()->formatVar($v);
+ }
+ $data[$k] = $v;
+ }
+ return $data;
+ }
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function getWidgets()
+ {
+ $name = $this->getName();
+ return array(
+ "$name" => array(
+ "icon" => "gear",
+ "widget" => "PhpDebugBar.Widgets.VariableListWidget",
+ "map" => "$name",
+ "default" => "{}"
+ )
+ );
+ }
+}
diff --git a/htdocs/includes/DebugBar/DataCollector/DataCollector.php b/htdocs/includes/DebugBar/DataCollector/DataCollector.php
new file mode 100644
index 00000000000..081f66e6872
--- /dev/null
+++ b/htdocs/includes/DebugBar/DataCollector/DataCollector.php
@@ -0,0 +1,90 @@
+dataFormater = $formater;
+ return $this;
+ }
+
+ public function getDataFormatter()
+ {
+ if ($this->dataFormater === null) {
+ $this->dataFormater = self::getDefaultDataFormatter();
+ }
+ return $this->dataFormater;
+ }
+
+ /**
+ * @deprecated
+ */
+ public function formatVar($var)
+ {
+ return $this->getDataFormatter()->formatVar($var);
+ }
+
+ /**
+ * @deprecated
+ */
+ public function formatDuration($seconds)
+ {
+ return $this->getDataFormatter()->formatDuration($seconds);
+ }
+
+ /**
+ * @deprecated
+ */
+ public function formatBytes($size, $precision = 2)
+ {
+ return $this->getDataFormatter()->formatBytes($size, $precision);
+ }
+}
diff --git a/htdocs/includes/DebugBar/DataCollector/DataCollectorInterface.php b/htdocs/includes/DebugBar/DataCollector/DataCollectorInterface.php
new file mode 100644
index 00000000000..b7f234cbff9
--- /dev/null
+++ b/htdocs/includes/DebugBar/DataCollector/DataCollectorInterface.php
@@ -0,0 +1,31 @@
+exceptions[] = $e;
+ if ($this->chainExceptions && $previous = $e->getPrevious()) {
+ $this->addException($previous);
+ }
+ }
+
+ /**
+ * Configure whether or not all chained exceptions should be shown.
+ *
+ * @param bool $chainExceptions
+ */
+ public function setChainExceptions($chainExceptions = true)
+ {
+ $this->chainExceptions = $chainExceptions;
+ }
+
+ /**
+ * Returns the list of exceptions being profiled
+ *
+ * @return array[Exception]
+ */
+ public function getExceptions()
+ {
+ return $this->exceptions;
+ }
+
+ public function collect()
+ {
+ return array(
+ 'count' => count($this->exceptions),
+ 'exceptions' => array_map(array($this, 'formatExceptionData'), $this->exceptions)
+ );
+ }
+
+ /**
+ * Returns exception data as an array
+ *
+ * @param Exception $e
+ * @return array
+ */
+ public function formatExceptionData(Exception $e)
+ {
+ $filePath = $e->getFile();
+ if ($filePath && file_exists($filePath)) {
+ $lines = file($filePath);
+ $start = $e->getLine() - 4;
+ $lines = array_slice($lines, $start < 0 ? 0 : $start, 7);
+ } else {
+ $lines = array("Cannot open the file ($filePath) in which the exception occurred ");
+ }
+
+ return array(
+ 'type' => get_class($e),
+ 'message' => $e->getMessage(),
+ 'code' => $e->getCode(),
+ 'file' => $filePath,
+ 'line' => $e->getLine(),
+ 'surrounding_lines' => $lines
+ );
+ }
+
+ public function getName()
+ {
+ return 'exceptions';
+ }
+
+ public function getWidgets()
+ {
+ return array(
+ 'exceptions' => array(
+ 'icon' => 'bug',
+ 'widget' => 'PhpDebugBar.Widgets.ExceptionsWidget',
+ 'map' => 'exceptions.exceptions',
+ 'default' => '[]'
+ ),
+ 'exceptions:badge' => array(
+ 'map' => 'exceptions.count',
+ 'default' => 'null'
+ )
+ );
+ }
+}
diff --git a/htdocs/includes/DebugBar/DataCollector/LocalizationCollector.php b/htdocs/includes/DebugBar/DataCollector/LocalizationCollector.php
new file mode 100644
index 00000000000..98b9e6334b2
--- /dev/null
+++ b/htdocs/includes/DebugBar/DataCollector/LocalizationCollector.php
@@ -0,0 +1,64 @@
+ $this->getLocale(),
+ 'domain' => $this->getDomain(),
+ );
+ }
+
+ public function getName()
+ {
+ return 'localization';
+ }
+
+ public function getWidgets()
+ {
+ return array(
+ 'domain' => array(
+ 'icon' => 'bookmark',
+ 'map' => 'localization.domain',
+ ),
+ 'locale' => array(
+ 'icon' => 'flag',
+ 'map' => 'localization.locale',
+ )
+ );
+ }
+}
diff --git a/htdocs/includes/DebugBar/DataCollector/MemoryCollector.php b/htdocs/includes/DebugBar/DataCollector/MemoryCollector.php
new file mode 100644
index 00000000000..1a27c40bf3a
--- /dev/null
+++ b/htdocs/includes/DebugBar/DataCollector/MemoryCollector.php
@@ -0,0 +1,63 @@
+peakUsage;
+ }
+
+ /**
+ * Updates the peak memory usage value
+ */
+ public function updatePeakUsage()
+ {
+ $this->peakUsage = memory_get_peak_usage(true);
+ }
+
+ public function collect()
+ {
+ $this->updatePeakUsage();
+ return array(
+ 'peak_usage' => $this->peakUsage,
+ 'peak_usage_str' => $this->getDataFormatter()->formatBytes($this->peakUsage)
+ );
+ }
+
+ public function getName()
+ {
+ return 'memory';
+ }
+
+ public function getWidgets()
+ {
+ return array(
+ "memory" => array(
+ "icon" => "cogs",
+ "tooltip" => "Memory Usage",
+ "map" => "memory.peak_usage_str",
+ "default" => "'0B'"
+ )
+ );
+ }
+}
diff --git a/htdocs/includes/DebugBar/DataCollector/MessagesAggregateInterface.php b/htdocs/includes/DebugBar/DataCollector/MessagesAggregateInterface.php
new file mode 100644
index 00000000000..1e2d4d2d3f2
--- /dev/null
+++ b/htdocs/includes/DebugBar/DataCollector/MessagesAggregateInterface.php
@@ -0,0 +1,21 @@
+name = $name;
+ }
+
+ /**
+ * Sets the data formater instance used by this collector
+ *
+ * @param DataFormatterInterface $formater
+ */
+ public function setDataFormatter(DataFormatterInterface $formater)
+ {
+ $this->dataFormater = $formater;
+ return $this;
+ }
+
+ public function getDataFormatter()
+ {
+ if ($this->dataFormater === null) {
+ $this->dataFormater = DataCollector::getDefaultDataFormatter();
+ }
+ return $this->dataFormater;
+ }
+
+ /**
+ * Adds a message
+ *
+ * A message can be anything from an object to a string
+ *
+ * @param mixed $message
+ * @param string $label
+ */
+ public function addMessage($message, $label = 'info', $isString = true)
+ {
+ if (!is_string($message)) {
+ $message = $this->getDataFormatter()->formatVar($message);
+ $isString = false;
+ }
+ $this->messages[] = array(
+ 'message' => $message,
+ 'is_string' => $isString,
+ 'label' => $label,
+ 'time' => microtime(true)
+ );
+ }
+
+ /**
+ * Aggregates messages from other collectors
+ *
+ * @param MessagesAggregateInterface $messages
+ */
+ public function aggregate(MessagesAggregateInterface $messages)
+ {
+ $this->aggregates[] = $messages;
+ }
+
+ public function getMessages()
+ {
+ $messages = $this->messages;
+ foreach ($this->aggregates as $collector) {
+ $msgs = array_map(function ($m) use ($collector) {
+ $m['collector'] = $collector->getName();
+ return $m;
+ }, $collector->getMessages());
+ $messages = array_merge($messages, $msgs);
+ }
+
+ // sort messages by their timestamp
+ usort($messages, function ($a, $b) {
+ if ($a['time'] === $b['time']) {
+ return 0;
+ }
+ return $a['time'] < $b['time'] ? -1 : 1;
+ });
+
+ return $messages;
+ }
+
+ public function log($level, $message, array $context = array())
+ {
+ $this->addMessage($message, $level);
+ }
+
+ /**
+ * Deletes all messages
+ */
+ public function clear()
+ {
+ $this->messages = array();
+ }
+
+ public function collect()
+ {
+ $messages = $this->getMessages();
+ return array(
+ 'count' => count($messages),
+ 'messages' => $messages
+ );
+ }
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function getWidgets()
+ {
+ $name = $this->getName();
+ return array(
+ "$name" => array(
+ 'icon' => 'list-alt',
+ "widget" => "PhpDebugBar.Widgets.MessagesWidget",
+ "map" => "$name.messages",
+ "default" => "[]"
+ ),
+ "$name:badge" => array(
+ "map" => "$name.count",
+ "default" => "null"
+ )
+ );
+ }
+}
diff --git a/htdocs/includes/DebugBar/DataCollector/PDO/PDOCollector.php b/htdocs/includes/DebugBar/DataCollector/PDO/PDOCollector.php
new file mode 100644
index 00000000000..37e7b020b1f
--- /dev/null
+++ b/htdocs/includes/DebugBar/DataCollector/PDO/PDOCollector.php
@@ -0,0 +1,182 @@
+';
+
+ /**
+ * @param TraceablePDO $pdo
+ * @param TimeDataCollector $timeCollector
+ */
+ public function __construct(TraceablePDO $pdo = null, TimeDataCollector $timeCollector = null)
+ {
+ $this->timeCollector = $timeCollector;
+ if ($pdo !== null) {
+ $this->addConnection($pdo, 'default');
+ }
+ }
+
+ /**
+ * Renders the SQL of traced statements with params embeded
+ *
+ * @param boolean $enabled
+ */
+ public function setRenderSqlWithParams($enabled = true, $quotationChar = '<>')
+ {
+ $this->renderSqlWithParams = $enabled;
+ $this->sqlQuotationChar = $quotationChar;
+ }
+
+ public function isSqlRenderedWithParams()
+ {
+ return $this->renderSqlWithParams;
+ }
+
+ public function getSqlQuotationChar()
+ {
+ return $this->sqlQuotationChar;
+ }
+
+ /**
+ * Adds a new PDO instance to be collector
+ *
+ * @param TraceablePDO $pdo
+ * @param string $name Optional connection name
+ */
+ public function addConnection(TraceablePDO $pdo, $name = null)
+ {
+ if ($name === null) {
+ $name = spl_object_hash($pdo);
+ }
+ $this->connections[$name] = $pdo;
+ }
+
+ /**
+ * Returns PDO instances to be collected
+ *
+ * @return array
+ */
+ public function getConnections()
+ {
+ return $this->connections;
+ }
+
+ public function collect()
+ {
+ $data = array(
+ 'nb_statements' => 0,
+ 'nb_failed_statements' => 0,
+ 'accumulated_duration' => 0,
+ 'memory_usage' => 0,
+ 'peak_memory_usage' => 0,
+ 'statements' => array()
+ );
+
+ foreach ($this->connections as $name => $pdo) {
+ $pdodata = $this->collectPDO($pdo, $this->timeCollector);
+ $data['nb_statements'] += $pdodata['nb_statements'];
+ $data['nb_failed_statements'] += $pdodata['nb_failed_statements'];
+ $data['accumulated_duration'] += $pdodata['accumulated_duration'];
+ $data['memory_usage'] += $pdodata['memory_usage'];
+ $data['peak_memory_usage'] = max($data['peak_memory_usage'], $pdodata['peak_memory_usage']);
+ $data['statements'] = array_merge($data['statements'],
+ array_map(function ($s) use ($name) { $s['connection'] = $name; return $s; }, $pdodata['statements']));
+ }
+
+ $data['accumulated_duration_str'] = $this->getDataFormatter()->formatDuration($data['accumulated_duration']);
+ $data['memory_usage_str'] = $this->getDataFormatter()->formatBytes($data['memory_usage']);
+ $data['peak_memory_usage_str'] = $this->getDataFormatter()->formatBytes($data['peak_memory_usage']);
+
+ return $data;
+ }
+
+ /**
+ * Collects data from a single TraceablePDO instance
+ *
+ * @param TraceablePDO $pdo
+ * @param TimeDataCollector $timeCollector
+ * @return array
+ */
+ protected function collectPDO(TraceablePDO $pdo, TimeDataCollector $timeCollector = null)
+ {
+ $stmts = array();
+ foreach ($pdo->getExecutedStatements() as $stmt) {
+ $stmts[] = array(
+ 'sql' => $this->renderSqlWithParams ? $stmt->getSqlWithParams($this->sqlQuotationChar) : $stmt->getSql(),
+ 'row_count' => $stmt->getRowCount(),
+ 'stmt_id' => $stmt->getPreparedId(),
+ 'prepared_stmt' => $stmt->getSql(),
+ 'params' => (object) $stmt->getParameters(),
+ 'duration' => $stmt->getDuration(),
+ 'duration_str' => $this->getDataFormatter()->formatDuration($stmt->getDuration()),
+ 'memory' => $stmt->getMemoryUsage(),
+ 'memory_str' => $this->getDataFormatter()->formatBytes($stmt->getMemoryUsage()),
+ 'end_memory' => $stmt->getEndMemory(),
+ 'end_memory_str' => $this->getDataFormatter()->formatBytes($stmt->getEndMemory()),
+ 'is_success' => $stmt->isSuccess(),
+ 'error_code' => $stmt->getErrorCode(),
+ 'error_message' => $stmt->getErrorMessage()
+ );
+ if ($timeCollector !== null) {
+ $timeCollector->addMeasure($stmt->getSql(), $stmt->getStartTime(), $stmt->getEndTime());
+ }
+ }
+
+ return array(
+ 'nb_statements' => count($stmts),
+ 'nb_failed_statements' => count($pdo->getFailedExecutedStatements()),
+ 'accumulated_duration' => $pdo->getAccumulatedStatementsDuration(),
+ 'accumulated_duration_str' => $this->getDataFormatter()->formatDuration($pdo->getAccumulatedStatementsDuration()),
+ 'memory_usage' => $pdo->getMemoryUsage(),
+ 'memory_usage_str' => $this->getDataFormatter()->formatBytes($pdo->getPeakMemoryUsage()),
+ 'peak_memory_usage' => $pdo->getPeakMemoryUsage(),
+ 'peak_memory_usage_str' => $this->getDataFormatter()->formatBytes($pdo->getPeakMemoryUsage()),
+ 'statements' => $stmts
+ );
+ }
+
+ public function getName()
+ {
+ return 'pdo';
+ }
+
+ public function getWidgets()
+ {
+ return array(
+ "database" => array(
+ "icon" => "inbox",
+ "widget" => "PhpDebugBar.Widgets.SQLQueriesWidget",
+ "map" => "pdo",
+ "default" => "[]"
+ ),
+ "database:badge" => array(
+ "map" => "pdo.nb_statements",
+ "default" => 0
+ )
+ );
+ }
+
+ public function getAssets()
+ {
+ return array(
+ 'css' => 'widgets/sqlqueries/widget.css',
+ 'js' => 'widgets/sqlqueries/widget.js'
+ );
+ }
+}
diff --git a/htdocs/includes/DebugBar/DataCollector/PDO/TraceablePDO.php b/htdocs/includes/DebugBar/DataCollector/PDO/TraceablePDO.php
new file mode 100644
index 00000000000..5f7688b978e
--- /dev/null
+++ b/htdocs/includes/DebugBar/DataCollector/PDO/TraceablePDO.php
@@ -0,0 +1,196 @@
+pdo = $pdo;
+ $this->pdo->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('DebugBar\DataCollector\PDO\TraceablePDOStatement', array($this)));
+ }
+
+ public function beginTransaction()
+ {
+ return $this->pdo->beginTransaction();
+ }
+
+ public function commit()
+ {
+ return $this->pdo->commit();
+ }
+
+ public function errorCode()
+ {
+ return $this->pdo->errorCode();
+ }
+
+ public function errorInfo()
+ {
+ return $this->pdo->errorInfo();
+ }
+
+ public function exec($sql)
+ {
+ return $this->profileCall('exec', $sql, func_get_args());
+ }
+
+ public function getAttribute($attr)
+ {
+ return $this->pdo->getAttribute($attr);
+ }
+
+ public function inTransaction()
+ {
+ return $this->pdo->inTransaction();
+ }
+
+ public function lastInsertId($name = null)
+ {
+ return $this->pdo->lastInsertId($name);
+ }
+
+ public function prepare($sql, $driver_options = array())
+ {
+ return $this->pdo->prepare($sql, $driver_options);
+ }
+
+ public function query($sql)
+ {
+ return $this->profileCall('query', $sql, func_get_args());
+ }
+
+ public function quote($expr, $parameter_type = PDO::PARAM_STR)
+ {
+ return $this->pdo->quote($expr, $parameter_type);
+ }
+
+ public function rollBack()
+ {
+ return $this->pdo->rollBack();
+ }
+
+ public function setAttribute($attr, $value)
+ {
+ return $this->pdo->setAttribute($attr, $value);
+ }
+
+ /**
+ * Profiles a call to a PDO method
+ *
+ * @param string $method
+ * @param string $sql
+ * @param array $args
+ * @return mixed The result of the call
+ */
+ protected function profileCall($method, $sql, array $args)
+ {
+ $trace = new TracedStatement($sql);
+ $trace->start();
+
+ $ex = null;
+ try {
+ $result = call_user_func_array(array($this->pdo, $method), $args);
+ } catch (PDOException $e) {
+ $ex = $e;
+ }
+
+ if ($this->pdo->getAttribute(PDO::ATTR_ERRMODE) !== PDO::ERRMODE_EXCEPTION && $result === false) {
+ $error = $this->pdo->errorInfo();
+ $ex = new PDOException($error[2], $error[0]);
+ }
+
+ $trace->end($ex);
+ $this->addExecutedStatement($trace);
+
+ if ($this->pdo->getAttribute(PDO::ATTR_ERRMODE) === PDO::ERRMODE_EXCEPTION && $ex !== null) {
+ throw $ex;
+ }
+ return $result;
+ }
+
+ /**
+ * Adds an executed TracedStatement
+ *
+ * @param TracedStatement $stmt
+ */
+ public function addExecutedStatement(TracedStatement $stmt)
+ {
+ $this->executedStatements[] = $stmt;
+ }
+
+ /**
+ * Returns the accumulated execution time of statements
+ *
+ * @return int
+ */
+ public function getAccumulatedStatementsDuration()
+ {
+ return array_reduce($this->executedStatements, function ($v, $s) { return $v + $s->getDuration(); });
+ }
+
+ /**
+ * Returns the peak memory usage while performing statements
+ *
+ * @return int
+ */
+ public function getMemoryUsage()
+ {
+ return array_reduce($this->executedStatements, function ($v, $s) { return $v + $s->getMemoryUsage(); });
+ }
+
+ /**
+ * Returns the peak memory usage while performing statements
+ *
+ * @return int
+ */
+ public function getPeakMemoryUsage()
+ {
+ return array_reduce($this->executedStatements, function ($v, $s) { $m = $s->getEndMemory(); return $m > $v ? $m : $v; });
+ }
+
+ /**
+ * Returns the list of executed statements as TracedStatement objects
+ *
+ * @return array
+ */
+ public function getExecutedStatements()
+ {
+ return $this->executedStatements;
+ }
+
+ /**
+ * Returns the list of failed statements
+ *
+ * @return array
+ */
+ public function getFailedExecutedStatements()
+ {
+ return array_filter($this->executedStatements, function ($s) { return !$s->isSuccess(); });
+ }
+
+ public function __get($name)
+ {
+ return $this->pdo->$name;
+ }
+
+ public function __set($name, $value)
+ {
+ $this->pdo->$name = $value;
+ }
+
+ public function __call($name, $args)
+ {
+ return call_user_func_array(array($this->pdo, $name), $args);
+ }
+}
diff --git a/htdocs/includes/DebugBar/DataCollector/PDO/TraceablePDOStatement.php b/htdocs/includes/DebugBar/DataCollector/PDO/TraceablePDOStatement.php
new file mode 100644
index 00000000000..b903b10c361
--- /dev/null
+++ b/htdocs/includes/DebugBar/DataCollector/PDO/TraceablePDOStatement.php
@@ -0,0 +1,74 @@
+pdo = $pdo;
+ }
+
+ public function bindColumn($column, &$param, $type = null, $maxlen = null, $driverdata = null)
+ {
+ $this->boundParameters[$column] = $param;
+ $args = array_merge(array($column, &$param), array_slice(func_get_args(), 2));
+ return call_user_func_array(array("parent", 'bindColumn'), $args);
+ }
+
+ public function bindParam($param, &$var, $data_type = PDO::PARAM_STR, $length = null, $driver_options = null)
+ {
+ $this->boundParameters[$param] = $var;
+ $args = array_merge(array($param, &$var), array_slice(func_get_args(), 2));
+ return call_user_func_array(array("parent", 'bindParam'), $args);
+ }
+
+ public function bindValue($param, $value, $data_type = PDO::PARAM_STR)
+ {
+ $this->boundParameters[$param] = $value;
+ return call_user_func_array(array("parent", 'bindValue'), func_get_args());
+ }
+
+ public function execute($params = null)
+ {
+ $preparedId = spl_object_hash($this);
+ $boundParameters = $this->boundParameters;
+ if (is_array($params)) {
+ $boundParameters = array_merge($boundParameters, $params);
+ }
+
+ $trace = new TracedStatement($this->queryString, $boundParameters, $preparedId);
+ $trace->start();
+
+ $ex = null;
+ try {
+ $result = parent::execute($params);
+ } catch (PDOException $e) {
+ $ex = $e;
+ }
+
+ if ($this->pdo->getAttribute(PDO::ATTR_ERRMODE) !== PDO::ERRMODE_EXCEPTION && $result === false) {
+ $error = $this->errorInfo();
+ $ex = new PDOException($error[2], $error[0]);
+ }
+
+ $trace->end($ex, $this->rowCount());
+ $this->pdo->addExecutedStatement($trace);
+
+ if ($this->pdo->getAttribute(PDO::ATTR_ERRMODE) === PDO::ERRMODE_EXCEPTION && $ex !== null) {
+ throw $ex;
+ }
+ return $result;
+ }
+}
diff --git a/htdocs/includes/DebugBar/DataCollector/PDO/TracedStatement.php b/htdocs/includes/DebugBar/DataCollector/PDO/TracedStatement.php
new file mode 100644
index 00000000000..dc51cee1764
--- /dev/null
+++ b/htdocs/includes/DebugBar/DataCollector/PDO/TracedStatement.php
@@ -0,0 +1,240 @@
+sql = $sql;
+ $this->parameters = $this->checkParameters($params);
+ $this->preparedId = $preparedId;
+ }
+
+ public function start($startTime = null, $startMemory = null)
+ {
+ $this->startTime = $startTime ?: microtime(true);
+ $this->startMemory = $startMemory ?: memory_get_usage(true);
+ }
+
+ public function end(\Exception $exception = null, $rowCount = 0, $endTime = null, $endMemory = null)
+ {
+ $this->endTime = $endTime ?: microtime(true);
+ $this->duration = $this->endTime - $this->startTime;
+ $this->endMemory = $endMemory ?: memory_get_usage(true);
+ $this->memoryDelta = $this->endMemory - $this->startMemory;
+ $this->exception = $exception;
+ $this->rowCount = $rowCount;
+ }
+
+ /**
+ * Check parameters for illegal (non UTF-8) strings, like Binary data.
+ *
+ * @param $params
+ * @return mixed
+ */
+ public function checkParameters($params)
+ {
+ foreach ($params as &$param) {
+ if (!mb_check_encoding($param, 'UTF-8')) {
+ $param = '[BINARY DATA]';
+ }
+ }
+ return $params;
+ }
+
+ /**
+ * Returns the SQL string used for the query
+ *
+ * @return string
+ */
+ public function getSql()
+ {
+ return $this->sql;
+ }
+
+ /**
+ * Returns the SQL string with any parameters used embedded
+ *
+ * @param string $quotationChar
+ * @return string
+ */
+ public function getSqlWithParams($quotationChar = '<>')
+ {
+ if (($l = strlen($quotationChar)) > 1) {
+ $quoteLeft = substr($quotationChar, 0, $l / 2);
+ $quoteRight = substr($quotationChar, $l / 2);
+ } else {
+ $quoteLeft = $quoteRight = $quotationChar;
+ }
+
+ $sql = $this->sql;
+ foreach ($this->parameters as $k => $v) {
+ $v = "$quoteLeft$v$quoteRight";
+ if (!is_numeric($k)) {
+ $sql = str_replace($k, $v, $sql);
+ } else {
+ $p = strpos($sql, '?');
+ $sql = substr($sql, 0, $p) . $v. substr($sql, $p + 1);
+ }
+ }
+ return $sql;
+ }
+
+ /**
+ * Returns the number of rows affected/returned
+ *
+ * @return int
+ */
+ public function getRowCount()
+ {
+ return $this->rowCount;
+ }
+
+ /**
+ * Returns an array of parameters used with the query
+ *
+ * @return array
+ */
+ public function getParameters()
+ {
+ $params = array();
+ foreach ($this->parameters as $param) {
+ $params[] = htmlentities($param, ENT_QUOTES, 'UTF-8', false);
+ }
+ return $params;
+ }
+
+ /**
+ * Returns the prepared statement id
+ *
+ * @return string
+ */
+ public function getPreparedId()
+ {
+ return $this->preparedId;
+ }
+
+ /**
+ * Checks if this is a prepared statement
+ *
+ * @return boolean
+ */
+ public function isPrepared()
+ {
+ return $this->preparedId !== null;
+ }
+
+ public function getStartTime()
+ {
+ return $this->startTime;
+ }
+
+ public function getEndTime()
+ {
+ return $this->endTime;
+ }
+
+ /**
+ * Returns the duration in seconds of the execution
+ *
+ * @return int
+ */
+ public function getDuration()
+ {
+ return $this->duration;
+ }
+
+ public function getStartMemory()
+ {
+ return $this->startMemory;
+ }
+
+ public function getEndMemory()
+ {
+ return $this->endMemory;
+ }
+
+ /**
+ * Returns the memory usage during the execution
+ *
+ * @return int
+ */
+ public function getMemoryUsage()
+ {
+ return $this->memoryDelta;
+ }
+
+ /**
+ * Checks if the statement was successful
+ *
+ * @return boolean
+ */
+ public function isSuccess()
+ {
+ return $this->exception === null;
+ }
+
+ /**
+ * Returns the exception triggered
+ *
+ * @return \Exception
+ */
+ public function getException()
+ {
+ return $this->exception;
+ }
+
+ /**
+ * Returns the exception's code
+ *
+ * @return string
+ */
+ public function getErrorCode()
+ {
+ return $this->exception !== null ? $this->exception->getCode() : 0;
+ }
+
+ /**
+ * Returns the exception's message
+ *
+ * @return string
+ */
+ public function getErrorMessage()
+ {
+ return $this->exception !== null ? $this->exception->getMessage() : '';
+ }
+}
diff --git a/htdocs/includes/DebugBar/DataCollector/PhpInfoCollector.php b/htdocs/includes/DebugBar/DataCollector/PhpInfoCollector.php
new file mode 100644
index 00000000000..57e9e45f47f
--- /dev/null
+++ b/htdocs/includes/DebugBar/DataCollector/PhpInfoCollector.php
@@ -0,0 +1,51 @@
+ PHP_VERSION,
+ 'interface' => PHP_SAPI
+ );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getWidgets()
+ {
+ return array(
+ "php_version" => array(
+ "icon" => "code",
+ "tooltip" => "Version",
+ "map" => "php.version",
+ "default" => ""
+ ),
+ );
+ }
+}
diff --git a/htdocs/includes/DebugBar/DataCollector/Renderable.php b/htdocs/includes/DebugBar/DataCollector/Renderable.php
new file mode 100644
index 00000000000..1a6a833f5d1
--- /dev/null
+++ b/htdocs/includes/DebugBar/DataCollector/Renderable.php
@@ -0,0 +1,25 @@
+getDataFormatter()->formatVar($GLOBALS[$var]);
+ }
+ }
+
+ return $data;
+ }
+
+ public function getName()
+ {
+ return 'request';
+ }
+
+ public function getWidgets()
+ {
+ return array(
+ "request" => array(
+ "icon" => "tags",
+ "widget" => "PhpDebugBar.Widgets.VariableListWidget",
+ "map" => "request",
+ "default" => "{}"
+ )
+ );
+ }
+}
diff --git a/htdocs/includes/DebugBar/DataCollector/TimeDataCollector.php b/htdocs/includes/DebugBar/DataCollector/TimeDataCollector.php
new file mode 100644
index 00000000000..19e5a63ced1
--- /dev/null
+++ b/htdocs/includes/DebugBar/DataCollector/TimeDataCollector.php
@@ -0,0 +1,228 @@
+requestStartTime = $requestStartTime;
+ }
+
+ /**
+ * Starts a measure
+ *
+ * @param string $name Internal name, used to stop the measure
+ * @param string|null $label Public name
+ * @param string|null $collector The source of the collector
+ */
+ public function startMeasure($name, $label = null, $collector = null)
+ {
+ $start = microtime(true);
+ $this->startedMeasures[$name] = array(
+ 'label' => $label ?: $name,
+ 'start' => $start,
+ 'collector' => $collector
+ );
+ }
+
+ /**
+ * Check a measure exists
+ *
+ * @param string $name
+ * @return bool
+ */
+ public function hasStartedMeasure($name)
+ {
+ return isset($this->startedMeasures[$name]);
+ }
+
+ /**
+ * Stops a measure
+ *
+ * @param string $name
+ * @param array $params
+ * @throws DebugBarException
+ */
+ public function stopMeasure($name, $params = array())
+ {
+ $end = microtime(true);
+ if (!$this->hasStartedMeasure($name)) {
+ throw new DebugBarException("Failed stopping measure '$name' because it hasn't been started");
+ }
+ $this->addMeasure(
+ $this->startedMeasures[$name]['label'],
+ $this->startedMeasures[$name]['start'],
+ $end,
+ $params,
+ $this->startedMeasures[$name]['collector']
+ );
+ unset($this->startedMeasures[$name]);
+ }
+
+ /**
+ * Adds a measure
+ *
+ * @param string $label
+ * @param float $start
+ * @param float $end
+ * @param array $params
+ * @param string|null $collector
+ */
+ public function addMeasure($label, $start, $end, $params = array(), $collector = null)
+ {
+ $this->measures[] = array(
+ 'label' => $label,
+ 'start' => $start,
+ 'relative_start' => $start - $this->requestStartTime,
+ 'end' => $end,
+ 'relative_end' => $end - $this->requestEndTime,
+ 'duration' => $end - $start,
+ 'duration_str' => $this->getDataFormatter()->formatDuration($end - $start),
+ 'params' => $params,
+ 'collector' => $collector
+ );
+ }
+
+ /**
+ * Utility function to measure the execution of a Closure
+ *
+ * @param string $label
+ * @param \Closure $closure
+ * @param string|null $collector
+ */
+ public function measure($label, \Closure $closure, $collector = null)
+ {
+ $name = spl_object_hash($closure);
+ $this->startMeasure($name, $label, $collector);
+ $result = $closure();
+ $params = is_array($result) ? $result : array();
+ $this->stopMeasure($name, $params);
+ }
+
+ /**
+ * Returns an array of all measures
+ *
+ * @return array
+ */
+ public function getMeasures()
+ {
+ return $this->measures;
+ }
+
+ /**
+ * Returns the request start time
+ *
+ * @return float
+ */
+ public function getRequestStartTime()
+ {
+ return $this->requestStartTime;
+ }
+
+ /**
+ * Returns the request end time
+ *
+ * @return float
+ */
+ public function getRequestEndTime()
+ {
+ return $this->requestEndTime;
+ }
+
+ /**
+ * Returns the duration of a request
+ *
+ * @return float
+ */
+ public function getRequestDuration()
+ {
+ if ($this->requestEndTime !== null) {
+ return $this->requestEndTime - $this->requestStartTime;
+ }
+ return microtime(true) - $this->requestStartTime;
+ }
+
+ public function collect()
+ {
+ $this->requestEndTime = microtime(true);
+ foreach (array_keys($this->startedMeasures) as $name) {
+ $this->stopMeasure($name);
+ }
+
+ return array(
+ 'start' => $this->requestStartTime,
+ 'end' => $this->requestEndTime,
+ 'duration' => $this->getRequestDuration(),
+ 'duration_str' => $this->getDataFormatter()->formatDuration($this->getRequestDuration()),
+ 'measures' => array_values($this->measures)
+ );
+ }
+
+ public function getName()
+ {
+ return 'time';
+ }
+
+ public function getWidgets()
+ {
+ return array(
+ "time" => array(
+ "icon" => "clock-o",
+ "tooltip" => "Request Duration",
+ "map" => "time.duration_str",
+ "default" => "'0ms'"
+ ),
+ "timeline" => array(
+ "icon" => "tasks",
+ "widget" => "PhpDebugBar.Widgets.TimelineWidget",
+ "map" => "time",
+ "default" => "{}"
+ )
+ );
+ }
+}
diff --git a/htdocs/includes/DebugBar/DataFormatter/DataFormatter.php b/htdocs/includes/DebugBar/DataFormatter/DataFormatter.php
new file mode 100644
index 00000000000..73269459838
--- /dev/null
+++ b/htdocs/includes/DebugBar/DataFormatter/DataFormatter.php
@@ -0,0 +1,169 @@
+kintLite($data);
+ }
+
+ public function formatDuration($seconds)
+ {
+ if ($seconds < 0.001) {
+ return round($seconds * 1000000) . 'μs';
+ } elseif ($seconds < 1) {
+ return round($seconds * 1000, 2) . 'ms';
+ }
+ return round($seconds, 2) . 's';
+ }
+
+ public function formatBytes($size, $precision = 2)
+ {
+ if ($size === 0 || $size === null) {
+ return "0B";
+ }
+ $base = log($size) / log(1024);
+ $suffixes = array('B', 'KB', 'MB', 'GB', 'TB');
+ return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
+ }
+
+ /**
+ * lightweight version of Kint::dump(). Uses whitespace for formatting instead of html
+ * sadly not DRY yet
+ *
+ * Extracted from Kint.class.php in raveren/kint, https://github.com/raveren/kint
+ * Copyright (c) 2013 Rokas Šleinius (raveren@gmail.com)
+ *
+ * @param mixed $var
+ * @param int $level
+ *
+ * @return string
+ */
+ protected function kintLite(&$var, $level = 0)
+ {
+ // initialize function names into variables for prettier string output (html and implode are also DRY)
+ $html = "htmlspecialchars";
+ $implode = "implode";
+ $strlen = "strlen";
+ $count = "count";
+ $getClass = "get_class";
+
+ if ( $var === null ) {
+ return 'NULL';
+ } elseif ( is_bool( $var ) ) {
+ return 'bool ' . ( $var ? 'TRUE' : 'FALSE' );
+ } elseif ( is_float( $var ) ) {
+ return 'float ' . $var;
+ } elseif ( is_int( $var ) ) {
+ return 'integer ' . $var;
+ } elseif ( is_resource( $var ) ) {
+ if ( ( $type = get_resource_type( $var ) ) === 'stream' and $meta = stream_get_meta_data( $var ) ) {
+ if ( isset( $meta['uri'] ) ) {
+ $file = $meta['uri'];
+
+ return "resource ({$type}) {$html( $file, 0 )}";
+ } else {
+ return "resource ({$type})";
+ }
+ } else {
+ return "resource ({$type})";
+ }
+ } elseif ( is_string( $var ) ) {
+ return "string ({$strlen( $var )}) \"{$html( $var )}\"";
+ } elseif ( is_array( $var ) ) {
+ $output = array();
+ $space = str_repeat( $s = ' ', $level );
+
+ static $marker;
+
+ if ( $marker === null ) {
+ // Make a unique marker
+ $marker = uniqid( "\x00" );
+ }
+
+ if ( empty( $var ) ) {
+ return "array()";
+ } elseif ( isset( $var[$marker] ) ) {
+ $output[] = "[\n$space$s*RECURSION*\n$space]";
+ } elseif ( $level < 7 ) {
+ $isSeq = array_keys( $var ) === range( 0, count( $var ) - 1 );
+
+ $output[] = "[";
+
+ $var[$marker] = true;
+
+ foreach ( $var as $key => &$val ) {
+ if ( $key === $marker ) {
+ continue;
+ }
+
+ $key = $space . $s . ( $isSeq ? "" : "'{$html( $key, 0 )}' => " );
+
+ $dump = $this->kintLite( $val, $level + 1 );
+ $output[] = "{$key}{$dump}";
+ }
+
+ unset( $var[$marker] );
+ $output[] = "$space]";
+ } else {
+ $output[] = "[\n$space$s*depth too great*\n$space]";
+ }
+ return "array({$count( $var )}) {$implode( "\n", $output )}";
+ } elseif ( is_object( $var ) ) {
+ if ( $var instanceof SplFileInfo ) {
+ return "object SplFileInfo " . $var->getRealPath();
+ }
+
+ // Copy the object as an array
+ $array = (array) $var;
+
+ $output = array();
+ $space = str_repeat( $s = ' ', $level );
+
+ $hash = spl_object_hash( $var );
+
+ // Objects that are being dumped
+ static $objects = array();
+
+ if ( empty( $array ) ) {
+ return "object {$getClass( $var )} {}";
+ } elseif ( isset( $objects[$hash] ) ) {
+ $output[] = "{\n$space$s*RECURSION*\n$space}";
+ } elseif ( $level < 7 ) {
+ $output[] = "{";
+ $objects[$hash] = true;
+
+ foreach ( $array as $key => & $val ) {
+ if ( $key[0] === "\x00" ) {
+ $access = $key[1] === "*" ? "protected" : "private";
+
+ // Remove the access level from the variable name
+ $key = substr( $key, strrpos( $key, "\x00" ) + 1 );
+ } else {
+ $access = "public";
+ }
+
+ $output[] = "$space$s$access $key -> " . $this->kintLite( $val, $level + 1 );
+ }
+ unset( $objects[$hash] );
+ $output[] = "$space}";
+ } else {
+ $output[] = "{\n$space$s*depth too great*\n$space}";
+ }
+
+ return "object {$getClass( $var )} ({$count( $array )}) {$implode( "\n", $output )}";
+ } else {
+ return gettype( $var ) . htmlspecialchars( var_export( $var, true ), ENT_NOQUOTES );
+ }
+ }
+}
diff --git a/htdocs/includes/DebugBar/DataFormatter/DataFormatterInterface.php b/htdocs/includes/DebugBar/DataFormatter/DataFormatterInterface.php
new file mode 100644
index 00000000000..cb7b426e70b
--- /dev/null
+++ b/htdocs/includes/DebugBar/DataFormatter/DataFormatterInterface.php
@@ -0,0 +1,42 @@
+
+ * $debugbar = new DebugBar();
+ * $debugbar->addCollector(new DataCollector\MessagesCollector());
+ * $debugbar['messages']->addMessage("foobar");
+ *
+ */
+class DebugBar implements ArrayAccess
+{
+ public static $useOpenHandlerWhenSendingDataHeaders = false;
+
+ protected $collectors = array();
+
+ protected $data;
+
+ protected $jsRenderer;
+
+ protected $requestIdGenerator;
+
+ protected $requestId;
+
+ protected $storage;
+
+ protected $httpDriver;
+
+ protected $stackSessionNamespace = 'PHPDEBUGBAR_STACK_DATA';
+
+ protected $stackAlwaysUseSessionStorage = false;
+
+ /**
+ * Adds a data collector
+ *
+ * @param DataCollectorInterface $collector
+ *
+ * @throws DebugBarException
+ * @return $this
+ */
+ public function addCollector(DataCollectorInterface $collector)
+ {
+ if ($collector->getName() === '__meta') {
+ throw new DebugBarException("'__meta' is a reserved name and cannot be used as a collector name");
+ }
+ if (isset($this->collectors[$collector->getName()])) {
+ throw new DebugBarException("'{$collector->getName()}' is already a registered collector");
+ }
+ $this->collectors[$collector->getName()] = $collector;
+ return $this;
+ }
+
+ /**
+ * Checks if a data collector has been added
+ *
+ * @param string $name
+ * @return boolean
+ */
+ public function hasCollector($name)
+ {
+ return isset($this->collectors[$name]);
+ }
+
+ /**
+ * Returns a data collector
+ *
+ * @param string $name
+ * @return DataCollectorInterface
+ */
+ public function getCollector($name)
+ {
+ if (!isset($this->collectors[$name])) {
+ throw new DebugBarException("'$name' is not a registered collector");
+ }
+ return $this->collectors[$name];
+ }
+
+ /**
+ * Returns an array of all data collectors
+ *
+ * @return array[DataCollectorInterface]
+ */
+ public function getCollectors()
+ {
+ return $this->collectors;
+ }
+
+ /**
+ * Sets the request id generator
+ *
+ * @param RequestIdGeneratorInterface $generator
+ */
+ public function setRequestIdGenerator(RequestIdGeneratorInterface $generator)
+ {
+ $this->requestIdGenerator = $generator;
+ return $this;
+ }
+
+ /**
+ * @return RequestIdGeneratorInterface
+ */
+ public function getRequestIdGenerator()
+ {
+ if ($this->requestIdGenerator === null) {
+ $this->requestIdGenerator = new RequestIdGenerator();
+ }
+ return $this->requestIdGenerator;
+ }
+
+ /**
+ * Returns the id of the current request
+ *
+ * @return string
+ */
+ public function getCurrentRequestId()
+ {
+ if ($this->requestId === null) {
+ $this->requestId = $this->getRequestIdGenerator()->generate();
+ }
+ return $this->requestId;
+ }
+
+ /**
+ * Sets the storage backend to use to store the collected data
+ *
+ * @param StorageInterface $storage
+ */
+ public function setStorage(StorageInterface $storage = null)
+ {
+ $this->storage = $storage;
+ return $this;
+ }
+
+ /**
+ * @return StorageInterface
+ */
+ public function getStorage()
+ {
+ return $this->storage;
+ }
+
+ /**
+ * Checks if the data will be persisted
+ *
+ * @return boolean
+ */
+ public function isDataPersisted()
+ {
+ return $this->storage !== null;
+ }
+
+ /**
+ * Sets the HTTP driver
+ *
+ * @param HttpDriverInterface $driver
+ */
+ public function setHttpDriver(HttpDriverInterface $driver)
+ {
+ $this->httpDriver = $driver;
+ return $this;
+ }
+
+ /**
+ * Returns the HTTP driver
+ *
+ * If no http driver where defined, a PhpHttpDriver is automatically created
+ *
+ * @return HttpDriverInterface
+ */
+ public function getHttpDriver()
+ {
+ if ($this->httpDriver === null) {
+ $this->httpDriver = new PhpHttpDriver();
+ }
+ return $this->httpDriver;
+ }
+
+ /**
+ * Collects the data from the collectors
+ *
+ * @return array
+ */
+ public function collect()
+ {
+ $this->data = array(
+ '__meta' => array(
+ 'id' => $this->getCurrentRequestId(),
+ 'datetime' => date('Y-m-d H:i:s'),
+ 'utime' => microtime(true),
+ 'method' => isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : null,
+ 'uri' => isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : null,
+ 'ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null
+ )
+ );
+
+ foreach ($this->collectors as $name => $collector) {
+ $this->data[$name] = $collector->collect();
+ }
+
+ // Remove all invalid (non UTF-8) characters
+ array_walk_recursive($this->data, function (&$item) {
+ if (is_string($item) && !mb_check_encoding($item, 'UTF-8')) {
+ $item = mb_convert_encoding($item, 'UTF-8', 'UTF-8');
+ }
+ });
+
+ if ($this->storage !== null) {
+ $this->storage->save($this->getCurrentRequestId(), $this->data);
+ }
+
+ return $this->data;
+ }
+
+ /**
+ * Returns collected data
+ *
+ * Will collect the data if none have been collected yet
+ *
+ * @return array
+ */
+ public function getData()
+ {
+ if ($this->data === null) {
+ $this->collect();
+ }
+ return $this->data;
+ }
+
+ /**
+ * Returns an array of HTTP headers containing the data
+ *
+ * @param string $headerName
+ * @param integer $maxHeaderLength
+ * @return array
+ */
+ public function getDataAsHeaders($headerName = 'phpdebugbar', $maxHeaderLength = 4096, $maxTotalHeaderLength = 250000)
+ {
+ $data = rawurlencode(json_encode(array(
+ 'id' => $this->getCurrentRequestId(),
+ 'data' => $this->getData()
+ )));
+
+ if (strlen($data) > $maxTotalHeaderLength) {
+ $data = rawurlencode(json_encode(array(
+ 'error' => 'Maximum header size exceeded'
+ )));
+ }
+
+ $chunks = array();
+
+ while (strlen($data) > $maxHeaderLength) {
+ $chunks[] = substr($data, 0, $maxHeaderLength);
+ $data = substr($data, $maxHeaderLength);
+ }
+ $chunks[] = $data;
+
+ $headers = array();
+ for ($i = 0, $c = count($chunks); $i < $c; $i++) {
+ $name = $headerName . ($i > 0 ? "-$i" : '');
+ $headers[$name] = $chunks[$i];
+ }
+
+ return $headers;
+ }
+
+ /**
+ * Sends the data through the HTTP headers
+ *
+ * @param bool $useOpenHandler
+ * @param string $headerName
+ * @param integer $maxHeaderLength
+ */
+ public function sendDataInHeaders($useOpenHandler = null, $headerName = 'phpdebugbar', $maxHeaderLength = 4096)
+ {
+ if ($useOpenHandler === null) {
+ $useOpenHandler = self::$useOpenHandlerWhenSendingDataHeaders;
+ }
+ if ($useOpenHandler && $this->storage !== null) {
+ $this->getData();
+ $headerName .= '-id';
+ $headers = array($headerName => $this->getCurrentRequestId());
+ } else {
+ $headers = $this->getDataAsHeaders($headerName, $maxHeaderLength);
+ }
+ $this->getHttpDriver()->setHeaders($headers);
+ return $this;
+ }
+
+ /**
+ * Stacks the data in the session for later rendering
+ */
+ public function stackData()
+ {
+ $http = $this->initStackSession();
+
+ $data = null;
+ if (!$this->isDataPersisted() || $this->stackAlwaysUseSessionStorage) {
+ $data = $this->getData();
+ } elseif ($this->data === null) {
+ $this->collect();
+ }
+
+ $stack = $http->getSessionValue($this->stackSessionNamespace);
+ $stack[$this->getCurrentRequestId()] = $data;
+ $http->setSessionValue($this->stackSessionNamespace, $stack);
+ return $this;
+ }
+
+ /**
+ * Checks if there is stacked data in the session
+ *
+ * @return boolean
+ */
+ public function hasStackedData()
+ {
+ try {
+ $http = $this->initStackSession();
+ } catch (DebugBarException $e) {
+ return false;
+ }
+ return count($http->getSessionValue($this->stackSessionNamespace)) > 0;
+ }
+
+ /**
+ * Returns the data stacked in the session
+ *
+ * @param boolean $delete Whether to delete the data in the session
+ * @return array
+ */
+ public function getStackedData($delete = true)
+ {
+ $http = $this->initStackSession();
+ $stackedData = $http->getSessionValue($this->stackSessionNamespace);
+ if ($delete) {
+ $http->deleteSessionValue($this->stackSessionNamespace);
+ }
+
+ $datasets = array();
+ if ($this->isDataPersisted() && !$this->stackAlwaysUseSessionStorage) {
+ foreach ($stackedData as $id => $data) {
+ $datasets[$id] = $this->getStorage()->get($id);
+ }
+ } else {
+ $datasets = $stackedData;
+ }
+
+ return $datasets;
+ }
+
+ /**
+ * Sets the key to use in the $_SESSION array
+ *
+ * @param string $ns
+ */
+ public function setStackDataSessionNamespace($ns)
+ {
+ $this->stackSessionNamespace = $ns;
+ return $this;
+ }
+
+ /**
+ * Returns the key used in the $_SESSION array
+ *
+ * @return string
+ */
+ public function getStackDataSessionNamespace()
+ {
+ return $this->stackSessionNamespace;
+ }
+
+ /**
+ * Sets whether to only use the session to store stacked data even
+ * if a storage is enabled
+ *
+ * @param boolean $enabled
+ */
+ public function setStackAlwaysUseSessionStorage($enabled = true)
+ {
+ $this->stackAlwaysUseSessionStorage = $enabled;
+ return $this;
+ }
+
+ /**
+ * Checks if the session is always used to store stacked data
+ * even if a storage is enabled
+ *
+ * @return boolean
+ */
+ public function isStackAlwaysUseSessionStorage()
+ {
+ return $this->stackAlwaysUseSessionStorage;
+ }
+
+ /**
+ * Initializes the session for stacked data
+ *
+ * @return HttpDriverInterface
+ */
+ protected function initStackSession()
+ {
+ $http = $this->getHttpDriver();
+ if (!$http->isSessionStarted()) {
+ throw new DebugBarException("Session must be started before using stack data in the debug bar");
+ }
+
+ if (!$http->hasSessionValue($this->stackSessionNamespace)) {
+ $http->setSessionValue($this->stackSessionNamespace, array());
+ }
+
+ return $http;
+ }
+
+ /**
+ * Returns a JavascriptRenderer for this instance
+ *
+ * @param string $baseUrl
+ * @param string $basePathng
+ * @return JavascriptRenderer
+ */
+ public function getJavascriptRenderer($baseUrl = null, $basePath = null)
+ {
+ if ($this->jsRenderer === null) {
+ $this->jsRenderer = new JavascriptRenderer($this, $baseUrl, $basePath);
+ }
+ return $this->jsRenderer;
+ }
+
+ // --------------------------------------------
+ // ArrayAccess implementation
+
+ public function offsetSet($key, $value)
+ {
+ throw new DebugBarException("DebugBar[] is read-only");
+ }
+
+ public function offsetGet($key)
+ {
+ return $this->getCollector($key);
+ }
+
+ public function offsetExists($key)
+ {
+ return $this->hasCollector($key);
+ }
+
+ public function offsetUnset($key)
+ {
+ throw new DebugBarException("DebugBar[] is read-only");
+ }
+}
diff --git a/htdocs/includes/DebugBar/DebugBarException.php b/htdocs/includes/DebugBar/DebugBarException.php
new file mode 100644
index 00000000000..32ffe255cdc
--- /dev/null
+++ b/htdocs/includes/DebugBar/DebugBarException.php
@@ -0,0 +1,16 @@
+ 'vendor/font-awesome/css/font-awesome.min.css',
+ 'highlightjs' => 'vendor/highlightjs/styles/github.css'
+ );
+
+ protected $jsVendors = array(
+ 'jquery' => 'vendor/jquery/dist/jquery.min.js',
+ 'highlightjs' => 'vendor/highlightjs/highlight.pack.js'
+ );
+
+ protected $includeVendors = true;
+
+ protected $cssFiles = array('debugbar.css', 'widgets.css', 'openhandler.css');
+
+ protected $jsFiles = array('debugbar.js', 'widgets.js', 'openhandler.js');
+
+ protected $additionalAssets = array();
+
+ protected $javascriptClass = 'PhpDebugBar.DebugBar';
+
+ protected $variableName = 'phpdebugbar';
+
+ protected $enableJqueryNoConflict = true;
+
+ protected $initialization;
+
+ protected $controls = array();
+
+ protected $ignoredCollectors = array();
+
+ protected $ajaxHandlerClass = 'PhpDebugBar.AjaxHandler';
+
+ protected $ajaxHandlerBindToJquery = true;
+
+ protected $ajaxHandlerBindToXHR = false;
+
+ protected $openHandlerClass = 'PhpDebugBar.OpenHandler';
+
+ protected $openHandlerUrl;
+
+ /**
+ * @param \DebugBar\DebugBar $debugBar
+ * @param string $baseUrl
+ * @param string $basePath
+ */
+ public function __construct(DebugBar $debugBar, $baseUrl = null, $basePath = null)
+ {
+ $this->debugBar = $debugBar;
+
+ if ($baseUrl === null) {
+ $baseUrl = '/vendor/maximebf/debugbar/src/DebugBar/Resources';
+ }
+ $this->baseUrl = $baseUrl;
+
+ if ($basePath === null) {
+ $basePath = __DIR__ . DIRECTORY_SEPARATOR . 'Resources';
+ }
+ $this->basePath = $basePath;
+
+ // bitwise operations cannot be done in class definition :(
+ $this->initialization = self::INITIALIZE_CONSTRUCTOR | self::INITIALIZE_CONTROLS;
+ }
+
+ /**
+ * Sets options from an array
+ *
+ * Options:
+ * - base_path
+ * - base_url
+ * - include_vendors
+ * - javascript_class
+ * - variable_name
+ * - initialization
+ * - enable_jquery_noconflict
+ * - controls
+ * - disable_controls
+ * - ignore_collectors
+ * - ajax_handler_classname
+ * - ajax_handler_bind_to_jquery
+ * - open_handler_classname
+ * - open_handler_url
+ *
+ * @param array $options [description]
+ */
+ public function setOptions(array $options)
+ {
+ if (array_key_exists('base_path', $options)) {
+ $this->setBasePath($options['base_path']);
+ }
+ if (array_key_exists('base_url', $options)) {
+ $this->setBaseUrl($options['base_url']);
+ }
+ if (array_key_exists('include_vendors', $options)) {
+ $this->setIncludeVendors($options['include_vendors']);
+ }
+ if (array_key_exists('javascript_class', $options)) {
+ $this->setJavascriptClass($options['javascript_class']);
+ }
+ if (array_key_exists('variable_name', $options)) {
+ $this->setVariableName($options['variable_name']);
+ }
+ if (array_key_exists('initialization', $options)) {
+ $this->setInitialization($options['initialization']);
+ }
+ if (array_key_exists('enable_jquery_noconflict', $options)) {
+ $this->setEnableJqueryNoConflict($options['enable_jquery_noconflict']);
+ }
+ if (array_key_exists('controls', $options)) {
+ foreach ($options['controls'] as $name => $control) {
+ $this->addControl($name, $control);
+ }
+ }
+ if (array_key_exists('disable_controls', $options)) {
+ foreach ((array) $options['disable_controls'] as $name) {
+ $this->disableControl($name);
+ }
+ }
+ if (array_key_exists('ignore_collectors', $options)) {
+ foreach ((array) $options['ignore_collectors'] as $name) {
+ $this->ignoreCollector($name);
+ }
+ }
+ if (array_key_exists('ajax_handler_classname', $options)) {
+ $this->setAjaxHandlerClass($options['ajax_handler_classname']);
+ }
+ if (array_key_exists('ajax_handler_bind_to_jquery', $options)) {
+ $this->setBindAjaxHandlerToJquery($options['ajax_handler_bind_to_jquery']);
+ }
+ if (array_key_exists('open_handler_classname', $options)) {
+ $this->setOpenHandlerClass($options['open_handler_classname']);
+ }
+ if (array_key_exists('open_handler_url', $options)) {
+ $this->setOpenHandlerUrl($options['open_handler_url']);
+ }
+ }
+
+ /**
+ * Sets the path which assets are relative to
+ *
+ * @param string $path
+ */
+ public function setBasePath($path)
+ {
+ $this->basePath = $path;
+ return $this;
+ }
+
+ /**
+ * Returns the path which assets are relative to
+ *
+ * @return string
+ */
+ public function getBasePath()
+ {
+ return $this->basePath;
+ }
+
+ /**
+ * Sets the base URL from which assets will be served
+ *
+ * @param string $url
+ */
+ public function setBaseUrl($url)
+ {
+ $this->baseUrl = $url;
+ return $this;
+ }
+
+ /**
+ * Returns the base URL from which assets will be served
+ *
+ * @return string
+ */
+ public function getBaseUrl()
+ {
+ return $this->baseUrl;
+ }
+
+ /**
+ * Whether to include vendor assets
+ *
+ * You can only include js or css vendors using
+ * setIncludeVendors('css') or setIncludeVendors('js')
+ *
+ * @param boolean $enabled
+ */
+ public function setIncludeVendors($enabled = true)
+ {
+ if (is_string($enabled)) {
+ $enabled = array($enabled);
+ }
+ $this->includeVendors = $enabled;
+
+ if (!$enabled || (is_array($enabled) && !in_array('js', $enabled))) {
+ // no need to call jQuery.noConflict() if we do not include our own version
+ $this->enableJqueryNoConflict = false;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Checks if vendors assets are included
+ *
+ * @return boolean
+ */
+ public function areVendorsIncluded()
+ {
+ return $this->includeVendors !== false;
+ }
+
+ /**
+ * Disable a specific vendor's assets.
+ *
+ * @param string $name "jquery", "fontawesome", "highlightjs"
+ *
+ * @return void
+ */
+ public function disableVendor($name)
+ {
+ if (array_key_exists($name, $this->cssVendors)) {
+ unset($this->cssVendors[$name]);
+ }
+ if (array_key_exists($name, $this->jsVendors)) {
+ unset($this->jsVendors[$name]);
+ }
+ }
+
+ /**
+ * Sets the javascript class name
+ *
+ * @param string $className
+ */
+ public function setJavascriptClass($className)
+ {
+ $this->javascriptClass = $className;
+ return $this;
+ }
+
+ /**
+ * Returns the javascript class name
+ *
+ * @return string
+ */
+ public function getJavascriptClass()
+ {
+ return $this->javascriptClass;
+ }
+
+ /**
+ * Sets the variable name of the class instance
+ *
+ * @param string $name
+ */
+ public function setVariableName($name)
+ {
+ $this->variableName = $name;
+ return $this;
+ }
+
+ /**
+ * Returns the variable name of the class instance
+ *
+ * @return string
+ */
+ public function getVariableName()
+ {
+ return $this->variableName;
+ }
+
+ /**
+ * Sets what should be initialized
+ *
+ * - INITIALIZE_CONSTRUCTOR: only initializes the instance
+ * - INITIALIZE_CONTROLS: initializes the controls and data mapping
+ * - INITIALIZE_CONSTRUCTOR | INITIALIZE_CONTROLS: initialize everything (default)
+ *
+ * @param integer $init
+ */
+ public function setInitialization($init)
+ {
+ $this->initialization = $init;
+ return $this;
+ }
+
+ /**
+ * Returns what should be initialized
+ *
+ * @return integer
+ */
+ public function getInitialization()
+ {
+ return $this->initialization;
+ }
+
+ /**
+ * Sets whether to call jQuery.noConflict()
+ *
+ * @param boolean $enabled
+ */
+ public function setEnableJqueryNoConflict($enabled = true)
+ {
+ $this->enableJqueryNoConflict = $enabled;
+ return $this;
+ }
+
+ /**
+ * Checks if jQuery.noConflict() will be called
+ *
+ * @return boolean
+ */
+ public function isJqueryNoConflictEnabled()
+ {
+ return $this->enableJqueryNoConflict;
+ }
+
+ /**
+ * Adds a control to initialize
+ *
+ * Possible options:
+ * - icon: icon name
+ * - tooltip: string
+ * - widget: widget class name
+ * - title: tab title
+ * - map: a property name from the data to map the control to
+ * - default: a js string, default value of the data map
+ *
+ * "icon" or "widget" are at least needed
+ *
+ * @param string $name
+ * @param array $options
+ */
+ public function addControl($name, array $options)
+ {
+ if (count(array_intersect(array_keys($options), array('icon', 'widget', 'tab', 'indicator'))) === 0) {
+ throw new DebugBarException("Not enough options for control '$name'");
+ }
+ $this->controls[$name] = $options;
+ return $this;
+ }
+
+ /**
+ * Disables a control
+ *
+ * @param string $name
+ */
+ public function disableControl($name)
+ {
+ $this->controls[$name] = null;
+ return $this;
+ }
+
+ /**
+ * Returns the list of controls
+ *
+ * This does not include controls provided by collectors
+ *
+ * @return array
+ */
+ public function getControls()
+ {
+ return $this->controls;
+ }
+
+ /**
+ * Ignores widgets provided by a collector
+ *
+ * @param string $name
+ */
+ public function ignoreCollector($name)
+ {
+ $this->ignoredCollectors[] = $name;
+ return $this;
+ }
+
+ /**
+ * Returns the list of ignored collectors
+ *
+ * @return array
+ */
+ public function getIgnoredCollectors()
+ {
+ return $this->ignoredCollectors;
+ }
+
+ /**
+ * Sets the class name of the ajax handler
+ *
+ * Set to false to disable
+ *
+ * @param string $className
+ */
+ public function setAjaxHandlerClass($className)
+ {
+ $this->ajaxHandlerClass = $className;
+ return $this;
+ }
+
+ /**
+ * Returns the class name of the ajax handler
+ *
+ * @return string
+ */
+ public function getAjaxHandlerClass()
+ {
+ return $this->ajaxHandlerClass;
+ }
+
+ /**
+ * Sets whether to call bindToJquery() on the ajax handler
+ *
+ * @param boolean $bind
+ */
+ public function setBindAjaxHandlerToJquery($bind = true)
+ {
+ $this->ajaxHandlerBindToJquery = $bind;
+ return $this;
+ }
+
+ /**
+ * Checks whether bindToJquery() will be called on the ajax handler
+ *
+ * @return boolean
+ */
+ public function isAjaxHandlerBoundToJquery()
+ {
+ return $this->ajaxHandlerBindToJquery;
+ }
+
+ /**
+ * Sets whether to call bindToXHR() on the ajax handler
+ *
+ * @param boolean $bind
+ */
+ public function setBindAjaxHandlerToXHR($bind = true)
+ {
+ $this->ajaxHandlerBindToXHR = $bind;
+ return $this;
+ }
+
+ /**
+ * Checks whether bindToXHR() will be called on the ajax handler
+ *
+ * @return boolean
+ */
+ public function isAjaxHandlerBoundToXHR()
+ {
+ return $this->ajaxHandlerBindToXHR;
+ }
+
+ /**
+ * Sets the class name of the js open handler
+ *
+ * @param string $className
+ */
+ public function setOpenHandlerClass($className)
+ {
+ $this->openHandlerClass = $className;
+ return $this;
+ }
+
+ /**
+ * Returns the class name of the js open handler
+ *
+ * @return string
+ */
+ public function getOpenHandlerClass()
+ {
+ return $this->openHandlerClass;
+ }
+
+ /**
+ * Sets the url of the open handler
+ *
+ * @param string $url
+ */
+ public function setOpenHandlerUrl($url)
+ {
+ $this->openHandlerUrl = $url;
+ return $this;
+ }
+
+ /**
+ * Returns the url for the open handler
+ *
+ * @return string
+ */
+ public function getOpenHandlerUrl()
+ {
+ return $this->openHandlerUrl;
+ }
+
+ /**
+ * Add assets to render in the head
+ *
+ * @param array $cssFiles An array of filenames
+ * @param array $jsFiles An array of filenames
+ * @param string $basePath Base path of those files
+ * @param string $baseUrl Base url of those files
+ */
+ public function addAssets($cssFiles, $jsFiles, $basePath = null, $baseUrl = null)
+ {
+ $this->additionalAssets[] = array(
+ 'base_path' => $basePath,
+ 'base_url' => $baseUrl,
+ 'css' => (array) $cssFiles,
+ 'js' => (array) $jsFiles
+ );
+ return $this;
+ }
+
+ /**
+ * Returns the list of asset files
+ *
+ * @param string $type Only return css or js files
+ * @param string $relativeTo The type of path to which filenames must be relative (path, url or null)
+ * @return array
+ */
+ public function getAssets($type = null, $relativeTo = self::RELATIVE_PATH)
+ {
+ $cssFiles = $this->cssFiles;
+ $jsFiles = $this->jsFiles;
+
+ if ($this->includeVendors !== false) {
+ if ($this->includeVendors === true || in_array('css', $this->includeVendors)) {
+ $cssFiles = array_merge($this->cssVendors, $cssFiles);
+ }
+ if ($this->includeVendors === true || in_array('js', $this->includeVendors)) {
+ $jsFiles = array_merge($this->jsVendors, $jsFiles);
+ }
+ }
+
+ if ($relativeTo) {
+ $root = $this->getRelativeRoot($relativeTo, $this->basePath, $this->baseUrl);
+ $cssFiles = $this->makeUriRelativeTo($cssFiles, $root);
+ $jsFiles = $this->makeUriRelativeTo($jsFiles, $root);
+ }
+
+ $additionalAssets = $this->additionalAssets;
+ // finds assets provided by collectors
+ foreach ($this->debugBar->getCollectors() as $collector) {
+ if (($collector instanceof AssetProvider) && !in_array($collector->getName(), $this->ignoredCollectors)) {
+ $additionalAssets[] = $collector->getAssets();
+ }
+ }
+
+ foreach ($additionalAssets as $assets) {
+ $basePath = isset($assets['base_path']) ? $assets['base_path'] : null;
+ $baseUrl = isset($assets['base_url']) ? $assets['base_url'] : null;
+ $root = $this->getRelativeRoot($relativeTo,
+ $this->makeUriRelativeTo($basePath, $this->basePath),
+ $this->makeUriRelativeTo($baseUrl, $this->baseUrl));
+ $cssFiles = array_merge($cssFiles, $this->makeUriRelativeTo((array) $assets['css'], $root));
+ $jsFiles = array_merge($jsFiles, $this->makeUriRelativeTo((array) $assets['js'], $root));
+ }
+
+ return $this->filterAssetArray(array($cssFiles, $jsFiles), $type);
+ }
+
+ /**
+ * Returns the correct base according to the type
+ *
+ * @param string $relativeTo
+ * @param string $basePath
+ * @param string $baseUrl
+ * @return string
+ */
+ protected function getRelativeRoot($relativeTo, $basePath, $baseUrl)
+ {
+ if ($relativeTo === self::RELATIVE_PATH) {
+ return $basePath;
+ }
+ if ($relativeTo === self::RELATIVE_URL) {
+ return $baseUrl;
+ }
+ return null;
+ }
+
+ /**
+ * Makes a URI relative to another
+ *
+ * @param string|array $uri
+ * @param string $root
+ * @return string
+ */
+ protected function makeUriRelativeTo($uri, $root)
+ {
+ if (!$root) {
+ return $uri;
+ }
+
+ if (is_array($uri)) {
+ $uris = array();
+ foreach ($uri as $u) {
+ $uris[] = $this->makeUriRelativeTo($u, $root);
+ }
+ return $uris;
+ }
+
+ if (substr($uri, 0, 1) === '/' || preg_match('/^([a-zA-Z]+:\/\/|[a-zA-Z]:\/|[a-zA-Z]:\\\)/', $uri)) {
+ return $uri;
+ }
+ return rtrim($root, '/') . "/$uri";
+ }
+
+ /**
+ * Filters a tuple of (css, js) assets according to $type
+ *
+ * @param array $array
+ * @param string $type 'css', 'js' or null for both
+ * @return array
+ */
+ protected function filterAssetArray($array, $type = null)
+ {
+ $type = strtolower($type);
+ if ($type === 'css') {
+ return $array[0];
+ }
+ if ($type === 'js') {
+ return $array[1];
+ }
+ return $array;
+ }
+
+ /**
+ * Returns a tuple where the both items are Assetic AssetCollection,
+ * the first one being css files and the second js files
+ *
+ * @param string $type Only return css or js collection
+ * @return array or \Assetic\Asset\AssetCollection
+ */
+ public function getAsseticCollection($type = null)
+ {
+ list($cssFiles, $jsFiles) = $this->getAssets();
+ return $this->filterAssetArray(array(
+ $this->createAsseticCollection($cssFiles),
+ $this->createAsseticCollection($jsFiles)
+ ), $type);
+ }
+
+ /**
+ * Create an Assetic AssetCollection with the given files.
+ * Filenames will be converted to absolute path using
+ * the base path.
+ *
+ * @param array $files
+ * @return \Assetic\Asset\AssetCollection
+ */
+ protected function createAsseticCollection($files)
+ {
+ $assets = array();
+ foreach ($files as $file) {
+ $assets[] = new \Assetic\Asset\FileAsset($file);
+ }
+ return new \Assetic\Asset\AssetCollection($assets);
+ }
+
+ /**
+ * Write all CSS assets to standard output or in a file
+ *
+ * @param string $targetFilename
+ */
+ public function dumpCssAssets($targetFilename = null)
+ {
+ $this->dumpAssets($this->getAssets('css'), $targetFilename);
+ }
+
+ /**
+ * Write all JS assets to standard output or in a file
+ *
+ * @param string $targetFilename
+ */
+ public function dumpJsAssets($targetFilename = null)
+ {
+ $this->dumpAssets($this->getAssets('js'), $targetFilename);
+ }
+
+ /**
+ * Write assets to standard output or in a file
+ *
+ * @param array $files
+ * @param string $targetFilename
+ */
+ protected function dumpAssets($files, $targetFilename = null)
+ {
+ $content = '';
+ foreach ($files as $file) {
+ $content .= file_get_contents($file) . "\n";
+ }
+ if ($targetFilename !== null) {
+ file_put_contents($targetFilename, $content);
+ } else {
+ echo $content;
+ }
+ }
+
+ /**
+ * Renders the html to include needed assets
+ *
+ * Only useful if Assetic is not used
+ *
+ * @return string
+ */
+ public function renderHead()
+ {
+ list($cssFiles, $jsFiles) = $this->getAssets(null, self::RELATIVE_URL);
+ $html = '';
+
+ foreach ($cssFiles as $file) {
+ $html .= sprintf(' ' . "\n", $file);
+ }
+
+ foreach ($jsFiles as $file) {
+ $html .= sprintf('' . "\n", $file);
+ }
+
+ if ($this->enableJqueryNoConflict) {
+ $html .= '' . "\n";
+ }
+
+ return $html;
+ }
+
+ /**
+ * Register shutdown to display the debug bar
+ *
+ * @param boolean $here Set position of HTML. True if is to current position or false for end file
+ * @param boolean $initialize Whether to render the de bug bar initialization code
+ * @return string Return "{--DEBUGBAR_OB_START_REPLACE_ME--}" or return an empty string if $here == false
+ */
+ public function renderOnShutdown($here = true, $initialize = true, $renderStackedData = true, $head = false)
+ {
+ register_shutdown_function(array($this, "replaceTagInBuffer"), $here, $initialize, $renderStackedData, $head);
+
+ if (ob_get_level() === 0) {
+ ob_start();
+ }
+
+ return ($here) ? self::REPLACEABLE_TAG : "";
+ }
+
+ /**
+ * Same as renderOnShutdown() with $head = true
+ *
+ * @param boolean $here
+ * @param boolean $initialize
+ * @param boolean $renderStackedData
+ * @return string
+ */
+ public function renderOnShutdownWithHead($here = true, $initialize = true, $renderStackedData = true)
+ {
+ return $this->renderOnShutdown($here, $initialize, $renderStackedData, true);
+ }
+
+ /**
+ * Is callback function for register_shutdown_function(...)
+ *
+ * @param boolean $here Set position of HTML. True if is to current position or false for end file
+ * @param boolean $initialize Whether to render the de bug bar initialization code
+ */
+ public function replaceTagInBuffer($here = true, $initialize = true, $renderStackedData = true, $head = false)
+ {
+ $render = ($head ? $this->renderHead() : "")
+ . $this->render($initialize, $renderStackedData);
+
+ $current = ($here && ob_get_level() > 0) ? ob_get_clean() : self::REPLACEABLE_TAG;
+
+ echo str_replace(self::REPLACEABLE_TAG, $render, $current, $count);
+
+ if ($count === 0) {
+ echo $render;
+ }
+ }
+
+ /**
+ * Returns the code needed to display the debug bar
+ *
+ * AJAX request should not render the initialization code.
+ *
+ * @param boolean $initialize Whether to render the de bug bar initialization code
+ * @return string
+ */
+ public function render($initialize = true, $renderStackedData = true)
+ {
+ $js = '';
+
+ if ($initialize) {
+ $js = $this->getJsInitializationCode();
+ }
+
+ if ($renderStackedData && $this->debugBar->hasStackedData()) {
+ foreach ($this->debugBar->getStackedData() as $id => $data) {
+ $js .= $this->getAddDatasetCode($id, $data, '(stacked)');
+ }
+ }
+
+ $suffix = !$initialize ? '(ajax)' : null;
+ $js .= $this->getAddDatasetCode($this->debugBar->getCurrentRequestId(), $this->debugBar->getData(), $suffix);
+
+ return "\n";
+ }
+
+ /**
+ * Returns the js code needed to initialize the debug bar
+ *
+ * @return string
+ */
+ protected function getJsInitializationCode()
+ {
+ $js = '';
+
+ if (($this->initialization & self::INITIALIZE_CONSTRUCTOR) === self::INITIALIZE_CONSTRUCTOR) {
+ $js .= sprintf("var %s = new %s();\n", $this->variableName, $this->javascriptClass);
+ }
+
+ if (($this->initialization & self::INITIALIZE_CONTROLS) === self::INITIALIZE_CONTROLS) {
+ $js .= $this->getJsControlsDefinitionCode($this->variableName);
+ }
+
+ if ($this->ajaxHandlerClass) {
+ $js .= sprintf("%s.ajaxHandler = new %s(%s);\n", $this->variableName, $this->ajaxHandlerClass, $this->variableName);
+ if ($this->ajaxHandlerBindToXHR) {
+ $js .= sprintf("%s.ajaxHandler.bindToXHR();\n", $this->variableName);
+ } elseif ($this->ajaxHandlerBindToJquery) {
+ $js .= sprintf("if (jQuery) %s.ajaxHandler.bindToJquery(jQuery);\n", $this->variableName);
+ }
+ }
+
+ if ($this->openHandlerUrl !== null) {
+ $js .= sprintf("%s.setOpenHandler(new %s(%s));\n", $this->variableName,
+ $this->openHandlerClass,
+ json_encode(array("url" => $this->openHandlerUrl)));
+ }
+
+ return $js;
+ }
+
+ /**
+ * Returns the js code needed to initialized the controls and data mapping of the debug bar
+ *
+ * Controls can be defined by collectors themselves or using {@see addControl()}
+ *
+ * @param string $varname Debug bar's variable name
+ * @return string
+ */
+ protected function getJsControlsDefinitionCode($varname)
+ {
+ $js = '';
+ $dataMap = array();
+ $excludedOptions = array('indicator', 'tab', 'map', 'default', 'widget', 'position');
+
+ // finds controls provided by collectors
+ $widgets = array();
+ foreach ($this->debugBar->getCollectors() as $collector) {
+ if (($collector instanceof Renderable) && !in_array($collector->getName(), $this->ignoredCollectors)) {
+ if ($w = $collector->getWidgets()) {
+ $widgets = array_merge($widgets, $w);
+ }
+ }
+ }
+ $controls = array_merge($widgets, $this->controls);
+
+ foreach (array_filter($controls) as $name => $options) {
+ $opts = array_diff_key($options, array_flip($excludedOptions));
+
+ if (isset($options['tab']) || isset($options['widget'])) {
+ if (!isset($opts['title'])) {
+ $opts['title'] = ucfirst(str_replace('_', ' ', $name));
+ }
+ $js .= sprintf("%s.addTab(\"%s\", new %s({%s%s}));\n",
+ $varname,
+ $name,
+ isset($options['tab']) ? $options['tab'] : 'PhpDebugBar.DebugBar.Tab',
+ substr(json_encode($opts, JSON_FORCE_OBJECT), 1, -1),
+ isset($options['widget']) ? sprintf('%s"widget": new %s()', count($opts) ? ', ' : '', $options['widget']) : ''
+ );
+ } elseif (isset($options['indicator']) || isset($options['icon'])) {
+ $js .= sprintf("%s.addIndicator(\"%s\", new %s(%s), \"%s\");\n",
+ $varname,
+ $name,
+ isset($options['indicator']) ? $options['indicator'] : 'PhpDebugBar.DebugBar.Indicator',
+ json_encode($opts, JSON_FORCE_OBJECT),
+ isset($options['position']) ? $options['position'] : 'right'
+ );
+ }
+
+ if (isset($options['map']) && isset($options['default'])) {
+ $dataMap[$name] = array($options['map'], $options['default']);
+ }
+ }
+
+ // creates the data mapping object
+ $mapJson = array();
+ foreach ($dataMap as $name => $values) {
+ $mapJson[] = sprintf('"%s": ["%s", %s]', $name, $values[0], $values[1]);
+ }
+ $js .= sprintf("%s.setDataMap({\n%s\n});\n", $varname, implode(",\n", $mapJson));
+
+ // activate state restoration
+ $js .= sprintf("%s.restoreState();\n", $varname);
+
+ return $js;
+ }
+
+ /**
+ * Returns the js code needed to add a dataset
+ *
+ * @param string $requestId
+ * @param array $data
+ * @return string
+ */
+ protected function getAddDatasetCode($requestId, $data, $suffix = null)
+ {
+ $js = sprintf("%s.addDataSet(%s, \"%s\"%s);\n",
+ $this->variableName,
+ json_encode($data),
+ $requestId,
+ $suffix ? ", " . json_encode($suffix) : ''
+ );
+ return $js;
+ }
+}
diff --git a/htdocs/includes/DebugBar/OpenHandler.php b/htdocs/includes/DebugBar/OpenHandler.php
new file mode 100644
index 00000000000..cbabea268ae
--- /dev/null
+++ b/htdocs/includes/DebugBar/OpenHandler.php
@@ -0,0 +1,107 @@
+isDataPersisted()) {
+ throw new DebugBarException("DebugBar must have a storage backend to use OpenHandler");
+ }
+ $this->debugBar = $debugBar;
+ }
+
+ /**
+ * Handles the current request
+ *
+ * @param array $request Request data
+ */
+ public function handle($request = null, $echo = true, $sendHeader = true)
+ {
+ if ($request === null) {
+ $request = $_REQUEST;
+ }
+
+ $op = 'find';
+ if (isset($request['op'])) {
+ $op = $request['op'];
+ if (!in_array($op, array('find', 'get', 'clear'))) {
+ throw new DebugBarException("Invalid operation '{$request['op']}'");
+ }
+ }
+
+ if ($sendHeader) {
+ $this->debugBar->getHttpDriver()->setHeaders(array(
+ 'Content-Type' => 'application/json'
+ ));
+ }
+
+ $response = json_encode(call_user_func(array($this, $op), $request));
+ if ($echo) {
+ echo $response;
+ }
+ return $response;
+ }
+
+ /**
+ * Find operation
+ */
+ protected function find($request)
+ {
+ $max = 20;
+ if (isset($request['max'])) {
+ $max = $request['max'];
+ }
+
+ $offset = 0;
+ if (isset($request['offset'])) {
+ $offset = $request['offset'];
+ }
+
+ $filters = array();
+ foreach (array('utime', 'datetime', 'ip', 'uri', 'method') as $key) {
+ if (isset($request[$key])) {
+ $filters[$key] = $request[$key];
+ }
+ }
+
+ return $this->debugBar->getStorage()->find($filters, $max, $offset);
+ }
+
+ /**
+ * Get operation
+ */
+ protected function get($request)
+ {
+ if (!isset($request['id'])) {
+ throw new DebugBarException("Missing 'id' parameter in 'get' operation");
+ }
+ return $this->debugBar->getStorage()->get($request['id']);
+ }
+
+ /**
+ * Clear operation
+ */
+ protected function clear($request)
+ {
+ $this->debugBar->getStorage()->clear();
+ return array('success' => true);
+ }
+}
diff --git a/htdocs/includes/DebugBar/PhpHttpDriver.php b/htdocs/includes/DebugBar/PhpHttpDriver.php
new file mode 100644
index 00000000000..af07060d279
--- /dev/null
+++ b/htdocs/includes/DebugBar/PhpHttpDriver.php
@@ -0,0 +1,49 @@
+ $value) {
+ header("$name: $value");
+ }
+ }
+
+ function isSessionStarted()
+ {
+ return isset($_SESSION);
+ }
+
+ function setSessionValue($name, $value)
+ {
+ $_SESSION[$name] = $value;
+ }
+
+ function hasSessionValue($name)
+ {
+ return array_key_exists($name, $_SESSION);
+ }
+
+ function getSessionValue($name)
+ {
+ return $_SESSION[$name];
+ }
+
+ function deleteSessionValue($name)
+ {
+ unset($_SESSION[$name]);
+ }
+}
diff --git a/htdocs/includes/DebugBar/RequestIdGenerator.php b/htdocs/includes/DebugBar/RequestIdGenerator.php
new file mode 100644
index 00000000000..934f407ff8f
--- /dev/null
+++ b/htdocs/includes/DebugBar/RequestIdGenerator.php
@@ -0,0 +1,22 @@
+ div > * {
+ padding: 10px 10px;
+ font-size: 14px;
+ color: #555;
+ text-decoration: none;
+ outline: none;
+}
+div.phpdebugbar-header-left > * {
+ float: left;
+}
+div.phpdebugbar-header-right > * {
+ float: right;
+}
+div.phpdebugbar-header-right > select {
+ padding: 0;
+}
+
+/* -------------------------------------- */
+
+span.phpdebugbar-indicator,
+a.phpdebugbar-indicator,
+a.phpdebugbar-close-btn {
+ border-right: 1px solid #ddd;
+}
+
+a.phpdebugbar-tab.phpdebugbar-active {
+ background: #3d6c99;
+ color: #fff;
+}
+
+a.phpdebugbar-tab.phpdebugbar-active span.phpdebugbar-badge {
+ background: #fff;
+ color: #3d6c99;
+}
+
+ a.phpdebugbar-tab span.phpdebugbar-badge {
+ display: none;
+ margin-left: 5px;
+ float: right;
+ font-size: 11px;
+ line-height: 14px;
+ padding: 1px 7px;
+ background: #3d6c99;
+ border-radius: 4px;
+ color: #fff;
+ font-weight: normal;
+ text-shadow: none;
+ vertical-align: middle;
+ }
+ a.phpdebugbar-tab i {
+ display: none;
+ vertical-align: middle;
+ }
+ a.phpdebugbar-tab span.phpdebugbar-badge.phpdebugbar-important {
+ background: #ed6868;
+ color: white;
+ }
+
+a.phpdebugbar-close-btn, a.phpdebugbar-open-btn, a.phpdebugbar-minimize-btn , a.phpdebugbar-maximize-btn {
+ width: 16px;
+ height: 16px;
+}
+
+a.phpdebugbar-restore-btn {
+ width: 26px;
+ height: 16px;
+}
+
+a.phpdebugbar-minimize-btn , a.phpdebugbar-maximize-btn {
+ padding-right: 0px !important;
+}
+
+a.phpdebugbar-maximize-btn { display: none}
+
+a.phpdebugbar-minimize-btn { display: block}
+
+div.phpdebugbar-minimized a.phpdebugbar-maximize-btn { display: block}
+
+div.phpdebugbar-minimized a.phpdebugbar-minimize-btn { display: none}
+
+a.phpdebugbar-minimize-btn {
+ background: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201792%201792%22%20id%3D%22chevron-down%22%3E%3Cpath%20d%3D%22M1683%20808l-742%20741q-19%2019-45%2019t-45-19l-742-741q-19-19-19-45.5t19-45.5l166-165q19-19%2045-19t45%2019l531%20531%20531-531q19-19%2045-19t45%2019l166%20165q19%2019%2019%2045.5t-19%2045.5z%22%2F%3E%3C%2Fsvg%3E) no-repeat 10px 10px / 14px 14px;
+}
+
+a.phpdebugbar-maximize-btn {
+ background: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201792%201792%22%20id%3D%22chevron-up%22%3E%3Cpath%20d%3D%22M1683%201331l-166%20165q-19%2019-45%2019t-45-19l-531-531-531%20531q-19%2019-45%2019t-45-19l-166-165q-19-19-19-45.5t19-45.5l742-741q19-19%2045-19t45%2019l742%20741q19%2019%2019%2045.5t-19%2045.5z%22%2F%3E%3C%2Fsvg%3E) no-repeat 10px 10px / 14px 14px;
+}
+
+a.phpdebugbar-close-btn {
+ background: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201792%201792%22%20id%3D%22close%22%3E%3Cpath%20d%3D%22M1490%201322q0%2040-28%2068l-136%20136q-28%2028-68%2028t-68-28l-294-294-294%20294q-28%2028-68%2028t-68-28l-136-136q-28-28-28-68t28-68l294-294-294-294q-28-28-28-68t28-68l136-136q28-28%2068-28t68%2028l294%20294%20294-294q28-28%2068-28t68%2028l136%20136q28%2028%2028%2068t-28%2068l-294%20294%20294%20294q28%2028%2028%2068z%22%2F%3E%3C%2Fsvg%3E) no-repeat 10px 10px / 14px 14px;
+}
+
+a.phpdebugbar-open-btn {
+ background: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201792%201792%22%20id%3D%22folder-open%22%3E%3Cpath%20d%3D%22M1815%20952q0%2031-31%2066l-336%20396q-43%2051-120.5%2086.5t-143.5%2035.5h-1088q-34%200-60.5-13t-26.5-43q0-31%2031-66l336-396q43-51%20120.5-86.5t143.5-35.5h1088q34%200%2060.5%2013t26.5%2043zm-343-344v160h-832q-94%200-197%2047.5t-164%20119.5l-337%20396-5%206q0-4-.5-12.5t-.5-12.5v-960q0-92%2066-158t158-66h320q92%200%20158%2066t66%20158v32h544q92%200%20158%2066t66%20158z%22%2F%3E%3C%2Fsvg%3E) no-repeat 10px 10px / 14px 14px;
+}
+
+.phpdebugbar-indicator {
+ position: relative;
+ cursor: pointer;
+}
+ .phpdebugbar-indicator span.phpdebugbar-text {
+ margin-left: 5px;
+ }
+ .phpdebugbar-indicator span.phpdebugbar-tooltip {
+ display: none;
+ position: absolute;
+ bottom: 45px;
+ background: #efefef;
+ border: 1px solid #ccc;
+ color: #555;
+ font-size: 11px;
+ padding: 2px 3px;
+ z-index: 1000;
+ text-align: center;
+ width: 200%;
+ right: 0;
+ }
+ .phpdebugbar-indicator:hover span.phpdebugbar-tooltip:not(.phpdebugbar-disabled) {
+ display: block;
+ }
+ .phpdebugbar-indicator span.phpdebugbar-tooltip-wide {
+ width: 300%;
+ }
+ .phpdebugbar-indicator span.phpdebugbar-tooltip-extra-wide {
+ width: 400%;
+ }
+ .phpdebugbar-indicator span.phpdebugbar-tooltip-html {
+ display: inline-block;
+ text-align: left;
+ }
+
+select.phpdebugbar-datasets-switcher {
+ float: right;
+ display: none;
+ margin: 8px 0 0 7px;
+ max-width: 200px;
+ max-height: 23px;
+ padding: 0;
+}
+
+/* -------------------------------------- */
+
+div.phpdebugbar-body {
+ border-top: 1px solid #ccc;
+ display: none;
+ position: relative;
+ height: 300px;
+}
+
+/* -------------------------------------- */
+
+div.phpdebugbar-panel {
+ display: none;
+ height: 100%;
+ overflow: auto;
+ width: 100%;
+}
+div.phpdebugbar-panel.phpdebugbar-active {
+ display: block;
+}
+
+/* -------------------------------------- */
+
+div.phpdebugbar-mini-design a.phpdebugbar-tab {
+ position: relative;
+ border-right: 1px solid #ddd;
+}
+ div.phpdebugbar-mini-design a.phpdebugbar-tab span.phpdebugbar-text {
+ display: none;
+ }
+ div.phpdebugbar-mini-design a.phpdebugbar-tab:hover span.phpdebugbar-text {
+ display: block;
+ position: absolute;
+ top: -30px;
+ background: #efefef;
+ opacity: .7;
+ border: 1px solid #ccc;
+ color: #555;
+ font-size: 11px;
+ padding: 2px 3px;
+ z-index: 1000;
+ text-align: center;
+ right: 0;
+ }
+ div.phpdebugbar-mini-design a.phpdebugbar-tab i {
+ display:inline-block;
+ }
diff --git a/htdocs/includes/DebugBar/Resources/debugbar.js b/htdocs/includes/DebugBar/Resources/debugbar.js
new file mode 100644
index 00000000000..faf567e37c1
--- /dev/null
+++ b/htdocs/includes/DebugBar/Resources/debugbar.js
@@ -0,0 +1,1161 @@
+if (typeof(PhpDebugBar) == 'undefined') {
+ // namespace
+ var PhpDebugBar = {};
+ PhpDebugBar.$ = jQuery;
+}
+
+(function($) {
+
+ if (typeof(localStorage) == 'undefined') {
+ // provide mock localStorage object for dumb browsers
+ localStorage = {
+ setItem: function(key, value) {},
+ getItem: function(key) { return null; }
+ };
+ }
+
+ if (typeof(PhpDebugBar.utils) == 'undefined') {
+ PhpDebugBar.utils = {};
+ }
+
+ /**
+ * Returns the value from an object property.
+ * Using dots in the key, it is possible to retrieve nested property values
+ *
+ * @param {Object} dict
+ * @param {String} key
+ * @param {Object} default_value
+ * @return {Object}
+ */
+ var getDictValue = PhpDebugBar.utils.getDictValue = function(dict, key, default_value) {
+ var d = dict, parts = key.split('.');
+ for (var i = 0; i < parts.length; i++) {
+ if (!d[parts[i]]) {
+ return default_value;
+ }
+ d = d[parts[i]];
+ }
+ return d;
+ }
+
+ /**
+ * Counts the number of properties in an object
+ *
+ * @param {Object} obj
+ * @return {Integer}
+ */
+ var getObjectSize = PhpDebugBar.utils.getObjectSize = function(obj) {
+ if (Object.keys) {
+ return Object.keys(obj).length;
+ }
+ var count = 0;
+ for (var k in obj) {
+ if (obj.hasOwnProperty(k)) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ /**
+ * Returns a prefixed css class name
+ *
+ * @param {String} cls
+ * @return {String}
+ */
+ PhpDebugBar.utils.csscls = function(cls, prefix) {
+ if (cls.indexOf(' ') > -1) {
+ var clss = cls.split(' '), out = [];
+ for (var i = 0, c = clss.length; i < c; i++) {
+ out.push(PhpDebugBar.utils.csscls(clss[i], prefix));
+ }
+ return out.join(' ');
+ }
+ if (cls.indexOf('.') === 0) {
+ return '.' + prefix + cls.substr(1);
+ }
+ return prefix + cls;
+ };
+
+ /**
+ * Creates a partial function of csscls where the second
+ * argument is already defined
+ *
+ * @param {string} prefix
+ * @return {Function}
+ */
+ PhpDebugBar.utils.makecsscls = function(prefix) {
+ var f = function(cls) {
+ return PhpDebugBar.utils.csscls(cls, prefix);
+ };
+ return f;
+ }
+
+ var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-');
+
+
+ // ------------------------------------------------------------------
+
+ /**
+ * Base class for all elements with a visual component
+ *
+ * @param {Object} options
+ * @constructor
+ */
+ var Widget = PhpDebugBar.Widget = function(options) {
+ this._attributes = $.extend({}, this.defaults);
+ this._boundAttributes = {};
+ this.$el = $('<' + this.tagName + ' />');
+ if (this.className) {
+ this.$el.addClass(this.className);
+ }
+ this.initialize.apply(this, [options || {}]);
+ this.render.apply(this);
+ };
+
+ $.extend(Widget.prototype, {
+
+ tagName: 'div',
+
+ className: null,
+
+ defaults: {},
+
+ /**
+ * Called after the constructor
+ *
+ * @param {Object} options
+ */
+ initialize: function(options) {
+ this.set(options);
+ },
+
+ /**
+ * Called after the constructor to render the element
+ */
+ render: function() {},
+
+ /**
+ * Sets the value of an attribute
+ *
+ * @param {String} attr Can also be an object to set multiple attributes at once
+ * @param {Object} value
+ */
+ set: function(attr, value) {
+ if (typeof(attr) != 'string') {
+ for (var k in attr) {
+ this.set(k, attr[k]);
+ }
+ return;
+ }
+
+ this._attributes[attr] = value;
+ if (typeof(this._boundAttributes[attr]) !== 'undefined') {
+ for (var i = 0, c = this._boundAttributes[attr].length; i < c; i++) {
+ this._boundAttributes[attr][i].apply(this, [value]);
+ }
+ }
+ },
+
+ /**
+ * Checks if an attribute exists and is not null
+ *
+ * @param {String} attr
+ * @return {[type]} [description]
+ */
+ has: function(attr) {
+ return typeof(this._attributes[attr]) !== 'undefined' && this._attributes[attr] !== null;
+ },
+
+ /**
+ * Returns the value of an attribute
+ *
+ * @param {String} attr
+ * @return {Object}
+ */
+ get: function(attr) {
+ return this._attributes[attr];
+ },
+
+ /**
+ * Registers a callback function that will be called whenever the value of the attribute changes
+ *
+ * If cb is a jQuery element, text() will be used to fill the element
+ *
+ * @param {String} attr
+ * @param {Function} cb
+ */
+ bindAttr: function(attr, cb) {
+ if ($.isArray(attr)) {
+ for (var i = 0, c = attr.length; i < c; i++) {
+ this.bindAttr(attr[i], cb);
+ }
+ return;
+ }
+
+ if (typeof(this._boundAttributes[attr]) == 'undefined') {
+ this._boundAttributes[attr] = [];
+ }
+ if (typeof(cb) == 'object') {
+ var el = cb;
+ cb = function(value) { el.text(value || ''); };
+ }
+ this._boundAttributes[attr].push(cb);
+ if (this.has(attr)) {
+ cb.apply(this, [this._attributes[attr]]);
+ }
+ }
+
+ });
+
+
+ /**
+ * Creates a subclass
+ *
+ * Code from Backbone.js
+ *
+ * @param {Array} props Prototype properties
+ * @return {Function}
+ */
+ Widget.extend = function(props) {
+ var parent = this;
+
+ var child = function() { return parent.apply(this, arguments); };
+ $.extend(child, parent);
+
+ var Surrogate = function(){ this.constructor = child; };
+ Surrogate.prototype = parent.prototype;
+ child.prototype = new Surrogate;
+ $.extend(child.prototype, props);
+
+ child.__super__ = parent.prototype;
+
+ return child;
+ };
+
+ // ------------------------------------------------------------------
+
+ /**
+ * Tab
+ *
+ * A tab is composed of a tab label which is always visible and
+ * a tab panel which is visible only when the tab is active.
+ *
+ * The panel must contain a widget. A widget is an object which has
+ * an element property containing something appendable to a jQuery object.
+ *
+ * Options:
+ * - title
+ * - badge
+ * - widget
+ * - data: forward data to widget data
+ */
+ var Tab = Widget.extend({
+
+ className: csscls('panel'),
+
+ render: function() {
+ this.$tab = $(' ').addClass(csscls('tab'));
+
+ this.$icon = $(' ').appendTo(this.$tab);
+ this.bindAttr('icon', function(icon) {
+ if (icon) {
+ this.$icon.attr('class', 'fa fa-' + icon);
+ } else {
+ this.$icon.attr('class', '');
+ }
+ });
+
+ this.bindAttr('title', $(' ').addClass(csscls('text')).appendTo(this.$tab));
+
+ this.$badge = $(' ').addClass(csscls('badge')).appendTo(this.$tab);
+ this.bindAttr('badge', function(value) {
+ if (value !== null) {
+ this.$badge.text(value);
+ this.$badge.show();
+ } else {
+ this.$badge.hide();
+ }
+ });
+
+ this.bindAttr('widget', function(widget) {
+ this.$el.empty().append(widget.$el);
+ });
+
+ this.bindAttr('data', function(data) {
+ if (this.has('widget')) {
+ this.get('widget').set('data', data);
+ }
+ })
+ }
+
+ });
+
+ // ------------------------------------------------------------------
+
+ /**
+ * Indicator
+ *
+ * An indicator is a text and an icon to display single value information
+ * right inside the always visible part of the debug bar
+ *
+ * Options:
+ * - icon
+ * - title
+ * - tooltip
+ * - data: alias of title
+ */
+ var Indicator = Widget.extend({
+
+ tagName: 'span',
+
+ className: csscls('indicator'),
+
+ render: function() {
+ this.$icon = $(' ').appendTo(this.$el);
+ this.bindAttr('icon', function(icon) {
+ if (icon) {
+ this.$icon.attr('class', 'fa fa-' + icon);
+ } else {
+ this.$icon.attr('class', '');
+ }
+ });
+
+ this.bindAttr(['title', 'data'], $(' ').addClass(csscls('text')).appendTo(this.$el));
+
+ this.$tooltip = $(' ').addClass(csscls('tooltip disabled')).appendTo(this.$el);
+ this.bindAttr('tooltip', function(tooltip) {
+ if (tooltip) {
+ this.$tooltip.text(tooltip).removeClass(csscls('disabled'));
+ } else {
+ this.$tooltip.addClass(csscls('disabled'));
+ }
+ });
+ }
+
+ });
+
+ // ------------------------------------------------------------------
+
+ /**
+ * Dataset title formater
+ *
+ * Formats the title of a dataset for the select box
+ */
+ var DatasetTitleFormater = PhpDebugBar.DatasetTitleFormater = function(debugbar) {
+ this.debugbar = debugbar;
+ };
+
+ $.extend(DatasetTitleFormater.prototype, {
+
+ /**
+ * Formats the title of a dataset
+ *
+ * @this {DatasetTitleFormater}
+ * @param {String} id
+ * @param {Object} data
+ * @param {String} suffix
+ * @return {String}
+ */
+ format: function(id, data, suffix) {
+ if (suffix) {
+ suffix = ' ' + suffix;
+ } else {
+ suffix = '';
+ }
+
+ var nb = getObjectSize(this.debugbar.datasets) + 1;
+
+ if (typeof(data['__meta']) === 'undefined') {
+ return "#" + nb + suffix;
+ }
+
+ var uri = data['__meta']['uri'], filename;
+ if (uri.length && uri.charAt(uri.length - 1) === '/') {
+ // URI ends in a trailing /: get the portion before then to avoid returning an empty string
+ filename = uri.substr(0, uri.length - 1); // strip trailing '/'
+ filename = filename.substr(filename.lastIndexOf('/') + 1); // get last path segment
+ filename += '/'; // add the trailing '/' back
+ } else {
+ filename = uri.substr(uri.lastIndexOf('/') + 1);
+ }
+
+ // truncate the filename in the label, if it's too long
+ var maxLength = 150;
+ if (filename.length > maxLength) {
+ filename = filename.substr(0, maxLength) + '...';
+ }
+
+ var label = "#" + nb + " " + filename + suffix + ' (' + data['__meta']['datetime'].split(' ')[1] + ')';
+ return label;
+ }
+
+ });
+
+ // ------------------------------------------------------------------
+
+
+ /**
+ * DebugBar
+ *
+ * Creates a bar that appends itself to the body of your page
+ * and sticks to the bottom.
+ *
+ * The bar can be customized by adding tabs and indicators.
+ * A data map is used to fill those controls with data provided
+ * from datasets.
+ */
+ var DebugBar = PhpDebugBar.DebugBar = Widget.extend({
+
+ className: "phpdebugbar " + csscls('minimized'),
+
+ options: {
+ bodyMarginBottom: true,
+ bodyMarginBottomHeight: parseInt($('body').css('margin-bottom'))
+ },
+
+ initialize: function() {
+ this.controls = {};
+ this.dataMap = {};
+ this.datasets = {};
+ this.firstTabName = null;
+ this.activePanelName = null;
+ this.datesetTitleFormater = new DatasetTitleFormater(this);
+ this.registerResizeHandler();
+ },
+
+ /**
+ * Register resize event, for resize debugbar with reponsive css.
+ *
+ * @this {DebugBar}
+ */
+ registerResizeHandler: function() {
+ if (typeof this.resize.bind == 'undefined') return;
+
+ var f = this.resize.bind(this);
+ this.respCSSSize = 0;
+ $(window).resize(f);
+ setTimeout(f, 20);
+ },
+
+ /**
+ * Resizes the debugbar to fit the current browser window
+ */
+ resize: function() {
+ var contentSize = this.respCSSSize;
+ if (this.respCSSSize == 0) {
+ this.$header.find("> div > *:visible").each(function () {
+ contentSize += $(this).outerWidth();
+ });
+ }
+
+ var currentSize = this.$header.width();
+ var cssClass = "phpdebugbar-mini-design";
+ var bool = this.$header.hasClass(cssClass);
+
+ if (currentSize <= contentSize && !bool) {
+ this.respCSSSize = contentSize;
+ this.$header.addClass(cssClass);
+ } else if (contentSize < currentSize && bool) {
+ this.respCSSSize = 0;
+ this.$header.removeClass(cssClass);
+ }
+
+ // Reset height to ensure bar is still visible
+ this.setHeight(this.$body.height());
+ },
+
+ /**
+ * Initialiazes the UI
+ *
+ * @this {DebugBar}
+ */
+ render: function() {
+ var self = this;
+ this.$el.appendTo('body');
+ this.$dragCapture = $('
').addClass(csscls('drag-capture')).appendTo(this.$el);
+ this.$resizehdle = $('
').addClass(csscls('resize-handle')).appendTo(this.$el);
+ this.$header = $('
').addClass(csscls('header')).appendTo(this.$el);
+ this.$headerLeft = $('
').addClass(csscls('header-left')).appendTo(this.$header);
+ this.$headerRight = $('
').addClass(csscls('header-right')).appendTo(this.$header);
+ var $body = this.$body = $('
').addClass(csscls('body')).appendTo(this.$el);
+ this.recomputeBottomOffset();
+
+ // dragging of resize handle
+ var pos_y, orig_h;
+ this.$resizehdle.on('mousedown', function(e) {
+ orig_h = $body.height(), pos_y = e.pageY;
+ $body.parents().on('mousemove', mousemove).on('mouseup', mouseup);
+ self.$dragCapture.show();
+ e.preventDefault();
+ });
+ var mousemove = function(e) {
+ var h = orig_h + (pos_y - e.pageY);
+ self.setHeight(h);
+ };
+ var mouseup = function() {
+ $body.parents().off('mousemove', mousemove).off('mouseup', mouseup);
+ self.$dragCapture.hide();
+ };
+
+ // close button
+ this.$closebtn = $(' ').addClass(csscls('close-btn')).appendTo(this.$headerRight);
+ this.$closebtn.click(function() {
+ self.close();
+ });
+
+ // minimize button
+ this.$minimizebtn = $(' ').addClass(csscls('minimize-btn') ).appendTo(this.$headerRight);
+ this.$minimizebtn.click(function() {
+ self.minimize();
+ });
+
+ // maximize button
+ this.$maximizebtn = $(' ').addClass(csscls('maximize-btn') ).appendTo(this.$headerRight);
+ this.$maximizebtn.click(function() {
+ self.restore();
+ });
+
+ // restore button
+ this.$restorebtn = $(' ').addClass(csscls('restore-btn')).hide().appendTo(this.$el);
+ this.$restorebtn.click(function() {
+ self.restore();
+ });
+
+ // open button
+ this.$openbtn = $(' ').addClass(csscls('open-btn')).appendTo(this.$headerRight).hide();
+ this.$openbtn.click(function() {
+ self.openHandler.show(function(id, dataset) {
+ self.addDataSet(dataset, id, "(opened)");
+ self.showTab();
+ });
+ });
+
+ // select box for data sets
+ this.$datasets = $(' ').addClass(csscls('datasets-switcher')).appendTo(this.$headerRight);
+ this.$datasets.change(function() {
+ self.dataChangeHandler(self.datasets[this.value]);
+ self.showTab();
+ });
+ },
+
+ /**
+ * Sets the height of the debugbar body section
+ * Forces the height to lie within a reasonable range
+ * Stores the height in local storage so it can be restored
+ * Resets the document body bottom offset
+ *
+ * @this {DebugBar}
+ */
+ setHeight: function(height) {
+ var min_h = 40;
+ var max_h = $(window).innerHeight() - this.$header.height() - 10;
+ height = Math.min(height, max_h);
+ height = Math.max(height, min_h);
+ this.$body.css('height', height);
+ localStorage.setItem('phpdebugbar-height', height);
+ this.recomputeBottomOffset();
+ },
+
+ /**
+ * Restores the state of the DebugBar using localStorage
+ * This is not called by default in the constructor and
+ * needs to be called by subclasses in their init() method
+ *
+ * @this {DebugBar}
+ */
+ restoreState: function() {
+ // bar height
+ var height = localStorage.getItem('phpdebugbar-height');
+ this.setHeight(height || this.$body.height());
+
+ // bar visibility
+ var open = localStorage.getItem('phpdebugbar-open');
+ if (open && open == '0') {
+ this.close();
+ } else {
+ var visible = localStorage.getItem('phpdebugbar-visible');
+ if (visible && visible == '1') {
+ var tab = localStorage.getItem('phpdebugbar-tab');
+ if (this.isTab(tab)) {
+ this.showTab(tab);
+ }
+ }
+ }
+ },
+
+ /**
+ * Creates and adds a new tab
+ *
+ * @this {DebugBar}
+ * @param {String} name Internal name
+ * @param {Object} widget A widget object with an element property
+ * @param {String} title The text in the tab, if not specified, name will be used
+ * @return {Tab}
+ */
+ createTab: function(name, widget, title) {
+ var tab = new Tab({
+ title: title || (name.replace(/[_\-]/g, ' ').charAt(0).toUpperCase() + name.slice(1)),
+ widget: widget
+ });
+ return this.addTab(name, tab);
+ },
+
+ /**
+ * Adds a new tab
+ *
+ * @this {DebugBar}
+ * @param {String} name Internal name
+ * @param {Tab} tab Tab object
+ * @return {Tab}
+ */
+ addTab: function(name, tab) {
+ if (this.isControl(name)) {
+ throw new Error(name + ' already exists');
+ }
+
+ var self = this;
+ tab.$tab.appendTo(this.$headerLeft).click(function() {
+ if (!self.isMinimized() && self.activePanelName == name) {
+ self.minimize();
+ } else {
+ self.showTab(name);
+ }
+ });
+ tab.$el.appendTo(this.$body);
+
+ this.controls[name] = tab;
+ if (this.firstTabName == null) {
+ this.firstTabName = name;
+ }
+ return tab;
+ },
+
+ /**
+ * Creates and adds an indicator
+ *
+ * @this {DebugBar}
+ * @param {String} name Internal name
+ * @param {String} icon
+ * @param {String} tooltip
+ * @param {String} position "right" or "left", default is "right"
+ * @return {Indicator}
+ */
+ createIndicator: function(name, icon, tooltip, position) {
+ var indicator = new Indicator({
+ icon: icon,
+ tooltip: tooltip
+ });
+ return this.addIndicator(name, indicator, position);
+ },
+
+ /**
+ * Adds an indicator
+ *
+ * @this {DebugBar}
+ * @param {String} name Internal name
+ * @param {Indicator} indicator Indicator object
+ * @return {Indicator}
+ */
+ addIndicator: function(name, indicator, position) {
+ if (this.isControl(name)) {
+ throw new Error(name + ' already exists');
+ }
+
+ if (position == 'left') {
+ indicator.$el.insertBefore(this.$headerLeft.children().first());
+ } else {
+ indicator.$el.appendTo(this.$headerRight);
+ }
+
+ this.controls[name] = indicator;
+ return indicator;
+ },
+
+ /**
+ * Returns a control
+ *
+ * @param {String} name
+ * @return {Object}
+ */
+ getControl: function(name) {
+ if (this.isControl(name)) {
+ return this.controls[name];
+ }
+ },
+
+ /**
+ * Checks if there's a control under the specified name
+ *
+ * @this {DebugBar}
+ * @param {String} name
+ * @return {Boolean}
+ */
+ isControl: function(name) {
+ return typeof(this.controls[name]) != 'undefined';
+ },
+
+ /**
+ * Checks if a tab with the specified name exists
+ *
+ * @this {DebugBar}
+ * @param {String} name
+ * @return {Boolean}
+ */
+ isTab: function(name) {
+ return this.isControl(name) && this.controls[name] instanceof Tab;
+ },
+
+ /**
+ * Checks if an indicator with the specified name exists
+ *
+ * @this {DebugBar}
+ * @param {String} name
+ * @return {Boolean}
+ */
+ isIndicator: function(name) {
+ return this.isControl(name) && this.controls[name] instanceof Indicator;
+ },
+
+ /**
+ * Removes all tabs and indicators from the debug bar and hides it
+ *
+ * @this {DebugBar}
+ */
+ reset: function() {
+ this.minimize();
+ var self = this;
+ $.each(this.controls, function(name, control) {
+ if (self.isTab(name)) {
+ control.$tab.remove();
+ }
+ control.$el.remove();
+ });
+ this.controls = {};
+ },
+
+ /**
+ * Open the debug bar and display the specified tab
+ *
+ * @this {DebugBar}
+ * @param {String} name If not specified, display the first tab
+ */
+ showTab: function(name) {
+ if (!name) {
+ if (this.activePanelName) {
+ name = this.activePanelName;
+ } else {
+ name = this.firstTabName;
+ }
+ }
+
+ if (!this.isTab(name)) {
+ throw new Error("Unknown tab '" + name + "'");
+ }
+
+ this.$resizehdle.show();
+ this.$body.show();
+ this.recomputeBottomOffset();
+
+ $(this.$header).find('> div > .' + csscls('active')).removeClass(csscls('active'));
+ $(this.$body).find('> .' + csscls('active')).removeClass(csscls('active'));
+
+ this.controls[name].$tab.addClass(csscls('active'));
+ this.controls[name].$el.addClass(csscls('active'));
+ this.activePanelName = name;
+
+ this.$el.removeClass(csscls('minimized'));
+ localStorage.setItem('phpdebugbar-visible', '1');
+ localStorage.setItem('phpdebugbar-tab', name);
+ this.resize();
+ },
+
+ /**
+ * Hide panels and minimize the debug bar
+ *
+ * @this {DebugBar}
+ */
+ minimize: function() {
+ this.$header.find('> div > .' + csscls('active')).removeClass(csscls('active'));
+ this.$body.hide();
+ this.$resizehdle.hide();
+ this.recomputeBottomOffset();
+ localStorage.setItem('phpdebugbar-visible', '0');
+ this.$el.addClass(csscls('minimized'));
+ this.resize();
+ },
+
+ /**
+ * Checks if the panel is minimized
+ *
+ * @return {Boolean}
+ */
+ isMinimized: function() {
+ return this.$el.hasClass(csscls('minimized'));
+ },
+
+ /**
+ * Close the debug bar
+ *
+ * @this {DebugBar}
+ */
+ close: function() {
+ this.$resizehdle.hide();
+ this.$header.hide();
+ this.$body.hide();
+ this.$restorebtn.show();
+ localStorage.setItem('phpdebugbar-open', '0');
+ this.$el.addClass(csscls('closed'));
+ this.recomputeBottomOffset();
+ },
+
+ /**
+ * Checks if the panel is closed
+ *
+ * @return {Boolean}
+ */
+ isClosed: function() {
+ return this.$el.hasClass(csscls('closed'));
+ },
+
+ /**
+ * Restore the debug bar
+ *
+ * @this {DebugBar}
+ */
+ restore: function() {
+ this.$resizehdle.show();
+ this.$header.show();
+ this.$restorebtn.hide();
+ localStorage.setItem('phpdebugbar-open', '1');
+ var tab = localStorage.getItem('phpdebugbar-tab');
+ if (this.isTab(tab)) {
+ this.showTab(tab);
+ } else {
+ this.showTab();
+ }
+ this.$el.removeClass(csscls('closed'));
+ this.resize();
+ },
+
+ /**
+ * Recomputes the margin-bottom css property of the body so
+ * that the debug bar never hides any content
+ */
+ recomputeBottomOffset: function() {
+ if (this.options.bodyMarginBottom) {
+ if (this.isClosed()) {
+ return $('body').css('margin-bottom', this.options.bodyMarginBottomHeight || '');
+ }
+
+ var offset = parseInt(this.$el.height()) + this.options.bodyMarginBottomHeight;
+ $('body').css('margin-bottom', offset);
+ }
+ },
+
+ /**
+ * Sets the data map used by dataChangeHandler to populate
+ * indicators and widgets
+ *
+ * A data map is an object where properties are control names.
+ * The value of each property should be an array where the first
+ * item is the name of a property from the data object (nested properties
+ * can be specified) and the second item the default value.
+ *
+ * Example:
+ * {"memory": ["memory.peak_usage_str", "0B"]}
+ *
+ * @this {DebugBar}
+ * @param {Object} map
+ */
+ setDataMap: function(map) {
+ this.dataMap = map;
+ },
+
+ /**
+ * Same as setDataMap() but appends to the existing map
+ * rather than replacing it
+ *
+ * @this {DebugBar}
+ * @param {Object} map
+ */
+ addDataMap: function(map) {
+ $.extend(this.dataMap, map);
+ },
+
+ /**
+ * Resets datasets and add one set of data
+ *
+ * For this method to be usefull, you need to specify
+ * a dataMap using setDataMap()
+ *
+ * @this {DebugBar}
+ * @param {Object} data
+ * @return {String} Dataset's id
+ */
+ setData: function(data) {
+ this.datasets = {};
+ return this.addDataSet(data);
+ },
+
+ /**
+ * Adds a dataset
+ *
+ * If more than one dataset are added, the dataset selector
+ * will be displayed.
+ *
+ * For this method to be usefull, you need to specify
+ * a dataMap using setDataMap()
+ *
+ * @this {DebugBar}
+ * @param {Object} data
+ * @param {String} id The name of this set, optional
+ * @param {String} suffix
+ * @return {String} Dataset's id
+ */
+ addDataSet: function(data, id, suffix) {
+ var label = this.datesetTitleFormater.format(id, data, suffix);
+ id = id || (getObjectSize(this.datasets) + 1);
+ this.datasets[id] = data;
+
+ this.$datasets.append($('' + label + ' '));
+ if (this.$datasets.children().length > 1) {
+ this.$datasets.show();
+ }
+
+ this.showDataSet(id);
+ return id;
+ },
+
+ /**
+ * Loads a dataset using the open handler
+ *
+ * @param {String} id
+ */
+ loadDataSet: function(id, suffix, callback) {
+ if (!this.openHandler) {
+ throw new Error('loadDataSet() needs an open handler');
+ }
+ var self = this;
+ this.openHandler.load(id, function(data) {
+ self.addDataSet(data, id, suffix);
+ callback && callback(data);
+ });
+ },
+
+ /**
+ * Returns the data from a dataset
+ *
+ * @this {DebugBar}
+ * @param {String} id
+ * @return {Object}
+ */
+ getDataSet: function(id) {
+ return this.datasets[id];
+ },
+
+ /**
+ * Switch the currently displayed dataset
+ *
+ * @this {DebugBar}
+ * @param {String} id
+ */
+ showDataSet: function(id) {
+ this.dataChangeHandler(this.datasets[id]);
+ this.$datasets.val(id);
+ },
+
+ /**
+ * Called when the current dataset is modified.
+ *
+ * @this {DebugBar}
+ * @param {Object} data
+ */
+ dataChangeHandler: function(data) {
+ var self = this;
+ $.each(this.dataMap, function(key, def) {
+ var d = getDictValue(data, def[0], def[1]);
+ if (key.indexOf(':') != -1) {
+ key = key.split(':');
+ self.getControl(key[0]).set(key[1], d);
+ } else {
+ self.getControl(key).set('data', d);
+ }
+ });
+ },
+
+ /**
+ * Sets the handler to open past dataset
+ *
+ * @this {DebugBar}
+ * @param {object} handler
+ */
+ setOpenHandler: function(handler) {
+ this.openHandler = handler;
+ if (handler !== null) {
+ this.$openbtn.show();
+ } else {
+ this.$openbtn.hide();
+ }
+ },
+
+ /**
+ * Returns the handler to open past dataset
+ *
+ * @this {DebugBar}
+ * @return {object}
+ */
+ getOpenHandler: function() {
+ return this.openHandler;
+ }
+
+ });
+
+ DebugBar.Tab = Tab;
+ DebugBar.Indicator = Indicator;
+
+ // ------------------------------------------------------------------
+
+ /**
+ * AjaxHandler
+ *
+ * Extract data from headers of an XMLHttpRequest and adds a new dataset
+ */
+ var AjaxHandler = PhpDebugBar.AjaxHandler = function(debugbar, headerName) {
+ this.debugbar = debugbar;
+ this.headerName = headerName || 'phpdebugbar';
+ };
+
+ $.extend(AjaxHandler.prototype, {
+
+ /**
+ * Handles an XMLHttpRequest
+ *
+ * @this {AjaxHandler}
+ * @param {XMLHttpRequest} xhr
+ * @return {Bool}
+ */
+ handle: function(xhr) {
+ if (!this.loadFromId(xhr)) {
+ return this.loadFromData(xhr);
+ }
+ return true;
+ },
+
+ /**
+ * Checks if the HEADER-id exists and loads the dataset using the open handler
+ *
+ * @param {XMLHttpRequest} xhr
+ * @return {Bool}
+ */
+ loadFromId: function(xhr) {
+ var id = this.extractIdFromHeaders(xhr);
+ if (id && this.debugbar.openHandler) {
+ this.debugbar.loadDataSet(id, "(ajax)");
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * Extracts the id from the HEADER-id
+ *
+ * @param {XMLHttpRequest} xhr
+ * @return {String}
+ */
+ extractIdFromHeaders: function(xhr) {
+ return xhr.getResponseHeader(this.headerName + '-id');
+ },
+
+ /**
+ * Checks if the HEADER exists and loads the dataset
+ *
+ * @param {XMLHttpRequest} xhr
+ * @return {Bool}
+ */
+ loadFromData: function(xhr) {
+ var raw = this.extractDataFromHeaders(xhr);
+ if (!raw) {
+ return false;
+ }
+
+ var data = this.parseHeaders(raw);
+ if (data.error) {
+ throw new Error('Error loading debugbar data: ' + data.error);
+ } else if(data.data) {
+ this.debugbar.addDataSet(data.data, data.id, "(ajax)");
+ }
+ return true;
+ },
+
+ /**
+ * Extract the data as a string from headers of an XMLHttpRequest
+ *
+ * @this {AjaxHandler}
+ * @param {XMLHttpRequest} xhr
+ * @return {string}
+ */
+ extractDataFromHeaders: function(xhr) {
+ var data = xhr.getResponseHeader(this.headerName);
+ if (!data) {
+ return;
+ }
+ for (var i = 1;; i++) {
+ var header = xhr.getResponseHeader(this.headerName + '-' + i);
+ if (!header) {
+ break;
+ }
+ data += header;
+ }
+ return decodeURIComponent(data);
+ },
+
+ /**
+ * Parses the string data into an object
+ *
+ * @this {AjaxHandler}
+ * @param {string} data
+ * @return {string}
+ */
+ parseHeaders: function(data) {
+ return JSON.parse(data);
+ },
+
+ /**
+ * Attaches an event listener to jQuery.ajaxComplete()
+ *
+ * @this {AjaxHandler}
+ * @param {jQuery} jq Optional
+ */
+ bindToJquery: function(jq) {
+ var self = this;
+ jq(document).ajaxComplete(function(e, xhr, settings) {
+ if (!settings.ignoreDebugBarAjaxHandler) {
+ self.handle(xhr);
+ }
+ });
+ },
+
+ /**
+ * Attaches an event listener to XMLHttpRequest
+ *
+ * @this {AjaxHandler}
+ */
+ bindToXHR: function() {
+ var self = this;
+ var proxied = XMLHttpRequest.prototype.open;
+ XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
+ var xhr = this;
+ this.addEventListener("readystatechange", function() {
+ var skipUrl = self.debugbar.openHandler ? self.debugbar.openHandler.get('url') : null;
+ if (xhr.readyState == 4 && url.indexOf(skipUrl) !== 0) {
+ self.handle(xhr);
+ }
+ }, false);
+ proxied.apply(this, Array.prototype.slice.call(arguments));
+ };
+ }
+
+ });
+
+})(PhpDebugBar.$);
diff --git a/htdocs/includes/DebugBar/Resources/openhandler.css b/htdocs/includes/DebugBar/Resources/openhandler.css
new file mode 100644
index 00000000000..d72aba5a6f6
--- /dev/null
+++ b/htdocs/includes/DebugBar/Resources/openhandler.css
@@ -0,0 +1,69 @@
+div.phpdebugbar-openhandler-overlay {
+ position: fixed;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ background: #000;
+ opacity: .3;
+ z-index: 20000;
+}
+
+div.phpdebugbar-openhandler {
+ position: fixed;
+ margin: auto;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ width: 70%;
+ height: 70%;
+ background: #fff;
+ border: 2px solid #888;
+ overflow: auto;
+ z-index: 20001;
+ font-family: arial;
+ font-size: 14px;
+ padding-bottom: 10px;
+}
+ div.phpdebugbar-openhandler a {
+ color: #555;
+ }
+ div.phpdebugbar-openhandler .phpdebugbar-openhandler-header {
+ background: #efefef url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAUCAYAAABvVQZ0AAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfdBgcKHQH1H7EUAAADV0lEQVQ4y7WUy28bVRSHvzvjJPbYY48dj80rTe28gCbCivPsAhBthJCoBIEQQGr/BMRjh1gA20plEYSQumFFQbBBEWVV0bLoQ1BC1YfcBDt1UicFZZzYje06M57LokVNaZJ2w7e7597zOzpX53fgfhSgzYzGDmk+7YQe0DMD/UNSD+gZzaedMKOxQ0DbnXf3IP5z1hLtyc8k8q1IuFX/N+i6LopyN7dYtNYR4ti1fO5doLqVmD+oBy90JLs6pJQ8CCEE2dxctnyz/AxQ2SwWjYRbzycTHbscx+Fh8Xg85OazC8VVKw2sqIDS3dlzJBo1X3Bdd8skKSVCiPvirusSChmhoB40rKJ1XFFVT/uGvXFwu+pBQ6erp5OdWq9v1A8KIdo9Ab9/MhJu9TUaDdbWVlEUFYlEureTP/n0IwpLNzh75gwetRlN06jdqoF7+5Mcx8br9fk0nzaJ1+s7nU4NysTupLRtW5ZKJVmpVOWpkz/LjkRCFgoFaduOrFarcnb2quzb0ytnZmZktVaT5fJNWSqV5P59+2RTU9Npxa/5e10p0XU/lmUxOryX7q5OIpEw4xPjxOMxnn/uWdqeaCNmxhgeHSSVSvHi2BidyS6OHv2S9z94D1e6exQzauqObZMeSGOtWNiOQ9iI4iIZGhplfb1CNpulNWyiqAr2xi0A5nN5QiEDze+n0QAkmic7/+diZ6K7bXLyTTxNKr19T/Hq+Css5Be4vpinWCwS8BsEQi3UajVMM45t24zsHaKv72leG59gcuINFKEsC6/X+13cfOT1S1cu8u03x8jl8ti2zfT0NCMjo9RqFS5fyhAMBejp6WZsbD9mLM6pk7+gqio/Hf+Ret1hLpv5Xhgh4+WwEZmey84ykO5HuuqWMwXgOA6ffzHF1NQR5jJ5FPWuxZaWCwcEEHzs0cfPeVtangwGjQdOfbVSpcXrRd0ktFZazVzLzw8rQHlpuXA4FAo/lIU0v3aPkBCCxesLh4Gyeic2c+Ov5d0xM57arsWtcF2XCxdnvpJSfgygbrr7wbJWioYRfqm5uXlH+6iqSr1eJ3P1yjuudD/cbp8BJIUQX/enBoYbjcaWQr//8ds5KeXbQG6n5biZXcABIDaYHkn+ev5sDvgbmAYW+L/5B5NrVZNHcIujAAAAAElFTkSuQmCC) no-repeat 5px 4px;
+ padding-left: 29px;
+ min-height: 26px;
+ line-height: 25px;
+ color: #555;
+ margin-bottom: 10px;
+ }
+ div.phpdebugbar-openhandler .phpdebugbar-openhandler-header a {
+ font-size: 14px;
+ color: #555;
+ text-decoration: none;
+ float: right;
+ padding: 5px 8px;
+ }
+ div.phpdebugbar-openhandler table {
+ width: 100%;
+ table-layout: fixed;
+ font-size: 14px;
+ }
+ div.phpdebugbar-openhandler table td {
+ padding: 6px 3px;
+ border-bottom: 1px solid #ddd;
+ }
+ div.phpdebugbar-openhandler table td a{
+ display: block;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions {
+ text-align: center;
+ padding: 7px 0;
+ }
+ div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions a {
+ margin: 0 10px;
+ color: #555;
+ }
diff --git a/htdocs/includes/DebugBar/Resources/openhandler.js b/htdocs/includes/DebugBar/Resources/openhandler.js
new file mode 100644
index 00000000000..08d13b3fd27
--- /dev/null
+++ b/htdocs/includes/DebugBar/Resources/openhandler.js
@@ -0,0 +1,202 @@
+if (typeof(PhpDebugBar) == 'undefined') {
+ // namespace
+ var PhpDebugBar = {};
+ PhpDebugBar.$ = jQuery;
+}
+
+(function($) {
+
+ var csscls = function(cls) {
+ return PhpDebugBar.utils.csscls(cls, 'phpdebugbar-openhandler-');
+ };
+
+ PhpDebugBar.OpenHandler = PhpDebugBar.Widget.extend({
+
+ className: 'phpdebugbar-openhandler',
+
+ defaults: {
+ items_per_page: 20
+ },
+
+ render: function() {
+ var self = this;
+
+ this.$el.appendTo('body').hide();
+ this.$closebtn = $(' ');
+ this.$table = $(' ');
+ $('PHP DebugBar | Open
').addClass(csscls('header')).append(this.$closebtn).appendTo(this.$el);
+ $('Date Method URL IP Filter data
').append(this.$table).appendTo(this.$el);
+ this.$actions = $('
').addClass(csscls('actions')).appendTo(this.$el);
+
+ this.$closebtn.on('click', function() {
+ self.hide();
+ });
+
+ this.$loadmorebtn = $('Load more ')
+ .appendTo(this.$actions)
+ .on('click', function() {
+ self.find(self.last_find_request, self.last_find_request.offset + self.get('items_per_page'), self.handleFind.bind(self));
+ });
+
+ this.$showonlycurrentbtn = $('Show only current URL ')
+ .appendTo(this.$actions)
+ .on('click', function() {
+ self.$table.empty();
+ self.find({uri: window.location.pathname}, 0, self.handleFind.bind(self));
+ });
+
+ this.$showallbtn = $('Show all ')
+ .appendTo(this.$actions)
+ .on('click', function() {
+ self.refresh();
+ });
+
+ this.$clearbtn = $('Delete all ')
+ .appendTo(this.$actions)
+ .on('click', function() {
+ self.clear(function() {
+ self.hide();
+ });
+ });
+
+ this.addSearch();
+
+ this.$overlay = $('
').addClass(csscls('overlay')).hide().appendTo('body');
+ this.$overlay.on('click', function() {
+ self.hide();
+ });
+ },
+
+ refresh: function() {
+ this.$table.empty();
+ this.$loadmorebtn.show();
+ this.find({}, 0, this.handleFind.bind(this));
+ },
+
+ addSearch: function(){
+ var self = this;
+ var searchBtn = $(' ')
+ .text('Search')
+ .attr('type', 'submit')
+ .on('click', function(e) {
+ self.$table.empty();
+ var search = {};
+ var a = $(this).parent().serializeArray();
+ $.each(a, function() {
+ if(this.value){
+ search[this.name] = this.value;
+ }
+ });
+
+ self.find(search, 0, self.handleFind.bind(self));
+ e.preventDefault();
+ });
+
+ $(' ')
+ .append('Filter results ')
+ .append('Method: GET POST PUT DELETE ')
+ .append('Uri: ')
+ .append('IP: ')
+ .append(searchBtn)
+ .appendTo(this.$actions);
+ },
+
+ handleFind: function(data) {
+ var self = this;
+ $.each(data, function(i, meta) {
+ var a = $(' ')
+ .text('Load dataset')
+ .on('click', function(e) {
+ self.hide();
+ self.load(meta['id'], function(data) {
+ self.callback(meta['id'], data);
+ });
+ e.preventDefault();
+ });
+
+ var method = $(' ')
+ .text(meta['method'])
+ .on('click', function(e) {
+ self.$table.empty();
+ self.find({method: meta['method']}, 0, self.handleFind.bind(self));
+ e.preventDefault();
+ });
+
+ var uri = $(' ')
+ .text(meta['uri'])
+ .on('click', function(e) {
+ self.hide();
+ self.load(meta['id'], function(data) {
+ self.callback(meta['id'], data);
+ });
+ e.preventDefault();
+ });
+
+ var ip = $(' ')
+ .text(meta['ip'])
+ .on('click', function(e) {
+ self.$table.empty();
+ self.find({ip: meta['ip']}, 0, self.handleFind.bind(self));
+ e.preventDefault();
+ });
+
+ var search = $(' ')
+ .text('Show URL')
+ .on('click', function(e) {
+ self.$table.empty();
+ self.find({uri: meta['uri']}, 0, self.handleFind.bind(self));
+ e.preventDefault();
+ });
+
+ $(' ')
+ .append('' + meta['datetime'] + ' ')
+ .append('' + meta['method'] + ' ')
+ .append($(' ').append(uri))
+ .append($(' ').append(ip))
+ .append($(' ').append(search))
+ .appendTo(self.$table);
+ });
+ if (data.length < this.get('items_per_page')) {
+ this.$loadmorebtn.hide();
+ }
+ },
+
+ show: function(callback) {
+ this.callback = callback;
+ this.$el.show();
+ this.$overlay.show();
+ this.refresh();
+ },
+
+ hide: function() {
+ this.$el.hide();
+ this.$overlay.hide();
+ },
+
+ find: function(filters, offset, callback) {
+ var data = $.extend({}, filters, {max: this.get('items_per_page'), offset: offset || 0});
+ this.last_find_request = data;
+ this.ajax(data, callback);
+ },
+
+ load: function(id, callback) {
+ this.ajax({op: "get", id: id}, callback);
+ },
+
+ clear: function(callback) {
+ this.ajax({op: "clear"}, callback);
+ },
+
+ ajax: function(data, callback) {
+ $.ajax({
+ dataType: 'json',
+ url: this.get('url'),
+ data: data,
+ success: callback,
+ ignoreDebugBarAjaxHandler: true
+ });
+ }
+
+ });
+
+})(PhpDebugBar.$);
diff --git a/htdocs/includes/DebugBar/Resources/vendor/font-awesome/css/font-awesome.min.css b/htdocs/includes/DebugBar/Resources/vendor/font-awesome/css/font-awesome.min.css
new file mode 100644
index 00000000000..ec53d4d6d5b
--- /dev/null
+++ b/htdocs/includes/DebugBar/Resources/vendor/font-awesome/css/font-awesome.min.css
@@ -0,0 +1,4 @@
+/*!
+ * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome
+ * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.2.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.2.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.2.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.2.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}
\ No newline at end of file
diff --git a/htdocs/includes/DebugBar/Resources/vendor/font-awesome/fonts/FontAwesome.otf b/htdocs/includes/DebugBar/Resources/vendor/font-awesome/fonts/FontAwesome.otf
new file mode 100644
index 00000000000..81c9ad949b4
Binary files /dev/null and b/htdocs/includes/DebugBar/Resources/vendor/font-awesome/fonts/FontAwesome.otf differ
diff --git a/htdocs/includes/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.eot b/htdocs/includes/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.eot
new file mode 100644
index 00000000000..84677bc0c5f
Binary files /dev/null and b/htdocs/includes/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.eot differ
diff --git a/htdocs/includes/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.svg b/htdocs/includes/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.svg
new file mode 100644
index 00000000000..d907b25ae60
--- /dev/null
+++ b/htdocs/includes/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.svg
@@ -0,0 +1,520 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/htdocs/includes/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.ttf b/htdocs/includes/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.ttf
new file mode 100644
index 00000000000..96a3639cdde
Binary files /dev/null and b/htdocs/includes/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.ttf differ
diff --git a/htdocs/includes/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.woff b/htdocs/includes/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.woff
new file mode 100644
index 00000000000..628b6a52a87
Binary files /dev/null and b/htdocs/includes/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.woff differ
diff --git a/htdocs/includes/DebugBar/Resources/vendor/highlightjs/highlight.pack.js b/htdocs/includes/DebugBar/Resources/vendor/highlightjs/highlight.pack.js
new file mode 100644
index 00000000000..cf7215a66e1
--- /dev/null
+++ b/htdocs/includes/DebugBar/Resources/vendor/highlightjs/highlight.pack.js
@@ -0,0 +1 @@
+var hljs=new function(){function k(v){return v.replace(/&/gm,"&").replace(//gm,">")}function t(v){return v.nodeName.toLowerCase()}function i(w,x){var v=w&&w.exec(x);return v&&v.index==0}function d(v){return Array.prototype.map.call(v.childNodes,function(w){if(w.nodeType==3){return b.useBR?w.nodeValue.replace(/\n/g,""):w.nodeValue}if(t(w)=="br"){return"\n"}return d(w)}).join("")}function r(w){var v=(w.className+" "+(w.parentNode?w.parentNode.className:"")).split(/\s+/);v=v.map(function(x){return x.replace(/^language-/,"")});return v.filter(function(x){return j(x)||x=="no-highlight"})[0]}function o(x,y){var v={};for(var w in x){v[w]=x[w]}if(y){for(var w in y){v[w]=y[w]}}return v}function u(x){var v=[];(function w(y,z){for(var A=y.firstChild;A;A=A.nextSibling){if(A.nodeType==3){z+=A.nodeValue.length}else{if(t(A)=="br"){z+=1}else{if(A.nodeType==1){v.push({event:"start",offset:z,node:A});z=w(A,z);v.push({event:"stop",offset:z,node:A})}}}}return z})(x,0);return v}function q(w,y,C){var x=0;var F="";var z=[];function B(){if(!w.length||!y.length){return w.length?w:y}if(w[0].offset!=y[0].offset){return(w[0].offset"}function E(G){F+=""+t(G)+">"}function v(G){(G.event=="start"?A:E)(G.node)}while(w.length||y.length){var D=B();F+=k(C.substr(x,D[0].offset-x));x=D[0].offset;if(D==w){z.reverse().forEach(E);do{v(D.splice(0,1)[0]);D=B()}while(D==w&&D.length&&D[0].offset==x);z.reverse().forEach(A)}else{if(D[0].event=="start"){z.push(D[0].node)}else{z.pop()}v(D.splice(0,1)[0])}}return F+k(C.substr(x))}function m(y){function v(z){return(z&&z.source)||z}function w(A,z){return RegExp(v(A),"m"+(y.cI?"i":"")+(z?"g":""))}function x(D,C){if(D.compiled){return}D.compiled=true;D.k=D.k||D.bK;if(D.k){var z={};function E(G,F){if(y.cI){F=F.toLowerCase()}F.split(" ").forEach(function(H){var I=H.split("|");z[I[0]]=[G,I[1]?Number(I[1]):1]})}if(typeof D.k=="string"){E("keyword",D.k)}else{Object.keys(D.k).forEach(function(F){E(F,D.k[F])})}D.k=z}D.lR=w(D.l||/\b[A-Za-z0-9_]+\b/,true);if(C){if(D.bK){D.b=D.bK.split(" ").join("|")}if(!D.b){D.b=/\B|\b/}D.bR=w(D.b);if(!D.e&&!D.eW){D.e=/\B|\b/}if(D.e){D.eR=w(D.e)}D.tE=v(D.e)||"";if(D.eW&&C.tE){D.tE+=(D.e?"|":"")+C.tE}}if(D.i){D.iR=w(D.i)}if(D.r===undefined){D.r=1}if(!D.c){D.c=[]}var B=[];D.c.forEach(function(F){if(F.v){F.v.forEach(function(G){B.push(o(F,G))})}else{B.push(F=="self"?D:F)}});D.c=B;D.c.forEach(function(F){x(F,D)});if(D.starts){x(D.starts,C)}var A=D.c.map(function(F){return F.bK?"\\.?\\b("+F.b+")\\b\\.?":F.b}).concat([D.tE]).concat([D.i]).map(v).filter(Boolean);D.t=A.length?w(A.join("|"),true):{exec:function(F){return null}};D.continuation={}}x(y)}function c(S,L,J,R){function v(U,V){for(var T=0;T";U+=Z+'">';return U+X+Y}function N(){var U=k(C);if(!I.k){return U}var T="";var X=0;I.lR.lastIndex=0;var V=I.lR.exec(U);while(V){T+=U.substr(X,V.index-X);var W=E(I,V);if(W){H+=W[1];T+=w(W[0],V[0])}else{T+=V[0]}X=I.lR.lastIndex;V=I.lR.exec(U)}return T+U.substr(X)}function F(){if(I.sL&&!f[I.sL]){return k(C)}var T=I.sL?c(I.sL,C,true,I.continuation.top):g(C);if(I.r>0){H+=T.r}if(I.subLanguageMode=="continuous"){I.continuation.top=T.top}return w(T.language,T.value,false,true)}function Q(){return I.sL!==undefined?F():N()}function P(V,U){var T=V.cN?w(V.cN,"",true):"";if(V.rB){D+=T;C=""}else{if(V.eB){D+=k(U)+T;C=""}else{D+=T;C=U}}I=Object.create(V,{parent:{value:I}})}function G(T,X){C+=T;if(X===undefined){D+=Q();return 0}var V=v(X,I);if(V){D+=Q();P(V,X);return V.rB?0:X.length}var W=z(I,X);if(W){var U=I;if(!(U.rE||U.eE)){C+=X}D+=Q();do{if(I.cN){D+=""}H+=I.r;I=I.parent}while(I!=W.parent);if(U.eE){D+=k(X)}C="";if(W.starts){P(W.starts,"")}return U.rE?0:X.length}if(A(X,I)){throw new Error('Illegal lexeme "'+X+'" for mode "'+(I.cN||"")+'"')}C+=X;return X.length||1}var M=j(S);if(!M){throw new Error('Unknown language: "'+S+'"')}m(M);var I=R||M;var D="";for(var K=I;K!=M;K=K.parent){if(K.cN){D=w(K.cN,D,true)}}var C="";var H=0;try{var B,y,x=0;while(true){I.t.lastIndex=x;B=I.t.exec(L);if(!B){break}y=G(L.substr(x,B.index-x),B[0]);x=B.index+y}G(L.substr(x));for(var K=I;K.parent;K=K.parent){if(K.cN){D+=""}}return{r:H,value:D,language:S,top:I}}catch(O){if(O.message.indexOf("Illegal")!=-1){return{r:0,value:k(L)}}else{throw O}}}function g(y,x){x=x||b.languages||Object.keys(f);var v={r:0,value:k(y)};var w=v;x.forEach(function(z){if(!j(z)){return}var A=c(z,y,false);A.language=z;if(A.r>w.r){w=A}if(A.r>v.r){w=v;v=A}});if(w.language){v.second_best=w}return v}function h(v){if(b.tabReplace){v=v.replace(/^((<[^>]+>|\t)+)/gm,function(w,z,y,x){return z.replace(/\t/g,b.tabReplace)})}if(b.useBR){v=v.replace(/\n/g," ")}return v}function p(z){var y=d(z);var A=r(z);if(A=="no-highlight"){return}var v=A?c(A,y,true):g(y);var w=u(z);if(w.length){var x=document.createElementNS("http://www.w3.org/1999/xhtml","pre");x.innerHTML=v.value;v.value=q(w,u(x),y)}v.value=h(v.value);z.innerHTML=v.value;z.className+=" hljs "+(!A&&v.language||"");z.result={language:v.language,re:v.r};if(v.second_best){z.second_best={language:v.second_best.language,re:v.second_best.r}}}var b={classPrefix:"hljs-",tabReplace:null,useBR:false,languages:undefined};function s(v){b=o(b,v)}function l(){if(l.called){return}l.called=true;var v=document.querySelectorAll("pre code");Array.prototype.forEach.call(v,p)}function a(){addEventListener("DOMContentLoaded",l,false);addEventListener("load",l,false)}var f={};var n={};function e(v,x){var w=f[v]=x(this);if(w.aliases){w.aliases.forEach(function(y){n[y]=v})}}function j(v){return f[v]||f[n[v]]}this.highlight=c;this.highlightAuto=g;this.fixMarkup=h;this.highlightBlock=p;this.configure=s;this.initHighlighting=l;this.initHighlightingOnLoad=a;this.registerLanguage=e;this.getLanguage=j;this.inherit=o;this.IR="[a-zA-Z][a-zA-Z0-9_]*";this.UIR="[a-zA-Z_][a-zA-Z0-9_]*";this.NR="\\b\\d+(\\.\\d+)?";this.CNR="(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)";this.BNR="\\b(0b[01]+)";this.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~";this.BE={b:"\\\\[\\s\\S]",r:0};this.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[this.BE]};this.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[this.BE]};this.CLCM={cN:"comment",b:"//",e:"$"};this.CBLCLM={cN:"comment",b:"/\\*",e:"\\*/"};this.HCM={cN:"comment",b:"#",e:"$"};this.NM={cN:"number",b:this.NR,r:0};this.CNM={cN:"number",b:this.CNR,r:0};this.BNM={cN:"number",b:this.BNR,r:0};this.REGEXP_MODE={cN:"regexp",b:/\//,e:/\/[gim]*/,i:/\n/,c:[this.BE,{b:/\[/,e:/\]/,r:0,c:[this.BE]}]};this.TM={cN:"title",b:this.IR,r:0};this.UTM={cN:"title",b:this.UIR,r:0}}();hljs.registerLanguage("scilab",function(a){var b=[a.CNM,{cN:"string",b:"'|\"",e:"'|\"",c:[a.BE,{b:"''"}]}];return{k:{keyword:"abort break case clear catch continue do elseif else endfunction end for functionglobal if pause return resume select try then while%f %F %t %T %pi %eps %inf %nan %e %i %z %s",built_in:"abs and acos asin atan ceil cd chdir clearglobal cosh cos cumprod deff disp errorexec execstr exists exp eye gettext floor fprintf fread fsolve imag isdef isemptyisinfisnan isvector lasterror length load linspace list listfiles log10 log2 logmax min msprintf mclose mopen ones or pathconvert poly printf prod pwd rand realround sinh sin size gsort sprintf sqrt strcat strcmps tring sum system tanh tantype typename warning zeros matrix"},i:'("|#|/\\*|\\s+/\\w+)',c:[{cN:"function",bK:"function endfunction",e:"$",k:"function endfunction|10",c:[a.UTM,{cN:"params",b:"\\(",e:"\\)"},],},{cN:"transposed_variable",b:"[a-zA-Z_][a-zA-Z_0-9]*('+[\\.']*|[\\.']+)",e:"",r:0},{cN:"matrix",b:"\\[",e:"\\]'*[\\.']*",r:0,c:b},{cN:"comment",b:"//",e:"$"}].concat(b)}});hljs.registerLanguage("xml",function(a){var c="[A-Za-z0-9\\._:-]+";var d={b:/<\?(php)?(?!\w)/,e:/\?>/,sL:"php",subLanguageMode:"continuous"};var b={eW:true,i:/,r:0,c:[d,{cN:"attribute",b:c,r:0},{b:"=",r:0,c:[{cN:"value",v:[{b:/"/,e:/"/},{b:/'/,e:/'/},{b:/[^\s\/>]+/}]}]}]};return{aliases:["html"],cI:true,c:[{cN:"doctype",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},{cN:"comment",b:"",r:10},{cN:"cdata",b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{cN:"tag",b:"",rE:true,sL:"css"}},{cN:"tag",b:"