diff --git a/ChangeLog b/ChangeLog index 0516ecc9b34..f3e3bb08194 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,9 +9,8 @@ For users: --------------- NEW: Minimal PHP version is now PHP 7.0 instead of PHP 5.6 -NEW: #21750 Added "Get lines and Post lines from BOM" at the REST Service NEW: #21780 Add pid field to Cronjob class and store PID on job execution -NEW: #19680 Add option PRODUCT_ALLOW_EXTERNAL_DOWNLOAD +NEW: #19680 Add option PRODUCT_ALLOW_EXTERNAL_DOWNLOAD to automatically have uploaded files shared publicly by a link NEW: #20650 can move the checkbox column on left (experimental option) NEW: #21000 Added columns 'alias_name' on poject, supplier invoice, supplier order, supplier proposals and taks list NEW: #21395 Added option for dark theme mode in display - color and theme @@ -19,11 +18,9 @@ NEW: #21397 added option to auto define barcode numbers for third-parties in bar NEW: #21399 NEW: #21442 Enhancement of module builder init NEW: #21654 add bank account number used on invoices for debit -NEW: #21775 Template 03 manages send mails NEW: #22048 Added notes to productlot module -NEW: #22298 Bank - Add salaries & vat in tab planned entries +NEW: #22298 Bank - Add salaries & vat in the tab of planned entries of a bank account NEW: #22328 -NEW: #22370 Modulebuilder supports 'alwayseditable' (like extrafields) NEW: #22424 NEW: #22500 member module set up made easier NEW: #22527 projects and thirdparties can be viewed as conversation ("Message" view), like events/agenda. @@ -57,7 +54,6 @@ NEW: Add hidden option MAIN_EMAIL_SUPPORT_ACK to restore Email ack checkbox (fea NEW: Add IMAP port setting on email collector module NEW: Adding JAPAN Chart-of-Account and regions/departments NEW: Adding NIF verification for Algeria -NEW: Add 4 other templates in website module NEW: Add link to create an element from the category page NEW: add margin infos to takepos invoice lines NEW: Add max size send for "backup and link to mail" option @@ -98,6 +94,7 @@ NEW: Website Can remove a website template NEW: Website can set header "Strict-Transport-Security" in web sites. NEW: Website Can switch status of website and page from the website toolbar NEW: Website Templates of websites are now directories and not zip into core repo +NEW: Website Add 4 other templates in website module NEW: Can use products categories to make inventory NEW: Change filter type on tickets list into a multiselect combo NEW: conf TIMESPENT_ALWAYS_UPDATE_THM, when it's on we always check current thm of user to update it in task time line @@ -129,7 +126,6 @@ NEW: manage no email with thirdparties (better for GDPR) NEW: Manage Position (Rank) on Contract Lines NEW: Manage VAT on all lines on purchases cycle NEW: manage virtual stock at a future date -NEW: ModuleBuilder can generate code of class from an existing SQL table NEW: On a bank reconciled line, we can modify the bank receipt NEW: On a form to send an email, we show all emails of all contacts of object NEW: Option PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT showing wh on PDF @@ -163,7 +159,6 @@ NEW: SMTP using oauth2 authentication NEW: can substitue project title in mail template NEW: Supplier order list - Add column private and public note NEW: Support IP type in extrafields -NEW: support multilang in Civilities API NEW: Table of membership types NEW: The purge of files can purge only if older than a number of seconds NEW: Update ActionComm type_code on email message ticket @@ -174,8 +169,11 @@ NEW: expand/collapse permissions on user permission page For developers or integrators: ------------------------------ +NEW: ModuleBuilder can generate code of class from an existing SQL table +NEW: #22370 Modulebuilder supports 'alwayseditable' (like extrafields) NEW: #20912 Add trigger to record the event of sending an email from a project -NEW: Removed completely the need for library adodbtime +NEW: #21750 Added "Get lines and Post lines from BOM" at the REST Service +NEW: Removed completely the need for the library adodbtime NEW: hook on agenda pages NEW: hook to complete payment in TakePOS NEW: hook "changeHelpURL" to modify target of the help button @@ -186,6 +184,7 @@ NEW: Add new hooks for actioncomm NEW: conf->global->SYSLOG_FILE_ONEPERSESSION accept a string NEW: translate for contact type API, setup/ticket API, shipping method API NEW: All ajax pages have now a top_httphead() +NEW: support multilang in Civilities API NEW: Add API for the partnership module NEW: Add "Get lines and Post lines from BOM" in the API NEW: Replace fk_categories_product with categories_product in inventory diff --git a/htdocs/admin/geoipmaxmind.php b/htdocs/admin/geoipmaxmind.php index c7373fd02db..8f76f9a7b2b 100644 --- a/htdocs/admin/geoipmaxmind.php +++ b/htdocs/admin/geoipmaxmind.php @@ -53,27 +53,20 @@ if ($action == 'set') { $error++; } - if (!$error && $gimcdf && !file_exists($gimcdf)) { - setEventMessages($langs->trans("ErrorFileNotFound", $gimcdf), null, 'errors'); + $res1 = dolibarr_set_const($db, "GEOIP_VERSION", GETPOST('geoipversion', 'aZ09'), 'chaine', 0, '', $conf->entity); + if (!($res1 > 0)) { + $error++; + } + + $res2 = dolibarr_set_const($db, "GEOIPMAXMIND_COUNTRY_DATAFILE", $gimcdf, 'chaine', 0, '', $conf->entity); + if (!($res2 > 0)) { $error++; } if (!$error) { - $res1 = dolibarr_set_const($db, "GEOIP_VERSION", GETPOST('geoipversion', 'aZ09'), 'chaine', 0, '', $conf->entity); - if (!($res1 > 0)) { - $error++; - } - - $res2 = dolibarr_set_const($db, "GEOIPMAXMIND_COUNTRY_DATAFILE", $gimcdf, 'chaine', 0, '', $conf->entity); - if (!($res2 > 0)) { - $error++; - } - - if (!$error) { - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } else { - setEventMessages($langs->trans("Error"), null, 'errors'); - } + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); + } else { + //setEventMessages($langs->trans("Error"), null, 'errors'); } } @@ -112,8 +105,8 @@ print '\n"; // Lib version -print ''.$langs->trans("GeoIPLibVersion").''; -print ''; +print ''.$langs->trans("GeoIPLibVersion").''; +print ''; $arrayofvalues = array('php' => 'Native PHP functions', '1' => 'Embedded GeoIP v1', '2' => 'Embedded GeoIP v2'); print $form->selectarray('geoipversion', $arrayofvalues, (isset($conf->global->GEOIP_VERSION) ? $conf->global->GEOIP_VERSION : '2')); if ($conf->global->GEOIP_VERSION == 'php') { @@ -124,16 +117,29 @@ if ($conf->global->GEOIP_VERSION == 'php') { print '
'.$langs->trans("Version").': '.$version; } } +print ''; +print ''; print ''; +$gimcdf = getDolGlobalString('GEOIPMAXMIND_COUNTRY_DATAFILE'); + // Path to database file print ''.$langs->trans("PathToGeoIPMaxmindCountryDataFile").''; -print ''; - +print ''; if ($conf->global->GEOIP_VERSION == 'php') { print 'Using geoip PHP internal functions. Value must be '.geoip_db_filename(GEOIP_COUNTRY_EDITION).' or '.geoip_db_filename(GEOIP_CITY_EDITION_REV1).' or /pathtodatafile/GeoLite2-Country.mmdb
'; } -print ''; +print ''; +if (!file_exists($gimcdf)) { + print '
'.$langs->trans("ErrorFileNotFound", $gimcdf).'
'; +} +print ''; +print ''; +print $langs->trans("Example").'
'; +print '/usr/local/share/GeoIP/GeoIP.dat
+/usr/share/GeoIP/GeoIP.dat
+/usr/share/GeoIP/GeoLite2-Country.mmdb'; +print '
'; print ''; print ''; @@ -145,12 +151,16 @@ print '
'; print $langs->trans("NoteOnPathLocation").'
'; $url1 = 'http://www.maxmind.com/en/city?rId=awstats'; -print $langs->trans("YouCanDownloadFreeDatFileTo", ''.$url1.''); +$textoshow = $langs->trans("YouCanDownloadFreeDatFileTo", '{s1}'); +$textoshow = str_replace('{s1}', ''.$url1.'', $textoshow); +print $textoshow; print '
'; $url2 = 'http://www.maxmind.com/en/city?rId=awstats'; -print $langs->trans("YouCanDownloadAdvancedDatFileTo", ''.$url2.''); +$textoshow = $langs->trans("YouCanDownloadAdvancedDatFileTo", '{s1}'); +$textoshow = str_replace('{s1}', ''.$url2.'', $textoshow); +print $textoshow; if ($geoip) { print '

