dolibarr  16.0.5
sqlite3.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2001 Fabien Seisen <seisen@linuxfr.org>
3  * Copyright (C) 2002-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
4  * Copyright (C) 2004-2011 Laurent Destailleur <eldy@users.sourceforge.net>
5  * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
6  * Copyright (C) 2005-2009 Regis Houssin <regis.houssin@inodbox.com>
7  * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  */
22 
28 require_once DOL_DOCUMENT_ROOT.'/core/db/DoliDB.class.php';
29 
33 class DoliDBSqlite3 extends DoliDB
34 {
36  public $type = 'sqlite3';
38  const LABEL = 'Sqlite3';
40  const VERSIONMIN = '3.0.0';
41 
45  private $_results;
46 
47  const WEEK_MONDAY_FIRST = 1;
48  const WEEK_YEAR = 2;
49  const WEEK_FIRST_WEEKDAY = 4;
50 
51 
63  public function __construct($type, $host, $user, $pass, $name = '', $port = 0)
64  {
65  global $conf;
66 
67  // Note that having "static" property for "$forcecharset" and "$forcecollate" will make error here in strict mode, so they are not static
68  if (!empty($conf->db->character_set)) {
69  $this->forcecharset = $conf->db->character_set;
70  }
71  if (!empty($conf->db->dolibarr_main_db_collation)) {
72  $this->forcecollate = $conf->db->dolibarr_main_db_collation;
73  }
74 
75  $this->database_user = $user;
76  $this->database_host = $host;
77  $this->database_port = $port;
78 
79  $this->transaction_opened = 0;
80 
81  //print "Name DB: $host,$user,$pass,$name<br>";
82 
83  /*if (! function_exists("sqlite_query"))
84  {
85  $this->connected = false;
86  $this->ok = false;
87  $this->error="Sqlite PHP functions for using Sqlite driver are not available in this version of PHP. Try to use another driver.";
88  dol_syslog(get_class($this)."::DoliDBSqlite3 : Sqlite PHP functions for using Sqlite driver are not available in this version of PHP. Try to use another driver.",LOG_ERR);
89  return $this->ok;
90  }*/
91 
92  /*if (! $host)
93  {
94  $this->connected = false;
95  $this->ok = false;
96  $this->error=$langs->trans("ErrorWrongHostParameter");
97  dol_syslog(get_class($this)."::DoliDBSqlite3 : Erreur Connect, wrong host parameters",LOG_ERR);
98  return $this->ok;
99  }*/
100 
101  // Essai connexion serveur
102  // We do not try to connect to database, only to server. Connect to database is done later in constrcutor
103  $this->db = $this->connect($host, $user, $pass, $name, $port);
104 
105  if ($this->db) {
106  $this->connected = true;
107  $this->ok = true;
108  $this->database_selected = true;
109  $this->database_name = $name;
110 
111  $this->addCustomFunction('IF');
112  $this->addCustomFunction('MONTH');
113  $this->addCustomFunction('CURTIME');
114  $this->addCustomFunction('CURDATE');
115  $this->addCustomFunction('WEEK', 1);
116  $this->addCustomFunction('WEEK', 2);
117  $this->addCustomFunction('WEEKDAY');
118  $this->addCustomFunction('date_format');
119  //$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
120  } else {
121  // host, login ou password incorrect
122  $this->connected = false;
123  $this->ok = false;
124  $this->database_selected = false;
125  $this->database_name = '';
126  //$this->error=sqlite_connect_error();
127  dol_syslog(get_class($this)."::DoliDBSqlite3 : Error Connect ".$this->error, LOG_ERR);
128  }
129 
130  return $this->ok;
131  }
132 
133 
141  public static function convertSQLFromMysql($line, $type = 'ddl')
142  {
143  // Removed empty line if this is a comment line for SVN tagging
144  if (preg_match('/^--\s\$Id/i', $line)) {
145  return '';
146  }
147  // Return line if this is a comment
148  if (preg_match('/^#/i', $line) || preg_match('/^$/i', $line) || preg_match('/^--/i', $line)) {
149  return $line;
150  }
151  if ($line != "") {
152  if ($type == 'auto') {
153  if (preg_match('/ALTER TABLE/i', $line)) {
154  $type = 'dml';
155  } elseif (preg_match('/CREATE TABLE/i', $line)) {
156  $type = 'dml';
157  } elseif (preg_match('/DROP TABLE/i', $line)) {
158  $type = 'dml';
159  }
160  }
161 
162  if ($type == 'dml') {
163  $line = preg_replace('/\s/', ' ', $line); // Replace tabulation with space
164 
165  // we are inside create table statement so lets process datatypes
166  if (preg_match('/(ISAM|innodb)/i', $line)) { // end of create table sequence
167  $line = preg_replace('/\)[\s\t]*type[\s\t]*=[\s\t]*(MyISAM|innodb);/i', ');', $line);
168  $line = preg_replace('/\)[\s\t]*engine[\s\t]*=[\s\t]*(MyISAM|innodb);/i', ');', $line);
169  $line = preg_replace('/,$/', '', $line);
170  }
171 
172  // Process case: "CREATE TABLE llx_mytable(rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY,code..."
173  if (preg_match('/[\s\t\(]*(\w*)[\s\t]+int.*auto_increment/i', $line, $reg)) {
174  $newline = preg_replace('/([\s\t\(]*)([a-zA-Z_0-9]*)[\s\t]+int.*auto_increment[^,]*/i', '\\1 \\2 integer PRIMARY KEY AUTOINCREMENT', $line);
175  //$line = "-- ".$line." replaced by --\n".$newline;
176  $line = $newline;
177  }
178 
179  // tinyint type conversion
180  $line = str_replace('tinyint', 'smallint', $line);
181 
182  // nuke unsigned
183  $line = preg_replace('/(int\w+|smallint)\s+unsigned/i', '\\1', $line);
184 
185  // blob -> text
186  $line = preg_replace('/\w*blob/i', 'text', $line);
187 
188  // tinytext/mediumtext -> text
189  $line = preg_replace('/tinytext/i', 'text', $line);
190  $line = preg_replace('/mediumtext/i', 'text', $line);
191 
192  // change not null datetime field to null valid ones
193  // (to support remapping of "zero time" to null
194  $line = preg_replace('/datetime not null/i', 'datetime', $line);
195  $line = preg_replace('/datetime/i', 'timestamp', $line);
196 
197  // double -> numeric
198  $line = preg_replace('/^double/i', 'numeric', $line);
199  $line = preg_replace('/(\s*)double/i', '\\1numeric', $line);
200  // float -> numeric
201  $line = preg_replace('/^float/i', 'numeric', $line);
202  $line = preg_replace('/(\s*)float/i', '\\1numeric', $line);
203 
204  // unique index(field1,field2)
205  if (preg_match('/unique index\s*\((\w+\s*,\s*\w+)\)/i', $line)) {
206  $line = preg_replace('/unique index\s*\((\w+\s*,\s*\w+)\)/i', 'UNIQUE\(\\1\)', $line);
207  }
208 
209  // We remove end of requests "AFTER fieldxxx"
210  $line = preg_replace('/AFTER [a-z0-9_]+/i', '', $line);
211 
212  // We remove start of requests "ALTER TABLE tablexxx" if this is a DROP INDEX
213  $line = preg_replace('/ALTER TABLE [a-z0-9_]+ DROP INDEX/i', 'DROP INDEX', $line);
214 
215  // Translate order to rename fields
216  if (preg_match('/ALTER TABLE ([a-z0-9_]+) CHANGE(?: COLUMN)? ([a-z0-9_]+) ([a-z0-9_]+)(.*)$/i', $line, $reg)) {
217  $line = "-- ".$line." replaced by --\n";
218  $line .= "ALTER TABLE ".$reg[1]." RENAME COLUMN ".$reg[2]." TO ".$reg[3];
219  }
220 
221  // Translate order to modify field format
222  if (preg_match('/ALTER TABLE ([a-z0-9_]+) MODIFY(?: COLUMN)? ([a-z0-9_]+) (.*)$/i', $line, $reg)) {
223  $line = "-- ".$line." replaced by --\n";
224  $newreg3 = $reg[3];
225  $newreg3 = preg_replace('/ DEFAULT NULL/i', '', $newreg3);
226  $newreg3 = preg_replace('/ NOT NULL/i', '', $newreg3);
227  $newreg3 = preg_replace('/ NULL/i', '', $newreg3);
228  $newreg3 = preg_replace('/ DEFAULT 0/i', '', $newreg3);
229  $newreg3 = preg_replace('/ DEFAULT \'[0-9a-zA-Z_@]*\'/i', '', $newreg3);
230  $line .= "ALTER TABLE ".$reg[1]." ALTER COLUMN ".$reg[2]." TYPE ".$newreg3;
231  // TODO Add alter to set default value or null/not null if there is this in $reg[3]
232  }
233 
234  // alter table add primary key (field1, field2 ...) -> We create a unique index instead as dynamic creation of primary key is not supported
235  // ALTER TABLE llx_dolibarr_modules ADD PRIMARY KEY pk_dolibarr_modules (numero, entity);
236  if (preg_match('/ALTER\s+TABLE\s*(.*)\s*ADD\s+PRIMARY\s+KEY\s*(.*)\s*\((.*)$/i', $line, $reg)) {
237  $line = "-- ".$line." replaced by --\n";
238  $line .= "CREATE UNIQUE INDEX ".$reg[2]." ON ".$reg[1]."(".$reg[3];
239  }
240 
241  // Translate order to drop foreign keys
242  // ALTER TABLE llx_dolibarr_modules DROP FOREIGN KEY fk_xxx;
243  if (preg_match('/ALTER\s+TABLE\s*(.*)\s*DROP\s+FOREIGN\s+KEY\s*(.*)$/i', $line, $reg)) {
244  $line = "-- ".$line." replaced by --\n";
245  $line .= "ALTER TABLE ".$reg[1]." DROP CONSTRAINT ".$reg[2];
246  }
247 
248  // alter table add [unique] [index] (field1, field2 ...)
249  // ALTER TABLE llx_accountingaccount ADD INDEX idx_accountingaccount_fk_pcg_version (fk_pcg_version)
250  if (preg_match('/ALTER\s+TABLE\s*(.*)\s*ADD\s+(UNIQUE INDEX|INDEX|UNIQUE)\s+(.*)\s*\(([\w,\s]+)\)/i', $line, $reg)) {
251  $fieldlist = $reg[4];
252  $idxname = $reg[3];
253  $tablename = $reg[1];
254  $line = "-- ".$line." replaced by --\n";
255  $line .= "CREATE ".(preg_match('/UNIQUE/', $reg[2]) ? 'UNIQUE ' : '')."INDEX ".$idxname." ON ".$tablename." (".$fieldlist.")";
256  }
257  if (preg_match('/ALTER\s+TABLE\s*(.*)\s*ADD\s+CONSTRAINT\s+(.*)\s*FOREIGN\s+KEY\s*\(([\w,\s]+)\)\s*REFERENCES\s+(\w+)\s*\(([\w,\s]+)\)/i', $line, $reg)) {
258  // Pour l'instant les contraintes ne sont pas créées
259  dol_syslog(get_class().'::query line emptied');
260  $line = 'SELECT 0;';
261  }
262 
263  //if (preg_match('/rowid\s+.*\s+PRIMARY\s+KEY,/i', $line)) {
264  //preg_replace('/(rowid\s+.*\s+PRIMARY\s+KEY\s*,)/i', '/* \\1 */', $line);
265  //}
266  }
267 
268  // Delete using criteria on other table must not declare twice the deleted table
269  // DELETE FROM tabletodelete USING tabletodelete, othertable -> DELETE FROM tabletodelete USING othertable
270  if (preg_match('/DELETE FROM ([a-z_]+) USING ([a-z_]+), ([a-z_]+)/i', $line, $reg)) {
271  if ($reg[1] == $reg[2]) { // If same table, we remove second one
272  $line = preg_replace('/DELETE FROM ([a-z_]+) USING ([a-z_]+), ([a-z_]+)/i', 'DELETE FROM \\1 USING \\3', $line);
273  }
274  }
275 
276  // Remove () in the tables in FROM if one table
277  $line = preg_replace('/FROM\s*\((([a-z_]+)\s+as\s+([a-z_]+)\s*)\)/i', 'FROM \\1', $line);
278  //print $line."\n";
279 
280  // Remove () in the tables in FROM if two table
281  $line = preg_replace('/FROM\s*\(([a-z_]+\s+as\s+[a-z_]+)\s*,\s*([a-z_]+\s+as\s+[a-z_]+\s*)\)/i', 'FROM \\1, \\2', $line);
282  //print $line."\n";
283 
284  // Remove () in the tables in FROM if two table
285  $line = preg_replace('/FROM\s*\(([a-z_]+\s+as\s+[a-z_]+)\s*,\s*([a-z_]+\s+as\s+[a-z_]+\s*),\s*([a-z_]+\s+as\s+[a-z_]+\s*)\)/i', 'FROM \\1, \\2, \\3', $line);
286  //print $line."\n";
287 
288  //print "type=".$type." newline=".$line."<br>\n";
289  }
290 
291  return $line;
292  }
293 
294  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
301  public function select_db($database)
302  {
303  // phpcs:enable
304  dol_syslog(get_class($this)."::select_db database=".$database, LOG_DEBUG);
305  // sqlite_select_db() does not exist
306  //return sqlite_select_db($this->db,$database);
307  return true;
308  }
309 
310 
322  public function connect($host, $login, $passwd, $name, $port = 0)
323  {
324  global $main_data_dir;
325 
326  dol_syslog(get_class($this)."::connect name=".$name, LOG_DEBUG);
327 
328  $dir = $main_data_dir;
329  if (empty($dir)) {
330  $dir = DOL_DATA_ROOT;
331  }
332  // With sqlite, port must be in connect parameters
333  //if (! $newport) $newport=3306;
334  $database_name = $dir.'/database_'.$name.'.sdb';
335  try {
336  /*** connect to SQLite database ***/
337  //$this->db = new PDO("sqlite:".$dir.'/database_'.$name.'.sdb');
338  $this->db = new SQLite3($database_name);
339  //$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
340  } catch (Exception $e) {
341  $this->error = self::LABEL.' '.$e->getMessage().' current dir='.$database_name;
342  return '';
343  }
344 
345  //print "Resultat fonction connect: ".$this->db;
346  return $this->db;
347  }
348 
349 
355  public function getVersion()
356  {
357  $tmp = $this->db->version();
358  return $tmp['versionString'];
359  }
360 
366  public function getDriverInfo()
367  {
368  return 'sqlite3 php driver';
369  }
370 
371 
378  public function close()
379  {
380  if ($this->db) {
381  if ($this->transaction_opened > 0) {
382  dol_syslog(get_class($this)."::close Closing a connection with an opened transaction depth=".$this->transaction_opened, LOG_ERR);
383  }
384  $this->connected = false;
385  $this->db->close();
386  unset($this->db); // Clean this->db
387  return true;
388  }
389  return false;
390  }
391 
402  public function query($query, $usesavepoint = 0, $type = 'auto', $result_mode = 0)
403  {
404  global $conf, $dolibarr_main_db_readonly;
405 
406  $ret = null;
407 
408  $query = trim($query);
409 
410  $this->error = '';
411 
412  // Convert MySQL syntax to SQLite syntax
413  $reg = array();
414  if (preg_match('/ALTER\s+TABLE\s*(.*)\s*ADD\s+CONSTRAINT\s+(.*)\s*FOREIGN\s+KEY\s*\(([\w,\s]+)\)\s*REFERENCES\s+(\w+)\s*\(([\w,\s]+)\)/i', $query, $reg)) {
415  // Ajout d'une clef étrangère à la table
416  // procédure de remplacement de la table pour ajouter la contrainte
417  // Exemple : ALTER TABLE llx_adherent ADD CONSTRAINT adherent_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe (rowid)
418  // -> CREATE TABLE ( ... ,CONSTRAINT adherent_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe (rowid))
419  $foreignFields = $reg[5];
420  $foreignTable = $reg[4];
421  $localfields = $reg[3];
422  $constraintname = trim($reg[2]);
423  $tablename = trim($reg[1]);
424 
425  $descTable = $this->db->querySingle("SELECT sql FROM sqlite_master WHERE name='".$this->escape($tablename)."'");
426 
427  // 1- Renommer la table avec un nom temporaire
428  $this->query("ALTER TABLE ".$tablename." RENAME TO tmp_".$tablename);
429 
430  // 2- Recréer la table avec la contrainte ajoutée
431 
432  // on bricole la requete pour ajouter la contrainte
433  $descTable = substr($descTable, 0, strlen($descTable) - 1);
434  $descTable .= ", CONSTRAINT ".$constraintname." FOREIGN KEY (".$localfields.") REFERENCES ".$foreignTable."(".$foreignFields.")";
435 
436  // fermeture de l'instruction
437  $descTable .= ')';
438 
439  // Création proprement dite de la table
440  $this->query($descTable);
441 
442  // 3- Transférer les données
443  $this->query("INSERT INTO ".$tablename." SELECT * FROM tmp_".$tablename);
444 
445  // 4- Supprimer la table temporaire
446  $this->query("DROP TABLE tmp_".$tablename);
447 
448  // dummy statement
449  $query = "SELECT 0";
450  } else {
451  $query = $this->convertSQLFromMysql($query, $type);
452  }
453  //print "After convertSQLFromMysql:\n".$query."<br>\n";
454 
455  if (!in_array($query, array('BEGIN', 'COMMIT', 'ROLLBACK'))) {
456  $SYSLOG_SQL_LIMIT = 10000; // limit log to 10kb per line to limit DOS attacks
457  dol_syslog('sql='.substr($query, 0, $SYSLOG_SQL_LIMIT), LOG_DEBUG);
458  }
459  if (empty($query)) {
460  return false; // Return false = error if empty request
461  }
462 
463  if (!empty($dolibarr_main_db_readonly)) {
464  if (preg_match('/^(INSERT|UPDATE|REPLACE|DELETE|CREATE|ALTER|TRUNCATE|DROP)/i', $query)) {
465  $this->lasterror = 'Application in read-only mode';
466  $this->lasterrno = 'APPREADONLY';
467  $this->lastquery = $query;
468  return false;
469  }
470  }
471 
472  // Ordre SQL ne necessitant pas de connexion a une base (exemple: CREATE DATABASE)
473  try {
474  //$ret = $this->db->exec($query);
475  $ret = $this->db->query($query); // $ret is a Sqlite3Result
476  if ($ret) {
477  $ret->queryString = $query;
478  }
479  } catch (Exception $e) {
480  $this->error = $this->db->lastErrorMsg();
481  }
482 
483  if (!preg_match("/^COMMIT/i", $query) && !preg_match("/^ROLLBACK/i", $query)) {
484  // Si requete utilisateur, on la sauvegarde ainsi que son resultset
485  if (!is_object($ret) || $this->error) {
486  $this->lastqueryerror = $query;
487  $this->lasterror = $this->error();
488  $this->lasterrno = $this->errno();
489 
490  dol_syslog(get_class($this)."::query SQL Error query: ".$query, LOG_ERR);
491 
492  $errormsg = get_class($this)."::query SQL Error message: ".$this->lasterror;
493 
494  if (preg_match('/[0-9]/', $this->lasterrno)) {
495  $errormsg .= ' ('.$this->lasterrno.')';
496  }
497 
498  if ($conf->global->SYSLOG_LEVEL < LOG_DEBUG) {
499  dol_syslog(get_class($this)."::query SQL Error query: ".$query, LOG_ERR); // Log of request was not yet done previously
500  }
501  dol_syslog(get_class($this)."::query SQL Error message: ".$errormsg, LOG_ERR);
502  }
503  $this->lastquery = $query;
504  $this->_results = $ret;
505  }
506 
507  return $ret;
508  }
509 
510  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
517  public function fetch_object($resultset)
518  {
519  // phpcs:enable
520  // Si le resultset n'est pas fourni, on prend le dernier utilise sur cette connexion
521  if (!is_object($resultset)) {
522  $resultset = $this->_results;
523  }
524  //return $resultset->fetch(PDO::FETCH_OBJ);
525  $ret = $resultset->fetchArray(SQLITE3_ASSOC);
526  if ($ret) {
527  return (object) $ret;
528  }
529  return false;
530  }
531 
532 
533  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
540  public function fetch_array($resultset)
541  {
542  // phpcs:enable
543  // If resultset not provided, we take the last used by connexion
544  if (!is_object($resultset)) {
545  $resultset = $this->_results;
546  }
547  //return $resultset->fetch(PDO::FETCH_ASSOC);
548  $ret = $resultset->fetchArray(SQLITE3_ASSOC);
549  return $ret;
550  }
551 
552  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
559  public function fetch_row($resultset)
560  {
561  // phpcs:enable
562  // If resultset not provided, we take the last used by connexion
563  if (!is_bool($resultset)) {
564  if (!is_object($resultset)) {
565  $resultset = $this->_results;
566  }
567  return $resultset->fetchArray(SQLITE3_NUM);
568  } else {
569  // si le curseur est un booleen on retourne la valeur 0
570  return false;
571  }
572  }
573 
574  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
582  public function num_rows($resultset)
583  {
584  // phpcs:enable
585  // FIXME: SQLite3Result does not have a queryString member
586 
587  // If resultset not provided, we take the last used by connexion
588  if (!is_object($resultset)) {
589  $resultset = $this->_results;
590  }
591  if (preg_match("/^SELECT/i", $resultset->queryString)) {
592  return $this->db->querySingle("SELECT count(*) FROM (".$resultset->queryString.") q");
593  }
594  return 0;
595  }
596 
597  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
605  public function affected_rows($resultset)
606  {
607  // phpcs:enable
608  // FIXME: SQLite3Result does not have a queryString member
609 
610  // If resultset not provided, we take the last used by connexion
611  if (!is_object($resultset)) {
612  $resultset = $this->_results;
613  }
614  if (preg_match("/^SELECT/i", $resultset->queryString)) {
615  return $this->num_rows($resultset);
616  }
617  // mysql necessite un link de base pour cette fonction contrairement
618  // a pqsql qui prend un resultset
619  return $this->db->changes();
620  }
621 
622 
629  public function free($resultset = null)
630  {
631  // If resultset not provided, we take the last used by connexion
632  if (!is_object($resultset)) {
633  $resultset = $this->_results;
634  }
635  // Si resultset en est un, on libere la memoire
636  if ($resultset && is_object($resultset)) {
637  $resultset->finalize();
638  }
639  }
640 
647  public function escape($stringtoencode)
648  {
649  return Sqlite3::escapeString($stringtoencode);
650  }
651 
659  public function escapeunderscore($stringtoencode)
660  {
661  return str_replace('_', '\_', (string) $stringtoencode);
662  }
663 
670  public function escapeforlike($stringtoencode)
671  {
672  return str_replace(array('_', '\\', '%'), array('\_', '\\\\', '\%'), (string) $stringtoencode);
673  }
674 
680  public function errno()
681  {
682  if (!$this->connected) {
683  // Si il y a eu echec de connexion, $this->db n'est pas valide.
684  return 'DB_ERROR_FAILED_TO_CONNECT';
685  } else {
686  // Constants to convert error code to a generic Dolibarr error code
687  /*$errorcode_map = array(
688  1004 => 'DB_ERROR_CANNOT_CREATE',
689  1005 => 'DB_ERROR_CANNOT_CREATE',
690  1006 => 'DB_ERROR_CANNOT_CREATE',
691  1007 => 'DB_ERROR_ALREADY_EXISTS',
692  1008 => 'DB_ERROR_CANNOT_DROP',
693  1025 => 'DB_ERROR_NO_FOREIGN_KEY_TO_DROP',
694  1044 => 'DB_ERROR_ACCESSDENIED',
695  1046 => 'DB_ERROR_NODBSELECTED',
696  1048 => 'DB_ERROR_CONSTRAINT',
697  'HY000' => 'DB_ERROR_TABLE_ALREADY_EXISTS',
698  1051 => 'DB_ERROR_NOSUCHTABLE',
699  1054 => 'DB_ERROR_NOSUCHFIELD',
700  1060 => 'DB_ERROR_COLUMN_ALREADY_EXISTS',
701  1061 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
702  1062 => 'DB_ERROR_RECORD_ALREADY_EXISTS',
703  1064 => 'DB_ERROR_SYNTAX',
704  1068 => 'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS',
705  1075 => 'DB_ERROR_CANT_DROP_PRIMARY_KEY',
706  1091 => 'DB_ERROR_NOSUCHFIELD',
707  1100 => 'DB_ERROR_NOT_LOCKED',
708  1136 => 'DB_ERROR_VALUE_COUNT_ON_ROW',
709  1146 => 'DB_ERROR_NOSUCHTABLE',
710  1216 => 'DB_ERROR_NO_PARENT',
711  1217 => 'DB_ERROR_CHILD_EXISTS',
712  1451 => 'DB_ERROR_CHILD_EXISTS'
713  );
714 
715  if (isset($errorcode_map[$this->db->errorCode()]))
716  {
717  return $errorcode_map[$this->db->errorCode()];
718  }*/
719  $errno = $this->db->lastErrorCode();
720  if ($errno == 'HY000' || $errno == 0) {
721  if (preg_match('/table.*already exists/i', $this->error)) {
722  return 'DB_ERROR_TABLE_ALREADY_EXISTS';
723  } elseif (preg_match('/index.*already exists/i', $this->error)) {
724  return 'DB_ERROR_KEY_NAME_ALREADY_EXISTS';
725  } elseif (preg_match('/syntax error/i', $this->error)) {
726  return 'DB_ERROR_SYNTAX';
727  }
728  }
729  if ($errno == '23000') {
730  if (preg_match('/column.* not unique/i', $this->error)) {
731  return 'DB_ERROR_RECORD_ALREADY_EXISTS';
732  } elseif (preg_match('/PRIMARY KEY must be unique/i', $this->error)) {
733  return 'DB_ERROR_RECORD_ALREADY_EXISTS';
734  }
735  }
736  if ($errno > 1) {
737  // TODO Voir la liste des messages d'erreur
738  }
739 
740  return ($errno ? 'DB_ERROR_'.$errno : '0');
741  }
742  }
743 
749  public function error()
750  {
751  if (!$this->connected) {
752  // Si il y a eu echec de connexion, $this->db n'est pas valide pour sqlite_error.
753  return 'Not connected. Check setup parameters in conf/conf.php file and your sqlite version';
754  } else {
755  return $this->error;
756  }
757  }
758 
759  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
767  public function last_insert_id($tab, $fieldid = 'rowid')
768  {
769  // phpcs:enable
770  return $this->db->lastInsertRowId();
771  }
772 
781  public function encrypt($fieldorvalue, $withQuotes = 1)
782  {
783  global $conf;
784 
785  // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption)
786  $cryptType = (!empty($conf->db->dolibarr_main_db_encryption) ? $conf->db->dolibarr_main_db_encryption : 0);
787 
788  //Encryption key
789  $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey) ? $conf->db->dolibarr_main_db_cryptkey : '');
790 
791  $escapedstringwithquotes = ($withQuotes ? "'" : "").$this->escape($fieldorvalue).($withQuotes ? "'" : "");
792 
793  if ($cryptType && !empty($cryptKey)) {
794  if ($cryptType == 2) {
795  $escapedstringwithquotes = "AES_ENCRYPT(".$escapedstringwithquotes.", '".$this->escape($cryptKey)."')";
796  } elseif ($cryptType == 1) {
797  $escapedstringwithquotes = "DES_ENCRYPT(".$escapedstringwithquotes.", '".$this->escape($cryptKey)."')";
798  }
799  }
800 
801  return $escapedstringwithquotes;
802  }
803 
810  public function decrypt($value)
811  {
812  global $conf;
813 
814  // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption)
815  $cryptType = ($conf->db->dolibarr_main_db_encryption ? $conf->db->dolibarr_main_db_encryption : 0);
816 
817  //Encryption key
818  $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey) ? $conf->db->dolibarr_main_db_cryptkey : '');
819 
820  $return = $value;
821 
822  if ($cryptType && !empty($cryptKey)) {
823  if ($cryptType == 2) {
824  $return = 'AES_DECRYPT('.$value.',\''.$cryptKey.'\')';
825  } elseif ($cryptType == 1) {
826  $return = 'DES_DECRYPT('.$value.',\''.$cryptKey.'\')';
827  }
828  }
829 
830  return $return;
831  }
832 
833 
834  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
840  public function DDLGetConnectId()
841  {
842  // phpcs:enable
843  return '?';
844  }
845 
846 
847  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
859  public function DDLCreateDb($database, $charset = '', $collation = '', $owner = '')
860  {
861  // phpcs:enable
862  if (empty($charset)) {
863  $charset = $this->forcecharset;
864  }
865  if (empty($collation)) {
866  $collation = $this->forcecollate;
867  }
868 
869  // ALTER DATABASE dolibarr_db DEFAULT CHARACTER SET latin DEFAULT COLLATE latin1_swedish_ci
870  $sql = "CREATE DATABASE ".$this->escape($database);
871  $sql .= " DEFAULT CHARACTER SET ".$this->escape($charset)." DEFAULT COLLATE ".$this->escape($collation);
872 
873  dol_syslog($sql, LOG_DEBUG);
874  $ret = $this->query($sql);
875 
876  return $ret;
877  }
878 
879  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
887  public function DDLListTables($database, $table = '')
888  {
889  // phpcs:enable
890  $listtables = array();
891 
892  $like = '';
893  if ($table) {
894  $tmptable = preg_replace('/[^a-z0-9\.\-\_%]/i', '', $table);
895 
896  $like = "LIKE '".$this->escape($tmptable)."'";
897  }
898  $tmpdatabase = preg_replace('/[^a-z0-9\.\-\_]/i', '', $database);
899 
900  $sql = "SHOW TABLES FROM ".$tmpdatabase." ".$like.";";
901  //print $sql;
902  $result = $this->query($sql);
903  if ($result) {
904  while ($row = $this->fetch_row($result)) {
905  $listtables[] = $row[0];
906  }
907  }
908  return $listtables;
909  }
910 
911  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
919  public function DDLInfoTable($table)
920  {
921  // phpcs:enable
922  $infotables = array();
923 
924  $tmptable = preg_replace('/[^a-z0-9\.\-\_]/i', '', $table);
925 
926  $sql = "SHOW FULL COLUMNS FROM ".$tmptable.";";
927 
928  dol_syslog($sql, LOG_DEBUG);
929  $result = $this->query($sql);
930  if ($result) {
931  while ($row = $this->fetch_row($result)) {
932  $infotables[] = $row;
933  }
934  }
935  return $infotables;
936  }
937 
938  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
951  public function DDLCreateTable($table, $fields, $primary_key, $type, $unique_keys = null, $fulltext_keys = null, $keys = null)
952  {
953  // phpcs:enable
954  // FIXME: $fulltext_keys parameter is unused
955 
956  // cles recherchees dans le tableau des descriptions (fields) : type,value,attribute,null,default,extra
957  // ex. : $fields['rowid'] = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment');
958  $sql = "create table ".$table."(";
959  $i = 0;
960  foreach ($fields as $field_name => $field_desc) {
961  $sqlfields[$i] = $field_name." ";
962  $sqlfields[$i] .= $field_desc['type'];
963  if (preg_match("/^[^\s]/i", $field_desc['value'])) {
964  $sqlfields[$i] .= "(".$field_desc['value'].")";
965  } elseif (preg_match("/^[^\s]/i", $field_desc['attribute'])) {
966  $sqlfields[$i] .= " ".$field_desc['attribute'];
967  } elseif (preg_match("/^[^\s]/i", $field_desc['default'])) {
968  if (preg_match("/null/i", $field_desc['default'])) {
969  $sqlfields[$i] .= " default ".$field_desc['default'];
970  } else {
971  $sqlfields[$i] .= " default '".$this->escape($field_desc['default'])."'";
972  }
973  } elseif (preg_match("/^[^\s]/i", $field_desc['null'])) {
974  $sqlfields[$i] .= " ".$field_desc['null'];
975  } elseif (preg_match("/^[^\s]/i", $field_desc['extra'])) {
976  $sqlfields[$i] .= " ".$field_desc['extra'];
977  }
978  $i++;
979  }
980  if ($primary_key != "") {
981  $pk = "primary key(".$primary_key.")";
982  }
983 
984  if (is_array($unique_keys)) {
985  $i = 0;
986  foreach ($unique_keys as $key => $value) {
987  $sqluq[$i] = "UNIQUE KEY '".$key."' ('".$this->escape($value)."')";
988  $i++;
989  }
990  }
991  if (is_array($keys)) {
992  $i = 0;
993  foreach ($keys as $key => $value) {
994  $sqlk[$i] = "KEY ".$key." (".$value.")";
995  $i++;
996  }
997  }
998  $sql .= implode(',', $sqlfields);
999  if ($primary_key != "") {
1000  $sql .= ",".$pk;
1001  }
1002  if (is_array($unique_keys)) {
1003  $sql .= ",".implode(',', $sqluq);
1004  }
1005  if (is_array($keys)) {
1006  $sql .= ",".implode(',', $sqlk);
1007  }
1008  $sql .= ") type=".$type;
1009 
1010  dol_syslog($sql, LOG_DEBUG);
1011  if (!$this -> query($sql)) {
1012  return -1;
1013  }
1014  return 1;
1015  }
1016 
1017  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1024  public function DDLDropTable($table)
1025  {
1026  // phpcs:enable
1027  $tmptable = preg_replace('/[^a-z0-9\.\-\_]/i', '', $table);
1028 
1029  $sql = "DROP TABLE ".$tmptable;
1030 
1031  if (!$this->query($sql)) {
1032  return -1;
1033  } else {
1034  return 1;
1035  }
1036  }
1037 
1038  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1046  public function DDLDescTable($table, $field = "")
1047  {
1048  // phpcs:enable
1049  $sql = "DESC ".$table." ".$field;
1050 
1051  dol_syslog(get_class($this)."::DDLDescTable ".$sql, LOG_DEBUG);
1052  $this->_results = $this->query($sql);
1053  return $this->_results;
1054  }
1055 
1056  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1066  public function DDLAddField($table, $field_name, $field_desc, $field_position = "")
1067  {
1068  // phpcs:enable
1069  // cles recherchees dans le tableau des descriptions (field_desc) : type,value,attribute,null,default,extra
1070  // ex. : $field_desc = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment');
1071  $sql = "ALTER TABLE ".$table." ADD ".$field_name." ";
1072  $sql .= $field_desc['type'];
1073  if (preg_match("/^[^\s]/i", $field_desc['value'])) {
1074  if (!in_array($field_desc['type'], array('date', 'datetime'))) {
1075  $sql .= "(".$field_desc['value'].")";
1076  }
1077  }
1078  if (preg_match("/^[^\s]/i", $field_desc['attribute'])) {
1079  $sql .= " ".$field_desc['attribute'];
1080  }
1081  if (preg_match("/^[^\s]/i", $field_desc['null'])) {
1082  $sql .= " ".$field_desc['null'];
1083  }
1084  if (preg_match("/^[^\s]/i", $field_desc['default'])) {
1085  if (preg_match("/null/i", $field_desc['default'])) {
1086  $sql .= " default ".$field_desc['default'];
1087  } else {
1088  $sql .= " default '".$this->escape($field_desc['default'])."'";
1089  }
1090  }
1091  if (preg_match("/^[^\s]/i", $field_desc['extra'])) {
1092  $sql .= " ".$field_desc['extra'];
1093  }
1094  $sql .= " ".$field_position;
1095 
1096  dol_syslog(get_class($this)."::DDLAddField ".$sql, LOG_DEBUG);
1097  if (!$this->query($sql)) {
1098  return -1;
1099  }
1100  return 1;
1101  }
1102 
1103  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1112  public function DDLUpdateField($table, $field_name, $field_desc)
1113  {
1114  // phpcs:enable
1115  $sql = "ALTER TABLE ".$table;
1116  $sql .= " MODIFY COLUMN ".$field_name." ".$field_desc['type'];
1117  if ($field_desc['type'] == 'tinyint' || $field_desc['type'] == 'int' || $field_desc['type'] == 'varchar') {
1118  $sql .= "(".$field_desc['value'].")";
1119  }
1120 
1121  dol_syslog(get_class($this)."::DDLUpdateField ".$sql, LOG_DEBUG);
1122  if (!$this->query($sql)) {
1123  return -1;
1124  }
1125  return 1;
1126  }
1127 
1128  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1136  public function DDLDropField($table, $field_name)
1137  {
1138  // phpcs:enable
1139  $tmp_field_name = preg_replace('/[^a-z0-9\.\-\_]/i', '', $field_name);
1140 
1141  $sql = "ALTER TABLE ".$table." DROP COLUMN `".$tmp_field_name."`";
1142  if (!$this->query($sql)) {
1143  $this->error = $this->lasterror();
1144  return -1;
1145  }
1146  return 1;
1147  }
1148 
1149 
1150  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1160  public function DDLCreateUser($dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name)
1161  {
1162  // phpcs:enable
1163  $sql = "INSERT INTO user ";
1164  $sql .= "(Host,User,password,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Index_Priv,Alter_priv,Lock_tables_priv)";
1165  $sql .= " VALUES ('".$this->escape($dolibarr_main_db_host)."','".$this->escape($dolibarr_main_db_user)."',password('".addslashes($dolibarr_main_db_pass)."')";
1166  $sql .= ",'Y','Y','Y','Y','Y','Y','Y','Y','Y')";
1167 
1168  dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log
1169  $resql = $this->query($sql);
1170  if (!$resql) {
1171  return -1;
1172  }
1173 
1174  $sql = "INSERT INTO db ";
1175  $sql .= "(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Index_Priv,Alter_priv,Lock_tables_priv)";
1176  $sql .= " VALUES ('".$this->escape($dolibarr_main_db_host)."','".$this->escape($dolibarr_main_db_name)."','".addslashes($dolibarr_main_db_user)."'";
1177  $sql .= ",'Y','Y','Y','Y','Y','Y','Y','Y','Y')";
1178 
1179  dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG);
1180  $resql = $this->query($sql);
1181  if (!$resql) {
1182  return -1;
1183  }
1184 
1185  $sql = "FLUSH Privileges";
1186 
1187  dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG);
1188  $resql = $this->query($sql);
1189  if (!$resql) {
1190  return -1;
1191  }
1192  return 1;
1193  }
1194 
1200  public function getDefaultCharacterSetDatabase()
1201  {
1202  return 'UTF-8';
1203  }
1204 
1210  public function getListOfCharacterSet()
1211  {
1212  $liste = array();
1213  $i = 0;
1214  $liste[$i]['charset'] = 'UTF-8';
1215  $liste[$i]['description'] = 'UTF-8';
1216  return $liste;
1217  }
1218 
1224  public function getDefaultCollationDatabase()
1225  {
1226  return 'UTF-8';
1227  }
1228 
1234  public function getListOfCollation()
1235  {
1236  $liste = array();
1237  $i = 0;
1238  $liste[$i]['charset'] = 'UTF-8';
1239  $liste[$i]['description'] = 'UTF-8';
1240  return $liste;
1241  }
1242 
1248  public function getPathOfDump()
1249  {
1250  // FIXME: not for SQLite
1251  $fullpathofdump = '/pathtomysqldump/mysqldump';
1252 
1253  $resql = $this->query('SHOW VARIABLES LIKE \'basedir\'');
1254  if ($resql) {
1255  $liste = $this->fetch_array($resql);
1256  $basedir = $liste['Value'];
1257  $fullpathofdump = $basedir.(preg_match('/\/$/', $basedir) ? '' : '/').'bin/mysqldump';
1258  }
1259  return $fullpathofdump;
1260  }
1261 
1267  public function getPathOfRestore()
1268  {
1269  // FIXME: not for SQLite
1270  $fullpathofimport = '/pathtomysql/mysql';
1271 
1272  $resql = $this->query('SHOW VARIABLES LIKE \'basedir\'');
1273  if ($resql) {
1274  $liste = $this->fetch_array($resql);
1275  $basedir = $liste['Value'];
1276  $fullpathofimport = $basedir.(preg_match('/\/$/', $basedir) ? '' : '/').'bin/mysql';
1277  }
1278  return $fullpathofimport;
1279  }
1280 
1287  public function getServerParametersValues($filter = '')
1288  {
1289  $result = array();
1290  static $pragmas;
1291  if (!isset($pragmas)) {
1292  // Définition de la liste des pragmas utilisés qui ne retournent qu'une seule valeur
1293  // indépendante de la base de données.
1294  // cf. http://www.sqlite.org/pragma.html
1295  $pragmas = array(
1296  'application_id', 'auto_vacuum', 'automatic_index', 'busy_timeout', 'cache_size',
1297  'cache_spill', 'case_sensitive_like', 'checkpoint_fullsync', 'collation_list',
1298  'compile_options', 'data_version', /*'database_list',*/
1299  'defer_foreign_keys', 'encoding', 'foreign_key_check', 'freelist_count',
1300  'full_column_names', 'fullsync', 'ingore_check_constraints', 'integrity_check',
1301  'journal_mode', 'journal_size_limit', 'legacy_file_format', 'locking_mode',
1302  'max_page_count', 'page_count', 'page_size', 'parser_trace',
1303  'query_only', 'quick_check', 'read_uncommitted', 'recursive_triggers',
1304  'reverse_unordered_selects', 'schema_version', 'user_version',
1305  'secure_delete', 'short_column_names', 'shrink_memory', 'soft_heap_limit',
1306  'synchronous', 'temp_store', /*'temp_store_directory',*/ 'threads',
1307  'vdbe_addoptrace', 'vdbe_debug', 'vdbe_listing', 'vdbe_trace',
1308  'wal_autocheckpoint',
1309  );
1310  }
1311 
1312  // TODO prendre en compte le filtre
1313  foreach ($pragmas as $var) {
1314  $sql = "PRAGMA $var";
1315  $resql = $this->query($sql);
1316  if ($resql) {
1317  $obj = $this->fetch_row($resql);
1318  //dol_syslog(get_class($this)."::select_db getServerParametersValues $var=". print_r($obj, true), LOG_DEBUG);
1319  $result[$var] = $obj[0];
1320  } else {
1321  // TODO Récupérer le message
1322  $result[$var] = 'FAIL';
1323  }
1324  }
1325  return $result;
1326  }
1327 
1334  public function getServerStatusValues($filter = '')
1335  {
1336  $result = array();
1337  /*
1338  $sql='SHOW STATUS';
1339  if ($filter) $sql.=" LIKE '".$this->escape($filter)."'";
1340  $resql=$this->query($sql);
1341  if ($resql)
1342  {
1343  while ($obj=$this->fetch_object($resql)) $result[$obj->Variable_name]=$obj->Value;
1344  }
1345  */
1346 
1347  return $result;
1348  }
1349 
1359  private function addCustomFunction($name, $arg_count = -1)
1360  {
1361  if ($this->db) {
1362  $newname = preg_replace('/_/', '', $name);
1363  $localname = __CLASS__.'::db'.$newname;
1364  $reflectClass = new ReflectionClass(__CLASS__);
1365  $reflectFunction = $reflectClass->getMethod('db'.$newname);
1366  if ($arg_count < 0) {
1367  $arg_count = $reflectFunction->getNumberOfParameters();
1368  }
1369  if (!$this->db->createFunction($name, $localname, $arg_count)) {
1370  $this->error = "unable to create custom function '$name'";
1371  }
1372  }
1373  }
1374 
1375  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1384  private static function calc_daynr($year, $month, $day)
1385  {
1386  // phpcs:enable
1387  $y = $year;
1388  if ($y == 0 && $month == 0) {
1389  return 0;
1390  }
1391  $num = (365 * $y + 31 * ($month - 1) + $day);
1392  if ($month <= 2) {
1393  $y--;
1394  } else {
1395  $num -= floor(($month * 4 + 23) / 10);
1396  }
1397  $temp = floor(($y / 100 + 1) * 3 / 4);
1398  return $num + floor($y / 4) - $temp;
1399  }
1400 
1401  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1409  private static function calc_weekday($daynr, $sunday_first_day_of_week)
1410  {
1411  // phpcs:enable
1412  $ret = floor(($daynr + 5 + ($sunday_first_day_of_week ? 1 : 0)) % 7);
1413  return $ret;
1414  }
1415 
1416  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1423  private static function calc_days_in_year($year)
1424  {
1425  // phpcs:enable
1426  return (($year & 3) == 0 && ($year % 100 || ($year % 400 == 0 && $year)) ? 366 : 365);
1427  }
1428 
1429  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1440  private static function calc_week($year, $month, $day, $week_behaviour, &$calc_year)
1441  {
1442  // phpcs:enable
1443  $daynr = self::calc_daynr($year, $month, $day);
1444  $first_daynr = self::calc_daynr($year, 1, 1);
1445  $monday_first = ($week_behaviour & self::WEEK_MONDAY_FIRST) ? 1 : 0;
1446  $week_year = ($week_behaviour & self::WEEK_YEAR) ? 1 : 0;
1447  $first_weekday = ($week_behaviour & self::WEEK_FIRST_WEEKDAY) ? 1 : 0;
1448 
1449  $weekday = self::calc_weekday($first_daynr, !$monday_first);
1450  $calc_year = $year;
1451 
1452  if ($month == 1 && $day <= 7 - $weekday) {
1453  if (!$week_year && (($first_weekday && $weekday != 0) || (!$first_weekday && $weekday >= 4))) {
1454  return 0;
1455  }
1456  $week_year = 1;
1457  $calc_year--;
1458  $first_daynr -= ($days = self::calc_days_in_year($calc_year));
1459  $weekday = ($weekday + 53 * 7 - $days) % 7;
1460  }
1461 
1462  if (($first_weekday && $weekday != 0) || (!$first_weekday && $weekday >= 4)) {
1463  $days = $daynr - ($first_daynr + (7 - $weekday));
1464  } else {
1465  $days = $daynr - ($first_daynr - $weekday);
1466  }
1467 
1468  if ($week_year && $days >= 52 * 7) {
1469  $weekday = ($weekday + self::calc_days_in_year($calc_year)) % 7;
1470  if ((!$first_weekday && $weekday < 4) || ($first_weekday && $weekday == 0)) {
1471  $calc_year++;
1472  return 1;
1473  }
1474  }
1475  return floor($days / 7 + 1);
1476  }
1477 }
DoliDBSqlite3\getDriverInfo
getDriverInfo()
Return version of database client driver.
Definition: sqlite3.class.php:366
db
$conf db
API class for accounts.
Definition: inc.php:41
DoliDBSqlite3\addCustomFunction
addCustomFunction($name, $arg_count=-1)
Permet le chargement d'une fonction personnalisee dans le moteur de base de donnees.
Definition: sqlite3.class.php:1359
DoliDBSqlite3\last_insert_id
last_insert_id($tab, $fieldid='rowid')
Get last ID after an insert INSERT.
Definition: sqlite3.class.php:767
description
print *****$script_file(".$version.") pid cd cd cd description as description
Definition: email_expire_services_to_customers.php:83
DoliDBSqlite3\__construct
__construct($type, $host, $user, $pass, $name='', $port=0)
Constructor.
Definition: sqlite3.class.php:63
DoliDB\lasterror
lasterror()
Return last error label.
Definition: DoliDB.class.php:309
DoliDBSqlite3\error
error()
Renvoie le texte de l'erreur mysql de l'operation precedente.
Definition: sqlite3.class.php:749
DoliDB
Class to manage Dolibarr database access.
Definition: DoliDB.class.php:30
DoliDBSqlite3\select_db
select_db($database)
Select a database.
Definition: sqlite3.class.php:301
DoliDBSqlite3\convertSQLFromMysql
static convertSQLFromMysql($line, $type='ddl')
Convert a SQL request in Mysql syntax to native syntax.
Definition: sqlite3.class.php:141
DoliDBSqlite3\$type
$type
Database type.
Definition: sqlite3.class.php:36
DoliDBSqlite3\escape
escape($stringtoencode)
Escape a string to insert data.
Definition: sqlite3.class.php:647
rowid
print *****$script_file(".$version.") pid c cd cd cd description as p label as s rowid
Definition: email_expire_services_to_representatives.php:79
DoliDBSqlite3\calc_days_in_year
static calc_days_in_year($year)
calc_days_in_year
Definition: sqlite3.class.php:1423
DoliDBSqlite3\connect
connect($host, $login, $passwd, $name, $port=0)
Connexion to server.
Definition: sqlite3.class.php:322
DoliDBSqlite3\encrypt
encrypt($fieldorvalue, $withQuotes=1)
Encrypt sensitive data in database Warning: This function includes the escape and add the SQL simple ...
Definition: sqlite3.class.php:781
DoliDBSqlite3\getServerStatusValues
getServerStatusValues($filter='')
Return value of server status.
Definition: sqlite3.class.php:1334
DoliDBSqlite3\free
free($resultset=null)
Free last resultset used.
Definition: sqlite3.class.php:629
DoliDB\lastquery
lastquery()
Return last request executed with query()
Definition: DoliDB.class.php:254
Exception
DoliDBSqlite3\close
close()
Close database connexion.
Definition: sqlite3.class.php:378
DoliDBSqlite3\calc_week
static calc_week($year, $month, $day, $week_behaviour, &$calc_year)
calc_week
Definition: sqlite3.class.php:1440
DoliDBSqlite3\VERSIONMIN
const VERSIONMIN
Version min database.
Definition: sqlite3.class.php:40
DoliDB\lasterrno
lasterrno()
Return last error code.
Definition: DoliDB.class.php:129
DoliDBSqlite3\fetch_row
fetch_row($resultset)
Return datas as an array.
Definition: sqlite3.class.php:559
dol_syslog
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
Definition: functions.lib.php:1603
DoliDBSqlite3\fetch_array
fetch_array($resultset)
Return datas as an array.
Definition: sqlite3.class.php:540
DoliDBSqlite3\escapeunderscore
escapeunderscore($stringtoencode)
Escape a string to insert data.
Definition: sqlite3.class.php:659
DoliDBSqlite3\affected_rows
affected_rows($resultset)
Return number of lines for result of a SELECT.
Definition: sqlite3.class.php:605
DoliDBSqlite3\getPathOfRestore
getPathOfRestore()
Return full path of restore program.
Definition: sqlite3.class.php:1267
DoliDBSqlite3\fetch_object
fetch_object($resultset)
Returns the current line (as an object) for the resultset cursor.
Definition: sqlite3.class.php:517
DoliDBSqlite3\num_rows
num_rows($resultset)
Return number of lines for result of a SELECT.
Definition: sqlite3.class.php:582
DoliDB\lastqueryerror
lastqueryerror()
Return last query in error.
Definition: DoliDB.class.php:340
DoliDBSqlite3\query
query($query, $usesavepoint=0, $type='auto', $result_mode=0)
Execute a SQL request and return the resultset.
Definition: sqlite3.class.php:402
DoliDBSqlite3\calc_weekday
static calc_weekday($daynr, $sunday_first_day_of_week)
calc_weekday
Definition: sqlite3.class.php:1409
DoliDBSqlite3\escapeforlike
escapeforlike($stringtoencode)
Escape a string to insert data into a like.
Definition: sqlite3.class.php:670
$resql
if(isModEnabled('facture') &&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire)||(isModEnabled('supplier_invoice') && $user->rights->supplier_invoice->lire)) if(isModEnabled('don') &&!empty($user->rights->don->lire)) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
Definition: index.php:742
DoliDBSqlite3\calc_daynr
static calc_daynr($year, $month, $day)
calc_daynr
Definition: sqlite3.class.php:1384
DoliDBSqlite3\getVersion
getVersion()
Return version of database server.
Definition: sqlite3.class.php:355
DoliDBSqlite3
Class to manage Dolibarr database access for a SQLite database.
Definition: sqlite3.class.php:33
type
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:119
DoliDBSqlite3\getServerParametersValues
getServerParametersValues($filter='')
Return value of server parameters.
Definition: sqlite3.class.php:1287
DoliDBSqlite3\decrypt
decrypt($value)
Decrypt sensitive data in database.
Definition: sqlite3.class.php:810
DoliDBSqlite3\errno
errno()
Renvoie le code erreur generique de l'operation precedente.
Definition: sqlite3.class.php:680
DoliDBSqlite3\LABEL
const LABEL
Database label.
Definition: sqlite3.class.php:38