'; diff --git a/htdocs/admin/system/security.php b/htdocs/admin/system/security.php index 1ea81cd5dd3..62b012858b5 100644 --- a/htdocs/admin/system/security.php +++ b/htdocs/admin/system/security.php @@ -542,13 +542,13 @@ print '
'; print 'MAIN_SECURITY_CSRF_TOKEN_RENEWAL_ON_EACH_CALL = '.(empty($conf->global->MAIN_SECURITY_CSRF_TOKEN_RENEWAL_ON_EACH_CALL) ? ''.$langs->trans("Undefined").'   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or").' 0)' : $conf->global->MAIN_SECURITY_CSRF_TOKEN_RENEWAL_ON_EACH_CALL)."
"; print '
'; -print 'MAIN_SECURITY_FORCECSP = '.(empty($conf->global->MAIN_SECURITY_FORCECSP) ? ''.$langs->trans("Undefined").'' : $conf->global->MAIN_SECURITY_FORCECSP).'   ('.$langs->trans("Example").": \"default-src 'self'; img-src *;\")
"; +print 'MAIN_SECURITY_FORCECSP = '.(empty($conf->global->MAIN_SECURITY_FORCECSP) ? ''.$langs->trans("Undefined").'' : $conf->global->MAIN_SECURITY_FORCECSP).'   ('.$langs->trans("Example").": \"frame-ancestors 'self'; default-src 'self'; img-src *;\")
"; print '
'; -print 'MAIN_SECURITY_FORCERP = '.(empty($conf->global->MAIN_SECURITY_FORCERP) ? ''.$langs->trans("Undefined").'' : $conf->global->MAIN_SECURITY_FORCERP).'   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or")." \"same-origin\")
"; +print 'MAIN_SECURITY_FORCERP = '.(empty($conf->global->MAIN_SECURITY_FORCERP) ? ''.$langs->trans("Undefined").'' : $conf->global->MAIN_SECURITY_FORCERP).'   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or")." \"same-origin\" so browser doesn't send any referrer when going into another web site domain)
"; print '
'; -print 'WEBSITE_MAIN_SECURITY_FORCECSP = '.(empty($conf->global->WEBSITE_MAIN_SECURITY_FORCECSP) ? ''.$langs->trans("Undefined").'' : $conf->global->WEBSITE_MAIN_SECURITY_FORCECSP).'   ('.$langs->trans("Example").": \"default-src 'self'; style-src: https://cdnjs.cloudflare.com https://fonts.googleapis.com; script-src: https://cdn.transifex.com https://www.googletagmanager.com; object-src https://youtube.com; frame-src https://youtube.com; img-src: *;\")
"; +print 'WEBSITE_MAIN_SECURITY_FORCECSP = '.(empty($conf->global->WEBSITE_MAIN_SECURITY_FORCECSP) ? ''.$langs->trans("Undefined").'' : $conf->global->WEBSITE_MAIN_SECURITY_FORCECSP).'   ('.$langs->trans("Example").": \"frame-ancestors 'self'; default-src 'self'; style-src https://cdnjs.cloudflare.com https://fonts.googleapis.com; script-src https://cdn.transifex.com https://www.googletagmanager.com; object-src https://youtube.com; frame-src https://youtube.com; img-src *;\")
"; print '
'; print 'WEBSITE_MAIN_SECURITY_FORCERP = '.(empty($conf->global->WEBSITE_MAIN_SECURITY_FORCERP) ? ''.$langs->trans("Undefined").'' : $conf->global->WEBSITE_MAIN_SECURITY_FORCERP).'   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or")." \"strict-origin-when-cross-origin\")
"; diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index 2bfdf9d1f66..062d041c81a 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -567,16 +567,17 @@ if (isModEnabled('socialnetworks')) { if ($value['active'] && strlen($search_[$key])) { $searchkeyinjsonformat = preg_replace('/"$/', '', preg_replace('/^"/', '', json_encode($search_[$key]))); if (in_array($db->type, array('mysql', 'mysqli'))) { - $sql .= " AND p.socialnetworks REGEXP '\"".$db->escapeforlike($db->escape($key))."\":\"[^\"]*".$db->escapeforlike($db->escape($searchkeyinjsonformat))."'"; + $sql .= " AND p.socialnetworks REGEXP '\"".$db->escape($db->escapeforlike($key))."\":\"[^\"]*".$db->escape($db->escapeforlike($searchkeyinjsonformat))."'"; } elseif ($db->type == 'pgsql') { - $sql .= " AND p.socialnetworks ~ '\"".$db->escapeforlike($db->escape($key))."\":\"[^\"]*".$db->escapeforlike($db->escape($searchkeyinjsonformat))."'"; + $sql .= " AND p.socialnetworks ~ '\"".$db->escape($db->escapeforlike($key))."\":\"[^\"]*".$db->escape($db->escapeforlike($searchkeyinjsonformat))."'"; } else { // Works with all database but not reliable because search only for social network code starting with earched value - $sql .= " AND p.socialnetworks LIKE '%\"".$db->escapeforlike($db->escape($key))."\":\"".$db->escapeforlike($db->escape($searchkeyinjsonformat))."%'"; + $sql .= " AND p.socialnetworks LIKE '%\"".$db->escape($db->escapeforlike($key))."\":\"".$db->escape($db->escapeforlike($searchkeyinjsonformat))."%'"; } } } } +//print $sql; if (strlen($search_email)) { $sql .= natural_search('p.email', $search_email); } diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index 4b43230adda..c258e3198ce 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -936,7 +936,7 @@ function getSocialNetworkSharingLinks() * @param string $langcode Language code ('' or 'en', 'fr', 'es', ...) * @param array $otherfilters Other filters * @param int $status 0 or 1, or -1 for both - * @return string HTML content + * @return array Array with results of search */ function getPagesFromSearchCriterias($type, $algo, $searchstring, $max = 25, $sortfield = 'date_creation', $sortorder = 'DESC', $langcode = '', $otherfilters = 'null', $status = 1) { @@ -974,6 +974,8 @@ function getPagesFromSearchCriterias($type, $algo, $searchstring, $max = 25, $so $found = 0; if (!$error && (empty($max) || ($found < $max)) && (preg_match('/meta/', $algo) || preg_match('/content/', $algo))) { + include_once DOL_DOCUMENT_ROOT.'/website/class/websitepage.class.php'; + $sql = 'SELECT wp.rowid FROM '.MAIN_DB_PREFIX.'website_page as wp'; if (is_array($otherfilters) && !empty($otherfilters['category'])) { $sql .= ', '.MAIN_DB_PREFIX.'categorie_website_page as cwp'; @@ -983,7 +985,7 @@ function getPagesFromSearchCriterias($type, $algo, $searchstring, $max = 25, $so $sql .= " AND wp.status = ".((int) $status); } if ($langcode) { - $sql .= " AND wp.lang ='".$db->escape($langcode)."'"; + $sql .= " AND wp.lang = '".$db->escape($langcode)."'"; } if ($type) { $tmparrayoftype = explode(',', $type); @@ -996,11 +998,11 @@ function getPagesFromSearchCriterias($type, $algo, $searchstring, $max = 25, $so $sql .= " AND ("; $searchalgo = ''; if (preg_match('/meta/', $algo)) { - $searchalgo .= ($searchalgo ? ' OR ' : '')."wp.title LIKE '%".$db->escapeforlike($db->escape($searchstring))."%' OR wp.description LIKE '%".$db->escapeforlike($db->escape($searchstring))."%'"; - $searchalgo .= ($searchalgo ? ' OR ' : '')."wp.keywords LIKE '".$db->escapeforlike($db->escape($searchstring)).",%' OR wp.keywords LIKE '% ".$db->escapeforlike($db->escape($searchstring))."%'"; // TODO Use a better way to scan keywords + $searchalgo .= ($searchalgo ? ' OR ' : '')."wp.title LIKE '%".$db->escape($db->escapeforlike($searchstring))."%' OR wp.description LIKE '%".$db->escape($db->escapeforlike($searchstring))."%'"; + $searchalgo .= ($searchalgo ? ' OR ' : '')."wp.keywords LIKE '".$db->escape($db->escapeforlike($searchstring)).",%' OR wp.keywords LIKE '% ".$db->escape($db->escapeforlike($searchstring))."%'"; // TODO Use a better way to scan keywords } if (preg_match('/content/', $algo)) { - $searchalgo .= ($searchalgo ? ' OR ' : '')."wp.content LIKE '%".$db->escapeforlike($db->escape($searchstring))."%'"; + $searchalgo .= ($searchalgo ? ' OR ' : '')."wp.content LIKE '%".$db->escape($db->escapeforlike($searchstring))."%'"; } $sql .= $searchalgo; if (is_array($otherfilters) && !empty($otherfilters['category'])) { @@ -1012,6 +1014,7 @@ function getPagesFromSearchCriterias($type, $algo, $searchstring, $max = 25, $so //print $sql; $resql = $db->query($sql); + if ($resql) { $i = 0; while (($obj = $db->fetch_object($resql)) && ($i < $max || $max == 0)) { diff --git a/htdocs/core/modules/import/import_csv.modules.php b/htdocs/core/modules/import/import_csv.modules.php index 09f93a436ea..22c12024c2b 100644 --- a/htdocs/core/modules/import/import_csv.modules.php +++ b/htdocs/core/modules/import/import_csv.modules.php @@ -862,8 +862,8 @@ class ImportCsv extends ModeleImports $stringtosearch = json_encode($socialnetwork).':'.json_encode($json->$socialnetwork); //var_dump($stringtosearch); //var_dump($this->db->escape($stringtosearch)); // This provide a value for sql string (but not for a like) - $where[] = $key." LIKE '%".$this->db->escapeforlike($this->db->escape($stringtosearch))."%'"; - $filters[] = $col." LIKE '%".$this->db->escapeforlike($this->db->escape($stringtosearch))."%'"; + $where[] = $key." LIKE '%".$this->db->escape($this->db->escapeforlike($stringtosearch))."%'"; + $filters[] = $col." LIKE '%".$this->db->escape($this->db->escapeforlike($stringtosearch))."%'"; //var_dump($where[1]); // This provide a value for sql string inside a like } else { $where[] = $key.' = '.$data[$key]; diff --git a/htdocs/core/modules/import/import_xlsx.modules.php b/htdocs/core/modules/import/import_xlsx.modules.php index ecf7d8b4a77..35adc4476a0 100644 --- a/htdocs/core/modules/import/import_xlsx.modules.php +++ b/htdocs/core/modules/import/import_xlsx.modules.php @@ -908,8 +908,8 @@ class ImportXlsx extends ModeleImports $stringtosearch = json_encode($socialnetwork).':'.json_encode($json->$socialnetwork); //var_dump($stringtosearch); //var_dump($this->db->escape($stringtosearch)); // This provide a value for sql string (but not for a like) - $where[] = $key." LIKE '%".$this->db->escapeforlike($this->db->escape($stringtosearch))."%'"; - $filters[] = $col." LIKE '%".$this->db->escapeforlike($this->db->escape($stringtosearch))."%'"; + $where[] = $key." LIKE '%".$this->db->escape($this->db->escapeforlike($stringtosearch))."%'"; + $filters[] = $col." LIKE '%".$this->db->escape($this->db->escapeforlike($stringtosearch))."%'"; //var_dump($where[1]); // This provide a value for sql string inside a like } else { $where[] = $key.' = '.$data[$key]; diff --git a/htdocs/imports/import.php b/htdocs/imports/import.php index 1ce6d859266..9a33bd25c05 100644 --- a/htdocs/imports/import.php +++ b/htdocs/imports/import.php @@ -1068,6 +1068,7 @@ if ($step == 4 && $datatoimport) { print '
'."\n"; // List of source fields + $var = false; $lefti = 1; foreach ($fieldssource as $key => $val) { @@ -1090,6 +1091,7 @@ if ($step == 4 && $datatoimport) { print ''; // Set the list of all possible target fields in Dolibarr. + $optionsall = array(); foreach ($fieldstarget as $code => $line) { //var_dump($line); @@ -1141,8 +1143,7 @@ if ($step == 4 && $datatoimport) { $entityicon = !empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity; // $entityicon must string name of picto of the field like 'project', 'company', 'contact', 'modulename', ... $entitylang = $entitytolang[$entity] ? $entitytolang[$entity] : $objimport->array_import_label[0]; // $entitylang must be a translation key to describe object the field is related to, like 'Company', 'Contact', 'MyModyle', ... - //print '=> '.img_object('', $entityicon).' '.$langs->trans($entitylang).''; - print '=> '; + print '=> '; print ''; //var_dump($_SESSION['dol_array_match_file_to_database_select']); @@ -1510,7 +1511,7 @@ if ($step == 4 && $datatoimport) { print ''; print $obj->label; print ''; - print ''; + print ''; if (empty($obj->fk_user)) { print $langs->trans("Everybody"); } else { @@ -2338,7 +2339,7 @@ $db->close(); */ function show_elem($fieldssource, $pos, $key, $var, $nostyle = '') { - global $langs; + global $conf, $langs; $height = '32px'; @@ -2384,7 +2385,7 @@ function show_elem($fieldssource, $pos, $key, $var, $nostyle = '') if (isset($fieldssource[$pos]['imported']) && $fieldssource[$pos]['imported'] == false) { print ''; } else { - print ''; + print ''; } print $langs->trans("Column").' '.num2Alpha($pos - 1).' (#'.$pos.')'; if (empty($fieldssource[$pos]['example1'])) { @@ -2396,7 +2397,12 @@ function show_elem($fieldssource, $pos, $key, $var, $nostyle = '') if (!utf8_check($example)) { $example = utf8_encode($example); } - print ' - '; + if (!empty($conf->dol_optimize_smallscreen)) { + //print '
'; + print ' - '; + } else { + print ' - '; + } //print ''.$langs->trans("ExampleOnFirstLine").': '; print ''.$example.''; } diff --git a/htdocs/includes/adodbtime/README.txt b/htdocs/includes/adodbtime/README.txt deleted file mode 100644 index 3e2969a2868..00000000000 --- a/htdocs/includes/adodbtime/README.txt +++ /dev/null @@ -1,7 +0,0 @@ -README -====== - -ADOdb Date Library, part of the ADOdb abstraction library - -See Wiki: https://adodb.org/dokuwiki/doku.php?id=v5:datetime:datetime_index -Download: https://github.com/ADOdb/ADOdb/blob/master/adodb-time.inc.php diff --git a/htdocs/includes/adodbtime/adodb-time.inc.php b/htdocs/includes/adodbtime/adodb-time.inc.php deleted file mode 100644 index 1dfa97929a2..00000000000 --- a/htdocs/includes/adodbtime/adodb-time.inc.php +++ /dev/null @@ -1,1459 +0,0 @@ - 4 digit year conversion. The maximum is billions of years in the -future, but this is a theoretical limit as the computation of that year -would take too long with the current implementation of adodb_mktime(). - -This library replaces native functions as follows: - -
-	getdate()  with  adodb_getdate()
-	date()     with  adodb_date()
-	gmdate()   with  adodb_gmdate()
-	mktime()   with  adodb_mktime()
-	gmmktime() with  adodb_gmmktime()
-	strftime() with  adodb_strftime()
-	strftime() with  adodb_gmstrftime()
-
- -The parameters are identical, except that adodb_date() accepts a subset -of date()'s field formats. Mktime() will convert from local time to GMT, -and date() will convert from GMT to local time, but daylight savings is -not handled currently. - -This library is independant of the rest of ADOdb, and can be used -as standalone code. - -PERFORMANCE - -For high speed, this library uses the native date functions where -possible, and only switches to PHP code when the dates fall outside -the 32-bit signed integer range. - -GREGORIAN CORRECTION - -Pope Gregory shortened October of A.D. 1582 by ten days. Thursday, -October 4, 1582 (Julian) was followed immediately by Friday, October 15, -1582 (Gregorian). - -Since 0.06, we handle this correctly, so: - -adodb_mktime(0,0,0,10,15,1582) - adodb_mktime(0,0,0,10,4,1582) - == 24 * 3600 (1 day) - -============================================================================= - -COPYRIGHT - -(c) 2003-2014 John Lim and released under BSD-style license except for code by -jackbbs, which includes adodb_mktime, adodb_get_gmt_diff, adodb_is_leap_year -and originally found at http://www.php.net/manual/en/function.mktime.php - -============================================================================= - -BUG REPORTS - -These should be posted to the ADOdb forums at - - http://phplens.com/lens/lensforum/topics.php?id=4 - -============================================================================= - -FUNCTION DESCRIPTIONS - -** FUNCTION adodb_time() - -Returns the current time measured in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT) as an unsigned integer. - -** FUNCTION adodb_getdate($date=false) - -Returns an array containing date information, as getdate(), but supports -dates greater than 1901 to 2038. The local date/time format is derived from a -heuristic the first time adodb_getdate is called. - - -** FUNCTION adodb_date($fmt, $timestamp = false) - -Convert a timestamp to a formatted local date. If $timestamp is not defined, the -current timestamp is used. Unlike the function date(), it supports dates -outside the 1901 to 2038 range. - -The format fields that adodb_date supports: - -
-	a - "am" or "pm"
-	A - "AM" or "PM"
-	d - day of the month, 2 digits with leading zeros; i.e. "01" to "31"
-	D - day of the week, textual, 3 letters; e.g. "Fri"
-	F - month, textual, long; e.g. "January"
-	g - hour, 12-hour format without leading zeros; i.e. "1" to "12"
-	G - hour, 24-hour format without leading zeros; i.e. "0" to "23"
-	h - hour, 12-hour format; i.e. "01" to "12"
-	H - hour, 24-hour format; i.e. "00" to "23"
-	i - minutes; i.e. "00" to "59"
-	j - day of the month without leading zeros; i.e. "1" to "31"
-	l (lowercase 'L') - day of the week, textual, long; e.g. "Friday"
-	L - boolean for whether it is a leap year; i.e. "0" or "1"
-	m - month; i.e. "01" to "12"
-	M - month, textual, 3 letters; e.g. "Jan"
-	n - month without leading zeros; i.e. "1" to "12"
-	O - Difference to Greenwich time in hours; e.g. "+0200"
-	Q - Quarter, as in 1, 2, 3, 4
-	r - RFC 2822 formatted date; e.g. "Thu, 21 Dec 2000 16:01:07 +0200"
-	s - seconds; i.e. "00" to "59"
-	S - English ordinal suffix for the day of the month, 2 characters;
-	   			i.e. "st", "nd", "rd" or "th"
-	t - number of days in the given month; i.e. "28" to "31"
-	T - Timezone setting of this machine; e.g. "EST" or "MDT"
-	U - seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
-	w - day of the week, numeric, i.e. "0" (Sunday) to "6" (Saturday)
-	Y - year, 4 digits; e.g. "1999"
-	y - year, 2 digits; e.g. "99"
-	z - day of the year; i.e. "0" to "365"
-	Z - timezone offset in seconds (i.e. "-43200" to "43200").
-	   			The offset for timezones west of UTC is always negative,
-				and for those east of UTC is always positive.
-
- -Unsupported: -
-	B - Swatch Internet time
-	I (capital i) - "1" if Daylight Savings Time, "0" otherwise.
-	W - ISO-8601 week number of year, weeks starting on Monday
-
-
- - -** FUNCTION adodb_date2($fmt, $isoDateString = false) -Same as adodb_date, but 2nd parameter accepts iso date, eg. - - adodb_date2('d-M-Y H:i','2003-12-25 13:01:34'); - - -** FUNCTION adodb_gmdate($fmt, $timestamp = false) - -Convert a timestamp to a formatted GMT date. If $timestamp is not defined, the -current timestamp is used. Unlike the function date(), it supports dates -outside the 1901 to 2038 range. - - -** FUNCTION adodb_mktime($hr, $min, $sec[, $month, $day, $year]) - -Converts a local date to a unix timestamp. Unlike the function mktime(), it supports -dates outside the 1901 to 2038 range. All parameters are optional. - - -** FUNCTION adodb_gmmktime($hr, $min, $sec [, $month, $day, $year]) - -Converts a gmt date to a unix timestamp. Unlike the function gmmktime(), it supports -dates outside the 1901 to 2038 range. Differs from gmmktime() in that all parameters -are currently compulsory. - -** FUNCTION adodb_gmstrftime($fmt, $timestamp = false) -Convert a timestamp to a formatted GMT date. - -** FUNCTION adodb_strftime($fmt, $timestamp = false) - -Convert a timestamp to a formatted local date. Internally converts $fmt into -adodb_date format, then echo result. - -For best results, you can define the local date format yourself. Define a global -variable $ADODB_DATE_LOCALE which is an array, 1st element is date format using -adodb_date syntax, and 2nd element is the time format, also in adodb_date syntax. - - eg. $ADODB_DATE_LOCALE = array('d/m/Y','H:i:s'); - - Supported format codes: - -
-	%a - abbreviated weekday name according to the current locale
-	%A - full weekday name according to the current locale
-	%b - abbreviated month name according to the current locale
-	%B - full month name according to the current locale
-	%c - preferred date and time representation for the current locale
-	%d - day of the month as a decimal number (range 01 to 31)
-	%D - same as %m/%d/%y
-	%e - day of the month as a decimal number, a single digit is preceded by a space (range ' 1' to '31')
-	%h - same as %b
-	%H - hour as a decimal number using a 24-hour clock (range 00 to 23)
-	%I - hour as a decimal number using a 12-hour clock (range 01 to 12)
-	%m - month as a decimal number (range 01 to 12)
-	%M - minute as a decimal number
-	%n - newline character
-	%p - either `am' or `pm' according to the given time value, or the corresponding strings for the current locale
-	%r - time in a.m. and p.m. notation
-	%R - time in 24 hour notation
-	%S - second as a decimal number
-	%t - tab character
-	%T - current time, equal to %H:%M:%S
-	%x - preferred date representation for the current locale without the time
-	%X - preferred time representation for the current locale without the date
-	%y - year as a decimal number without a century (range 00 to 99)
-	%Y - year as a decimal number including the century
-	%Z - time zone or name or abbreviation
-	%% - a literal `%' character
-
- - Unsupported codes: -
-	%C - century number (the year divided by 100 and truncated to an integer, range 00 to 99)
-	%g - like %G, but without the century.
-	%G - The 4-digit year corresponding to the ISO week number (see %V).
-	     This has the same format and value as %Y, except that if the ISO week number belongs
-		 to the previous or next year, that year is used instead.
-	%j - day of the year as a decimal number (range 001 to 366)
-	%u - weekday as a decimal number [1,7], with 1 representing Monday
-	%U - week number of the current year as a decimal number, starting
-	    with the first Sunday as the first day of the first week
-	%V - The ISO 8601:1988 week number of the current year as a decimal number,
-	     range 01 to 53, where week 1 is the first week that has at least 4 days in the
-		 current year, and with Monday as the first day of the week. (Use %G or %g for
-		 the year component that corresponds to the week number for the specified timestamp.)
-	%w - day of the week as a decimal, Sunday being 0
-	%W - week number of the current year as a decimal number, starting with the
-	     first Monday as the first day of the first week
-
- -============================================================================= - -NOTES - -Useful url for generating test timestamps: - http://www.4webhelp.net/us/timestamp.php - -Possible future optimizations include - -a. Using an algorithm similar to Plauger's in "The Standard C Library" -(page 428, xttotm.c _Ttotm() function). Plauger's algorithm will not -work outside 32-bit signed range, so i decided not to implement it. - -b. Implement daylight savings, which looks awfully complicated, see - http://webexhibits.org/daylightsaving/ - - -CHANGELOG -- 16 Jan 2011 0.36 -Added adodb_time() which returns current time. If > 2038, will return as float - -- 7 Feb 2011 0.35 -Changed adodb_date to be symmetric with adodb_mktime. See $jan1_71. fix for bc. - -- 13 July 2010 0.34 -Changed adodb_get_gm_diff to use DateTimeZone(). - -- 11 Feb 2008 0.33 -* Bug in 0.32 fix for hour handling. Fixed. - -- 1 Feb 2008 0.32 -* Now adodb_mktime(0,0,0,12+$m,20,2040) works properly. - -- 10 Jan 2008 0.31 -* Now adodb_mktime(0,0,0,24,1,2037) works correctly. - -- 15 July 2007 0.30 -Added PHP 5.2.0 compatability fixes. - * gmtime behaviour for 1970 has changed. We use the actual date if it is between 1970 to 2038 to get the - * timezone, otherwise we use the current year as the baseline to retrieve the timezone. - * Also the timezone's in php 5.2.* support historical data better, eg. if timezone today was +8, but - in 1970 it was +7:30, then php 5.2 return +7:30, while this library will use +8. - * - -- 19 March 2006 0.24 -Changed strftime() locale detection, because some locales prepend the day of week to the date when %c is used. - -- 10 Feb 2006 0.23 -PHP5 compat: when we detect PHP5, the RFC2822 format for gmt 0000hrs is changed from -0000 to +0000. - In PHP4, we will still use -0000 for 100% compat with PHP4. - -- 08 Sept 2005 0.22 -In adodb_date2(), $is_gmt not supported properly. Fixed. - -- 18 July 2005 0.21 -In PHP 4.3.11, the 'r' format has changed. Leading 0 in day is added. Changed for compat. -Added support for negative months in adodb_mktime(). - -- 24 Feb 2005 0.20 -Added limited strftime/gmstrftime support. x10 improvement in performance of adodb_date(). - -- 21 Dec 2004 0.17 -In adodb_getdate(), the timestamp was accidentally converted to gmt when $is_gmt is false. -Also adodb_mktime(0,0,0) did not work properly. Both fixed thx Mauro. - -- 17 Nov 2004 0.16 -Removed intval typecast in adodb_mktime() for secs, allowing: - adodb_mktime(0,0,0 + 2236672153,1,1,1934); -Suggested by Ryan. - -- 18 July 2004 0.15 -All params in adodb_mktime were formerly compulsory. Now only the hour, min, secs is compulsory. -This brings it more in line with mktime (still not identical). - -- 23 June 2004 0.14 - -Allow you to define your own daylights savings function, adodb_daylight_sv. -If the function is defined (somewhere in an include), then you can correct for daylights savings. - -In this example, we apply daylights savings in June or July, adding one hour. This is extremely -unrealistic as it does not take into account time-zone, geographic location, current year. - -function adodb_daylight_sv(&$arr, $is_gmt) -{ - if ($is_gmt) return; - $m = $arr['mon']; - if ($m == 6 || $m == 7) $arr['hours'] += 1; -} - -This is only called by adodb_date() and not by adodb_mktime(). - -The format of $arr is -Array ( - [seconds] => 0 - [minutes] => 0 - [hours] => 0 - [mday] => 1 # day of month, eg 1st day of the month - [mon] => 2 # month (eg. Feb) - [year] => 2102 - [yday] => 31 # days in current year - [leap] => # true if leap year - [ndays] => 28 # no of days in current month - ) - - -- 28 Apr 2004 0.13 -Fixed adodb_date to properly support $is_gmt. Thx to Dimitar Angelov. - -- 20 Mar 2004 0.12 -Fixed month calculation error in adodb_date. 2102-June-01 appeared as 2102-May-32. - -- 26 Oct 2003 0.11 -Because of daylight savings problems (some systems apply daylight savings to -January!!!), changed adodb_get_gmt_diff() to ignore daylight savings. - -- 9 Aug 2003 0.10 -Fixed bug with dates after 2038. -See http://phplens.com/lens/lensforum/msgs.php?id=6980 - -- 1 July 2003 0.09 -Added support for Q (Quarter). -Added adodb_date2(), which accepts ISO date in 2nd param - -- 3 March 2003 0.08 -Added support for 'S' adodb_date() format char. Added constant ADODB_ALLOW_NEGATIVE_TS -if you want PHP to handle negative timestamps between 1901 to 1969. - -- 27 Feb 2003 0.07 -All negative numbers handled by adodb now because of RH 7.3+ problems. -See http://bugs.php.net/bug.php?id=20048&edit=2 - -- 4 Feb 2003 0.06 -Fixed a typo, 1852 changed to 1582! This means that pre-1852 dates -are now correctly handled. - -- 29 Jan 2003 0.05 - -Leap year checking differs under Julian calendar (pre 1582). Also -leap year code optimized by checking for most common case first. - -We also handle month overflow correctly in mktime (eg month set to 13). - -Day overflow for less than one month's days is supported. - -- 28 Jan 2003 0.04 - -Gregorian correction handled. In PHP5, we might throw an error if -mktime uses invalid dates around 5-14 Oct 1582. Released with ADOdb 3.10. -Added limbo 5-14 Oct 1582 check, when we set to 15 Oct 1582. - -- 27 Jan 2003 0.03 - -Fixed some more month problems due to gmt issues. Added constant ADODB_DATE_VERSION. -Fixed calculation of days since start of year for <1970. - -- 27 Jan 2003 0.02 - -Changed _adodb_getdate() to inline leap year checking for better performance. -Fixed problem with time-zones west of GMT +0000. - -- 24 Jan 2003 0.01 - -First implementation. -*/ - - -/* Initialization */ - -/* - Version Number -*/ -define('ADODB_DATE_VERSION',0.35); - -$ADODB_DATETIME_CLASS = (PHP_VERSION >= 5.2); - -/* - This code was originally for windows. But apparently this problem happens - also with Linux, RH 7.3 and later! - - glibc-2.2.5-34 and greater has been changed to return -1 for dates < - 1970. This used to work. The problem exists with RedHat 7.3 and 8.0 - echo (mktime(0, 0, 0, 1, 1, 1960)); // prints -1 - - References: - http://bugs.php.net/bug.php?id=20048&edit=2 - http://lists.debian.org/debian-glibc/2002/debian-glibc-200205/msg00010.html -*/ - -if (!defined('ADODB_ALLOW_NEGATIVE_TS')) define('ADODB_NO_NEGATIVE_TS',1); - -function adodb_date_test_date($y1,$m,$d=13) -{ - $h = round(rand()% 24); - $t = adodb_mktime($h,0,0,$m,$d,$y1); - $rez = adodb_date('Y-n-j H:i:s',$t); - if ($h == 0) $h = '00'; - else if ($h < 10) $h = '0'.$h; - if ("$y1-$m-$d $h:00:00" != $rez) { - print "$y1 error, expected=$y1-$m-$d $h:00:00, adodb=$rez
"; - return false; - } - return true; -} - -function adodb_date_test_strftime($fmt) -{ - $s1 = strftime($fmt); - $s2 = adodb_strftime($fmt); - - if ($s1 == $s2) return true; - - echo "error for $fmt, strftime=$s1, adodb=$s2
"; - return false; -} - -/** - Test Suite -*/ -function adodb_date_test() -{ - - for ($m=-24; $m<=24; $m++) - echo "$m :",adodb_date('d-m-Y',adodb_mktime(0,0,0,1+$m,20,2040)),"
"; - - error_reporting(E_ALL); - print "

Testing adodb_date and adodb_mktime. version=".ADODB_DATE_VERSION.' PHP='.PHP_VERSION."

"; - @set_time_limit(0); - $fail = false; - - // This flag disables calling of PHP native functions, so we can properly test the code - if (!defined('ADODB_TEST_DATES')) define('ADODB_TEST_DATES',1); - - $t = time(); - - - $fmt = 'Y-m-d H:i:s'; - echo '
';
-	echo 'adodb: ',adodb_date($fmt,$t),'
'; - echo 'php : ',date($fmt,$t),'
'; - echo '
'; - - adodb_date_test_strftime('%Y %m %x %X'); - adodb_date_test_strftime("%A %d %B %Y"); - adodb_date_test_strftime("%H %M S"); - - $t = adodb_mktime(0,0,0); - if (!(adodb_date('Y-m-d') == date('Y-m-d'))) print 'Error in '.adodb_mktime(0,0,0).'
'; - - $t = adodb_mktime(0,0,0,6,1,2102); - if (!(adodb_date('Y-m-d',$t) == '2102-06-01')) print 'Error in '.adodb_date('Y-m-d',$t).'
'; - - $t = adodb_mktime(0,0,0,2,1,2102); - if (!(adodb_date('Y-m-d',$t) == '2102-02-01')) print 'Error in '.adodb_date('Y-m-d',$t).'
'; - - - print "

Testing gregorian <=> julian conversion

"; - $t = adodb_mktime(0,0,0,10,11,1492); - //http://www.holidayorigins.com/html/columbus_day.html - Friday check - if (!(adodb_date('D Y-m-d',$t) == 'Fri 1492-10-11')) print 'Error in Columbus landing
'; - - $t = adodb_mktime(0,0,0,2,29,1500); - if (!(adodb_date('Y-m-d',$t) == '1500-02-29')) print 'Error in julian leap years
'; - - $t = adodb_mktime(0,0,0,2,29,1700); - if (!(adodb_date('Y-m-d',$t) == '1700-03-01')) print 'Error in gregorian leap years
'; - - print adodb_mktime(0,0,0,10,4,1582).' '; - print adodb_mktime(0,0,0,10,15,1582); - $diff = (adodb_mktime(0,0,0,10,15,1582) - adodb_mktime(0,0,0,10,4,1582)); - if ($diff != 3600*24) print " Error in gregorian correction = ".($diff/3600/24)." days
"; - - print " 15 Oct 1582, Fri=".(adodb_dow(1582,10,15) == 5 ? 'Fri' : 'Error')."
"; - print " 4 Oct 1582, Thu=".(adodb_dow(1582,10,4) == 4 ? 'Thu' : 'Error')."
"; - - print "

Testing overflow

"; - - $t = adodb_mktime(0,0,0,3,33,1965); - if (!(adodb_date('Y-m-d',$t) == '1965-04-02')) print 'Error in day overflow 1
'; - $t = adodb_mktime(0,0,0,4,33,1971); - if (!(adodb_date('Y-m-d',$t) == '1971-05-03')) print 'Error in day overflow 2
'; - $t = adodb_mktime(0,0,0,1,60,1965); - if (!(adodb_date('Y-m-d',$t) == '1965-03-01')) print 'Error in day overflow 3 '.adodb_date('Y-m-d',$t).'
'; - $t = adodb_mktime(0,0,0,12,32,1965); - if (!(adodb_date('Y-m-d',$t) == '1966-01-01')) print 'Error in day overflow 4 '.adodb_date('Y-m-d',$t).'
'; - $t = adodb_mktime(0,0,0,12,63,1965); - if (!(adodb_date('Y-m-d',$t) == '1966-02-01')) print 'Error in day overflow 5 '.adodb_date('Y-m-d',$t).'
'; - $t = adodb_mktime(0,0,0,13,3,1965); - if (!(adodb_date('Y-m-d',$t) == '1966-01-03')) print 'Error in mth overflow 1
'; - - print "Testing 2-digit => 4-digit year conversion

"; - if (adodb_year_digit_check(00) != 2000) print "Err 2-digit 2000
"; - if (adodb_year_digit_check(10) != 2010) print "Err 2-digit 2010
"; - if (adodb_year_digit_check(20) != 2020) print "Err 2-digit 2020
"; - if (adodb_year_digit_check(30) != 2030) print "Err 2-digit 2030
"; - if (adodb_year_digit_check(40) != 1940) print "Err 2-digit 1940
"; - if (adodb_year_digit_check(50) != 1950) print "Err 2-digit 1950
"; - if (adodb_year_digit_check(90) != 1990) print "Err 2-digit 1990
"; - - // Test string formating - print "

Testing date formating

"; - - $fmt = '\d\a\t\e T Y-m-d H:i:s a A d D F g G h H i j l L m M n O \R\F\C2822 r s t U w y Y z Z 2003'; - $s1 = date($fmt,0); - $s2 = adodb_date($fmt,0); - if ($s1 != $s2) { - print " date() 0 failed
$s1
$s2
"; - } - flush(); - for ($i=100; --$i > 0; ) { - - $ts = 3600.0*((rand()%60000)+(rand()%60000))+(rand()%60000); - $s1 = date($fmt,$ts); - $s2 = adodb_date($fmt,$ts); - //print "$s1
$s2

"; - $pos = strcmp($s1,$s2); - - if (($s1) != ($s2)) { - for ($j=0,$k=strlen($s1); $j < $k; $j++) { - if ($s1[$j] != $s2[$j]) { - print substr($s1,$j).' '; - break; - } - } - print "Error date(): $ts

-  \"$s1\" (date len=".strlen($s1).")
-  \"$s2\" (adodb_date len=".strlen($s2).")

"; - $fail = true; - } - - $a1 = getdate($ts); - $a2 = adodb_getdate($ts); - $rez = array_diff($a1,$a2); - if (sizeof($rez)>0) { - print "Error getdate() $ts
"; - print_r($a1); - print "
"; - print_r($a2); - print "

"; - $fail = true; - } - } - - // Test generation of dates outside 1901-2038 - print "

Testing random dates between 100 and 4000

"; - adodb_date_test_date(100,1); - for ($i=100; --$i >= 0;) { - $y1 = 100+rand(0,1970-100); - $m = rand(1,12); - adodb_date_test_date($y1,$m); - - $y1 = 3000-rand(0,3000-1970); - adodb_date_test_date($y1,$m); - } - print '

'; - $start = 1960+rand(0,10); - $yrs = 12; - $i = 365.25*86400*($start-1970); - $offset = 36000+rand(10000,60000); - $max = 365*$yrs*86400; - $lastyear = 0; - - // we generate a timestamp, convert it to a date, and convert it back to a timestamp - // and check if the roundtrip broke the original timestamp value. - print "Testing $start to ".($start+$yrs).", or $max seconds, offset=$offset: "; - $cnt = 0; - for ($max += $i; $i < $max; $i += $offset) { - $ret = adodb_date('m,d,Y,H,i,s',$i); - $arr = explode(',',$ret); - if ($lastyear != $arr[2]) { - $lastyear = $arr[2]; - print " $lastyear "; - flush(); - } - $newi = adodb_mktime($arr[3],$arr[4],$arr[5],$arr[0],$arr[1],$arr[2]); - if ($i != $newi) { - print "Error at $i, adodb_mktime returned $newi ($ret)"; - $fail = true; - break; - } - $cnt += 1; - } - echo "Tested $cnt dates
"; - if (!$fail) print "

Passed !

"; - else print "

Failed :-(

"; -} - -function adodb_time() -{ - $d = new DateTime(); - return $d->format('U'); -} - -/** - Returns day of week, 0 = Sunday,... 6=Saturday. - Algorithm from PEAR::Date_Calc -*/ -function adodb_dow($year, $month, $day) -{ -/* -Pope Gregory removed 10 days - October 5 to October 14 - from the year 1582 and -proclaimed that from that time onwards 3 days would be dropped from the calendar -every 400 years. - -Thursday, October 4, 1582 (Julian) was followed immediately by Friday, October 15, 1582 (Gregorian). -*/ - if ($year <= 1582) { - if ($year < 1582 || - ($year == 1582 && ($month < 10 || ($month == 10 && $day < 15)))) $greg_correction = 3; - else - $greg_correction = 0; - } else - $greg_correction = 0; - - if($month > 2) - $month -= 2; - else { - $month += 10; - $year--; - } - - $day = floor((13 * $month - 1) / 5) + - $day + ($year % 100) + - floor(($year % 100) / 4) + - floor(($year / 100) / 4) - 2 * - floor($year / 100) + 77 + $greg_correction; - - return $day - 7 * floor($day / 7); -} - - -/** - Checks for leap year, returns true if it is. No 2-digit year check. Also - handles julian calendar correctly. -*/ -function _adodb_is_leap_year($year) -{ - if ($year % 4 != 0) return false; - - if ($year % 400 == 0) { - return true; - // if gregorian calendar (>1582), century not-divisible by 400 is not leap - } else if ($year > 1582 && $year % 100 == 0 ) { - return false; - } - - return true; -} - - -/** - checks for leap year, returns true if it is. Has 2-digit year check -*/ -function adodb_is_leap_year($year) -{ - return _adodb_is_leap_year(adodb_year_digit_check($year)); -} - -/** - Fix 2-digit years. Works for any century. - Assumes that if 2-digit is more than 30 years in future, then previous century. -*/ -function adodb_year_digit_check($y) -{ - if ($y < 100) { - - $yr = (integer) date("Y"); - $century = (integer) ($yr /100); - - if ($yr%100 > 50) { - $c1 = $century + 1; - $c0 = $century; - } else { - $c1 = $century; - $c0 = $century - 1; - } - $c1 *= 100; - // if 2-digit year is less than 30 years in future, set it to this century - // otherwise if more than 30 years in future, then we set 2-digit year to the prev century. - if (($y + $c1) < $yr+30) $y = $y + $c1; - else $y = $y + $c0*100; - } - return $y; -} - -function adodb_get_gmt_diff_ts($ts) -{ - if (0 <= $ts && $ts <= 0x7FFFFFFF) { // check if number in 32-bit signed range) { - $arr = getdate($ts); - $y = $arr['year']; - $m = $arr['mon']; - $d = $arr['mday']; - return adodb_get_gmt_diff($y,$m,$d); - } else { - return adodb_get_gmt_diff(false,false,false); - } - -} - -/** - get local time zone offset from GMT. Does not handle historical timezones before 1970. -*/ -function adodb_get_gmt_diff($y,$m,$d) -{ -static $TZ,$tzo; -global $ADODB_DATETIME_CLASS; - - if (!defined('ADODB_TEST_DATES')) $y = false; - else if ($y < 1970 || $y >= 2038) $y = false; - - if ($ADODB_DATETIME_CLASS && $y !== false) { - $dt = new DateTime(); - $dt->setISODate($y,$m,$d); - if (empty($tzo)) { - $tzo = new DateTimeZone(date_default_timezone_get()); - # $tzt = timezone_transitions_get( $tzo ); - } - return -$tzo->getOffset($dt); - } else { - if (isset($TZ)) return $TZ; - $y = date('Y'); - /* - if (function_exists('date_default_timezone_get') && function_exists('timezone_offset_get')) { - $tzonename = date_default_timezone_get(); - if ($tzonename) { - $tobj = new DateTimeZone($tzonename); - $TZ = -timezone_offset_get($tobj,new DateTime("now",$tzo)); - } - } - */ - if (empty($TZ)) $TZ = mktime(0,0,0,12,2,$y) - gmmktime(0,0,0,12,2,$y); - } - return $TZ; -} - -/** - Returns an array with date info. -*/ -function adodb_getdate($d=false,$fast=false) -{ - if ($d === false) return getdate(); - if (!defined('ADODB_TEST_DATES')) { - if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range - if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= 0) // if windows, must be +ve integer - return @getdate($d); - } - } - return _adodb_getdate($d); -} - -/* -// generate $YRS table for _adodb_getdate() -function adodb_date_gentable($out=true) -{ - - for ($i=1970; $i >= 1600; $i-=10) { - $s = adodb_gmmktime(0,0,0,1,1,$i); - echo "$i => $s,
"; - } -} -adodb_date_gentable(); - -for ($i=1970; $i > 1500; $i--) { - -echo "
$i "; - adodb_date_test_date($i,1,1); -} - -*/ - - -$_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31); -$_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31); - -function adodb_validdate($y,$m,$d) -{ -global $_month_table_normal,$_month_table_leaf; - - if (_adodb_is_leap_year($y)) $marr = $_month_table_leaf; - else $marr = $_month_table_normal; - - if ($m > 12 || $m < 1) return false; - - if ($d > 31 || $d < 1) return false; - - if ($marr[$m] < $d) return false; - - if ($y < 1000 && $y > 3000) return false; - - return true; -} - -/** - Low-level function that returns the getdate() array. We have a special - $fast flag, which if set to true, will return fewer array values, - and is much faster as it does not calculate dow, etc. -*/ -function _adodb_getdate($origd=false,$fast=false,$is_gmt=false) -{ -static $YRS; -global $_month_table_normal,$_month_table_leaf; - - $d = $origd - ($is_gmt ? 0 : adodb_get_gmt_diff_ts($origd)); - $_day_power = 86400; - $_hour_power = 3600; - $_min_power = 60; - - if ($d < -12219321600) $d -= 86400*10; // if 15 Oct 1582 or earlier, gregorian correction - - $_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31); - $_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31); - - $d366 = $_day_power * 366; - $d365 = $_day_power * 365; - - if ($d < 0) { - - if (empty($YRS)) $YRS = array( - 1970 => 0, - 1960 => -315619200, - 1950 => -631152000, - 1940 => -946771200, - 1930 => -1262304000, - 1920 => -1577923200, - 1910 => -1893456000, - 1900 => -2208988800, - 1890 => -2524521600, - 1880 => -2840140800, - 1870 => -3155673600, - 1860 => -3471292800, - 1850 => -3786825600, - 1840 => -4102444800, - 1830 => -4417977600, - 1820 => -4733596800, - 1810 => -5049129600, - 1800 => -5364662400, - 1790 => -5680195200, - 1780 => -5995814400, - 1770 => -6311347200, - 1760 => -6626966400, - 1750 => -6942499200, - 1740 => -7258118400, - 1730 => -7573651200, - 1720 => -7889270400, - 1710 => -8204803200, - 1700 => -8520336000, - 1690 => -8835868800, - 1680 => -9151488000, - 1670 => -9467020800, - 1660 => -9782640000, - 1650 => -10098172800, - 1640 => -10413792000, - 1630 => -10729324800, - 1620 => -11044944000, - 1610 => -11360476800, - 1600 => -11676096000); - - if ($is_gmt) $origd = $d; - // The valid range of a 32bit signed timestamp is typically from - // Fri, 13 Dec 1901 20:45:54 GMT to Tue, 19 Jan 2038 03:14:07 GMT - // - - # old algorithm iterates through all years. new algorithm does it in - # 10 year blocks - - /* - # old algo - for ($a = 1970 ; --$a >= 0;) { - $lastd = $d; - - if ($leaf = _adodb_is_leap_year($a)) $d += $d366; - else $d += $d365; - - if ($d >= 0) { - $year = $a; - break; - } - } - */ - - $lastsecs = 0; - $lastyear = 1970; - foreach($YRS as $year => $secs) { - if ($d >= $secs) { - $a = $lastyear; - break; - } - $lastsecs = $secs; - $lastyear = $year; - } - - $d -= $lastsecs; - if (!isset($a)) $a = $lastyear; - - //echo ' yr=',$a,' ', $d,'.'; - - for (; --$a >= 0;) { - $lastd = $d; - - if ($leaf = _adodb_is_leap_year($a)) $d += $d366; - else $d += $d365; - - if ($d >= 0) { - $year = $a; - break; - } - } - /**/ - - $secsInYear = 86400 * ($leaf ? 366 : 365) + $lastd; - - $d = $lastd; - $mtab = ($leaf) ? $_month_table_leaf : $_month_table_normal; - for ($a = 13 ; --$a > 0;) { - $lastd = $d; - $d += $mtab[$a] * $_day_power; - if ($d >= 0) { - $month = $a; - $ndays = $mtab[$a]; - break; - } - } - - $d = $lastd; - $day = $ndays + ceil(($d+1) / ($_day_power)); - - $d += ($ndays - $day+1)* $_day_power; - $hour = floor($d/$_hour_power); - - } else { - for ($a = 1970 ;; $a++) { - $lastd = $d; - - if ($leaf = _adodb_is_leap_year($a)) $d -= $d366; - else $d -= $d365; - if ($d < 0) { - $year = $a; - break; - } - } - $secsInYear = $lastd; - $d = $lastd; - $mtab = ($leaf) ? $_month_table_leaf : $_month_table_normal; - for ($a = 1 ; $a <= 12; $a++) { - $lastd = $d; - $d -= $mtab[$a] * $_day_power; - if ($d < 0) { - $month = $a; - $ndays = $mtab[$a]; - break; - } - } - $d = $lastd; - $day = ceil(($d+1) / $_day_power); - $d = $d - ($day-1) * $_day_power; - $hour = floor($d /$_hour_power); - } - - $d -= $hour * $_hour_power; - $min = floor($d/$_min_power); - $secs = $d - $min * $_min_power; - if ($fast) { - return array( - 'seconds' => $secs, - 'minutes' => $min, - 'hours' => $hour, - 'mday' => $day, - 'mon' => $month, - 'year' => $year, - 'yday' => floor($secsInYear/$_day_power), - 'leap' => $leaf, - 'ndays' => $ndays - ); - } - - - $dow = adodb_dow($year,$month,$day); - - return array( - 'seconds' => $secs, - 'minutes' => $min, - 'hours' => $hour, - 'mday' => $day, - 'wday' => $dow, - 'mon' => $month, - 'year' => $year, - 'yday' => floor($secsInYear/$_day_power), - 'weekday' => gmdate('l',$_day_power*(3+$dow)), - 'month' => gmdate('F',mktime(0,0,0,$month,2,1971)), - 0 => $origd - ); -} -/* - if ($isphp5) - $dates .= sprintf('%s%04d',($gmt<=0)?'+':'-',abs($gmt)/36); - else - $dates .= sprintf('%s%04d',($gmt<0)?'+':'-',abs($gmt)/36); - break;*/ -function adodb_tz_offset($gmt,$isphp5) -{ - $zhrs = abs($gmt)/3600; - $hrs = floor($zhrs); - if ($isphp5) - return sprintf('%s%02d%02d',($gmt<=0)?'+':'-',floor($zhrs),($zhrs-$hrs)*60); - else - return sprintf('%s%02d%02d',($gmt<0)?'+':'-',floor($zhrs),($zhrs-$hrs)*60); -} - - -function adodb_gmdate($fmt,$d=false) -{ - return adodb_date($fmt,$d,true); -} - -// accepts unix timestamp and iso date format in $d -function adodb_date2($fmt, $d=false, $is_gmt=false) -{ - if ($d !== false) { - if (!preg_match( - "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})[ -]?(([0-9]{1,2}):?([0-9]{1,2}):?([0-9\.]{1,4}))?|", - ($d), $rr)) return adodb_date($fmt,false,$is_gmt); - - if ($rr[1] <= 100 && $rr[2]<= 1) return adodb_date($fmt,false,$is_gmt); - - // h-m-s-MM-DD-YY - if (!isset($rr[5])) $d = adodb_mktime(0,0,0,$rr[2],$rr[3],$rr[1],false,$is_gmt); - else $d = @adodb_mktime($rr[5],$rr[6],$rr[7],$rr[2],$rr[3],$rr[1],false,$is_gmt); - } - - return adodb_date($fmt,$d,$is_gmt); -} - - -/** - Return formatted date based on timestamp $d -*/ -function adodb_date($fmt,$d=false,$is_gmt=false) -{ -static $daylight; -global $ADODB_DATETIME_CLASS; -static $jan1_1971; - - - if (!isset($daylight)) { - $daylight = function_exists('adodb_daylight_sv'); - if (empty($jan1_1971)) $jan1_1971 = mktime(0,0,0,1,1,1971); // we only use date() when > 1970 as adodb_mktime() only uses mktime() when > 1970 - } - - if ($d === false) return ($is_gmt)? @gmdate($fmt): @date($fmt); - if (!defined('ADODB_TEST_DATES')) { - if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range - - if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= $jan1_1971) // if windows, must be +ve integer - return ($is_gmt)? @gmdate($fmt,$d): @date($fmt,$d); - - } - } - $_day_power = 86400; - - $arr = _adodb_getdate($d,true,$is_gmt); - - if ($daylight) adodb_daylight_sv($arr, $is_gmt); - - $year = $arr['year']; - $month = $arr['mon']; - $day = $arr['mday']; - $hour = $arr['hours']; - $min = $arr['minutes']; - $secs = $arr['seconds']; - - $max = strlen($fmt); - $dates = ''; - - $isphp5 = PHP_VERSION >= 5; - - /* - at this point, we have the following integer vars to manipulate: - $year, $month, $day, $hour, $min, $secs - */ - for ($i=0; $i < $max; $i++) { - switch($fmt[$i]) { - case 'e': - $dates .= date('e'); - break; - case 'T': - if ($ADODB_DATETIME_CLASS) { - $dt = new DateTime(); - $dt->SetDate($year,$month,$day); - $dates .= $dt->Format('T'); - } else - $dates .= date('T'); - break; - // YEAR - case 'L': $dates .= $arr['leap'] ? '1' : '0'; break; - case 'r': // Thu, 21 Dec 2000 16:01:07 +0200 - - // 4.3.11 uses '04 Jun 2004' - // 4.3.8 uses ' 4 Jun 2004' - $dates .= gmdate('D',$_day_power*(3+adodb_dow($year,$month,$day))).', ' - . ($day<10?'0'.$day:$day) . ' '.date('M',mktime(0,0,0,$month,2,1971)).' '.$year.' '; - - if ($hour < 10) $dates .= '0'.$hour; else $dates .= $hour; - - if ($min < 10) $dates .= ':0'.$min; else $dates .= ':'.$min; - - if ($secs < 10) $dates .= ':0'.$secs; else $dates .= ':'.$secs; - - $gmt = adodb_get_gmt_diff($year,$month,$day); - - $dates .= ' '.adodb_tz_offset($gmt,$isphp5); - break; - - case 'Y': $dates .= $year; break; - case 'y': $dates .= substr($year,strlen($year)-2,2); break; - // MONTH - case 'm': if ($month<10) $dates .= '0'.$month; else $dates .= $month; break; - case 'Q': $dates .= ($month+3)>>2; break; - case 'n': $dates .= $month; break; - case 'M': $dates .= date('M',mktime(0,0,0,$month,2,1971)); break; - case 'F': $dates .= date('F',mktime(0,0,0,$month,2,1971)); break; - // DAY - case 't': $dates .= $arr['ndays']; break; - case 'z': $dates .= $arr['yday']; break; - case 'w': $dates .= adodb_dow($year,$month,$day); break; - case 'l': $dates .= gmdate('l',$_day_power*(3+adodb_dow($year,$month,$day))); break; - case 'D': $dates .= gmdate('D',$_day_power*(3+adodb_dow($year,$month,$day))); break; - case 'j': $dates .= $day; break; - case 'd': if ($day<10) $dates .= '0'.$day; else $dates .= $day; break; - case 'S': - $d10 = $day % 10; - if ($d10 == 1) $dates .= 'st'; - else if ($d10 == 2 && $day != 12) $dates .= 'nd'; - else if ($d10 == 3) $dates .= 'rd'; - else $dates .= 'th'; - break; - - // HOUR - case 'Z': - $dates .= ($is_gmt) ? 0 : -adodb_get_gmt_diff($year,$month,$day); break; - case 'O': - $gmt = ($is_gmt) ? 0 : adodb_get_gmt_diff($year,$month,$day); - - $dates .= adodb_tz_offset($gmt,$isphp5); - break; - - case 'H': - if ($hour < 10) $dates .= '0'.$hour; - else $dates .= $hour; - break; - case 'h': - if ($hour > 12) $hh = $hour - 12; - else { - if ($hour == 0) $hh = '12'; - else $hh = $hour; - } - - if ($hh < 10) $dates .= '0'.$hh; - else $dates .= $hh; - break; - - case 'G': - $dates .= $hour; - break; - - case 'g': - if ($hour > 12) $hh = $hour - 12; - else { - if ($hour == 0) $hh = '12'; - else $hh = $hour; - } - $dates .= $hh; - break; - // MINUTES - case 'i': if ($min < 10) $dates .= '0'.$min; else $dates .= $min; break; - // SECONDS - case 'U': $dates .= $d; break; - case 's': if ($secs < 10) $dates .= '0'.$secs; else $dates .= $secs; break; - // AM/PM - // Note 00:00 to 11:59 is AM, while 12:00 to 23:59 is PM - case 'a': - if ($hour>=12) $dates .= 'pm'; - else $dates .= 'am'; - break; - case 'A': - if ($hour>=12) $dates .= 'PM'; - else $dates .= 'AM'; - break; - default: - $dates .= $fmt[$i]; break; - // ESCAPE - case "\\": - $i++; - if ($i < $max) $dates .= $fmt[$i]; - break; - } - } - return $dates; -} - -/** - Returns a timestamp given a GMT/UTC time. - Note that $is_dst is not implemented and is ignored. -*/ -function adodb_gmmktime($hr,$min,$sec,$mon=false,$day=false,$year=false,$is_dst=false) -{ - return adodb_mktime($hr,$min,$sec,$mon,$day,$year,$is_dst,true); -} - -/** - Return a timestamp given a local time. Originally by jackbbs. - Note that $is_dst is not implemented and is ignored. - - Not a very fast algorithm - O(n) operation. Could be optimized to O(1). -*/ -function adodb_mktime($hr,$min,$sec,$mon=false,$day=false,$year=false,$is_dst=false,$is_gmt=false) -{ - if (!defined('ADODB_TEST_DATES')) { - - if ($mon === false) { - return $is_gmt? @gmmktime($hr,$min,$sec): @mktime($hr,$min,$sec); - } - - // for windows, we don't check 1970 because with timezone differences, - // 1 Jan 1970 could generate negative timestamp, which is illegal - $usephpfns = (1970 < $year && $year < 2038 - || !defined('ADODB_NO_NEGATIVE_TS') && (1901 < $year && $year < 2038) - ); - - - if ($usephpfns && ($year + $mon/12+$day/365.25+$hr/(24*365.25) >= 2038)) $usephpfns = false; - - if ($usephpfns) { - return $is_gmt ? - @gmmktime($hr,$min,$sec,$mon,$day,$year): - @mktime($hr,$min,$sec,$mon,$day,$year); - } - } - - $gmt_different = ($is_gmt) ? 0 : adodb_get_gmt_diff($year,$mon,$day); - - /* - # disabled because some people place large values in $sec. - # however we need it for $mon because we use an array... - $hr = intval($hr); - $min = intval($min); - $sec = intval($sec); - */ - $mon = intval($mon); - $day = intval($day); - $year = intval($year); - - - $year = adodb_year_digit_check($year); - - if ($mon > 12) { - $y = floor(($mon-1)/ 12); - $year += $y; - $mon -= $y*12; - } else if ($mon < 1) { - $y = ceil((1-$mon) / 12); - $year -= $y; - $mon += $y*12; - } - - $_day_power = 86400; - $_hour_power = 3600; - $_min_power = 60; - - $_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31); - $_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31); - - $_total_date = 0; - if ($year >= 1970) { - for ($a = 1970 ; $a <= $year; $a++) { - $leaf = _adodb_is_leap_year($a); - if ($leaf == true) { - $loop_table = $_month_table_leaf; - $_add_date = 366; - } else { - $loop_table = $_month_table_normal; - $_add_date = 365; - } - if ($a < $year) { - $_total_date += $_add_date; - } else { - for($b=1;$b<$mon;$b++) { - $_total_date += $loop_table[$b]; - } - } - } - $_total_date +=$day-1; - $ret = $_total_date * $_day_power + $hr * $_hour_power + $min * $_min_power + $sec + $gmt_different; - - } else { - for ($a = 1969 ; $a >= $year; $a--) { - $leaf = _adodb_is_leap_year($a); - if ($leaf == true) { - $loop_table = $_month_table_leaf; - $_add_date = 366; - } else { - $loop_table = $_month_table_normal; - $_add_date = 365; - } - if ($a > $year) { $_total_date += $_add_date; - } else { - for($b=12;$b>$mon;$b--) { - $_total_date += $loop_table[$b]; - } - } - } - $_total_date += $loop_table[$mon] - $day; - - $_day_time = $hr * $_hour_power + $min * $_min_power + $sec; - $_day_time = $_day_power - $_day_time; - $ret = -( $_total_date * $_day_power + $_day_time - $gmt_different); - if ($ret < -12220185600) $ret += 10*86400; // if earlier than 5 Oct 1582 - gregorian correction - else if ($ret < -12219321600) $ret = -12219321600; // if in limbo, reset to 15 Oct 1582. - } - //print " dmy=$day/$mon/$year $hr:$min:$sec => " .$ret; - return $ret; -} - -function adodb_gmstrftime($fmt, $ts=false) -{ - return adodb_strftime($fmt,$ts,true); -} - -// hack - convert to adodb_date -function adodb_strftime($fmt, $ts=false,$is_gmt=false) -{ -global $ADODB_DATE_LOCALE; - - if (!defined('ADODB_TEST_DATES')) { - if ((abs($ts) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range - if (!defined('ADODB_NO_NEGATIVE_TS') || $ts >= 0) // if windows, must be +ve integer - return ($is_gmt)? @gmstrftime($fmt,$ts): @strftime($fmt,$ts); - - } - } - - if (empty($ADODB_DATE_LOCALE)) { - /* - $tstr = strtoupper(gmstrftime('%c',31366800)); // 30 Dec 1970, 1 am - $sep = substr($tstr,2,1); - $hasAM = strrpos($tstr,'M') !== false; - */ - # see http://phplens.com/lens/lensforum/msgs.php?id=14865 for reasoning, and changelog for version 0.24 - $dstr = gmstrftime('%x',31366800); // 30 Dec 1970, 1 am - $sep = substr($dstr,2,1); - $tstr = strtoupper(gmstrftime('%X',31366800)); // 30 Dec 1970, 1 am - $hasAM = strrpos($tstr,'M') !== false; - - $ADODB_DATE_LOCALE = array(); - $ADODB_DATE_LOCALE[] = strncmp($tstr,'30',2) == 0 ? 'd'.$sep.'m'.$sep.'y' : 'm'.$sep.'d'.$sep.'y'; - $ADODB_DATE_LOCALE[] = ($hasAM) ? 'h:i:s a' : 'H:i:s'; - - } - $inpct = false; - $fmtdate = ''; - for ($i=0,$max = strlen($fmt); $i < $max; $i++) { - $ch = $fmt[$i]; - if ($ch == '%') { - if ($inpct) { - $fmtdate .= '%'; - $inpct = false; - } else - $inpct = true; - } else if ($inpct) { - - $inpct = false; - switch($ch) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case 'E': - case 'O': - /* ignore format modifiers */ - $inpct = true; - break; - - case 'a': $fmtdate .= 'D'; break; - case 'A': $fmtdate .= 'l'; break; - case 'h': - case 'b': $fmtdate .= 'M'; break; - case 'B': $fmtdate .= 'F'; break; - case 'c': $fmtdate .= $ADODB_DATE_LOCALE[0].$ADODB_DATE_LOCALE[1]; break; - case 'C': $fmtdate .= '\C?'; break; // century - case 'd': $fmtdate .= 'd'; break; - case 'D': $fmtdate .= 'm/d/y'; break; - case 'e': $fmtdate .= 'j'; break; - case 'g': $fmtdate .= '\g?'; break; //? - case 'G': $fmtdate .= '\G?'; break; //? - case 'H': $fmtdate .= 'H'; break; - case 'I': $fmtdate .= 'h'; break; - case 'j': $fmtdate .= '?z'; $parsej = true; break; // wrong as j=1-based, z=0-basd - case 'm': $fmtdate .= 'm'; break; - case 'M': $fmtdate .= 'i'; break; - case 'n': $fmtdate .= "\n"; break; - case 'p': $fmtdate .= 'a'; break; - case 'r': $fmtdate .= 'h:i:s a'; break; - case 'R': $fmtdate .= 'H:i:s'; break; - case 'S': $fmtdate .= 's'; break; - case 't': $fmtdate .= "\t"; break; - case 'T': $fmtdate .= 'H:i:s'; break; - case 'u': $fmtdate .= '?u'; $parseu = true; break; // wrong strftime=1-based, date=0-based - case 'U': $fmtdate .= '?U'; $parseU = true; break;// wrong strftime=1-based, date=0-based - case 'x': $fmtdate .= $ADODB_DATE_LOCALE[0]; break; - case 'X': $fmtdate .= $ADODB_DATE_LOCALE[1]; break; - case 'w': $fmtdate .= '?w'; $parseu = true; break; // wrong strftime=1-based, date=0-based - case 'W': $fmtdate .= '?W'; $parseU = true; break;// wrong strftime=1-based, date=0-based - case 'y': $fmtdate .= 'y'; break; - case 'Y': $fmtdate .= 'Y'; break; - case 'Z': $fmtdate .= 'T'; break; - } - } else if (('A' <= ($ch) && ($ch) <= 'Z' ) || ('a' <= ($ch) && ($ch) <= 'z' )) - $fmtdate .= "\\".$ch; - else - $fmtdate .= $ch; - } - //echo "fmt=",$fmtdate,"
"; - if ($ts === false) $ts = time(); - $ret = adodb_date($fmtdate, $ts, $is_gmt); - return $ret; -} diff --git a/htdocs/install/doctemplates/websites/website_template-restaurant/README.md b/htdocs/install/doctemplates/websites/website_template-restaurant/README.md index 3a656b8ddaf..a5b5c5abba9 100644 --- a/htdocs/install/doctemplates/websites/website_template-restaurant/README.md +++ b/htdocs/install/doctemplates/websites/website_template-restaurant/README.md @@ -1 +1,2 @@ Website generated by Dolibarr ERP CRM +This website template is an example of website for a restaurant diff --git a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/LICENSE b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/LICENSE index 83294e71b2e..1143fd7823a 100644 --- a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/LICENSE +++ b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/LICENSE @@ -1,2 +1,8 @@ -Image are provided under the Unsplash+ License -Rest of templates (HTML and PHP code) content are GPLv3 +LICENSE +------- + +Images are provided under the license: +Unsplash+ License + +Rest of templates (HTML and PHP code) content are under license +CC-BY-SA - https://creativecommons.org/licenses/by/4.0/ diff --git a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/README.md b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/README.md index 3a656b8ddaf..a5b5c5abba9 100644 --- a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/README.md +++ b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/README.md @@ -1 +1,2 @@ Website generated by Dolibarr ERP CRM +This website template is an example of website for a restaurant diff --git a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/about.php b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/about.php index c4816800d17..560719a4fda 100644 --- a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/about.php +++ b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/about.php @@ -1,5 +1,5 @@ ref.'/page169.tpl.php'; +if (empty($dolibarr_main_data_root)) require './page248.tpl.php'; else require $dolibarr_main_data_root.'/website/'.$website->ref.'/page248.tpl.php'; ?> diff --git a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/contact.php b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/contact.php index 7d5db994e1b..e3a18e3b92d 100644 --- a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/contact.php +++ b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/contact.php @@ -1,5 +1,5 @@ ref.'/page170.tpl.php'; +if (empty($dolibarr_main_data_root)) require './page249.tpl.php'; else require $dolibarr_main_data_root.'/website/'.$website->ref.'/page249.tpl.php'; ?> diff --git a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/footer.php b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/footer.php new file mode 100644 index 00000000000..4052f2ff8e9 --- /dev/null +++ b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/footer.php @@ -0,0 +1,5 @@ +ref.'/page252.tpl.php'; +?> diff --git a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/header.php b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/header.php new file mode 100644 index 00000000000..530e4397e93 --- /dev/null +++ b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/header.php @@ -0,0 +1,5 @@ +ref.'/page253.tpl.php'; +?> diff --git a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/htmlheader.html b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/htmlheader.html index 0de0b36283f..41e782b5934 100644 --- a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/htmlheader.html +++ b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/htmlheader.html @@ -1,6 +1,6 @@ - + diff --git a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/index.php b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/index.php index dc10e0099f4..08ce45517af 100644 --- a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/index.php +++ b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/index.php @@ -1,11 +1,5 @@ ref.'/page250.tpl.php'; +?> diff --git a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/javascript.js.php b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/javascript.js.php index f58102cf00b..fe1f15266af 100644 --- a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/javascript.js.php +++ b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/javascript.js.php @@ -8,6 +8,7 @@ header('Cache-Control: max-age=3600, public, must-revalidate'); header('Content-type: application/javascript'); // END PHP ?> /* JS content (all pages) */ +// test diff --git a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/menu.php b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/menu.php index 7e4cd71a69d..57315e4da18 100644 --- a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/menu.php +++ b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/menu.php @@ -1,5 +1,5 @@ ref.'/page172.tpl.php'; +if (empty($dolibarr_main_data_root)) require './page251.tpl.php'; else require $dolibarr_main_data_root.'/website/'.$website->ref.'/page251.tpl.php'; ?> diff --git a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/page169.tpl.php b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/page169.tpl.php deleted file mode 100644 index a592c302c73..00000000000 --- a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/page169.tpl.php +++ /dev/null @@ -1,198 +0,0 @@ - - - -About us - - - - - - - - - -use_manifest) { print ''."\n"; } ?> - - - - - - - - - - - - -
- - -
- - - -
-
-
- -
-

Team Members

-
- -
-
- - -
-

Sophia

- -

CEO & Founder

-
-
-
- -
-
- - -

Benjamin W.

- -

Restaurant Manager

-
-
- -
-
- - -

Muchen Jack

- -

Senior Chef

-
-
- -
-
-
- - - - -
- -
- - - - diff --git a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/page172.tpl.php b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/page172.tpl.php deleted file mode 100644 index cf759e644a8..00000000000 --- a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/page172.tpl.php +++ /dev/null @@ -1,597 +0,0 @@ - - - -Our menus - - - - - - - - - -use_manifest) { print ''."\n"; } ?> - - - - - - - - - - - - -
- - -
- - - - - - - -
- -
-
-
-
-

name; ?>

-
- -
-
Location
- -

getFullAddress(); ?>

- - Directions -
- -
-
Opening Hours
- - - $day : " .getDolGlobalString("MAIN_INFO_OPENINGHOURS_$day") ."

"; - } - ?> - -

- Tel: - phone ?> -

-
- -
-
Social
- - - - -
-
- -
- -
- -
- - - - diff --git a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/page248.tpl.php b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/page248.tpl.php new file mode 100644 index 00000000000..9acf79aaec9 --- /dev/null +++ b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/page248.tpl.php @@ -0,0 +1,113 @@ + + + +About us + + + + + + + + + +use_manifest) { print ''."\n"; } ?> + + + + + + + + + + + + + + +
+
+ + + +
+
+
+ +
+

Team Members

+
+ +
+
+ + +
+

Sophia

+ +

CEO & Founder

+
+
+
+ +
+
+ + +

Benjamin W.

+ +

Restaurant Manager

+
+
+ +
+
+ + +

Muchen Jack

+ +

Senior Chef

+
+
+ +
+
+
+ +
+ +
+ + + + + + + + diff --git a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/page170.tpl.php b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/page249.tpl.php similarity index 70% rename from htdocs/install/doctemplates/websites/website_template-restaurant/containers/page170.tpl.php rename to htdocs/install/doctemplates/websites/website_template-restaurant/containers/page249.tpl.php index c444ce1292d..8742e231c27 100644 --- a/htdocs/install/doctemplates/websites/website_template-restaurant/containers/page170.tpl.php +++ b/htdocs/install/doctemplates/websites/website_template-restaurant/containers/page249.tpl.php @@ -18,8 +18,8 @@ ob_start(); - - + + use_manifest) { print ''."\n"; } ?> @@ -34,7 +34,7 @@ ob_start(); email; @@ -51,67 +51,12 @@ ob_start(); } } ?> + + + +
- - -
+
- +
@@ -144,6 +89,9 @@ ob_start(); method="post" role="form" > + + +
Phone Numbertrans("Phone"); ?> Emailtrans("Email"); ?> Messagetrans("Message"); ?> __N__
__N____N__
__N__ __N__
__N__ __N__
__N____N__
__N__
Weekdays
__N____N__
__N__ $day : \" .getDolGlobalString(\"MAIN_INFO_OPENINGHOURS_$day\") .\"

\"; __N__ }__N__ ?>__N__
__N____N__
Weekends
__N____N__
__N__

Saturday and Sunday

__N____N__

to be determined !

__N__
__N__
__N____N__
__N__

__N__ getFullAddress() ?>__N__

__N____N__
__N__ __N__
__N__
__N__
__N__ __N__ __N__ __N____N__ __N__ __N__ __N__ __N__ __N__ __N__ __N__ __N__
__N__
__N__
__N__

Reserve a table

__N____N__ __N__
__N____N__ __N__
__N__ __N__ \" />__N__ __N__
__N__
__N____N__
__N__
__N____N__
__N__
__N____N__
__N__
__N____N__
__N__
__N____N__
__N__
__N____N__
__N__
__N____N__
__N__ __N__
__N__ __N__
__N__
__N____N__
__N__
__N__ __N__ __N____N____N__', '', 0); --- File generated by Dolibarr 17.0.0-alpha -- 2022-10-08 18:18:50 UTC --; --- Page ID 171 -> 3__+MAX_llx_website_page__ - Aliases index --; -INSERT INTO llx_website_page(rowid, fk_page, fk_website, pageurl, aliasalt, title, description, lang, image, keywords, status, date_creation, tms, import_key, grabbed_from, type_container, htmlheader, content, author_alias, allowed_in_frames) VALUES(3__+MAX_llx_website_page__, null, __WEBSITE_ID__, 'index', '', 'index', '', '', '', '', '1', '2022-08-09 16:34:54', '2022-10-08 19:28:42', null, '', 'page', '', '__N____N__
__N____N____N__
__N__
__N__
__N__
__N__
__N__
__N__

__N__ Delicious Steaks__N__

__N____N__ __N__ __N__

__N__ 4.7/5__N__

__N____N__
__N__ __N__ __N__ __N__ __N__ __N__
__N__
__N____N__

__N__ From 1,206+ Customer__N__ Reviews__N__

__N__
__N__
__N__
__N____N__
__N__ __N__
__N__
__N__
__N__ __N__
__N____N__
__N__

__N__ Fine Dining Restaurant__N__

__N__
__N__
__N____N__
__N__
__N__ __N__
__N____N__
__N__ __N__

Steak

__N____N__ 26.50__N__
__N____N__ __N__ __N__ 3.8/5__N__ __N____N__
__N__ __N__ __N__ __N__ __N__ __N__
__N__
__N__
__N__
__N____N__
__N__
__N__ __N__
__N____N__
__N__ __N__

__N__ Sausage Pasta__N__

__N____N__ 18.25__N__
__N____N__ __N__ __N__ 4.2/5__N__ __N____N__
__N__ __N__ __N__ __N__ __N__ __N__
__N__
__N__ __N__ __N__ __N____N__ __N__ __N__ Previous__N__ __N____N__ __N__ __N__ Next__N__ __N__ __N__ __N__ __N__ __N____N__
__N__ __N__ __N__ Your browser does not support the video tag.__N__ __N__
__N____N__
__N__
__N____N__
__N__
__N__
__N__
__N__

__N__ Special Menus__N__

__N__
__N____N__
__N__
__N__
__N__ __N____N__ Breakfast__N__
__N____N__ __N__

Morning Fresh

__N____N__ 12.50__N____N__ __N__
__N__ 4.3/5__N__
__N____N__
__N__ __N__ __N__ __N__ __N__ __N__
__N____N__

__N__ 102 Reviews__N__

__N__
__N__
__N__
__N__
__N____N__
__N__
__N__
__N__ __N____N__ Lunch__N__
__N____N__ __N__

DoliCloud Soup

__N____N__ 24.50__N____N__ __N__
__N__ 3/5__N__
__N____N__
__N__ __N__ __N__ __N__ __N__ __N__
__N____N__

__N__ 50 Reviews__N__

__N__
__N__
__N__ __N__ __N____N__
__N__
__N__
__N__ __N____N__ Dinner__N__
__N____N__ __N__

Premium Steak

__N____N__ 45__N____N__ __N__
__N__ 3/5__N__
__N____N__
__N__ __N__ __N__ __N__ __N__ __N__
__N____N__

__N__ 86 Reviews__N__

__N__
__N__
__N__ __N__ __N____N__
__N__
__N__
__N__ __N____N__ Dinner__N__
__N____N__ __N__

Seafood Set

__N____N__ 86__N____N__ __N__
__N__ 3/5__N__
__N____N__
__N__ __N__ __N__ __N__ __N__ __N__
__N____N__

__N__ 44 Reviews__N__

__N__
__N__
__N__ __N__ __N____N__
__N__
__N__
__N__ __N____N__ Breakfast__N__
__N____N__ __N__

Burger Set

__N____N__ 20.50__N____N__ __N__
__N__ 4.3/5__N__
__N____N__
__N__ __N__ __N__ __N__ __N__ __N__
__N____N__

__N__ 102 Reviews__N__

__N__
__N__
__N__ __N__ __N____N__
__N__
__N__
__N__ __N____N__ Lunch__N__
__N____N__ __N__

Healthy Soup

__N____N__ 34.20__N____N__ __N__
__N__ 3/5__N__
__N____N__
__N__ __N__ __N__ __N__ __N__ __N__
__N____N__

__N__ 64 Reviews__N__

__N__
__N__
__N__ __N__ __N__ __N__ __N__
__N__
__N____N__ __N____N__
__N__', '', 0); -UPDATE llx_website SET fk_default_home = 3__+MAX_llx_website_page__ WHERE rowid = __WEBSITE_ID__; --- File generated by Dolibarr 17.0.0-alpha -- 2022-10-08 18:18:50 UTC --; --- Page ID 172 -> 4__+MAX_llx_website_page__ - Aliases menu --; -INSERT INTO llx_website_page(rowid, fk_page, fk_website, pageurl, aliasalt, title, description, lang, image, keywords, status, date_creation, tms, import_key, grabbed_from, type_container, htmlheader, content, author_alias, allowed_in_frames) VALUES(4__+MAX_llx_website_page__, null, __WEBSITE_ID__, 'menu', '', 'Our menus', '', '', '', '', '1', '2022-08-16 14:37:03', '2022-10-08 19:23:06', null, '', 'page', '', '__N__
__N__ __N____N__
__N__
__N__
__N__
__N__
__N__

Our Menus

__N____N__ Perfect for all Breakfast, Lunch and__N__ Dinner__N__
__N__
__N__
__N____N__
__N__
__N____N__
__N__
__N__
__N__
__N__

Breakfast Menu

__N__
__N____N__
__N__
__N__ __N____N__ __N__

Fresh Start

__N____N__ $24.50__N____N__ __N__
__N__ 4.4/5__N__
__N____N__
__N__ __N__ __N__ __N__ __N__ __N__
__N____N__

__N__ 128 Reviews__N__

__N__
__N__
__N__
__N__
__N____N__
__N__
__N__ __N____N__ __N__

Baked Creamy

__N____N__ $16.50__N____N__ __N__
__N__ 3/5__N__
__N____N__
__N__ __N__ __N__ __N__ __N__ __N__
__N____N__

__N__ 64 Reviews__N__

__N__
__N__
__N__ __N__ __N____N__
__N__
__N__ __N____N__ __N__

Burger Set

__N____N__ $24.50__N____N__ $36.50__N____N__ __N__
__N__ 3/5__N__
__N____N__
__N__ __N__ __N__ __N__ __N__ __N__
__N____N__

__N__ 32 Reviews__N__

__N__
__N__
__N__ __N__ __N__ __N__ __N__
__N____N__
__N__
__N__
__N__
__N__

Lunch Menu

__N__
__N____N__
__N__
__N__ __N____N__ __N__

Super Steak Set

__N____N__ $32.75__N____N__ $55__N____N__ __N__
__N__ 4.2/5__N__
__N____N__
__N__ __N__ __N__ __N__ __N__ __N__
__N____N__

__N__ 66 Reviews__N__

__N__
__N__
__N__
__N__
__N____N__
__N__
__N__ __N____N__ __N__

Bread & Steak Set

__N____N__ $42.50__N____N__ __N__
__N__ 3/5__N__
__N____N__
__N__ __N__ __N__ __N__ __N__ __N__
__N____N__

__N__ 84 Reviews__N__

__N__
__N__
__N__ __N__ __N__ __N__ __N__
__N____N__
__N__
__N__
__N__
__N__

Dinner Menu

__N__
__N____N__
__N__
__N__ __N____N__ __N__

Seafood Set

__N____N__ $65.50__N____N__ __N__
__N__ 4.4/5__N__
__N____N__
__N__ __N__ __N__ __N__ __N__ __N__
__N____N__

__N__ 102 Reviews__N__

__N__
__N__
__N__
__N__
__N____N__
__N__
__N__ __N____N__ __N__

Premium Steak

__N____N__ $74.25__N____N__ __N__
__N__ 3/5__N__
__N____N__
__N__ __N__ __N__ __N__ __N__ __N__
__N____N__

__N__ 56 Reviews__N__

__N__
__N__
__N__ __N__ __N____N__
__N__
__N__ __N____N__ __N__

Salmon Set

__N____N__ $60__N____N__ __N__
__N__ 3/5__N__
__N____N__
__N__ __N__ __N__ __N__ __N__ __N__
__N____N__

__N__ 76 Reviews__N__

__N__
__N__
__N__ __N__ __N__ __N__ __N__
__N__
__N____N__ __N____N__
__N__', '', 0); +-- File generated by Dolibarr 17.0.0-beta -- 2022-11-20 14:10:56 UTC --; +-- Page ID 248 -> 1__+MAX_llx_website_page__ - Aliases about --; +INSERT INTO llx_website_page(rowid, fk_page, fk_website, pageurl, aliasalt, title, description, lang, image, keywords, status, date_creation, tms, import_key, grabbed_from, type_container, htmlheader, content, author_alias, allowed_in_frames) VALUES(1__+MAX_llx_website_page__, null, __WEBSITE_ID__, 'about', '', 'About us', '', '', '', '', '1', '2022-08-09 16:40:13', '2022-11-20 14:15:19', null, '', 'page', '', '__N____N____N__
__N__
__N____N__
__N__
__N__
__N____N__
__N__

About Us

__N____N__ Get to know us more__N__
__N____N__
__N__
__N____N__
__N__
__N____N__
__N__
__N__
__N____N__
__N__

Team Members

__N__
__N____N__
__N__
__N__ \"\"__N__ __N__
__N__

Sophia

__N____N__

CEO & Founder

__N__
__N__
__N__
__N____N__
__N__
__N__ \"\"__N____N__

Benjamin W.

__N____N__

Restaurant Manager

__N__
__N__
__N____N__
__N__
__N__ \"\"__N__ __N__

Muchen Jack

__N____N__

Senior Chef

__N__
__N__
__N____N__
__N__
__N__
__N__ __N__
__N____N__
__N____N____N____N____N__', '', 0); +-- File generated by Dolibarr 17.0.0-beta -- 2022-11-20 14:10:56 UTC --; +-- Page ID 249 -> 2__+MAX_llx_website_page__ - Aliases contact --; +INSERT INTO llx_website_page(rowid, fk_page, fk_website, pageurl, aliasalt, title, description, lang, image, keywords, status, date_creation, tms, import_key, grabbed_from, type_container, htmlheader, content, author_alias, allowed_in_frames) VALUES(2__+MAX_llx_website_page__, null, __WEBSITE_ID__, 'contact', '', 'Contact us', '', '', '', '', '1', '2022-08-16 14:40:51', '2022-11-20 14:50:10', null, '', 'page', '', '__N__email;__N__ $message = GETPOST(\'message\', \'alpha\');__N__ $cmail = new CMailFile(\'Contact from website\', $to, $from, $message);__N__ if ($cmail->sendfile()) {__N__ ?>__N__ __N__ trans(\"ErrorFailedToSendMail\", $from, $to).\'. \'.$cmail->error;__N__ }__N__}__N__?>__N____N____N____N____N__
__N__
__N__
__N__
__N__
__N__
__N__

Say Hi

__N____N__ We are happy to get in touch with you__N__
__N__
__N__
__N____N__
__N__
__N____N__
__N__ __N__
__N__
__N__
__N__
__N__

Leave a message

__N__
__N____N__
__N__ __N__ __N__ \">__N__ __N__
__N__
__N____N__
__N__ trans(\"Phone\"); ?>__N____N__ __N__
__N____N__
__N__ trans(\"Email\"); ?>__N____N__ __N____N__ trans(\"Message\"); ?>__N____N__ __N__
__N____N__
__N__ __N__
__N__ __N__
__N____N__
__N__
Weekdays
__N____N__
__N__ $day : \" .getDolGlobalString(\"MAIN_INFO_OPENINGHOURS_$day\") .\"

\"; __N__ }__N__ ?>__N__
__N____N__
Weekends
__N____N__
__N__

Saturday and Sunday

__N____N__

to be determined !

__N__
__N__
__N____N__
__N__

__N__ __N__

__N__ getFullAddress() ?>__N__

__N____N__ __N__
__N__
__N__ __N__
__N__
__N__
__N__
__N__
__N__
__N____N____N__ __N__ __N__ __N__
__N__
__N__
__N__

Reserve a table

__N____N__ __N__
__N____N__ __N__
__N__ __N__ \" />__N__ __N__
__N__
__N____N__
__N__
__N____N__
__N__
__N____N__
__N__
__N____N__
__N__
__N____N__
__N__
__N____N__
__N__
__N____N__
__N__ __N__
__N__ __N__
__N__
__N____N__
__N__
__N__ __N__ __N____N__
__N____N____N____N____N__', '', 0); +-- File generated by Dolibarr 17.0.0-beta -- 2022-11-20 14:10:56 UTC --; +-- Page ID 252 -> 3__+MAX_llx_website_page__ - Aliases footer --; +INSERT INTO llx_website_page(rowid, fk_page, fk_website, pageurl, aliasalt, title, description, lang, image, keywords, status, date_creation, tms, import_key, grabbed_from, type_container, htmlheader, content, author_alias, allowed_in_frames) VALUES(3__+MAX_llx_website_page__, null, __WEBSITE_ID__, 'footer', '', 'Footer', '', '', '', '', '1', '2022-11-20 12:51:50', '2022-11-20 14:07:39', null, '', 'other', '', '__N__
__N__ __N__ __N__
__N__', '', 0); +-- File generated by Dolibarr 17.0.0-beta -- 2022-11-20 14:10:56 UTC --; +-- Page ID 253 -> 4__+MAX_llx_website_page__ - Aliases header --; +INSERT INTO llx_website_page(rowid, fk_page, fk_website, pageurl, aliasalt, title, description, lang, image, keywords, status, date_creation, tms, import_key, grabbed_from, type_container, htmlheader, content, author_alias, allowed_in_frames) VALUES(4__+MAX_llx_website_page__, null, __WEBSITE_ID__, 'header', '', 'Header', '', '', '', '', '1', '2022-11-20 13:12:33', '2022-11-20 14:21:25', null, '', 'menu', '', '
__N__ __N__
__N____N__', '', 0); +-- File generated by Dolibarr 17.0.0-beta -- 2022-11-20 14:10:56 UTC --; +-- Page ID 250 -> 5__+MAX_llx_website_page__ - Aliases index --; +INSERT INTO llx_website_page(rowid, fk_page, fk_website, pageurl, aliasalt, title, description, lang, image, keywords, status, date_creation, tms, import_key, grabbed_from, type_container, htmlheader, content, author_alias, allowed_in_frames) VALUES(5__+MAX_llx_website_page__, null, __WEBSITE_ID__, 'index', '', 'index', '', '', '', '', '1', '2022-08-09 16:34:54', '2022-11-20 15:10:45', null, '', 'page', '', '__N____N____N____N____N__
__N__
__N__
__N__
__N__
__N__
__N__
__N__

__N__ Delicious Steaks__N__

__N____N__
__N__ __N__
__N__ __N__ __N__ __N__ __N__ __N__
__N__
__N__
__N__
__N__
__N____N__
__N__ __N__
__N__
__N__
__N__ __N__
__N____N__
__N__

__N__ Fine Dining Restaurant__N__

__N__
__N__
__N____N__
__N__
__N__ __N__
__N____N__
__N__ __N__

Steak

__N____N__ 26.50__N__
__N__
__N__
__N____N__
__N__
__N__ __N__
__N____N__
__N__ __N__

__N__ Sausage Pasta__N__

__N____N__ 18.25__N__
__N__
__N__
__N__
__N____N__ __N__ __N__ Previous__N__ __N____N__ __N__ __N__ Next__N__ __N__ __N__ __N__ __N__ __N____N__
__N__
__N____N__
__N__
__N__
__N__
__N__

__N__ Special Menus__N__

__N__
__N____N__
__N__
__N__
__N__ __N____N__ Breakfast__N__
__N____N__ __N__

Morning Fresh

__N____N__ 12.50__N____N__ __N__
__N__ __N__ __N__ __N__ __N__ __N__
__N__
__N__
__N__
__N__
__N____N__
__N__
__N__
__N__ __N____N__ Lunch__N__
__N____N__ __N__

DoliCloud Soup

__N____N__ 24.50__N____N__ __N__
__N__ __N__ __N__ __N__ __N__ __N__
__N__
__N__
__N__ __N__ __N____N__
__N__
__N__
__N__ __N____N__ Dinner__N__
__N____N__ __N__

Premium Steak

__N____N__ 45__N____N__ __N__
__N__ __N__ __N__ __N__ __N__ __N__
__N__
__N__
__N__ __N__ __N____N__
__N__
__N__
__N__ __N____N__ Dinner__N__
__N____N__ __N__

Seafood Set

__N____N__ 86__N____N__ __N__
__N__ __N__ __N__ __N__ __N__ __N__
__N__
__N__
__N__ __N__ __N____N__
__N__
__N__
__N__ __N____N__ Breakfast__N__
__N____N__ __N__

Burger Set

__N____N__ 20.50__N____N__ __N__
__N__ __N__ __N__ __N__ __N__ __N__
__N__
__N__
__N__ __N__ __N____N__
__N__
__N__
__N__ __N____N__ Lunch__N__
__N____N__ __N__

Healthy Soup

__N____N__ 34.20__N____N__ __N__
__N__ __N__ __N__ __N__ __N__ __N__
__N__
__N__
__N__ __N__ __N__ __N__ __N__
__N__
__N____N__
__N____N____N____N__', '', 0); +UPDATE llx_website SET fk_default_home = 5__+MAX_llx_website_page__ WHERE rowid = __WEBSITE_ID__; +-- File generated by Dolibarr 17.0.0-beta -- 2022-11-20 14:10:56 UTC --; +-- Page ID 251 -> 6__+MAX_llx_website_page__ - Aliases menu --; +INSERT INTO llx_website_page(rowid, fk_page, fk_website, pageurl, aliasalt, title, description, lang, image, keywords, status, date_creation, tms, import_key, grabbed_from, type_container, htmlheader, content, author_alias, allowed_in_frames) VALUES(6__+MAX_llx_website_page__, null, __WEBSITE_ID__, 'menu', '', 'Our menus', '', '', '', '', '1', '2022-08-16 14:37:03', '2022-11-20 14:30:03', null, '', 'page', '', '__N____N____N____N____N__
__N__
__N__
__N__
__N__
__N__
__N__

Our Menus

__N____N__ Perfect for all Breakfast, Lunch and__N__ Dinner__N__
__N__
__N__
__N____N__
__N__
__N____N__
__N__
__N__
__N__
__N__

Breakfast Menu

__N__
__N____N__
__N__
__N__ __N____N__ __N__

Fresh Start

__N____N__ $24.50__N__
__N__
__N__
__N____N__
__N__
__N__ __N____N__ __N__

Baked Creamy

__N____N__ $16.50__N__
__N__
__N__
__N____N__
__N__
__N__ __N____N__ __N__

Burger Set

__N____N__ $24.50__N____N__ $36.50__N__
__N__
__N__ __N__ __N__ __N__
__N____N__
__N__
__N__
__N__
__N__

Lunch Menu

__N__
__N____N__
__N__
__N__ __N____N__ __N__

Super Steak Set

__N____N__ $32.75__N____N__ $55__N__
__N__
__N__
__N____N__
__N__
__N__ __N____N__ __N__

Bread & Steak Set

__N____N__ $42.50__N__
__N__
__N__
__N__ __N__ __N__
__N____N__
__N__
__N__
__N__
__N__

Dinner Menu

__N__
__N____N__
__N__
__N__ __N____N__ __N__

Seafood Set

__N____N__ $65.50__N__
__N__
__N__
__N____N__
__N__
__N__ __N____N__ __N__

Premium Steak

__N____N__ $74.25__N__
__N__
__N__
__N____N__
__N__
__N__ __N____N__ __N__

Salmon Set

__N____N__ $60__N__
__N__
__N__ __N__ __N__ __N__
__N__
__N____N__
__N____N____N____N__', '', 0); -- For Dolibarr v14+ --; UPDATE llx_website SET lang = 'en' WHERE rowid = __WEBSITE_ID__; diff --git a/htdocs/install/mysql/tables/llx_product.sql b/htdocs/install/mysql/tables/llx_product.sql index 0c2fdce5152..2267113e987 100644 --- a/htdocs/install/mysql/tables/llx_product.sql +++ b/htdocs/install/mysql/tables/llx_product.sql @@ -57,7 +57,7 @@ create table llx_product fk_user_modif integer, -- user making last change tosell tinyint DEFAULT 1, -- Product you sell tobuy tinyint DEFAULT 1, -- Product you buy - onportal tinyint DEFAULT 0, -- If it is a product you sell and you want to sell it on portal (module website must be on) + onportal tinyint DEFAULT 0, -- If it is a product you sell and you want to sell it from internal portal (module 'portal') tobatch tinyint DEFAULT 0 NOT NULL, -- Is it a product that need a batch management (eat-by or lot management) sell_or_eat_by_mandatory tinyint DEFAULT 0 NOT NULL, -- Make sell-by or eat-by date mandatory batch_mask varchar(32) DEFAULT NULL, -- If the product has batch feature, you may want to use a batch mask per product diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index adec92ba029..4a55dc2cffc 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1881,7 +1881,7 @@ SuppliersInvoiceNumberingModel=Vendor invoices numbering models IfSetToYesDontForgetPermission=If set to a non null value, don't forget to provide permissions to groups or users allowed for the second approval ##### GeoIPMaxmind ##### GeoIPMaxmindSetup=GeoIP Maxmind module setup -PathToGeoIPMaxmindCountryDataFile=Path to file containing Maxmind ip to country translation.
Examples:
/usr/local/share/GeoIP/GeoIP.dat
/usr/share/GeoIP/GeoIP.dat
/usr/share/GeoIP/GeoLite2-Country.mmdb +PathToGeoIPMaxmindCountryDataFile=Path to file containing Maxmind ip to country translation NoteOnPathLocation=Note that your ip to country data file must be inside a directory your PHP can read (Check your PHP open_basedir setup and filesystem permissions). YouCanDownloadFreeDatFileTo=You can download a free demo version of the Maxmind GeoIP country file at %s. YouCanDownloadAdvancedDatFileTo=You can also download a more complete version, with updates, of the Maxmind GeoIP country file at %s. diff --git a/htdocs/langs/en_US/website.lang b/htdocs/langs/en_US/website.lang index 874cdc76f28..742e3afff67 100644 --- a/htdocs/langs/en_US/website.lang +++ b/htdocs/langs/en_US/website.lang @@ -153,3 +153,5 @@ PreviousContainer=Previous page/container WebsiteMustBeDisabled=The website must have the status "%s" WebpageMustBeDisabled=The web page must have the status "%s" SetWebsiteOnlineBefore=When website is offline, all pages are offline. Change status of website first. +Booking=Booking +Reservation=Reservation diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 32d442008eb..4b580e7b808 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1484,7 +1484,7 @@ function top_httphead($contenttype = 'text/html', $forcenocache = 0) // Referrer-Policy // Say if we must provide the referrer when we jump onto another web page. - // Default browser are 'strict-origin-when-cross-origin', we want more so we use 'same-origin' so we don't send any referrer when going into another web site + // Default browser are 'strict-origin-when-cross-origin' (only domain is sent on other domain switching), we want more so we use 'same-origin' so browser doesn't send any referrer when going into another web site domain. if (!defined('MAIN_SECURITY_FORCERP')) { $referrerpolicy = getDolGlobalString('MAIN_SECURITY_FORCERP', "same-origin"); diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 95a8e47f009..6f246a0ce96 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -1709,6 +1709,7 @@ select.widthcentpercentminusxx, span.widthcentpercentminusxx:not(.select2-select select.minwidth100imp, select.minwidth100, select.minwidth200, select.minwidth200imp, select.minwidth300 { width: calc(100% - 40px) !important; + min-width: 100px; display: inline-block; } select.widthcentpercentminusxx, span.widthcentpercentminusxx:not(.select2-selection), input.widthcentpercentminusxx { diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index d532f7f475c..c34d49fc7ca 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -151,10 +151,10 @@ class Website extends CommonObject /** * Create object into database * - * @param User $user User that creates - * @param bool $notrigger false=launch triggers after, true=disable triggers + * @param User $user User that creates + * @param bool $notrigger false=launch triggers after, true=disable triggers * - * @return int <0 if KO, Id of created object if OK + * @return int <0 if KO, 0 if already exists, ID of created object if OK */ public function create(User $user, $notrigger = false) { @@ -282,8 +282,11 @@ class Website extends CommonObject // Commit or rollback if ($error) { $this->db->rollback(); - - return -1 * $error; + if ($this->db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') { + return 0; + } else { + return -1 * $error; + } } else { $this->db->commit(); diff --git a/htdocs/website/index.php b/htdocs/website/index.php index a87fce31734..98b5ac49795 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -694,7 +694,10 @@ if ($action == 'addsite' && $usercanedit) { $tmpobject->virtualhost = GETPOST('virtualhost', 'alpha'); $result = $tmpobject->create($user); - if ($result <= 0) { + if ($result == 0) { + $error++; + setEventMessages($langs->trans("ErrorLabelAlreadyExists"), null, 'errors'); + } elseif ($result < 0) { $error++; setEventMessages($tmpobject->error, $tmpobject->errors, 'errors'); } @@ -3678,7 +3681,7 @@ if ($action == 'editcss') { // Manifest.json print ''; $htmlhelp = $langs->trans("Example").' :
'; - $htmlhelp .= dol_htmlentitiesbr($manifestjsoncontentdefault); + $htmlhelp .= ''.dol_htmlentitiesbr($manifestjsoncontentdefault).''; print $form->textwithpicto($langs->trans('WEBSITE_MANIFEST_JSON'), $htmlhelp, 1, 'help', '', 0, 2, 'manifestjsontooltip'); print ''; print $langs->trans("UseManifest").': '.$form->selectyesno('use_manifest', $website->use_manifest, 1).'
'; diff --git a/test/phpunit/Website.class.php b/test/phpunit/Website.class.php new file mode 100644 index 00000000000..50d0c16453d --- /dev/null +++ b/test/phpunit/Website.class.php @@ -0,0 +1,178 @@ + + * + * 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 . + * or see https://www.gnu.org/ + */ + +/** + * \file test/phpunit/WebsiteTest.php + * \ingroup test + * \brief PHPUnit test + * \remarks To run this script as CLI: phpunit filename.php + */ + +global $conf,$user,$langs,$db; +//define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver +//require_once 'PHPUnit/Autoload.php'; + +if (! defined('NOREQUIRESOC')) { + define('NOREQUIRESOC', '1'); +} +if (! defined('NOCSRFCHECK')) { + define('NOCSRFCHECK', '1'); +} +if (! defined('NOTOKENRENEWAL')) { + define('NOTOKENRENEWAL', '1'); +} +if (! defined('NOREQUIREMENU')) { + define('NOREQUIREMENU', '1'); // If there is no menu to show +} +if (! defined('NOREQUIREHTML')) { + define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +} +if (! defined('NOREQUIREAJAX')) { + define('NOREQUIREAJAX', '1'); +} +if (! defined("NOLOGIN")) { + define("NOLOGIN", '1'); // If this page is public (can be called outside logged session) +} +if (! defined("NOSESSION")) { + define("NOSESSION", '1'); +} + +require_once dirname(__FILE__).'/../../htdocs/main.inc.php'; +require_once dirname(__FILE__).'/../../htdocs/core/lib/website.lib.php'; + + +if (empty($user->id)) { + print "Load permissions for admin user nb 1\n"; + $user->fetch(1); + $user->getrights(); +} +$conf->global->MAIN_DISABLE_ALL_MAILS=1; + + +/** + * Class for PHPUnit tests + * + * @backupGlobals disabled + * @backupStaticAttributes enabled + * @remarks backupGlobals must be disabled to have db,conf,user and lang not erased. + */ +class WebsiteTest extends PHPUnit\Framework\TestCase +{ + protected $savconf; + protected $savuser; + protected $savlangs; + protected $savdb; + + /** + * Constructor + * We save global variables into local variables + * + * @return SecurityTest + */ + public function __construct() + { + parent::__construct(); + + //$this->sharedFixture + global $conf,$user,$langs,$db; + $this->savconf=$conf; + $this->savuser=$user; + $this->savlangs=$langs; + $this->savdb=$db; + + print __METHOD__." db->type=".$db->type." user->id=".$user->id; + //print " - db ".$db->db; + print "\n"; + } + + /** + * setUpBeforeClass + * + * @return void + */ + public static function setUpBeforeClass() + { + global $conf,$user,$langs,$db; + $db->begin(); // This is to have all actions inside a transaction even if test launched without suite. + + print __METHOD__."\n"; + } + + /** + * tearDownAfterClass + * + * @return void + */ + public static function tearDownAfterClass() + { + global $conf,$user,$langs,$db; + $db->rollback(); + + print __METHOD__."\n"; + } + + /** + * Init phpunit tests + * + * @return void + */ + protected function setUp() + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + print __METHOD__."\n"; + } + + /** + * End phpunit tests + * + * @return void + */ + protected function tearDown() + { + print __METHOD__."\n"; + } + + + /** + * testGetPagesFromSearchCriterias + * + * @return void + */ + public function testGetPagesFromSearchCriterias() + { + global $db; + + $s = "123') OR 1=1-- \' xxx"; + /* + var_dump($s); + var_dump($db->escapeforlike($s)); + var_dump($db->escape($db->escapeforlike($s))); + */ + + $res = getPagesFromSearchCriterias('page,blogpost', 'meta,content', $s, 2, 'date_creation', 'DESC', 'en'); + //var_dump($res); + print __METHOD__." message=".$res['code']."\n"; + // We must found no line (so code should be KO). If we found somethiing, it means there is a SQL injection of the 1=1 + $this->assertEquals($res['code'], 'KO'); + } +}