From cce67aecf4040d78550075fa5c1b5c4ce1b9a3ba Mon Sep 17 00:00:00 2001 From: Deltik Date: Sun, 29 Apr 2018 04:03:09 -0500 Subject: [PATCH 01/59] Fix plugin upgrade version number mouseover text Fixes: #3109 --- e107_admin/plugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e107_admin/plugin.php b/e107_admin/plugin.php index 6581019ce..fba364e94 100755 --- a/e107_admin/plugin.php +++ b/e107_admin/plugin.php @@ -969,7 +969,7 @@ class plugin_form_ui extends e_admin_form_ui if($var['plugin_version'] != $var['plugin_version_file'] && $var['plugin_installflag']) { - $text .= "" . ADMIN_UPGRADEPLUGIN_ICON . ""; + $text .= "" . ADMIN_UPGRADEPLUGIN_ICON . ""; } if($var['plugin_installflag'] && e_DEBUG == true) From fa08c915a39397441bf605471d1883dea6f8e0f5 Mon Sep 17 00:00:00 2001 From: Nick Liu Date: Mon, 30 Apr 2018 05:50:19 -0500 Subject: [PATCH 02/59] Downloads: Basic support for NGINX secure_link_md5 - NEW: "Protection" section in Downloads >> Preferences - NEW: Basic support for NGINX secure_link_md5 in Downloads plugin - NEW: When configured with a URL protection mode, Downloads will modify the direct download URL and/or the mirror download URL to be compatible with the implemented URL protection Fixes: #3075 --- e107_plugins/download/includes/admin.php | 72 +++++++++++- .../download/includes/shim_http_build_url.php | 104 ++++++++++++++++++ .../languages/English/English_admin.php | 15 ++- e107_plugins/download/plugin.xml | 4 +- e107_plugins/download/request.php | 39 ++++++- 5 files changed, 223 insertions(+), 11 deletions(-) create mode 100644 e107_plugins/download/includes/shim_http_build_url.php diff --git a/e107_plugins/download/includes/admin.php b/e107_plugins/download/includes/admin.php index e992375aa..8cf6abd51 100644 --- a/e107_plugins/download/includes/admin.php +++ b/e107_plugins/download/includes/admin.php @@ -286,7 +286,11 @@ class download_main_admin_ui extends e_admin_ui //required - default column user prefs protected $fieldpref = array('checkboxes', 'download_image', 'download_id', 'download_datestamp', 'download_category', 'download_name', 'download_active', 'download_class', 'fb_order', 'options'); - // + // Security modes + protected $security_options = array( + 'none' => LAN_DL_SECURITY_MODE_NONE, + 'nginx-secure_link_md5' => LAN_DL_SECURITY_MODE_NGINX_SECURELINKMD5 + ); // optional - required only in case of e.g. tables JOIN. This also could be done with custom model (set it in init()) //protected $editQry = "SELECT * FROM #release WHERE release_id = {ID}"; @@ -1149,6 +1153,19 @@ $columnInfo = array( if ($_POST['download_subsub']) $temp['download_subsub'] = '1'; else $temp['download_subsub'] = '0'; if ($_POST['download_incinfo']) $temp['download_incinfo'] = '1'; else $temp['download_incinfo'] = '0'; + + if ($_POST['download_security_mode'] === 'nginx-secure_link_md5') + { + $temp['download_security_mode'] = $_POST['download_security_mode']; + $temp['download_security_expression'] = $_POST['download_security_expression']; + $temp['download_security_link_expiry'] = $_POST['download_security_link_expiry']; + } + else + { + e107::getConfig('core')->removePref('download_security_mode'); + e107::getConfig('core')->removePref('download_security_expression'); + e107::getConfig('core')->removePref('download_security_link_expiry'); + } e107::getConfig('core')->setPref($temp)->save(false); @@ -2115,14 +2132,15 @@ $columnInfo = array( "ASC" => DOWLAN_62, "DESC" => DOWLAN_63 ); - + $text = "
\n @@ -2226,6 +2244,39 @@ $columnInfo = array(
+
+

+ ".LAN_DL_SECURITY_DESCRIPTION." +

+ + + + + + + + + + + + + + + + + + + +
".LAN_DL_SECURITY_MODE."".$frm->select('download_security_mode', $this->security_options, $pref['download_security_mode'])."
".LAN_DL_SECURITY_NGINX_SECURELINKMD5_EXPRESSION." + ".$frm->text('download_security_expression', $pref['download_security_expression'], 1024)." +
".LAN_DL_SECURITY_NGINX_SECURELINKMD5_EXPRESSION_HELP."
+
".LAN_DL_SECURITY_LINK_EXPIRY." + ".$frm->text('download_security_link_expiry', $pref['download_security_link_expiry'], 16, array('pattern' => '\d+'))." +
".LAN_DL_SECURITY_LINK_EXPIRY_HELP."
+
+
+
+
@@ -2246,7 +2297,20 @@ $columnInfo = array( "; - // $ns->tablerender(LAN_DL_OPTIONS, $text); + + e107::js('footer-inline', " + $('#download-security-mode').on('change', function() { + var mode = $(this).val(); + + if (mode == 'nginx-secure_link_md5') { + $('#nginx-secure_link_md5').show('slow'); + return; + } + + $('#nginx-secure_link_md5').hide('slow'); + }); + "); + echo $text; } diff --git a/e107_plugins/download/includes/shim_http_build_url.php b/e107_plugins/download/includes/shim_http_build_url.php new file mode 100644 index 000000000..99b3337a3 --- /dev/null +++ b/e107_plugins/download/includes/shim_http_build_url.php @@ -0,0 +1,104 @@ + + +define("LAN_DL_SECURITY_DESCRIPTION", "Downloads can make use of server-side URL protection features to prevent hotlinking and/or enforce link expiry. " . + "The download server needs to be configured first before setting the options below."); +define("LAN_DL_SECURITY_MODE", "URL protection mode"); +define("LAN_DL_SECURITY_MODE_NONE", "None (Default)"); +define("LAN_DL_SECURITY_MODE_NGINX_SECURELINKMD5", "NGINX secure_link_md5"); +define("LAN_DL_SECURITY_NGINX_SECURELINKMD5_EXPRESSION", + "NGINX secure_link_md5 expression"); +define("LAN_DL_SECURITY_NGINX_SECURELINKMD5_EXPRESSION_HELP", "Same expression as configured on the server"); +define("LAN_DL_SECURITY_LINK_EXPIRY", "Duration of validity in seconds"); +define("LAN_DL_SECURITY_LINK_EXPIRY_HELP", "Number of seconds the download link should last after being generated. " . + "Only effective if the expression supports expiry time. " . + "Defaults to a very long time if this field is left blank."); \ No newline at end of file diff --git a/e107_plugins/download/plugin.xml b/e107_plugins/download/plugin.xml index 08dcdcb01..ece353f73 100755 --- a/e107_plugins/download/plugin.xml +++ b/e107_plugins/download/plugin.xml @@ -1,7 +1,7 @@ - + - This plugin is a fully featured File-download system + This plugin is a fully featured file download system content DOWLAN_CAPTION diff --git a/e107_plugins/download/request.php b/e107_plugins/download/request.php index fecf3c75c..346eae424 100644 --- a/e107_plugins/download/request.php +++ b/e107_plugins/download/request.php @@ -72,7 +72,7 @@ if(strstr(e_QUERY, "mirror")) } $sql->update("download", "download_requested = download_requested + 1, download_mirror = '{$mstr}' WHERE download_id = '".intval($download_id)."'"); $sql->update("download_mirror", "mirror_count = mirror_count + 1 WHERE mirror_id = '".intval($mirror_id)."'"); - header("Location: {$gaddress}"); + header("Location: ".decorate_download_location($gaddress)); exit(); } @@ -189,7 +189,7 @@ if ($type == "file") $sql->update("download", "download_requested = download_requested + 1, download_mirror = '{$mstr}' WHERE download_id = '".intval($download_id)."'"); $sql->update("download_mirror", "mirror_count = mirror_count + 1 WHERE mirror_id = '".intval($mirror_id)."'"); - header("Location: ".$gaddress); + header("Location: ".decorate_download_location($gaddress)); exit(); } @@ -217,7 +217,7 @@ if ($type == "file") if (strstr($download_url, "http://") || strstr($download_url, "ftp://") || strstr($download_url, "https://")) { $download_url = e107::getParser()->parseTemplate($download_url,true); // support for shortcode-driven dynamic URLS. - e107::redirect($download_url); + e107::redirect(decorate_download_location($download_url)); // header("Location: {$download_url}"); exit(); } @@ -435,4 +435,35 @@ function check_download_limits() } } -?> +function decorate_download_location($url) +{ + $pref = e107::getPref(); + if ($pref['download_security_mode'] !== 'nginx-secure_link_md5') + return $url; + $expiry = intval($pref['download_security_link_expiry']); + if ($expiry <= 0) + $expiry = PHP_INT_MAX; + else + $expiry = time() + $expiry; + $url_parts = parse_url($url); + $evaluation = str_replace( + array( + '$secure_link_expires', + '$uri', + '$remote_addr' + ), + array( + $expiry, + $url_parts['path'], + $_SERVER['REMOTE_ADDR'] + ), + $pref['download_security_expression'] + ); + $query_string = $url_parts['query']; + parse_str($query_string, $query_args); + $query_args['md5'] = md5($evaluation); + if (strpos($pref['download_security_expression'], '$secure_link_expires') !== false) + $query_args['expires'] = $expiry; + require_once(__DIR__.'/includes/shim_http_build_url.php'); + return http_build_url($url_parts, array('query' => http_build_query($query_args))); +} \ No newline at end of file From 0d7f7dc543d6c15fbaaf86284e85c796d8f4de8c Mon Sep 17 00:00:00 2001 From: Nick Liu Date: Mon, 30 Apr 2018 06:24:20 -0500 Subject: [PATCH 03/59] Improved: Downloads >> Preferences >> Protection - MOD: Refactored NGINX secure_link_md5 decorator into interface and class in Downloads plugin - NEW: Downloads plugin: Admin preferences UX improvement: Preferences >> Protection now shows the user a list of supported NGINX variables pulled from NginxSecureLinkMd5Decorator --- .../handlers/NginxSecureLinkMd5Decorator.php | 52 +++++++++++++++++++ .../download/handlers/SecureLinkDecorator.php | 6 +++ e107_plugins/download/includes/admin.php | 14 +++++ .../languages/English/English_admin.php | 1 + e107_plugins/download/request.php | 29 ++--------- 5 files changed, 76 insertions(+), 26 deletions(-) create mode 100644 e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php create mode 100644 e107_plugins/download/handlers/SecureLinkDecorator.php diff --git a/e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php b/e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php new file mode 100644 index 000000000..7ce9ffcca --- /dev/null +++ b/e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php @@ -0,0 +1,52 @@ +url = $url; + $this->prefs = $preferences; + } + + public function decorate() + { + $prefs = $this->prefs; + $url = $this->url; + $expiry = intval($prefs['download_security_link_expiry']); + if ($expiry <= 0) + $expiry = PHP_INT_MAX; + else + $expiry = time() + $expiry; + $url_parts = parse_url($url); + $evaluation = str_replace( + self::supported_variables(), + array( + $expiry, + $url_parts['path'], + $_SERVER['REMOTE_ADDR'] + ), + $prefs['download_security_expression'] + ); + $query_string = $url_parts['query']; + parse_str($query_string, $query_args); + $query_args['md5'] = md5($evaluation); + if (strpos($prefs['download_security_expression'], '$secure_link_expires') !== false) + $query_args['expires'] = $expiry; + require_once(__DIR__.'/../includes/shim_http_build_url.php'); + return http_build_url($url_parts, array('query' => http_build_query($query_args))); + } +} \ No newline at end of file diff --git a/e107_plugins/download/handlers/SecureLinkDecorator.php b/e107_plugins/download/handlers/SecureLinkDecorator.php new file mode 100644 index 000000000..0dd48ab93 --- /dev/null +++ b/e107_plugins/download/handlers/SecureLinkDecorator.php @@ -0,0 +1,6 @@ +"; + foreach(NginxSecureLinkMd5Decorator::supported_variables() as $variable) + { + $supported_secure_link_variables_html .= "
  • $variable
  • "; + } + $supported_secure_link_variables_html .= ""; require_once(e_HANDLER."form_handler.php"); $frm = new e_form(true); //enable inner tabindex counter @@ -2263,6 +2271,12 @@ $columnInfo = array(
    diff --git a/e107_plugins/download/languages/English/English_admin.php b/e107_plugins/download/languages/English/English_admin.php index 0a63c15ea..d3a6d1d33 100644 --- a/e107_plugins/download/languages/English/English_admin.php +++ b/e107_plugins/download/languages/English/English_admin.php @@ -235,6 +235,7 @@ define("LAN_DL_SECURITY_DESCRIPTION", "Downloads can make use of server-side URL define("LAN_DL_SECURITY_MODE", "URL protection mode"); define("LAN_DL_SECURITY_MODE_NONE", "None (Default)"); define("LAN_DL_SECURITY_MODE_NGINX_SECURELINKMD5", "NGINX secure_link_md5"); +define("LAN_DL_SECURITY_NGINX_SUPPORTED_VARIABLES_TOGGLE", "Click to toggle list of supported NGINX variables"); define("LAN_DL_SECURITY_NGINX_SECURELINKMD5_EXPRESSION", "NGINX secure_link_md5 expression"); define("LAN_DL_SECURITY_NGINX_SECURELINKMD5_EXPRESSION_HELP", "Same expression as configured on the server"); diff --git a/e107_plugins/download/request.php b/e107_plugins/download/request.php index 346eae424..afe4de188 100644 --- a/e107_plugins/download/request.php +++ b/e107_plugins/download/request.php @@ -440,30 +440,7 @@ function decorate_download_location($url) $pref = e107::getPref(); if ($pref['download_security_mode'] !== 'nginx-secure_link_md5') return $url; - $expiry = intval($pref['download_security_link_expiry']); - if ($expiry <= 0) - $expiry = PHP_INT_MAX; - else - $expiry = time() + $expiry; - $url_parts = parse_url($url); - $evaluation = str_replace( - array( - '$secure_link_expires', - '$uri', - '$remote_addr' - ), - array( - $expiry, - $url_parts['path'], - $_SERVER['REMOTE_ADDR'] - ), - $pref['download_security_expression'] - ); - $query_string = $url_parts['query']; - parse_str($query_string, $query_args); - $query_args['md5'] = md5($evaluation); - if (strpos($pref['download_security_expression'], '$secure_link_expires') !== false) - $query_args['expires'] = $expiry; - require_once(__DIR__.'/includes/shim_http_build_url.php'); - return http_build_url($url_parts, array('query' => http_build_query($query_args))); + require_once(__DIR__."/handlers/NginxSecureLinkMd5Decorator.php"); + $decorator = new NginxSecureLinkMd5Decorator($url, $pref); + return $decorator->decorate(); } \ No newline at end of file From e36b029f7851cc852c113b0ba80d76774a101b03 Mon Sep 17 00:00:00 2001 From: Nick Liu Date: Tue, 1 May 2018 05:26:40 -0500 Subject: [PATCH 04/59] Fixed Downloads security NGINX MD5 generation - FIX: Blocker bug generating the wrong MD5 string for NGINX secure_link_md5 - FIX: Bad instructions in LAN_DL_SECURITY_DESCRIPTION --- e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php | 2 +- e107_plugins/download/languages/English/English_admin.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php b/e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php index 7ce9ffcca..603ce55f2 100644 --- a/e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php +++ b/e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php @@ -43,7 +43,7 @@ class NginxSecureLinkMd5Decorator implements SecureLinkDecorator ); $query_string = $url_parts['query']; parse_str($query_string, $query_args); - $query_args['md5'] = md5($evaluation); + $query_args['md5'] = str_replace(array('+', '/', '='), array('-', '_', ''), base64_encode(md5($evaluation, true))); if (strpos($prefs['download_security_expression'], '$secure_link_expires') !== false) $query_args['expires'] = $expiry; require_once(__DIR__.'/../includes/shim_http_build_url.php'); diff --git a/e107_plugins/download/languages/English/English_admin.php b/e107_plugins/download/languages/English/English_admin.php index d3a6d1d33..a59d794dc 100644 --- a/e107_plugins/download/languages/English/English_admin.php +++ b/e107_plugins/download/languages/English/English_admin.php @@ -231,7 +231,7 @@ define("DOWLAN_HELP_10", "Help for upload options"); // define("DOWLAN_CAPTION", "Configure Download"); define("LAN_DL_SECURITY_DESCRIPTION", "Downloads can make use of server-side URL protection features to prevent hotlinking and/or enforce link expiry. " . - "The download server needs to be configured first before setting the options below."); + "This section should be configured before the download server is configured to reduce the chance of disruption to downloaders."); define("LAN_DL_SECURITY_MODE", "URL protection mode"); define("LAN_DL_SECURITY_MODE_NONE", "None (Default)"); define("LAN_DL_SECURITY_MODE_NGINX_SECURELINKMD5", "NGINX secure_link_md5"); From 4af400fd75edf280e1490d2ecc41023348acc6a1 Mon Sep 17 00:00:00 2001 From: Nick Liu Date: Tue, 1 May 2018 06:51:23 -0500 Subject: [PATCH 05/59] Refactored some Downloads plugin code --- .../handlers/NginxSecureLinkMd5Decorator.php | 2 +- e107_plugins/download/includes/admin.php | 79 ++++++++++--------- .../shim_http_build_url.php | 0 3 files changed, 43 insertions(+), 38 deletions(-) rename e107_plugins/download/{includes => vendor}/shim_http_build_url.php (100%) diff --git a/e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php b/e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php index 603ce55f2..7e36cbace 100644 --- a/e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php +++ b/e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php @@ -46,7 +46,7 @@ class NginxSecureLinkMd5Decorator implements SecureLinkDecorator $query_args['md5'] = str_replace(array('+', '/', '='), array('-', '_', ''), base64_encode(md5($evaluation, true))); if (strpos($prefs['download_security_expression'], '$secure_link_expires') !== false) $query_args['expires'] = $expiry; - require_once(__DIR__.'/../includes/shim_http_build_url.php'); + require_once(__DIR__ . '/../vendor/shim_http_build_url.php'); return http_build_url($url_parts, array('query' => http_build_query($query_args))); } } \ No newline at end of file diff --git a/e107_plugins/download/includes/admin.php b/e107_plugins/download/includes/admin.php index 54b0e2abc..d8548109e 100644 --- a/e107_plugins/download/includes/admin.php +++ b/e107_plugins/download/includes/admin.php @@ -1137,31 +1137,28 @@ $columnInfo = array( global $admin_log,$pref; $tp = e107::getParser(); + + $expected_params = array( + 'download_php', 'download_view', 'download_sort', 'download_order', + 'mirror_order', 'recent_download_days', 'agree_flag', 'download_email', + 'agree_text', 'download_denied', 'download_reportbroken', + 'download_security_mode', 'download_security_expression', 'download_security_link_expiry' + ); $temp = array(); - $temp['download_php'] = $_POST['download_php']; - $temp['download_view'] = $_POST['download_view']; - $temp['download_sort'] = $_POST['download_sort']; - $temp['download_order'] = $_POST['download_order']; - $temp['mirror_order'] = $_POST['mirror_order']; - $temp['recent_download_days'] = $_POST['recent_download_days']; - $temp['agree_flag'] = $_POST['agree_flag']; - $temp['download_email'] = $_POST['download_email']; - $temp['agree_text'] = $tp->toDB($_POST['agree_text']); - $temp['download_denied'] = $tp->toDB($_POST['download_denied']); - $temp['download_reportbroken'] = $_POST['download_reportbroken']; - - if ($_POST['download_subsub']) $temp['download_subsub'] = '1'; else $temp['download_subsub'] = '0'; - if ($_POST['download_incinfo']) $temp['download_incinfo'] = '1'; else $temp['download_incinfo'] = '0'; - - if ($_POST['download_security_mode'] === 'nginx-secure_link_md5') + foreach($expected_params as $expected_param) { - $temp['download_security_mode'] = $_POST['download_security_mode']; - $temp['download_security_expression'] = $_POST['download_security_expression']; - $temp['download_security_link_expiry'] = $_POST['download_security_link_expiry']; + $temp[$expected_param] = $_POST[$expected_param]; } - else + + $temp['download_subsub'] = $_POST['download_subsub'] ? '1' : '0'; + $temp['download_incinfo'] = $_POST['download_incinfo'] ? '1' : '0'; + + if ($_POST['download_security_mode'] !== 'nginx-secure_link_md5') { + unset($temp['download_security_mode']); + unset($temp['download_security_expression']); + unset($temp['download_security_link_expiry']); e107::getConfig('core')->removePref('download_security_mode'); e107::getConfig('core')->removePref('download_security_expression'); e107::getConfig('core')->removePref('download_security_link_expiry'); @@ -2110,22 +2107,33 @@ $columnInfo = array( } } + private function supported_secure_link_variables_html() + { + require_once(__DIR__."/../handlers/NginxSecureLinkMd5Decorator.php"); + $supported_secure_link_variables_html = "
      "; + foreach(NginxSecureLinkMd5Decorator::supported_variables() as $variable) + { + $supported_secure_link_variables_html .= "
    • $variable
    • "; + } + $supported_secure_link_variables_html .= "
    "; + return $supported_secure_link_variables_html; + } + + private function mirror_order_options_html($pref) + { + return ($pref['mirror_order'] == "0" ? "" : ""). + ($pref['mirror_order'] == "1" ? "" : ""). + ($pref['mirror_order'] == "2" ? "" : ""); + } + function show_download_options() { global $pref, $ns; - require_once(__DIR__."/../handlers/NginxSecureLinkMd5Decorator.php"); - $supported_secure_link_variables_html = "
      "; - foreach(NginxSecureLinkMd5Decorator::supported_variables() as $variable) - { - $supported_secure_link_variables_html .= "
    • $variable
    • "; - } - $supported_secure_link_variables_html .= "
    "; - - require_once(e_HANDLER."form_handler.php"); - $frm = new e_form(true); //enable inner tabindex counter - - $agree_flag = $pref['agree_flag']; + require_once(e_HANDLER."form_handler.php"); + $frm = new e_form(true); //enable inner tabindex counter + + $agree_flag = $pref['agree_flag']; $agree_text = $pref['agree_text']; $c = $pref['download_php'] ? " checked = 'checked' " : ""; $sacc = (varset($pref['download_incinfo'],0) == '1') ? " checked = 'checked' " : ""; @@ -2196,10 +2204,7 @@ $columnInfo = array(
    @@ -2275,7 +2280,7 @@ $columnInfo = array( ".LAN_DL_SECURITY_NGINX_SUPPORTED_VARIABLES_TOGGLE." diff --git a/e107_plugins/download/includes/shim_http_build_url.php b/e107_plugins/download/vendor/shim_http_build_url.php similarity index 100% rename from e107_plugins/download/includes/shim_http_build_url.php rename to e107_plugins/download/vendor/shim_http_build_url.php From beb2b1c0f6b46cb5e55e0b4bfcafb362955428df Mon Sep 17 00:00:00 2001 From: Nick Liu Date: Tue, 1 May 2018 08:18:15 -0500 Subject: [PATCH 06/59] Updated .codeclimate.yml for CodeClimate version 2 --- .codeclimate.yml | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/.codeclimate.yml b/.codeclimate.yml index 72d1a0307..fe51f29f1 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -1,5 +1,6 @@ --- -engines: +version: "2" +plugins: csslint: enabled: false duplication: @@ -36,20 +37,25 @@ engines: config: file_extensions: "php" rulesets: "cleancode,unusedcode,codesize" -ratings: - paths: - - "**.css" - - "**.js" - - "**.php" -exclude_paths: -- e107_admin/core_image.php -- e107_plugins/log/js/awesomechart.js -- e107_docs/**/* -- e107_images/**/* -- e107_handlers/hybridauth/**/* -- e107_handlers/jsshrink/**/* -- e107_handlers/phpmailer/**/* -- e107_handlers/phpthumb/**/* -- e107_handlers/xmlrpc/**/* -- e107_web/**/* - +exclude_patterns: +- "config/" +- "db/" +- "dist/" +- "features/" +- "**/node_modules/" +- "script/" +- "**/spec/" +- "**/test/" +- "**/tests/" +- "**/vendor/" +- "**/*.d.ts" +- "e107_admin/core_image.php" +- "e107_plugins/log/js/awesomechart.js" +- "e107_docs/**/*" +- "e107_images/**/*" +- "e107_handlers/hybridauth/**/*" +- "e107_handlers/jsshrink/**/*" +- "e107_handlers/phpmailer/**/*" +- "e107_handlers/phpthumb/**/*" +- "e107_handlers/xmlrpc/**/*" +- "e107_web/**/*" From 2a1a6d41181b308a037ccf8a8f915183c2563e5b Mon Sep 17 00:00:00 2001 From: Achim Ennenbach Date: Tue, 1 May 2018 23:29:50 +0200 Subject: [PATCH 07/59] closes e107inc/e107#3113 parses a string into a db ready number format value returned works also with floatval() --- e107_handlers/model_class.php | 43 ++++++++++++++++++++++++----------- e107_handlers/mysql_class.php | 42 +++++++++++++++++++++++++++------- 2 files changed, 64 insertions(+), 21 deletions(-) diff --git a/e107_handlers/model_class.php b/e107_handlers/model_class.php index 8d716382f..4573a12f2 100755 --- a/e107_handlers/model_class.php +++ b/e107_handlers/model_class.php @@ -1792,20 +1792,37 @@ class e_model extends e_object * @param string $value * @return integer|float */ - public function toNumber($value) - { - $larr = localeconv(); - $search = array( - $larr['decimal_point'], - $larr['mon_decimal_point'], - $larr['thousands_sep'], - $larr['mon_thousands_sep'], - $larr['currency_symbol'], - $larr['int_curr_symbol'] - ); - $replace = array('.', '.', '', '', '', ''); + // public function toNumber($value) + // { + // $larr = localeconv(); + // $search = array( + // $larr['decimal_point'], + // $larr['mon_decimal_point'], + // $larr['thousands_sep'], + // $larr['mon_thousands_sep'], + // $larr['currency_symbol'], + // $larr['int_curr_symbol'] + // ); + // $replace = array('.', '.', '', '', '', ''); - return str_replace($search, $replace, $value); + // return str_replace($search, $replace, $value); + // } + public function toNumber($value) + { + // adapted from: https://secure.php.net/manual/en/function.floatval.php#114486 + $dotPos = strrpos($value, '.'); + $commaPos = strrpos($value, ','); + $sep = (($dotPos > $commaPos) && $dotPos) ? $dotPos : + ((($commaPos > $dotPos) && $commaPos) ? $commaPos : false); + + if (!$sep) { + return preg_replace("/[^-0-9]/", "", $value); + } + + return ( + preg_replace("/[^-0-9]/", "", substr($value, 0, $sep)) . '.' . + preg_replace("/[^0-9]/", "", substr($value, $sep+1, strlen($value))) + ); } /** diff --git a/e107_handlers/mysql_class.php b/e107_handlers/mysql_class.php index c2a7d91f0..352fb8244 100644 --- a/e107_handlers/mysql_class.php +++ b/e107_handlers/mysql_class.php @@ -1301,11 +1301,13 @@ class e_db_mysql case 'float': // fix - convert localized float numbers - $larr = localeconv(); - $search = array($larr['decimal_point'], $larr['mon_decimal_point'], $larr['thousands_sep'], $larr['mon_thousands_sep'], $larr['currency_symbol'], $larr['int_curr_symbol']); - $replace = array('.', '.', '', '', '', ''); + // $larr = localeconv(); + // $search = array($larr['decimal_point'], $larr['mon_decimal_point'], $larr['thousands_sep'], $larr['mon_thousands_sep'], $larr['currency_symbol'], $larr['int_curr_symbol']); + // $replace = array('.', '.', '', '', '', ''); - return str_replace($search, $replace, floatval($fieldValue)); + // return str_replace($search, $replace, floatval($fieldValue)); + + return $this->_toNumber($fieldValue); break; case 'null': @@ -1360,11 +1362,12 @@ class e_db_mysql case 'float': // fix - convert localized float numbers - $larr = localeconv(); - $search = array($larr['decimal_point'], $larr['mon_decimal_point'], $larr['thousands_sep'], $larr['mon_thousands_sep'], $larr['currency_symbol'], $larr['int_curr_symbol']); - $replace = array('.', '.', '', '', '', ''); + // $larr = localeconv(); + // $search = array($larr['decimal_point'], $larr['mon_decimal_point'], $larr['thousands_sep'], $larr['mon_thousands_sep'], $larr['currency_symbol'], $larr['int_curr_symbol']); + // $replace = array('.', '.', '', '', '', ''); - return str_replace($search, $replace, floatval($fieldValue)); + // return str_replace($search, $replace, floatval($fieldValue)); + return $this->_toNumber($fieldValue); break; case 'null': @@ -1436,6 +1439,29 @@ class e_db_mysql } + /** + * Convert a string to a number (int/float) + * + * @param string $value + * @return int|float + */ + function _toNumber($value) + { + // adapted from: https://secure.php.net/manual/en/function.floatval.php#114486 + $dotPos = strrpos($value, '.'); + $commaPos = strrpos($value, ','); + $sep = (($dotPos > $commaPos) && $dotPos) ? $dotPos : + ((($commaPos > $dotPos) && $commaPos) ? $commaPos : false); + + if (!$sep) { + return preg_replace("/[^-0-9]/", "", $value); + } + + return ( + preg_replace("/[^-0-9]/", "", substr($value, 0, $sep)) . '.' . + preg_replace("/[^0-9]/", "", substr($value, $sep+1, strlen($value))) + ); + } /** From 84fc39228b1dd85defcb2f2d91171a178da08e41 Mon Sep 17 00:00:00 2001 From: Serios Date: Thu, 3 May 2018 10:36:10 +0300 Subject: [PATCH 08/59] Prevent form from multiply submission This change will set var value to true when form is submitted, then if we click submit button again will prevent it from another submission. Adding attribute disabled to form button prevents its name to get trough POST call, thus breaking the logic if we checking for form button submission trough PHP. --- e107_web/js/core/all.jquery.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/e107_web/js/core/all.jquery.js b/e107_web/js/core/all.jquery.js index 18f587ed5..cf4c175ea 100644 --- a/e107_web/js/core/all.jquery.js +++ b/e107_web/js/core/all.jquery.js @@ -351,7 +351,7 @@ var e107 = e107 || {'settings': {}, 'behaviors': {}}; { var $button = $(this); var $form = $button.closest('form'); - + var form_submited = false; var type = $button.data('loading-icon'); if(type === undefined || $form.length === 0) @@ -365,6 +365,10 @@ var e107 = e107 || {'settings': {}, 'behaviors': {}}; return false; } + if (form_submited) { + return false; + } + var caption = ""; caption += "" + $button.text() + ""; @@ -373,6 +377,7 @@ var e107 = e107 || {'settings': {}, 'behaviors': {}}; if($button.attr('data-disable') == 'true') { $button.addClass('disabled'); + form_submited = true; } }); From d01a97816f28a4a5a1c400feb715e890db27301b Mon Sep 17 00:00:00 2001 From: Achim Ennenbach Date: Fri, 4 May 2018 19:27:00 +0200 Subject: [PATCH 09/59] refactoring toNumber() into e_parse class --- e107_handlers/e_parse_class.php | 26 ++++++++++++++++++++++++ e107_handlers/model_class.php | 24 +++++----------------- e107_handlers/mysql_class.php | 29 ++------------------------- e107_handlers/validator_class.php | 33 ++++++++++++++++--------------- 4 files changed, 50 insertions(+), 62 deletions(-) diff --git a/e107_handlers/e_parse_class.php b/e107_handlers/e_parse_class.php index 6beee9b6b..ad25cec31 100644 --- a/e107_handlers/e_parse_class.php +++ b/e107_handlers/e_parse_class.php @@ -2385,6 +2385,32 @@ class e_parse extends e_parser } + /** + * Convert a string to a number (int/float) + * + * @param string $value + * @return int|float + */ + function toNumber($value) + { + // adapted from: https://secure.php.net/manual/en/function.floatval.php#114486 + $dotPos = strrpos($value, '.'); + $commaPos = strrpos($value, ','); + $sep = (($dotPos > $commaPos) && $dotPos) ? $dotPos : + ((($commaPos > $dotPos) && $commaPos) ? $commaPos : false); + + if (!$sep) { + return preg_replace("/[^-0-9]/", "", $value); + } + + return ( + preg_replace("/[^-0-9]/", "", substr($value, 0, $sep)) . '.' . + preg_replace("/[^0-9]/", "", substr($value, $sep+1, strlen($value))) + ); + } + + + /** * Clean and Encode Ampersands '&' for output to browser. * @param string $text diff --git a/e107_handlers/model_class.php b/e107_handlers/model_class.php index 4573a12f2..986a8f0a4 100755 --- a/e107_handlers/model_class.php +++ b/e107_handlers/model_class.php @@ -1792,6 +1792,7 @@ class e_model extends e_object * @param string $value * @return integer|float */ + // moved to e_parse // public function toNumber($value) // { // $larr = localeconv(); @@ -1807,23 +1808,6 @@ class e_model extends e_object // return str_replace($search, $replace, $value); // } - public function toNumber($value) - { - // adapted from: https://secure.php.net/manual/en/function.floatval.php#114486 - $dotPos = strrpos($value, '.'); - $commaPos = strrpos($value, ','); - $sep = (($dotPos > $commaPos) && $dotPos) ? $dotPos : - ((($commaPos > $dotPos) && $commaPos) ? $commaPos : false); - - if (!$sep) { - return preg_replace("/[^-0-9]/", "", $value); - } - - return ( - preg_replace("/[^-0-9]/", "", substr($value, 0, $sep)) . '.' . - preg_replace("/[^0-9]/", "", substr($value, $sep+1, strlen($value))) - ); - } /** * Convert object data to a string @@ -2721,7 +2705,8 @@ class e_front_model extends e_model { case 'int': case 'integer': - return intval($this->toNumber($value)); + //return intval($this->toNumber($value)); + return intval($tp->toNumber($value)); break; case 'safestr': @@ -2748,7 +2733,8 @@ class e_front_model extends e_model break; case 'float': - return $this->toNumber($value); + // return $this->toNumber($value); + return $tp->toNumber($value); break; case 'bool': diff --git a/e107_handlers/mysql_class.php b/e107_handlers/mysql_class.php index 352fb8244..13177476b 100644 --- a/e107_handlers/mysql_class.php +++ b/e107_handlers/mysql_class.php @@ -1307,7 +1307,7 @@ class e_db_mysql // return str_replace($search, $replace, floatval($fieldValue)); - return $this->_toNumber($fieldValue); + return e107::getParser()->toNumber($fieldValue); break; case 'null': @@ -1367,7 +1367,7 @@ class e_db_mysql // $replace = array('.', '.', '', '', '', ''); // return str_replace($search, $replace, floatval($fieldValue)); - return $this->_toNumber($fieldValue); + return e107::getParser()->toNumber($fieldValue); break; case 'null': @@ -1439,31 +1439,6 @@ class e_db_mysql } - /** - * Convert a string to a number (int/float) - * - * @param string $value - * @return int|float - */ - function _toNumber($value) - { - // adapted from: https://secure.php.net/manual/en/function.floatval.php#114486 - $dotPos = strrpos($value, '.'); - $commaPos = strrpos($value, ','); - $sep = (($dotPos > $commaPos) && $dotPos) ? $dotPos : - ((($commaPos > $dotPos) && $commaPos) ? $commaPos : false); - - if (!$sep) { - return preg_replace("/[^-0-9]/", "", $value); - } - - return ( - preg_replace("/[^-0-9]/", "", substr($value, 0, $sep)) . '.' . - preg_replace("/[^0-9]/", "", substr($value, $sep+1, strlen($value))) - ); - } - - /** * @DEPRECATED Similar to db_Update(), but splits the variables and the 'WHERE' clause. diff --git a/e107_handlers/validator_class.php b/e107_handlers/validator_class.php index d000f31b5..b91fe03f2 100644 --- a/e107_handlers/validator_class.php +++ b/e107_handlers/validator_class.php @@ -577,7 +577,7 @@ class e_validator break; case 'float': - $value = $this->toNumber($value); + $value = e107::getParser()->toNumber($value); if(!is_numeric($value)) { $this->addValidateResult($name, self::ERR_FLOAT_EXPECTED); @@ -728,22 +728,23 @@ class e_validator break; } } - - public function toNumber($value) - { - $larr = localeconv(); - $search = array( - $larr['decimal_point'], - $larr['mon_decimal_point'], - $larr['thousands_sep'], - $larr['mon_thousands_sep'], - $larr['currency_symbol'], - $larr['int_curr_symbol'] - ); - $replace = array('.', '.', '', '', '', ''); + + // moved to e_parse + // public function toNumber($value) + // { + // $larr = localeconv(); + // $search = array( + // $larr['decimal_point'], + // $larr['mon_decimal_point'], + // $larr['thousands_sep'], + // $larr['mon_thousands_sep'], + // $larr['currency_symbol'], + // $larr['int_curr_symbol'] + // ); + // $replace = array('.', '.', '', '', '', ''); - return str_replace($search, $replace, $value); - } + // return str_replace($search, $replace, $value); + // } protected function parseMinMax($string) { From ed360082868d722e48707805bc67a02f65ad0cd2 Mon Sep 17 00:00:00 2001 From: Cameron Date: Fri, 4 May 2018 17:57:43 -0700 Subject: [PATCH 10/59] Non-standard arg_separator.output value fix. --- e107_admin/cpage.php | 2 +- e107_admin/users.php | 2 +- e107_core/shortcodes/batch/admin_shortcodes.php | 2 +- e107_handlers/admin_ui.php | 4 ++-- e107_handlers/e107_class.php | 2 +- e107_handlers/e_parse_class.php | 2 +- e107_handlers/form_handler.php | 2 +- e107_plugins/download/download_shortcodes.php | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/e107_admin/cpage.php b/e107_admin/cpage.php index 2fc69f912..693777190 100644 --- a/e107_admin/cpage.php +++ b/e107_admin/cpage.php @@ -141,7 +141,7 @@ class page_admin_form_ui extends e_admin_form_ui parse_str(str_replace('&', '&', e_QUERY), $query); //FIXME - FIX THIS $query['action'] = 'edit'; $query['id'] = $id; - $query = http_build_query($query); + $query = http_build_query($query,null, '&'); $text = " ".ADMIN_EDIT_ICON.""; diff --git a/e107_admin/users.php b/e107_admin/users.php index dcd17bdff..acb83eaf8 100644 --- a/e107_admin/users.php +++ b/e107_admin/users.php @@ -2938,7 +2938,7 @@ class users_admin_form_ui extends e_admin_form_ui parse_str(str_replace('&', '&', e_QUERY), $query); //FIXME - FIX THIS $query['action'] = 'edit'; $query['id'] = $id; - $query = http_build_query($query); + $query = http_build_query($query, null, '&'); $text = " ".ADMIN_EDIT_ICON.""; diff --git a/e107_core/shortcodes/batch/admin_shortcodes.php b/e107_core/shortcodes/batch/admin_shortcodes.php index ead1b419a..878e5bfa5 100644 --- a/e107_core/shortcodes/batch/admin_shortcodes.php +++ b/e107_core/shortcodes/batch/admin_shortcodes.php @@ -2276,7 +2276,7 @@ Inverse 10 10 $get = $_GET; $get['elan'] = $code; - $qry = http_build_query($get); + $qry = http_build_query($get, null, '&'); $link = e_REQUEST_SELF.'?'.$qry; } diff --git a/e107_handlers/admin_ui.php b/e107_handlers/admin_ui.php index 4e78309ca..425da2e45 100755 --- a/e107_handlers/admin_ui.php +++ b/e107_handlers/admin_ui.php @@ -6680,7 +6680,7 @@ class e_admin_form_ui extends e_form $vars = $this->getController()->getQuery(); $vars['from'] = '[FROM]'; - $paginate = http_build_query($vars); + $paginate = http_build_query($vars, null, '&'); return $this->pagination(e_REQUEST_SELF.'?'.$paginate,$totalRecords,$fromPage,$perPage,array('template'=>'basic')); @@ -6744,7 +6744,7 @@ class e_admin_form_ui extends e_form $gridAction = $this->getController()->getAction() === 'grid' ? 'list' : 'grid'; $gridQuery = (array) $_GET; $gridQuery['action'] = $gridAction; - $toggleUrl = e_REQUEST_SELF."?".http_build_query($gridQuery); + $toggleUrl = e_REQUEST_SELF."?".http_build_query($gridQuery, null, '&'); $gridIcon = ($gridAction === 'grid') ? ADMIN_GRID_ICON : ADMIN_LIST_ICON; $gridTitle = ($gridAction === 'grid') ? LAN_UI_VIEW_GRID_LABEL : LAN_UI_VIEW_LIST_LABEL; $gridToggle = "".$gridIcon.""; diff --git a/e107_handlers/e107_class.php b/e107_handlers/e107_class.php index eaef7ed63..49113de2b 100755 --- a/e107_handlers/e107_class.php +++ b/e107_handlers/e107_class.php @@ -3788,7 +3788,7 @@ class e107 // setup some php options self::ini_set('magic_quotes_runtime', 0); self::ini_set('magic_quotes_sybase', 0); - self::ini_set('arg_separator.output', '&'); + // self::ini_set('arg_separator.output', '&'); // non-standard and bad for third-party script compatibility. @see https://github.com/e107inc/e107/issues/3116 self::ini_set('session.use_only_cookies', 1); self::ini_set('session.use_trans_sid', 0); self::ini_set('session.cookie_httponly', 1); // cookie won't be accessible by scripting languages, such as JavaScript. Can effectively help to reduce identity theft through XSS attacks diff --git a/e107_handlers/e_parse_class.php b/e107_handlers/e_parse_class.php index ad25cec31..b4c3b8512 100644 --- a/e107_handlers/e_parse_class.php +++ b/e107_handlers/e_parse_class.php @@ -4660,7 +4660,7 @@ class e_parser $ytpref['cc_lang_pref'] = e_LAN; // switch captions with chosen user language. } - $ytqry = http_build_query($ytpref); + $ytqry = http_build_query($ytpref, null, '&'); $defClass = (deftrue('BOOTSTRAP')) ? "embed-responsive embed-responsive-16by9" : "video-responsive"; // levacy backup. diff --git a/e107_handlers/form_handler.php b/e107_handlers/form_handler.php index a3c267c7b..47439ede9 100644 --- a/e107_handlers/form_handler.php +++ b/e107_handlers/form_handler.php @@ -4221,7 +4221,7 @@ class e_form $eModalCap = ""; } - $query = http_build_query($query); + $query = http_build_query($query, null, '&'); $value .= " ".$editIconDefault.""; } diff --git a/e107_plugins/download/download_shortcodes.php b/e107_plugins/download/download_shortcodes.php index d8a6ea43d..f197855b8 100644 --- a/e107_plugins/download/download_shortcodes.php +++ b/e107_plugins/download/download_shortcodes.php @@ -291,7 +291,7 @@ class download_shortcodes extends e_shortcode } - return "".$text."" ; + return "".$text."" ; } From f48927041d5e1d80c21e6611045c28edcde1d459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor?= Date: Tue, 8 May 2018 06:31:24 +0200 Subject: [PATCH 11/59] Update userposts.php --- userposts.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/userposts.php b/userposts.php index 7613d4b26..f95ae64f6 100644 --- a/userposts.php +++ b/userposts.php @@ -70,7 +70,8 @@ if ($action == "comments") $sql2 = e107::getDb('sql2'); if($user_name) { - $ccaption = UP_LAN_1.$user_name; + // $ccaption = UP_LAN_1.$user_name; + $ccaption = str_replace('[x]', $user_name, UP_LAN_1); /*$sql->db_Select("user", "user_comments", "user_id=".$id); $row = $sql->db_Fetch(); $ctotal = $row['user_comments'];*/ @@ -159,7 +160,8 @@ elseif ($action == 'forums') exit; } - $fcaption = UP_LAN_0.' '.$user_name; +// $fcaption = UP_LAN_0.' '.$user_name; + $fcaption = str_replace('[x]', $user_name, UP_LAN_0); /* if (!$USERPOSTS_FORUM_TABLE) { @@ -312,4 +314,4 @@ function parse_userposts_comments_table($row, $template) return e107::getParser()->simpleParse($template, $vars); } -?> \ No newline at end of file +?> From 01ad6fe896492fa6add94382e011420a0678aae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor?= Date: Tue, 8 May 2018 06:33:44 +0200 Subject: [PATCH 12/59] Update lan_userposts.php --- e107_languages/English/lan_userposts.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/e107_languages/English/lan_userposts.php b/e107_languages/English/lan_userposts.php index c23fc6037..d598e0adb 100644 --- a/e107_languages/English/lan_userposts.php +++ b/e107_languages/English/lan_userposts.php @@ -11,8 +11,8 @@ */ define("PAGE_NAME", "User Posts"); -define("UP_LAN_0", "All Forum Posts for "); -define("UP_LAN_1", "All Comments for "); +define("UP_LAN_0", "All Forum Posts for [x]"); +define("UP_LAN_1", "All Comments for [x]"); define("UP_LAN_2", "Thread"); define("UP_LAN_3", "Views"); define("UP_LAN_4", "Replies"); @@ -28,4 +28,4 @@ define("UP_LAN_12", "Search"); define("UP_LAN_14", "Forum Posts"); define("UP_LAN_15", "Re"); define("UP_LAN_16", "IP Address"); -?> \ No newline at end of file +?> From 7b13e891eefdbb445af68d3c3ad188fe6cd98713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor?= Date: Tue, 8 May 2018 08:22:12 +0200 Subject: [PATCH 13/59] Update lan_error.php --- e107_languages/English/lan_error.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/e107_languages/English/lan_error.php b/e107_languages/English/lan_error.php index b7e1e5d53..5d52e8470 100644 --- a/e107_languages/English/lan_error.php +++ b/e107_languages/English/lan_error.php @@ -64,4 +64,8 @@ define("LAN_ERROR_44", "Site logo"); define("LAN_ERROR_45", "What can you do now?"); define("LAN_ERROR_46", "Check log for details."); +define("LAN_ERROR_47", "Validation error: News title can\'t be empty!"); +define("LAN_ERROR_48", "Validation error: News SEF URL value is required field and can\'t be empty!"); +define("LAN_ERROR_49", "Validation error: News SEF URL is unique field - current value already in use! Please choose another SEF URL value."); +define("LAN_ERROR_50", "Validation error: News category can\'t be empty!"); ?> From 1109854538bb10df7987d7e67117935b581319a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor?= Date: Tue, 8 May 2018 08:26:17 +0200 Subject: [PATCH 14/59] Update news_class.php --- e107_handlers/news_class.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/e107_handlers/news_class.php b/e107_handlers/news_class.php index 68e4d7df3..43781be88 100644 --- a/e107_handlers/news_class.php +++ b/e107_handlers/news_class.php @@ -49,7 +49,8 @@ class news { if(empty($news['news_title'])) { $error = true; - $emessage->add('Validation error: News title can\'t be empty!', E_MESSAGE_ERROR, $smessages); + $message = LAN_ERROR_47; + $emessage->add(LAN_ERROR_47, E_MESSAGE_ERROR, $smessages); if(!empty($news['news_sef'])) { $news['news_sef'] = eHelper::secureSef($news['news_sef']); @@ -72,18 +73,21 @@ class news { if(empty($news['news_sef'])) { $error = true; - $emessage->add('Validation error: News SEF URL value is required field and can\'t be empty!', E_MESSAGE_ERROR, $smessages); + $message = LAN_ERROR_48; + $emessage->add(LAN_ERROR_48, E_MESSAGE_ERROR, $smessages); } elseif($sql->db_Count('news', '(news_id)', ($news['news_sef'] ? 'news_id<>'.intval($news['news_id']).' AND ' : '')."news_sef='".$tp->toDB($news['news_sef'])."'")) { $error = true; - $emessage->add('Validation error: News SEF URL is unique field - current value already in use! Please choose another SEF URL value.', E_MESSAGE_ERROR, $smessages); + $message = LAN_ERROR_49; + $emessage->add(LAN_ERROR_49, E_MESSAGE_ERROR, $smessages); } if(empty($news['news_category'])) { $error = true; - $emessage->add('Validation error: News category can\'t be empty!', E_MESSAGE_ERROR, $smessages); + $message = LAN_ERROR_50; + $emessage->add(LAN_ERROR_50, E_MESSAGE_ERROR, $smessages); } From cbfb476799ff149a47f7215efdbff831379622dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor?= Date: Wed, 9 May 2018 06:19:48 +0200 Subject: [PATCH 15/59] Update lan_error.php --- e107_languages/English/lan_error.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/e107_languages/English/lan_error.php b/e107_languages/English/lan_error.php index 5d52e8470..7ea413f67 100644 --- a/e107_languages/English/lan_error.php +++ b/e107_languages/English/lan_error.php @@ -64,8 +64,8 @@ define("LAN_ERROR_44", "Site logo"); define("LAN_ERROR_45", "What can you do now?"); define("LAN_ERROR_46", "Check log for details."); -define("LAN_ERROR_47", "Validation error: News title can\'t be empty!"); -define("LAN_ERROR_48", "Validation error: News SEF URL value is required field and can\'t be empty!"); +define("LAN_ERROR_47", "Validation error: News title can't be empty!"); +define("LAN_ERROR_48", "Validation error: News SEF URL value is required field and can't be empty!"); define("LAN_ERROR_49", "Validation error: News SEF URL is unique field - current value already in use! Please choose another SEF URL value."); -define("LAN_ERROR_50", "Validation error: News category can\'t be empty!"); +define("LAN_ERROR_50", "Validation error: News category can't be empty!"); ?> From c7c3c49daf58616683039fe06a29ad513ab475fe Mon Sep 17 00:00:00 2001 From: Cameron Date: Wed, 9 May 2018 11:13:05 -0700 Subject: [PATCH 16/59] Support for 'IGNORE' duplicate key on INSERT. --- e107_handlers/mysql_class.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/e107_handlers/mysql_class.php b/e107_handlers/mysql_class.php index 13177476b..5ac5a74bf 100644 --- a/e107_handlers/mysql_class.php +++ b/e107_handlers/mysql_class.php @@ -867,6 +867,7 @@ class e_db_mysql $this->mySQLcurTable = $table; $REPLACE = false; // kill any PHP notices $DUPEKEY_UPDATE = false; + $IGNORE = ''; if(is_array($arg)) { @@ -885,7 +886,12 @@ class e_db_mysql { $DUPEKEY_UPDATE = true; unset($arg['_DUPLICATE_KEY_UPDATE']); + } + if(isset($arg['_IGNORE'])) + { + $IGNORE = ' IGNORE'; + unset($arg['_IGNORE']); } if(!isset($arg['_FIELD_TYPES']) && !isset($arg['data'])) @@ -942,7 +948,7 @@ class e_db_mysql if($REPLACE === false) { - $query = "INSERT INTO `".$this->mySQLPrefix."{$table}` ({$keyList}) VALUES ({$valList})"; + $query = "INSERT".$IGNORE." INTO `".$this->mySQLPrefix."{$table}` ({$keyList}) VALUES ({$valList})"; if($DUPEKEY_UPDATE === true) { From c6c8c1c6d14e16497f9d0e777edcb2b2e7ad61ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor?= Date: Thu, 10 May 2018 09:21:17 +0200 Subject: [PATCH 17/59] Update e_footer.php --- e107_plugins/tinymce4/e_footer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e107_plugins/tinymce4/e_footer.php b/e107_plugins/tinymce4/e_footer.php index 3c131bbd0..3ac55d28a 100644 --- a/e107_plugins/tinymce4/e_footer.php +++ b/e107_plugins/tinymce4/e_footer.php @@ -23,7 +23,7 @@ if((e107::wysiwyg() === true && check_class($pref['post_html'])) || strpos(e_SEL // e107::js('footer', 'https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.5.3/tinymce.min.js'); - e107::js('footer', 'https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.5.8/tinymce.min.js'); + e107::js('footer', 'https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.7.12/tinymce.min.js'); // e107::js('footer', "//cdn.tinymce.com/4/tinymce.min.js"); @@ -180,4 +180,4 @@ if((e107::wysiwyg() === true && check_class($pref['post_html'])) || strpos(e_SEL } -?> \ No newline at end of file +?> From 301cf9bc563fbbc0b0aaea4852fb3bf1b21ea794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor?= Date: Thu, 10 May 2018 09:24:58 +0200 Subject: [PATCH 18/59] Add files via upload --- e107_plugins/tinymce4/langs/en_GB.js | 230 +++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 e107_plugins/tinymce4/langs/en_GB.js diff --git a/e107_plugins/tinymce4/langs/en_GB.js b/e107_plugins/tinymce4/langs/en_GB.js new file mode 100644 index 000000000..0f388fd7b --- /dev/null +++ b/e107_plugins/tinymce4/langs/en_GB.js @@ -0,0 +1,230 @@ +tinymce.addI18n('en_GB',{ +"Cut": "Cut", +"Heading 5": "Heading 5", +"Header 2": "Header 2", +"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.", +"Heading 4": "Heading 4", +"Div": "Div", +"Heading 2": "Heading 2", +"Paste": "Paste", +"Close": "Close", +"Font Family": "Font Family", +"Pre": "Pre", +"Align right": "Align right", +"New document": "New document", +"Blockquote": "Blockquote", +"Numbered list": "Numbered list", +"Heading 1": "Heading 1", +"Headings": "Headings", +"Increase indent": "Increase indent", +"Formats": "Formats", +"Headers": "Headers", +"Select all": "Select all", +"Header 3": "Header 3", +"Blocks": "Blocks", +"Undo": "Undo", +"Strikethrough": "Strike-through", +"Bullet list": "Bullet list", +"Header 1": "Header 1", +"Superscript": "Superscript", +"Clear formatting": "Clear formatting", +"Font Sizes": "Font Sizes", +"Subscript": "Subscript", +"Header 6": "Header 6", +"Redo": "Redo", +"Paragraph": "Paragraph", +"Ok": "Ok", +"Bold": "Bold", +"Code": "Code", +"Italic": "Italic", +"Align center": "Align centre", +"Header 5": "Header 5", +"Heading 6": "Heading 6", +"Heading 3": "Heading 3", +"Decrease indent": "Decrease indent", +"Header 4": "Header 4", +"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.", +"Underline": "Underline", +"Cancel": "Cancel", +"Justify": "Justify", +"Inline": "Inline", +"Copy": "Copy", +"Align left": "Align left", +"Visual aids": "Visual aids", +"Lower Greek": "Lower Greek", +"Square": "Square", +"Default": "Default", +"Lower Alpha": "Lower Alpha", +"Circle": "Circle", +"Disc": "Disc", +"Upper Alpha": "Upper Alpha", +"Upper Roman": "Upper Roman", +"Lower Roman": "Lower Roman", +"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "ID should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.", +"Name": "Name", +"Anchor": "Anchor", +"Id": "ID", +"You have unsaved changes are you sure you want to navigate away?": "You have unsaved changes are you sure you want to navigate away?", +"Restore last draft": "Restore last draft", +"Special character": "Special character", +"Source code": "Source code", +"Language": "Language", +"Insert\/Edit code sample": "Insert\/Edit code sample", +"B": "B", +"R": "R", +"G": "G", +"Color": "Colour", +"Right to left": "Right to left", +"Left to right": "Left to right", +"Emoticons": "Emoticons", +"Robots": "Robots", +"Document properties": "Document properties", +"Title": "Title", +"Keywords": "Keywords", +"Encoding": "Encoding", +"Description": "Description", +"Author": "Author", +"Fullscreen": "Full-screen", +"Horizontal line": "Horizontal line", +"Horizontal space": "Horizontal space", +"Insert\/edit image": "Insert\/edit image", +"General": "General", +"Advanced": "Advanced", +"Source": "Source", +"Border": "Border", +"Constrain proportions": "Constrain proportions", +"Vertical space": "Vertical space", +"Image description": "Image description", +"Style": "Style", +"Dimensions": "Dimensions", +"Insert image": "Insert image", +"Image": "Image", +"Zoom in": "Zoom in", +"Contrast": "Contrast", +"Back": "Back", +"Gamma": "Gamma", +"Flip horizontally": "Flip horizontally", +"Resize": "Resize", +"Sharpen": "Sharpen", +"Zoom out": "Zoom out", +"Image options": "Image options", +"Apply": "Apply", +"Brightness": "Brightness", +"Rotate clockwise": "Rotate clockwise", +"Rotate counterclockwise": "Rotate counterclockwise", +"Edit image": "Edit image", +"Color levels": "Colour levels", +"Crop": "Crop", +"Orientation": "Orientation", +"Flip vertically": "Flip vertically", +"Invert": "Invert", +"Date\/time": "Date\/time", +"Insert date\/time": "Insert date\/time", +"Remove link": "Remove link", +"Url": "URL", +"Text to display": "Text to display", +"Anchors": "Anchors", +"Insert link": "Insert link", +"Link": "Link", +"New window": "New window", +"None": "None", +"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?", +"Paste or type a link": "Paste or type a link", +"Target": "Target", +"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?", +"Insert\/edit link": "Insert\/edit link", +"Insert\/edit video": "Insert\/edit video", +"Media": "Media", +"Alternative source": "Alternative source", +"Paste your embed code below:": "Paste your embed code below:", +"Insert video": "Insert video", +"Poster": "Poster", +"Insert\/edit media": "Insert\/edit media", +"Embed": "Embed", +"Nonbreaking space": "Non-breaking space", +"Page break": "Page break", +"Paste as text": "Paste as text", +"Preview": "Preview", +"Print": "Print", +"Save": "Save", +"Could not find the specified string.": "Could not find the specified string.", +"Replace": "Replace", +"Next": "Next", +"Whole words": "Whole words", +"Find and replace": "Find and replace", +"Replace with": "Replace with", +"Find": "Find", +"Replace all": "Replace all", +"Match case": "Match case", +"Prev": "Prev", +"Spellcheck": "Spell-check", +"Finish": "Finish", +"Ignore all": "Ignore all", +"Ignore": "Ignore", +"Add to Dictionary": "Add to Dictionary", +"Insert row before": "Insert row before", +"Rows": "Rows", +"Height": "Height", +"Paste row after": "Paste row after", +"Alignment": "Alignment", +"Border color": "Border colour", +"Column group": "Column group", +"Row": "Row", +"Insert column before": "Insert column before", +"Split cell": "Split cell", +"Cell padding": "Cell padding", +"Cell spacing": "Cell spacing", +"Row type": "Row type", +"Insert table": "Insert table", +"Body": "Body", +"Caption": "Caption", +"Footer": "Footer", +"Delete row": "Delete row", +"Paste row before": "Paste row before", +"Scope": "Scope", +"Delete table": "Delete table", +"H Align": "H Align", +"Top": "Top", +"Header cell": "Header cell", +"Column": "Column", +"Row group": "Row group", +"Cell": "Cell", +"Middle": "Middle", +"Cell type": "Cell type", +"Copy row": "Copy row", +"Row properties": "Row properties", +"Table properties": "Table properties", +"Bottom": "Bottom", +"V Align": "V Align", +"Header": "Header", +"Right": "Right", +"Insert column after": "Insert column after", +"Cols": "Cols", +"Insert row after": "Insert row after", +"Width": "Width", +"Cell properties": "Cell properties", +"Left": "Left", +"Cut row": "Cut row", +"Delete column": "Delete column", +"Center": "Centre", +"Merge cells": "Merge cells", +"Insert template": "Insert template", +"Templates": "Templates", +"Background color": "Background colour", +"Custom...": "Custom...", +"Custom color": "Custom colour", +"No color": "No colour", +"Text color": "Text colour", +"Table of Contents": "Table of Contents", +"Show blocks": "Show blocks", +"Show invisible characters": "Show invisible characters", +"Words: {0}": "Words: {0}", +"Insert": "Insert", +"File": "File", +"Edit": "Edit", +"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help", +"Tools": "Tools", +"View": "View", +"Table": "Table", +"Format": "Format" +}); \ No newline at end of file From 88de1b38c811fa84e1a986df21725a1ae3de0495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor?= Date: Thu, 10 May 2018 09:25:59 +0200 Subject: [PATCH 19/59] Add files via upload --- .../tinymce4/plugins/bbcode/plugin.js | 212 ++++++++---------- .../tinymce4/plugins/bbcode/plugin.min.js | 2 +- 2 files changed, 96 insertions(+), 118 deletions(-) diff --git a/e107_plugins/tinymce4/plugins/bbcode/plugin.js b/e107_plugins/tinymce4/plugins/bbcode/plugin.js index b3ac04b80..10bb7cb9f 100644 --- a/e107_plugins/tinymce4/plugins/bbcode/plugin.js +++ b/e107_plugins/tinymce4/plugins/bbcode/plugin.js @@ -1,123 +1,101 @@ -/** - * plugin.js - * - * Copyright, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://www.tinymce.com/license - * Contributing: http://www.tinymce.com/contributing - */ +(function () { +var bbcode = (function () { + 'use strict'; -/*global tinymce:true */ + var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); -(function() { - tinymce.create('tinymce.plugins.BBCodePlugin', { - init : function(ed) { - var t = this, dialect = ed.getParam('bbcode_dialect', 'punbb').toLowerCase(); + var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools'); - ed.on('beforeSetContent', function(e) { - e.content = t['_' + dialect + '_bbcode2html'](e.content); - }); + var html2bbcode = function (s) { + s = global$1.trim(s); + var rep = function (re, str) { + s = s.replace(re, str); + }; + rep(/(.*?)<\/a>/gi, '[url=$1]$2[/url]'); + rep(/(.*?)<\/font>/gi, '[code][color=$1]$2[/color][/code]'); + rep(/(.*?)<\/font>/gi, '[quote][color=$1]$2[/color][/quote]'); + rep(/(.*?)<\/font>/gi, '[code][color=$1]$2[/color][/code]'); + rep(/(.*?)<\/font>/gi, '[quote][color=$1]$2[/color][/quote]'); + rep(/(.*?)<\/span>/gi, '[color=$1]$2[/color]'); + rep(/(.*?)<\/font>/gi, '[color=$1]$2[/color]'); + rep(/(.*?)<\/span>/gi, '[size=$1]$2[/size]'); + rep(/(.*?)<\/font>/gi, '$1'); + rep(//gi, '[img]$1[/img]'); + rep(/(.*?)<\/span>/gi, '[code]$1[/code]'); + rep(/(.*?)<\/span>/gi, '[quote]$1[/quote]'); + rep(/(.*?)<\/strong>/gi, '[code][b]$1[/b][/code]'); + rep(/(.*?)<\/strong>/gi, '[quote][b]$1[/b][/quote]'); + rep(/(.*?)<\/em>/gi, '[code][i]$1[/i][/code]'); + rep(/(.*?)<\/em>/gi, '[quote][i]$1[/i][/quote]'); + rep(/(.*?)<\/u>/gi, '[code][u]$1[/u][/code]'); + rep(/(.*?)<\/u>/gi, '[quote][u]$1[/u][/quote]'); + rep(/<\/(strong|b)>/gi, '[/b]'); + rep(/<(strong|b)>/gi, '[b]'); + rep(/<\/(em|i)>/gi, '[/i]'); + rep(/<(em|i)>/gi, '[i]'); + rep(/<\/u>/gi, '[/u]'); + rep(/(.*?)<\/span>/gi, '[u]$1[/u]'); + rep(//gi, '[u]'); + rep(/]*>/gi, '[quote]'); + rep(/<\/blockquote>/gi, '[/quote]'); + rep(/
    /gi, '\n'); + rep(//gi, '\n'); + rep(/
    /gi, '\n'); + rep(/

    /gi, ''); + rep(/<\/p>/gi, '\n'); + rep(/ |\u00a0/gi, ' '); + rep(/"/gi, '"'); + rep(/</gi, '<'); + rep(/>/gi, '>'); + rep(/&/gi, '&'); + return s; + }; + var bbcode2html = function (s) { + s = global$1.trim(s); + var rep = function (re, str) { + s = s.replace(re, str); + }; + rep(/\n/gi, '
    '); + rep(/\[b\]/gi, ''); + rep(/\[\/b\]/gi, ''); + rep(/\[i\]/gi, ''); + rep(/\[\/i\]/gi, ''); + rep(/\[u\]/gi, ''); + rep(/\[\/u\]/gi, ''); + rep(/\[url=([^\]]+)\](.*?)\[\/url\]/gi, '$2'); + rep(/\[url\](.*?)\[\/url\]/gi, '$1'); + rep(/\[img\](.*?)\[\/img\]/gi, ''); + rep(/\[color=(.*?)\](.*?)\[\/color\]/gi, '$2'); + rep(/\[code\](.*?)\[\/code\]/gi, '$1 '); + rep(/\[quote.*?\](.*?)\[\/quote\]/gi, '$1 '); + return s; + }; + var $_36akuw96jgqkwz4e = { + html2bbcode: html2bbcode, + bbcode2html: bbcode2html + }; - ed.on('postProcess', function(e) { - if (e.set) { - e.content = t['_' + dialect + '_bbcode2html'](e.content); - } + global.add('bbcode', function () { + return { + init: function (editor) { + editor.on('beforeSetContent', function (e) { + e.content = $_36akuw96jgqkwz4e.bbcode2html(e.content); + }); + editor.on('postProcess', function (e) { + if (e.set) { + e.content = $_36akuw96jgqkwz4e.bbcode2html(e.content); + } + if (e.get) { + e.content = $_36akuw96jgqkwz4e.html2bbcode(e.content); + } + }); + } + }; + }); + function Plugin () { + } - if (e.get) { - e.content = t['_' + dialect + '_html2bbcode'](e.content); - } - }); - }, + return Plugin; - getInfo: function() { - return { - longname: 'BBCode Plugin', - author: 'Moxiecode Systems AB', - authorurl: 'http://www.tinymce.com', - infourl: 'http://www.tinymce.com/wiki.php/Plugin:bbcode' - }; - }, - - // Private methods - - // HTML -> BBCode in PunBB dialect - _punbb_html2bbcode : function(s) { - s = tinymce.trim(s); - - function rep(re, str) { - s = s.replace(re, str); - } - - // example: to [b] - rep(/(.*?)<\/a>/gi,"[url=$1]$2[/url]"); - rep(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"); - rep(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"); - rep(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"); - rep(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"); - rep(/(.*?)<\/span>/gi,"[color=$1]$2[/color]"); - rep(/(.*?)<\/font>/gi,"[color=$1]$2[/color]"); - rep(/(.*?)<\/span>/gi,"[size=$1]$2[/size]"); - rep(/(.*?)<\/font>/gi,"$1"); - rep(//gi,"[img]$1[/img]"); - rep(/(.*?)<\/span>/gi,"[code]$1[/code]"); - rep(/(.*?)<\/span>/gi,"[quote]$1[/quote]"); - rep(/(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"); - rep(/(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"); - rep(/(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"); - rep(/(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"); - rep(/(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"); - rep(/(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"); - rep(/<\/(strong|b)>/gi,"[/b]"); - rep(/<(strong|b)>/gi,"[b]"); - rep(/<\/(em|i)>/gi,"[/i]"); - rep(/<(em|i)>/gi,"[i]"); - rep(/<\/u>/gi,"[/u]"); - rep(/(.*?)<\/span>/gi,"[u]$1[/u]"); - rep(//gi,"[u]"); - rep(/]*>/gi,"[quote]"); - rep(/<\/blockquote>/gi,"[/quote]"); - rep(/
    /gi,"\n"); - rep(//gi,"\n"); - rep(/
    /gi,"\n"); - rep(/

    /gi,""); - rep(/<\/p>/gi,"\n"); - rep(/ |\u00a0/gi," "); - rep(/"/gi,"\""); - rep(/</gi,"<"); - rep(/>/gi,">"); - rep(/&/gi,"&"); - - return s; - }, - - // BBCode -> HTML from PunBB dialect - _punbb_bbcode2html : function(s) { - s = tinymce.trim(s); - - function rep(re, str) { - s = s.replace(re, str); - } - - // example: [b] to - rep(/\n/gi,"
    "); - rep(/\[b\]/gi,""); - rep(/\[\/b\]/gi,""); - rep(/\[i\]/gi,""); - rep(/\[\/i\]/gi,""); - rep(/\[u\]/gi,""); - rep(/\[\/u\]/gi,""); - rep(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,"$2"); - rep(/\[url\](.*?)\[\/url\]/gi,"$1"); - rep(/\[img\](.*?)\[\/img\]/gi,""); - rep(/\[color=(.*?)\](.*?)\[\/color\]/gi,"$2"); - rep(/\[code\](.*?)\[\/code\]/gi,"$1 "); - rep(/\[quote.*?\](.*?)\[\/quote\]/gi,"$1 "); - - return s; - } - }); - - // Register plugin - tinymce.PluginManager.add('bbcode', tinymce.plugins.BBCodePlugin); -})(); \ No newline at end of file +}()); +})(); diff --git a/e107_plugins/tinymce4/plugins/bbcode/plugin.min.js b/e107_plugins/tinymce4/plugins/bbcode/plugin.min.js index 70a88a7d6..b2b9d701c 100644 --- a/e107_plugins/tinymce4/plugins/bbcode/plugin.min.js +++ b/e107_plugins/tinymce4/plugins/bbcode/plugin.min.js @@ -1 +1 @@ -!function(){tinymce.create("tinymce.plugins.BBCodePlugin",{init:function(e){var t=this,n=e.getParam("bbcode_dialect","punbb").toLowerCase();e.on("beforeSetContent",function(e){e.content=t["_"+n+"_bbcode2html"](e.content)}),e.on("postProcess",function(e){e.set&&(e.content=t["_"+n+"_bbcode2html"](e.content)),e.get&&(e.content=t["_"+n+"_html2bbcode"](e.content))})},getInfo:function(){return{longname:"BBCode Plugin",author:"Moxiecode Systems AB",authorurl:"http://www.tinymce.com",infourl:"http://www.tinymce.com/wiki.php/Plugin:bbcode"}},_punbb_html2bbcode:function(e){function t(t,n){e=e.replace(t,n)}return e=tinymce.trim(e),t(/(.*?)<\/a>/gi,"[url=$1]$2[/url]"),t(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),t(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),t(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),t(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),t(/(.*?)<\/span>/gi,"[color=$1]$2[/color]"),t(/(.*?)<\/font>/gi,"[color=$1]$2[/color]"),t(/(.*?)<\/span>/gi,"[size=$1]$2[/size]"),t(/(.*?)<\/font>/gi,"$1"),t(//gi,"[img]$1[/img]"),t(/(.*?)<\/span>/gi,"[code]$1[/code]"),t(/(.*?)<\/span>/gi,"[quote]$1[/quote]"),t(/(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"),t(/(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"),t(/(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"),t(/(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"),t(/(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"),t(/(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"),t(/<\/(strong|b)>/gi,"[/b]"),t(/<(strong|b)>/gi,"[b]"),t(/<\/(em|i)>/gi,"[/i]"),t(/<(em|i)>/gi,"[i]"),t(/<\/u>/gi,"[/u]"),t(/(.*?)<\/span>/gi,"[u]$1[/u]"),t(//gi,"[u]"),t(/]*>/gi,"[quote]"),t(/<\/blockquote>/gi,"[/quote]"),t(/
    /gi,"\n"),t(//gi,"\n"),t(/
    /gi,"\n"),t(/

    /gi,""),t(/<\/p>/gi,"\n"),t(/ |\u00a0/gi," "),t(/"/gi,'"'),t(/</gi,"<"),t(/>/gi,">"),t(/&/gi,"&"),e},_punbb_bbcode2html:function(e){function t(t,n){e=e.replace(t,n)}return e=tinymce.trim(e),t(/\n/gi,"
    "),t(/\[b\]/gi,""),t(/\[\/b\]/gi,""),t(/\[i\]/gi,""),t(/\[\/i\]/gi,""),t(/\[u\]/gi,""),t(/\[\/u\]/gi,""),t(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'$2'),t(/\[url\](.*?)\[\/url\]/gi,'$1'),t(/\[img\](.*?)\[\/img\]/gi,''),t(/\[color=(.*?)\](.*?)\[\/color\]/gi,'$2'),t(/\[code\](.*?)\[\/code\]/gi,'$1 '),t(/\[quote.*?\](.*?)\[\/quote\]/gi,'$1 '),e}}),tinymce.PluginManager.add("bbcode",tinymce.plugins.BBCodePlugin)}(); \ No newline at end of file +!function(){"use strict";var o=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.util.Tools"),e=function(e){e=t.trim(e);var o=function(o,t){e=e.replace(o,t)};return o(/(.*?)<\/a>/gi,"[url=$1]$2[/url]"),o(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),o(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),o(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),o(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),o(/(.*?)<\/span>/gi,"[color=$1]$2[/color]"),o(/(.*?)<\/font>/gi,"[color=$1]$2[/color]"),o(/(.*?)<\/span>/gi,"[size=$1]$2[/size]"),o(/(.*?)<\/font>/gi,"$1"),o(//gi,"[img]$1[/img]"),o(/(.*?)<\/span>/gi,"[code]$1[/code]"),o(/(.*?)<\/span>/gi,"[quote]$1[/quote]"),o(/(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"),o(/(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"),o(/(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"),o(/(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"),o(/(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"),o(/(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"),o(/<\/(strong|b)>/gi,"[/b]"),o(/<(strong|b)>/gi,"[b]"),o(/<\/(em|i)>/gi,"[/i]"),o(/<(em|i)>/gi,"[i]"),o(/<\/u>/gi,"[/u]"),o(/(.*?)<\/span>/gi,"[u]$1[/u]"),o(//gi,"[u]"),o(/]*>/gi,"[quote]"),o(/<\/blockquote>/gi,"[/quote]"),o(/
    /gi,"\n"),o(//gi,"\n"),o(/
    /gi,"\n"),o(/

    /gi,""),o(/<\/p>/gi,"\n"),o(/ |\u00a0/gi," "),o(/"/gi,'"'),o(/</gi,"<"),o(/>/gi,">"),o(/&/gi,"&"),e},i=function(e){e=t.trim(e);var o=function(o,t){e=e.replace(o,t)};return o(/\n/gi,"
    "),o(/\[b\]/gi,""),o(/\[\/b\]/gi,""),o(/\[i\]/gi,""),o(/\[\/i\]/gi,""),o(/\[u\]/gi,""),o(/\[\/u\]/gi,""),o(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'$2'),o(/\[url\](.*?)\[\/url\]/gi,'$1'),o(/\[img\](.*?)\[\/img\]/gi,''),o(/\[color=(.*?)\](.*?)\[\/color\]/gi,'$2'),o(/\[code\](.*?)\[\/code\]/gi,'$1 '),o(/\[quote.*?\](.*?)\[\/quote\]/gi,'$1 '),e};o.add("bbcode",function(){return{init:function(o){o.on("beforeSetContent",function(o){o.content=i(o.content)}),o.on("postProcess",function(o){o.set&&(o.content=i(o.content)),o.get&&(o.content=e(o.content))})}}})}(); \ No newline at end of file From a7646f0c4b9732c74dc5609279e80a629079956a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor?= Date: Thu, 10 May 2018 09:28:26 +0200 Subject: [PATCH 20/59] Add files via upload --- .../tinymce4/plugins/compat3x/plugin.js | 467 ++++---- .../tinymce4/plugins/compat3x/plugin.min.js | 2 +- .../plugins/compat3x/tiny_mce_popup.js | 1010 ++++++++--------- .../compat3x/utils/editable_selects.js | 96 +- .../plugins/compat3x/utils/form_utils.js | 250 ++-- .../tinymce4/plugins/compat3x/utils/mctabs.js | 224 ++-- .../plugins/compat3x/utils/validate.js | 379 ++++--- 7 files changed, 1243 insertions(+), 1185 deletions(-) diff --git a/e107_plugins/tinymce4/plugins/compat3x/plugin.js b/e107_plugins/tinymce4/plugins/compat3x/plugin.js index 85b2e0578..92d433edc 100644 --- a/e107_plugins/tinymce4/plugins/compat3x/plugin.js +++ b/e107_plugins/tinymce4/plugins/compat3x/plugin.js @@ -1,8 +1,8 @@ /** * plugin.js * - * Copyright, Moxiecode Systems AB * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing @@ -19,279 +19,304 @@ * - No editor.onEvent * - Can't cancel execCommands with beforeExecCommand */ -(function(tinymce) { - var reported; +(function (tinymce) { + var reported; - function noop() { - } + function noop() { + } - function log(apiCall) { - if (!reported && window && window.console) { - reported = true; - console.log("Deprecated TinyMCE API call: " + apiCall); - } - } + function log(apiCall) { + if (!reported && window && window.console) { + reported = true; + console.log("Deprecated TinyMCE API call: " + apiCall); + } + } - function Dispatcher(target, newEventName, argsMap, defaultScope) { - target = target || this; + function Dispatcher(target, newEventName, argsMap, defaultScope) { + target = target || this; + var cbs = []; - if (!newEventName) { - this.add = this.addToTop = this.remove = this.dispatch = noop; - return; - } + if (!newEventName) { + this.add = this.addToTop = this.remove = this.dispatch = noop; + return; + } - this.add = function(callback, scope, prepend) { - log('.on' + newEventName + ".add(..)"); + this.add = function (callback, scope, prepend) { + log('.on' + newEventName + ".add(..)"); - // Convert callback({arg1:x, arg2:x}) -> callback(arg1, arg2) - function patchedEventCallback(e) { - var callbackArgs = []; + // Convert callback({arg1:x, arg2:x}) -> callback(arg1, arg2) + function patchedEventCallback(e) { + var callbackArgs = []; - if (typeof argsMap == "string") { - argsMap = argsMap.split(" "); - } + if (typeof argsMap == "string") { + argsMap = argsMap.split(" "); + } - if (argsMap && typeof argsMap != "function") { - for (var i = 0; i < argsMap.length; i++) { - callbackArgs.push(e[argsMap[i]]); - } - } + if (argsMap && typeof argsMap !== "function") { + for (var i = 0; i < argsMap.length; i++) { + callbackArgs.push(e[argsMap[i]]); + } + } - if (typeof argsMap == "function") { - callbackArgs = argsMap(newEventName, e, target); - if (!callbackArgs) { - return; - } - } + if (typeof argsMap == "function") { + callbackArgs = argsMap(newEventName, e, target); + if (!callbackArgs) { + return; + } + } - if (!argsMap) { - callbackArgs = [e]; - } + if (!argsMap) { + callbackArgs = [e]; + } - callbackArgs.unshift(defaultScope || target); + callbackArgs.unshift(defaultScope || target); - if (callback.apply(scope || defaultScope || target, callbackArgs) === false) { - e.stopImmediatePropagation(); - } - } + if (callback.apply(scope || defaultScope || target, callbackArgs) === false) { + e.stopImmediatePropagation(); + } + } - target.on(newEventName, patchedEventCallback, prepend); + target.on(newEventName, patchedEventCallback, prepend); - return patchedEventCallback; - }; + var handlers = { + original: callback, + patched: patchedEventCallback + }; - this.addToTop = function(callback, scope) { - this.add(callback, scope, true); - }; + cbs.push(handlers); + return patchedEventCallback; + }; - this.remove = function(callback) { - return target.off(newEventName, callback); - }; + this.addToTop = function (callback, scope) { + this.add(callback, scope, true); + }; - this.dispatch = function() { - target.fire(newEventName); + this.remove = function (callback) { + cbs.forEach(function (item, i) { + if (item.original === callback) { + cbs.splice(i, 1); + return target.off(newEventName, item.patched); + } + }); - return true; - }; - } + return target.off(newEventName, callback); + }; - tinymce.util.Dispatcher = Dispatcher; - tinymce.onBeforeUnload = new Dispatcher(tinymce, "BeforeUnload"); - tinymce.onAddEditor = new Dispatcher(tinymce, "AddEditor", "editor"); - tinymce.onRemoveEditor = new Dispatcher(tinymce, "RemoveEditor", "editor"); + this.dispatch = function () { + target.fire(newEventName); + return true; + }; + } - tinymce.util.Cookie = { - get: noop, getHash: noop, remove: noop, set: noop, setHash: noop - }; + tinymce.util.Dispatcher = Dispatcher; + tinymce.onBeforeUnload = new Dispatcher(tinymce, "BeforeUnload"); + tinymce.onAddEditor = new Dispatcher(tinymce, "AddEditor", "editor"); + tinymce.onRemoveEditor = new Dispatcher(tinymce, "RemoveEditor", "editor"); - function patchEditor(editor) { - function patchEditorEvents(oldEventNames, argsMap) { - tinymce.each(oldEventNames.split(" "), function(oldName) { - editor["on" + oldName] = new Dispatcher(editor, oldName, argsMap); - }); - } + tinymce.util.Cookie = { + get: noop, getHash: noop, remove: noop, set: noop, setHash: noop + }; - function convertUndoEventArgs(type, event, target) { - return [ - event.level, - target - ]; - } + function patchEditor(editor) { - function filterSelectionEvents(needsSelection) { - return function(type, e) { - if ((!e.selection && !needsSelection) || e.selection == needsSelection) { - return [e]; - } - }; - } + function translate(str) { + var prefix = editor.settings.language || "en"; + var prefixedStr = [prefix, str].join('.'); + var translatedStr = tinymce.i18n.translate(prefixedStr); - if (editor.controlManager) { - return; - } + return prefixedStr !== translatedStr ? translatedStr : tinymce.i18n.translate(str); + } - function cmNoop() { - var obj = {}, methods = 'add addMenu addSeparator collapse createMenu destroy displayColor expand focus ' + - 'getLength hasMenus hideMenu isActive isCollapsed isDisabled isRendered isSelected mark ' + - 'postRender remove removeAll renderHTML renderMenu renderNode renderTo select selectByIndex ' + - 'setActive setAriaProperty setColor setDisabled setSelected setState showMenu update'; + function patchEditorEvents(oldEventNames, argsMap) { + tinymce.each(oldEventNames.split(" "), function (oldName) { + editor["on" + oldName] = new Dispatcher(editor, oldName, argsMap); + }); + } - log('editor.controlManager.*'); + function convertUndoEventArgs(type, event, target) { + return [ + event.level, + target + ]; + } - function _noop() { - return cmNoop(); - } + function filterSelectionEvents(needsSelection) { + return function (type, e) { + if ((!e.selection && !needsSelection) || e.selection == needsSelection) { + return [e]; + } + }; + } - tinymce.each(methods.split(' '), function(method) { - obj[method] = _noop; - }); + if (editor.controlManager) { + return; + } - return obj; - } + function cmNoop() { + var obj = {}, methods = 'add addMenu addSeparator collapse createMenu destroy displayColor expand focus ' + + 'getLength hasMenus hideMenu isActive isCollapsed isDisabled isRendered isSelected mark ' + + 'postRender remove removeAll renderHTML renderMenu renderNode renderTo select selectByIndex ' + + 'setActive setAriaProperty setColor setDisabled setSelected setState showMenu update'; - editor.controlManager = { - buttons: {}, + log('editor.controlManager.*'); - setDisabled: function(name, state) { - log("controlManager.setDisabled(..)"); + function _noop() { + return cmNoop(); + } - if (this.buttons[name]) { - this.buttons[name].disabled(state); - } - }, + tinymce.each(methods.split(' '), function (method) { + obj[method] = _noop; + }); - setActive: function(name, state) { - log("controlManager.setActive(..)"); + return obj; + } - if (this.buttons[name]) { - this.buttons[name].active(state); - } - }, + editor.controlManager = { + buttons: {}, - onAdd: new Dispatcher(), - onPostRender: new Dispatcher(), + setDisabled: function (name, state) { + log("controlManager.setDisabled(..)"); - add: function(obj) { - return obj; - }, - createButton: cmNoop, - createColorSplitButton: cmNoop, - createControl: cmNoop, - createDropMenu: cmNoop, - createListBox: cmNoop, - createMenuButton: cmNoop, - createSeparator: cmNoop, - createSplitButton: cmNoop, - createToolbar: cmNoop, - createToolbarGroup: cmNoop, - destroy: noop, - get: noop, - setControlType: cmNoop - }; + if (this.buttons[name]) { + this.buttons[name].disabled(state); + } + }, - patchEditorEvents("PreInit BeforeRenderUI PostRender Load Init Remove Activate Deactivate", "editor"); - patchEditorEvents("Click MouseUp MouseDown DblClick KeyDown KeyUp KeyPress ContextMenu Paste Submit Reset"); - patchEditorEvents("BeforeExecCommand ExecCommand", "command ui value args"); // args.terminate not supported - patchEditorEvents("PreProcess PostProcess LoadContent SaveContent Change"); - patchEditorEvents("BeforeSetContent BeforeGetContent SetContent GetContent", filterSelectionEvents(false)); - patchEditorEvents("SetProgressState", "state time"); - patchEditorEvents("VisualAid", "element hasVisual"); - patchEditorEvents("Undo Redo", convertUndoEventArgs); + setActive: function (name, state) { + log("controlManager.setActive(..)"); - patchEditorEvents("NodeChange", function(type, e) { - return [ - editor.controlManager, - e.element, - editor.selection.isCollapsed(), - e - ]; - }); + if (this.buttons[name]) { + this.buttons[name].active(state); + } + }, - var originalAddButton = editor.addButton; - editor.addButton = function(name, settings) { - var originalOnPostRender; + onAdd: new Dispatcher(), + onPostRender: new Dispatcher(), - function patchedPostRender() { - editor.controlManager.buttons[name] = this; + add: function (obj) { + return obj; + }, + createButton: cmNoop, + createColorSplitButton: cmNoop, + createControl: cmNoop, + createDropMenu: cmNoop, + createListBox: cmNoop, + createMenuButton: cmNoop, + createSeparator: cmNoop, + createSplitButton: cmNoop, + createToolbar: cmNoop, + createToolbarGroup: cmNoop, + destroy: noop, + get: noop, + setControlType: cmNoop + }; - if (originalOnPostRender) { - return originalOnPostRender.call(this); - } - } + patchEditorEvents("PreInit BeforeRenderUI PostRender Load Init Remove Activate Deactivate", "editor"); + patchEditorEvents("Click MouseUp MouseDown DblClick KeyDown KeyUp KeyPress ContextMenu Paste Submit Reset"); + patchEditorEvents("BeforeExecCommand ExecCommand", "command ui value args"); // args.terminate not supported + patchEditorEvents("PreProcess PostProcess LoadContent SaveContent Change"); + patchEditorEvents("BeforeSetContent BeforeGetContent SetContent GetContent", filterSelectionEvents(false)); + patchEditorEvents("SetProgressState", "state time"); + patchEditorEvents("VisualAid", "element hasVisual"); + patchEditorEvents("Undo Redo", convertUndoEventArgs); - for (var key in settings) { - if (key.toLowerCase() === "onpostrender") { - originalOnPostRender = settings[key]; - settings.onPostRender = patchedPostRender; - } - } + patchEditorEvents("NodeChange", function (type, e) { + return [ + editor.controlManager, + e.element, + editor.selection.isCollapsed(), + e + ]; + }); - if (!originalOnPostRender) { - settings.onPostRender = patchedPostRender; - } + var originalAddButton = editor.addButton; + editor.addButton = function (name, settings) { + var originalOnPostRender; - if (settings.title) { - settings.title = tinymce.i18n.translate((editor.settings.language || "en") + "." + settings.title); - } + function patchedPostRender() { + editor.controlManager.buttons[name] = this; - return originalAddButton.call(this, name, settings); - }; + if (originalOnPostRender) { + return originalOnPostRender.apply(this, arguments); + } + } - editor.on('init', function() { - var undoManager = editor.undoManager, selection = editor.selection; + for (var key in settings) { + if (key.toLowerCase() === "onpostrender") { + originalOnPostRender = settings[key]; + settings.onPostRender = patchedPostRender; + } + } - undoManager.onUndo = new Dispatcher(editor, "Undo", convertUndoEventArgs, null, undoManager); - undoManager.onRedo = new Dispatcher(editor, "Redo", convertUndoEventArgs, null, undoManager); - undoManager.onBeforeAdd = new Dispatcher(editor, "BeforeAddUndo", null, undoManager); - undoManager.onAdd = new Dispatcher(editor, "AddUndo", null, undoManager); + if (!originalOnPostRender) { + settings.onPostRender = patchedPostRender; + } - selection.onBeforeGetContent = new Dispatcher(editor, "BeforeGetContent", filterSelectionEvents(true), selection); - selection.onGetContent = new Dispatcher(editor, "GetContent", filterSelectionEvents(true), selection); - selection.onBeforeSetContent = new Dispatcher(editor, "BeforeSetContent", filterSelectionEvents(true), selection); - selection.onSetContent = new Dispatcher(editor, "SetContent", filterSelectionEvents(true), selection); - }); + if (settings.title) { + settings.title = translate(settings.title); + } - editor.on('BeforeRenderUI', function() { - var windowManager = editor.windowManager; + return originalAddButton.call(this, name, settings); + }; - windowManager.onOpen = new Dispatcher(); - windowManager.onClose = new Dispatcher(); - windowManager.createInstance = function(className, a, b, c, d, e) { - log("windowManager.createInstance(..)"); + editor.on('init', function () { + var undoManager = editor.undoManager, selection = editor.selection; - var constr = tinymce.resolve(className); - return new constr(a, b, c, d, e); - }; - }); - } + undoManager.onUndo = new Dispatcher(editor, "Undo", convertUndoEventArgs, null, undoManager); + undoManager.onRedo = new Dispatcher(editor, "Redo", convertUndoEventArgs, null, undoManager); + undoManager.onBeforeAdd = new Dispatcher(editor, "BeforeAddUndo", null, undoManager); + undoManager.onAdd = new Dispatcher(editor, "AddUndo", null, undoManager); - tinymce.on('SetupEditor', patchEditor); - tinymce.PluginManager.add("compat3x", patchEditor); + selection.onBeforeGetContent = new Dispatcher(editor, "BeforeGetContent", filterSelectionEvents(true), selection); + selection.onGetContent = new Dispatcher(editor, "GetContent", filterSelectionEvents(true), selection); + selection.onBeforeSetContent = new Dispatcher(editor, "BeforeSetContent", filterSelectionEvents(true), selection); + selection.onSetContent = new Dispatcher(editor, "SetContent", filterSelectionEvents(true), selection); + }); - tinymce.addI18n = function(prefix, o) { - var I18n = tinymce.util.I18n, each = tinymce.each; + editor.on('BeforeRenderUI', function () { + var windowManager = editor.windowManager; - if (typeof prefix == "string" && prefix.indexOf('.') === -1) { - I18n.add(prefix, o); - return; - } + windowManager.onOpen = new Dispatcher(); + windowManager.onClose = new Dispatcher(); + windowManager.createInstance = function (className, a, b, c, d, e) { + log("windowManager.createInstance(..)"); - if (!tinymce.is(prefix, 'string')) { - each(prefix, function(o, lc) { - each(o, function(o, g) { - each(o, function(o, k) { - if (g === 'common') { - I18n.data[lc + '.' + k] = o; - } else { - I18n.data[lc + '.' + g + '.' + k] = o; - } - }); - }); - }); - } else { - each(o, function(o, k) { - I18n.data[prefix + '.' + k] = o; - }); - } - }; + var constr = tinymce.resolve(className); + return new constr(a, b, c, d, e); + }; + }); + } + + tinymce.on('SetupEditor', function (e) { + patchEditor(e.editor); + }); + + tinymce.PluginManager.add("compat3x", patchEditor); + + tinymce.addI18n = function (prefix, o) { + var I18n = tinymce.util.I18n, each = tinymce.each; + + if (typeof prefix == "string" && prefix.indexOf('.') === -1) { + I18n.add(prefix, o); + return; + } + + if (!tinymce.is(prefix, 'string')) { + each(prefix, function (o, lc) { + each(o, function (o, g) { + each(o, function (o, k) { + if (g === 'common') { + I18n.data[lc + '.' + k] = o; + } else { + I18n.data[lc + '.' + g + '.' + k] = o; + } + }); + }); + }); + } else { + each(o, function (o, k) { + I18n.data[prefix + '.' + k] = o; + }); + } + }; })(tinymce); diff --git a/e107_plugins/tinymce4/plugins/compat3x/plugin.min.js b/e107_plugins/tinymce4/plugins/compat3x/plugin.min.js index d9fee4629..8562cb7c7 100644 --- a/e107_plugins/tinymce4/plugins/compat3x/plugin.min.js +++ b/e107_plugins/tinymce4/plugins/compat3x/plugin.min.js @@ -1 +1 @@ -!function(a){function b(){}function c(a){!f&&window&&window.console&&(f=!0,console.log("Deprecated TinyMCE API call: "+a))}function d(a,d,e,f){return a=a||this,d?(this.add=function(b,g,h){function i(c){var h=[];if("string"==typeof e&&(e=e.split(" ")),e&&"function"!=typeof e)for(var i=0;i.on"+d+".add(..)"),a.on(d,i,h),i},this.addToTop=function(a,b){this.add(a,b,!0)},this.remove=function(b){return a.off(d,b)},void(this.dispatch=function(){return a.fire(d),!0})):void(this.add=this.addToTop=this.remove=this.dispatch=b)}function e(e){function f(b,c){a.each(b.split(" "),function(a){e["on"+a]=new d(e,a,c)})}function g(a,b,c){return[b.level,c]}function h(a){return function(b,c){return!c.selection&&!a||c.selection==a?[c]:void 0}}function i(){function b(){return i()}var d={},e="add addMenu addSeparator collapse createMenu destroy displayColor expand focus getLength hasMenus hideMenu isActive isCollapsed isDisabled isRendered isSelected mark postRender remove removeAll renderHTML renderMenu renderNode renderTo select selectByIndex setActive setAriaProperty setColor setDisabled setSelected setState showMenu update";return c("editor.controlManager.*"),a.each(e.split(" "),function(a){d[a]=b}),d}if(!e.controlManager){e.controlManager={buttons:{},setDisabled:function(a,b){c("controlManager.setDisabled(..)"),this.buttons[a]&&this.buttons[a].disabled(b)},setActive:function(a,b){c("controlManager.setActive(..)"),this.buttons[a]&&this.buttons[a].active(b)},onAdd:new d,onPostRender:new d,add:function(a){return a},createButton:i,createColorSplitButton:i,createControl:i,createDropMenu:i,createListBox:i,createMenuButton:i,createSeparator:i,createSplitButton:i,createToolbar:i,createToolbarGroup:i,destroy:b,get:b,setControlType:i},f("PreInit BeforeRenderUI PostRender Load Init Remove Activate Deactivate","editor"),f("Click MouseUp MouseDown DblClick KeyDown KeyUp KeyPress ContextMenu Paste Submit Reset"),f("BeforeExecCommand ExecCommand","command ui value args"),f("PreProcess PostProcess LoadContent SaveContent Change"),f("BeforeSetContent BeforeGetContent SetContent GetContent",h(!1)),f("SetProgressState","state time"),f("VisualAid","element hasVisual"),f("Undo Redo",g),f("NodeChange",function(a,b){return[e.controlManager,b.element,e.selection.isCollapsed(),b]});var j=e.addButton;e.addButton=function(b,c){function d(){return e.controlManager.buttons[b]=this,f?f.call(this):void 0}var f;for(var g in c)"onpostrender"===g.toLowerCase()&&(f=c[g],c.onPostRender=d);return f||(c.onPostRender=d),c.title&&(c.title=a.i18n.translate((e.settings.language||"en")+"."+c.title)),j.call(this,b,c)},e.on("init",function(){var a=e.undoManager,b=e.selection;a.onUndo=new d(e,"Undo",g,null,a),a.onRedo=new d(e,"Redo",g,null,a),a.onBeforeAdd=new d(e,"BeforeAddUndo",null,a),a.onAdd=new d(e,"AddUndo",null,a),b.onBeforeGetContent=new d(e,"BeforeGetContent",h(!0),b),b.onGetContent=new d(e,"GetContent",h(!0),b),b.onBeforeSetContent=new d(e,"BeforeSetContent",h(!0),b),b.onSetContent=new d(e,"SetContent",h(!0),b)}),e.on("BeforeRenderUI",function(){var b=e.windowManager;b.onOpen=new d,b.onClose=new d,b.createInstance=function(b,d,e,f,g,h){c("windowManager.createInstance(..)");var i=a.resolve(b);return new i(d,e,f,g,h)}})}}var f;a.util.Dispatcher=d,a.onBeforeUnload=new d(a,"BeforeUnload"),a.onAddEditor=new d(a,"AddEditor","editor"),a.onRemoveEditor=new d(a,"RemoveEditor","editor"),a.util.Cookie={get:b,getHash:b,remove:b,set:b,setHash:b},a.on("SetupEditor",e),a.PluginManager.add("compat3x",e),a.addI18n=function(b,c){var d=a.util.I18n,e=a.each;return"string"==typeof b&&-1===b.indexOf(".")?void d.add(b,c):void(a.is(b,"string")?e(c,function(a,c){d.data[b+"."+c]=a}):e(b,function(a,b){e(a,function(a,c){e(a,function(a,e){"common"===c?d.data[b+"."+e]=a:d.data[b+"."+c+"."+e]=a})})}))}}(tinymce); \ No newline at end of file +!function(u){var t;function l(){}function f(e){!t&&window&&window.console&&(t=!0,console.log("Deprecated TinyMCE API call: "+e))}function i(i,a,d,s){i=i||this;var c=[];a?(this.add=function(o,r,e){function t(e){var t=[];if("string"==typeof d&&(d=d.split(" ")),d&&"function"!=typeof d)for(var n=0;n.on"+a+".add(..)"),i.on(a,t,e);var n={original:o,patched:t};return c.push(n),t},this.addToTop=function(e,t){this.add(e,t,!0)},this.remove=function(n){return c.forEach(function(e,t){if(e.original===n)return c.splice(t,1),i.off(a,e.patched)}),i.off(a,n)},this.dispatch=function(){return i.fire(a),!0}):this.add=this.addToTop=this.remove=this.dispatch=l}function n(s){function e(e,t){u.each(e.split(" "),function(e){s["on"+e]=new i(s,e,t)})}function n(e,t,n){return[t.level,n]}function o(n){return function(e,t){if(!t.selection&&!n||t.selection==n)return[t]}}if(!s.controlManager){s.controlManager={buttons:{},setDisabled:function(e,t){f("controlManager.setDisabled(..)"),this.buttons[e]&&this.buttons[e].disabled(t)},setActive:function(e,t){f("controlManager.setActive(..)"),this.buttons[e]&&this.buttons[e].active(t)},onAdd:new i,onPostRender:new i,add:function(e){return e},createButton:r,createColorSplitButton:r,createControl:r,createDropMenu:r,createListBox:r,createMenuButton:r,createSeparator:r,createSplitButton:r,createToolbar:r,createToolbarGroup:r,destroy:l,get:l,setControlType:r},e("PreInit BeforeRenderUI PostRender Load Init Remove Activate Deactivate","editor"),e("Click MouseUp MouseDown DblClick KeyDown KeyUp KeyPress ContextMenu Paste Submit Reset"),e("BeforeExecCommand ExecCommand","command ui value args"),e("PreProcess PostProcess LoadContent SaveContent Change"),e("BeforeSetContent BeforeGetContent SetContent GetContent",o(!1)),e("SetProgressState","state time"),e("VisualAid","element hasVisual"),e("Undo Redo",n),e("NodeChange",function(e,t){return[s.controlManager,t.element,s.selection.isCollapsed(),t]});var c=s.addButton;s.addButton=function(e,t){var n,o,r,i;function a(){if(s.controlManager.buttons[e]=this,n)return n.apply(this,arguments)}for(var d in t)"onpostrender"===d.toLowerCase()&&(n=t[d],t.onPostRender=a);return n||(t.onPostRender=a),t.title&&(t.title=(o=t.title,r=[s.settings.language||"en",o].join("."),i=u.i18n.translate(r),r!==i?i:u.i18n.translate(o))),c.call(this,e,t)},s.on("init",function(){var e=s.undoManager,t=s.selection;e.onUndo=new i(s,"Undo",n,null,e),e.onRedo=new i(s,"Redo",n,null,e),e.onBeforeAdd=new i(s,"BeforeAddUndo",null,e),e.onAdd=new i(s,"AddUndo",null,e),t.onBeforeGetContent=new i(s,"BeforeGetContent",o(!0),t),t.onGetContent=new i(s,"GetContent",o(!0),t),t.onBeforeSetContent=new i(s,"BeforeSetContent",o(!0),t),t.onSetContent=new i(s,"SetContent",o(!0),t)}),s.on("BeforeRenderUI",function(){var e=s.windowManager;e.onOpen=new i,e.onClose=new i,e.createInstance=function(e,t,n,o,r,i){return f("windowManager.createInstance(..)"),new(u.resolve(e))(t,n,o,r,i)}})}function r(){var t={};function n(){return r()}return f("editor.controlManager.*"),u.each("add addMenu addSeparator collapse createMenu destroy displayColor expand focus getLength hasMenus hideMenu isActive isCollapsed isDisabled isRendered isSelected mark postRender remove removeAll renderHTML renderMenu renderNode renderTo select selectByIndex setActive setAriaProperty setColor setDisabled setSelected setState showMenu update".split(" "),function(e){t[e]=n}),t}}u.util.Dispatcher=i,u.onBeforeUnload=new i(u,"BeforeUnload"),u.onAddEditor=new i(u,"AddEditor","editor"),u.onRemoveEditor=new i(u,"RemoveEditor","editor"),u.util.Cookie={get:l,getHash:l,remove:l,set:l,setHash:l},u.on("SetupEditor",function(e){n(e.editor)}),u.PluginManager.add("compat3x",n),u.addI18n=function(n,e){var r=u.util.I18n,t=u.each;"string"!=typeof n||-1!==n.indexOf(".")?u.is(n,"string")?t(e,function(e,t){r.data[n+"."+t]=e}):t(n,function(e,o){t(e,function(e,n){t(e,function(e,t){"common"===n?r.data[o+"."+t]=e:r.data[o+"."+n+"."+t]=e})})}):r.add(n,e)}}(tinymce); \ No newline at end of file diff --git a/e107_plugins/tinymce4/plugins/compat3x/tiny_mce_popup.js b/e107_plugins/tinymce4/plugins/compat3x/tiny_mce_popup.js index 733f4397e..92e87effe 100644 --- a/e107_plugins/tinymce4/plugins/compat3x/tiny_mce_popup.js +++ b/e107_plugins/tinymce4/plugins/compat3x/tiny_mce_popup.js @@ -1,8 +1,8 @@ /** - * Popup.js + * tinymce_mce_popup.js * - * Copyright, Moxiecode Systems AB * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing @@ -19,524 +19,524 @@ var tinymce, tinyMCE; * @class tinyMCEPopup */ var tinyMCEPopup = { - /** - * Initializes the popup this will be called automatically. - * - * @method init - */ - init: function() { - var self = this, parentWin, settings, uiWindow; - - // Find window & API - parentWin = self.getWin(); - tinymce = tinyMCE = parentWin.tinymce; - self.editor = tinymce.EditorManager.activeEditor; - self.params = self.editor.windowManager.getParams(); - - uiWindow = self.editor.windowManager.windows[self.editor.windowManager.windows.length - 1]; - self.features = uiWindow.features; - self.uiWindow = uiWindow; - - settings = self.editor.settings; - - // Setup popup CSS path(s) - if (settings.popup_css !== false) { - if (settings.popup_css) { - settings.popup_css = self.editor.documentBaseURI.toAbsolute(settings.popup_css); - } else { - settings.popup_css = self.editor.baseURI.toAbsolute("plugins/compat3x/css/dialog.css"); - } - } - - if (settings.popup_css_add) { - settings.popup_css += ',' + self.editor.documentBaseURI.toAbsolute(settings.popup_css_add); - } - - // Setup local DOM - self.dom = self.editor.windowManager.createInstance('tinymce.dom.DOMUtils', document, { - ownEvents: true, - proxy: tinyMCEPopup._eventProxy - }); - - self.dom.bind(window, 'ready', self._onDOMLoaded, self); - - // Enables you to skip loading the default css - if (self.features.popup_css !== false) { - self.dom.loadCSS(self.features.popup_css || self.editor.settings.popup_css); - } - - // Setup on init listeners - self.listeners = []; - - /** - * Fires when the popup is initialized. - * - * @event onInit - * @param {tinymce.Editor} editor Editor instance. - * @example - * // Alerts the selected contents when the dialog is loaded - * tinyMCEPopup.onInit.add(function(ed) { - * alert(ed.selection.getContent()); - * }); - * - * // Executes the init method on page load in some object using the SomeObject scope - * tinyMCEPopup.onInit.add(SomeObject.init, SomeObject); - */ - self.onInit = { - add: function(func, scope) { - self.listeners.push({func : func, scope : scope}); - } - }; - - self.isWindow = !self.getWindowArg('mce_inline'); - self.id = self.getWindowArg('mce_window_id'); - }, - - /** - * Returns the reference to the parent window that opened the dialog. - * - * @method getWin - * @return {Window} Reference to the parent window that opened the dialog. - */ - getWin: function() { - // Added frameElement check to fix bug: #2817583 - return (!window.frameElement && window.dialogArguments) || opener || parent || top; - }, - - /** - * Returns a window argument/parameter by name. - * - * @method getWindowArg - * @param {String} name Name of the window argument to retrive. - * @param {String} defaultValue Optional default value to return. - * @return {String} Argument value or default value if it wasn't found. - */ - getWindowArg : function(name, defaultValue) { - var value = this.params[name]; - - return tinymce.is(value) ? value : defaultValue; - }, - - /** - * Returns a editor parameter/config option value. - * - * @method getParam - * @param {String} name Name of the editor config option to retrive. - * @param {String} defaultValue Optional default value to return. - * @return {String} Parameter value or default value if it wasn't found. - */ - getParam : function(name, defaultValue) { - return this.editor.getParam(name, defaultValue); - }, - - /** - * Returns a language item by key. - * - * @method getLang - * @param {String} name Language item like mydialog.something. - * @param {String} defaultValue Optional default value to return. - * @return {String} Language value for the item like "my string" or the default value if it wasn't found. - */ - getLang : function(name, defaultValue) { - return this.editor.getLang(name, defaultValue); - }, - - /** - * Executed a command on editor that opened the dialog/popup. - * - * @method execCommand - * @param {String} cmd Command to execute. - * @param {Boolean} ui Optional boolean value if the UI for the command should be presented or not. - * @param {Object} val Optional value to pass with the comman like an URL. - * @param {Object} a Optional arguments object. - */ - execCommand : function(cmd, ui, val, args) { - args = args || {}; - args.skip_focus = 1; - - this.restoreSelection(); - return this.editor.execCommand(cmd, ui, val, args); - }, - - /** - * Resizes the dialog to the inner size of the window. This is needed since various browsers - * have different border sizes on windows. - * - * @method resizeToInnerSize - */ - resizeToInnerSize : function() { - /*var self = this; - - // Detach it to workaround a Chrome specific bug - // https://sourceforge.net/tracker/?func=detail&atid=635682&aid=2926339&group_id=103281 - setTimeout(function() { - var vp = self.dom.getViewPort(window); - - self.editor.windowManager.resizeBy( - self.getWindowArg('mce_width') - vp.w, - self.getWindowArg('mce_height') - vp.h, - self.id || window - ); - }, 10);*/ - }, - - /** - * Will executed the specified string when the page has been loaded. This function - * was added for compatibility with the 2.x branch. - * - * @method executeOnLoad - * @param {String} evil String to evalutate on init. - */ - executeOnLoad : function(evil) { - this.onInit.add(function() { - eval(evil); - }); - }, - - /** - * Stores the current editor selection for later restoration. This can be useful since some browsers - * looses it's selection if a control element is selected/focused inside the dialogs. - * - * @method storeSelection - */ - storeSelection : function() { - this.editor.windowManager.bookmark = tinyMCEPopup.editor.selection.getBookmark(1); - }, - - /** - * Restores any stored selection. This can be useful since some browsers - * looses it's selection if a control element is selected/focused inside the dialogs. - * - * @method restoreSelection - */ - restoreSelection : function() { - var self = tinyMCEPopup; - - if (!self.isWindow && tinymce.isIE) { - self.editor.selection.moveToBookmark(self.editor.windowManager.bookmark); - } - }, - - /** - * Loads a specific dialog language pack. If you pass in plugin_url as a argument - * when you open the window it will load the /langs/_dlg.js lang pack file. - * - * @method requireLangPack - */ - requireLangPack : function() { - var self = this, url = self.getWindowArg('plugin_url') || self.getWindowArg('theme_url'), settings = self.editor.settings, lang; - - if (settings.language !== false) { - lang = settings.language || "en"; - } - - if (url && lang && self.features.translate_i18n !== false && settings.language_load !== false) { - url += '/langs/' + lang + '_dlg.js'; - - if (!tinymce.ScriptLoader.isDone(url)) { - document.write(''); - tinymce.ScriptLoader.markDone(url); - } - } - }, - - /** - * Executes a color picker on the specified element id. When the user - * then selects a color it will be set as the value of the specified element. - * - * @method pickColor - * @param {DOMEvent} e DOM event object. - * @param {string} element_id Element id to be filled with the color value from the picker. - */ - pickColor : function(e, element_id) { - var el = document.getElementById(element_id), colorPickerCallback = this.editor.settings.color_picker_callback; - if (colorPickerCallback) { - colorPickerCallback.call( - this.editor, - function (value) { - el.value = value; - try { - el.onchange(); - } catch (ex) { - // Try fire event, ignore errors - } - }, - el.value - ); - } - }, - - /** - * Opens a filebrowser/imagebrowser this will set the output value from - * the browser as a value on the specified element. - * - * @method openBrowser - * @param {string} element_id Id of the element to set value in. - * @param {string} type Type of browser to open image/file/flash. - * @param {string} option Option name to get the file_broswer_callback function name from. - */ - openBrowser : function(element_id, type) { - tinyMCEPopup.restoreSelection(); - this.editor.execCallback('file_browser_callback', element_id, document.getElementById(element_id).value, type, window); - }, - - /** - * Creates a confirm dialog. Please don't use the blocking behavior of this - * native version use the callback method instead then it can be extended. - * - * @method confirm - * @param {String} t Title for the new confirm dialog. - * @param {function} cb Callback function to be executed after the user has selected ok or cancel. - * @param {Object} s Optional scope to execute the callback in. - */ - confirm : function(t, cb, s) { - this.editor.windowManager.confirm(t, cb, s, window); - }, - - /** - * Creates a alert dialog. Please don't use the blocking behavior of this - * native version use the callback method instead then it can be extended. - * - * @method alert - * @param {String} tx Title for the new alert dialog. - * @param {function} cb Callback function to be executed after the user has selected ok. - * @param {Object} s Optional scope to execute the callback in. - */ - alert : function(tx, cb, s) { - this.editor.windowManager.alert(tx, cb, s, window); - }, - - /** - * Closes the current window. - * - * @method close - */ - close : function() { - var t = this; - - // To avoid domain relaxing issue in Opera - function close() { - t.editor.windowManager.close(window); - tinymce = tinyMCE = t.editor = t.params = t.dom = t.dom.doc = null; // Cleanup - } - - if (tinymce.isOpera) { - t.getWin().setTimeout(close, 0); - } else { - close(); - } - }, - - // Internal functions - - _restoreSelection : function() { - var e = window.event.srcElement; - - if (e.nodeName == 'INPUT' && (e.type == 'submit' || e.type == 'button')) { - tinyMCEPopup.restoreSelection(); - } - }, - -/* _restoreSelection : function() { - var e = window.event.srcElement; - - // If user focus a non text input or textarea - if ((e.nodeName != 'INPUT' && e.nodeName != 'TEXTAREA') || e.type != 'text') - tinyMCEPopup.restoreSelection(); - },*/ - - _onDOMLoaded : function() { - var t = tinyMCEPopup, ti = document.title, h, nv; - - // Translate page - if (t.features.translate_i18n !== false) { - var map = { - "update": "Ok", - "insert": "Ok", - "cancel": "Cancel", - "not_set": "--", - "class_name": "Class name", - "browse": "Browse" - }; - - var langCode = tinymce.settings.language || 'en'; - for (var key in map) { - tinymce.i18n.data[langCode + "." + key] = tinymce.i18n.translate(map[key]); - } - - h = document.body.innerHTML; - - // Replace a=x with a="x" in IE - if (tinymce.isIE) { - h = h.replace(/ (value|title|alt)=([^"][^\s>]+)/gi, ' $1="$2"'); - } - - document.dir = t.editor.getParam('directionality',''); - - if ((nv = t.editor.translate(h)) && nv != h) { - document.body.innerHTML = nv; - } - - if ((nv = t.editor.translate(ti)) && nv != ti) { - document.title = ti = nv; - } - } - - if (!t.editor.getParam('browser_preferred_colors', false) || !t.isWindow) { - t.dom.addClass(document.body, 'forceColors'); - } - - document.body.style.display = ''; - - // Restore selection in IE when focus is placed on a non textarea or input element of the type text - if (tinymce.Env.ie) { - if (tinymce.Env.ie < 11) { - document.attachEvent('onmouseup', tinyMCEPopup._restoreSelection); - - // Add base target element for it since it would fail with modal dialogs - t.dom.add(t.dom.select('head')[0], 'base', {target: '_self'}); - } else { - document.addEventListener('mouseup', tinyMCEPopup._restoreSelection, false); - } - } - - t.restoreSelection(); - t.resizeToInnerSize(); - - // Set inline title - if (!t.isWindow) { - t.editor.windowManager.setTitle(window, ti); - } else { - window.focus(); - } - - if (!tinymce.isIE && !t.isWindow) { - t.dom.bind(document, 'focus', function() { - t.editor.windowManager.focus(t.id); - }); - } - - // Patch for accessibility - tinymce.each(t.dom.select('select'), function(e) { - e.onkeydown = tinyMCEPopup._accessHandler; - }); - - // Call onInit - // Init must be called before focus so the selection won't get lost by the focus call - tinymce.each(t.listeners, function(o) { - o.func.call(o.scope, t.editor); - }); - - // Move focus to window - if (t.getWindowArg('mce_auto_focus', true)) { - window.focus(); - - // Focus element with mceFocus class - tinymce.each(document.forms, function(f) { - tinymce.each(f.elements, function(e) { - if (t.dom.hasClass(e, 'mceFocus') && !e.disabled) { - e.focus(); - return false; // Break loop - } - }); - }); - } - - document.onkeyup = tinyMCEPopup._closeWinKeyHandler; - - if ('textContent' in document) { - t.uiWindow.getEl('head').firstChild.textContent = document.title; - } else { - t.uiWindow.getEl('head').firstChild.innerText = document.title; - } - }, - - _accessHandler : function(e) { - e = e || window.event; - - if (e.keyCode == 13 || e.keyCode == 32) { - var elm = e.target || e.srcElement; - - if (elm.onchange) { - elm.onchange(); - } - - return tinymce.dom.Event.cancel(e); - } - }, - - _closeWinKeyHandler : function(e) { - e = e || window.event; - - if (e.keyCode == 27) { - tinyMCEPopup.close(); - } - }, - - _eventProxy: function(id) { - return function(evt) { - tinyMCEPopup.dom.events.callNativeHandler(id, evt); - }; - } + /** + * Initializes the popup this will be called automatically. + * + * @method init + */ + init: function () { + var self = this, parentWin, settings, uiWindow; + + // Find window & API + parentWin = self.getWin(); + tinymce = tinyMCE = parentWin.tinymce; + self.editor = tinymce.EditorManager.activeEditor; + self.params = self.editor.windowManager.getParams(); + + uiWindow = self.editor.windowManager.windows[self.editor.windowManager.windows.length - 1]; + self.features = uiWindow.features; + self.uiWindow = uiWindow; + + settings = self.editor.settings; + + // Setup popup CSS path(s) + if (settings.popup_css !== false) { + if (settings.popup_css) { + settings.popup_css = self.editor.documentBaseURI.toAbsolute(settings.popup_css); + } else { + settings.popup_css = self.editor.baseURI.toAbsolute("plugins/compat3x/css/dialog.css"); + } + } + + if (settings.popup_css_add) { + settings.popup_css += ',' + self.editor.documentBaseURI.toAbsolute(settings.popup_css_add); + } + + // Setup local DOM + self.dom = self.editor.windowManager.createInstance('tinymce.dom.DOMUtils', document, { + ownEvents: true, + proxy: tinyMCEPopup._eventProxy + }); + + self.dom.bind(window, 'ready', self._onDOMLoaded, self); + + // Enables you to skip loading the default css + if (self.features.popup_css !== false) { + self.dom.loadCSS(self.features.popup_css || self.editor.settings.popup_css); + } + + // Setup on init listeners + self.listeners = []; + + /** + * Fires when the popup is initialized. + * + * @event onInit + * @param {tinymce.Editor} editor Editor instance. + * @example + * // Alerts the selected contents when the dialog is loaded + * tinyMCEPopup.onInit.add(function(ed) { + * alert(ed.selection.getContent()); + * }); + * + * // Executes the init method on page load in some object using the SomeObject scope + * tinyMCEPopup.onInit.add(SomeObject.init, SomeObject); + */ + self.onInit = { + add: function (func, scope) { + self.listeners.push({ func: func, scope: scope }); + } + }; + + self.isWindow = !self.getWindowArg('mce_inline'); + self.id = self.getWindowArg('mce_window_id'); + }, + + /** + * Returns the reference to the parent window that opened the dialog. + * + * @method getWin + * @return {Window} Reference to the parent window that opened the dialog. + */ + getWin: function () { + // Added frameElement check to fix bug: #2817583 + return (!window.frameElement && window.dialogArguments) || opener || parent || top; + }, + + /** + * Returns a window argument/parameter by name. + * + * @method getWindowArg + * @param {String} name Name of the window argument to retrieve. + * @param {String} defaultValue Optional default value to return. + * @return {String} Argument value or default value if it wasn't found. + */ + getWindowArg: function (name, defaultValue) { + var value = this.params[name]; + + return tinymce.is(value) ? value : defaultValue; + }, + + /** + * Returns a editor parameter/config option value. + * + * @method getParam + * @param {String} name Name of the editor config option to retrieve. + * @param {String} defaultValue Optional default value to return. + * @return {String} Parameter value or default value if it wasn't found. + */ + getParam: function (name, defaultValue) { + return this.editor.getParam(name, defaultValue); + }, + + /** + * Returns a language item by key. + * + * @method getLang + * @param {String} name Language item like mydialog.something. + * @param {String} defaultValue Optional default value to return. + * @return {String} Language value for the item like "my string" or the default value if it wasn't found. + */ + getLang: function (name, defaultValue) { + return this.editor.getLang(name, defaultValue); + }, + + /** + * Executed a command on editor that opened the dialog/popup. + * + * @method execCommand + * @param {String} cmd Command to execute. + * @param {Boolean} ui Optional boolean value if the UI for the command should be presented or not. + * @param {Object} val Optional value to pass with the comman like an URL. + * @param {Object} a Optional arguments object. + */ + execCommand: function (cmd, ui, val, args) { + args = args || {}; + args.skip_focus = 1; + + this.restoreSelection(); + return this.editor.execCommand(cmd, ui, val, args); + }, + + /** + * Resizes the dialog to the inner size of the window. This is needed since various browsers + * have different border sizes on windows. + * + * @method resizeToInnerSize + */ + resizeToInnerSize: function () { + /*var self = this; + + // Detach it to workaround a Chrome specific bug + // https://sourceforge.net/tracker/?func=detail&atid=635682&aid=2926339&group_id=103281 + setTimeout(function() { + var vp = self.dom.getViewPort(window); + + self.editor.windowManager.resizeBy( + self.getWindowArg('mce_width') - vp.w, + self.getWindowArg('mce_height') - vp.h, + self.id || window + ); + }, 10);*/ + }, + + /** + * Will executed the specified string when the page has been loaded. This function + * was added for compatibility with the 2.x branch. + * + * @method executeOnLoad + * @param {String} evil String to evalutate on init. + */ + executeOnLoad: function (evil) { + this.onInit.add(function () { + eval(evil); + }); + }, + + /** + * Stores the current editor selection for later restoration. This can be useful since some browsers + * looses it's selection if a control element is selected/focused inside the dialogs. + * + * @method storeSelection + */ + storeSelection: function () { + this.editor.windowManager.bookmark = tinyMCEPopup.editor.selection.getBookmark(1); + }, + + /** + * Restores any stored selection. This can be useful since some browsers + * looses it's selection if a control element is selected/focused inside the dialogs. + * + * @method restoreSelection + */ + restoreSelection: function () { + var self = tinyMCEPopup; + + if (!self.isWindow && tinymce.isIE) { + self.editor.selection.moveToBookmark(self.editor.windowManager.bookmark); + } + }, + + /** + * Loads a specific dialog language pack. If you pass in plugin_url as a argument + * when you open the window it will load the /langs/_dlg.js lang pack file. + * + * @method requireLangPack + */ + requireLangPack: function () { + var self = this, url = self.getWindowArg('plugin_url') || self.getWindowArg('theme_url'), settings = self.editor.settings, lang; + + if (settings.language !== false) { + lang = settings.language || "en"; + } + + if (url && lang && self.features.translate_i18n !== false && settings.language_load !== false) { + url += '/langs/' + lang + '_dlg.js'; + + if (!tinymce.ScriptLoader.isDone(url)) { + document.write(''); + tinymce.ScriptLoader.markDone(url); + } + } + }, + + /** + * Executes a color picker on the specified element id. When the user + * then selects a color it will be set as the value of the specified element. + * + * @method pickColor + * @param {DOMEvent} e DOM event object. + * @param {string} element_id Element id to be filled with the color value from the picker. + */ + pickColor: function (e, element_id) { + var el = document.getElementById(element_id), colorPickerCallback = this.editor.settings.color_picker_callback; + if (colorPickerCallback) { + colorPickerCallback.call( + this.editor, + function (value) { + el.value = value; + try { + el.onchange(); + } catch (ex) { + // Try fire event, ignore errors + } + }, + el.value + ); + } + }, + + /** + * Opens a filebrowser/imagebrowser this will set the output value from + * the browser as a value on the specified element. + * + * @method openBrowser + * @param {string} element_id Id of the element to set value in. + * @param {string} type Type of browser to open image/file/flash. + * @param {string} option Option name to get the file_broswer_callback function name from. + */ + openBrowser: function (element_id, type) { + tinyMCEPopup.restoreSelection(); + this.editor.execCallback('file_browser_callback', element_id, document.getElementById(element_id).value, type, window); + }, + + /** + * Creates a confirm dialog. Please don't use the blocking behavior of this + * native version use the callback method instead then it can be extended. + * + * @method confirm + * @param {String} t Title for the new confirm dialog. + * @param {function} cb Callback function to be executed after the user has selected ok or cancel. + * @param {Object} s Optional scope to execute the callback in. + */ + confirm: function (t, cb, s) { + this.editor.windowManager.confirm(t, cb, s, window); + }, + + /** + * Creates a alert dialog. Please don't use the blocking behavior of this + * native version use the callback method instead then it can be extended. + * + * @method alert + * @param {String} tx Title for the new alert dialog. + * @param {function} cb Callback function to be executed after the user has selected ok. + * @param {Object} s Optional scope to execute the callback in. + */ + alert: function (tx, cb, s) { + this.editor.windowManager.alert(tx, cb, s, window); + }, + + /** + * Closes the current window. + * + * @method close + */ + close: function () { + var t = this; + + // To avoid domain relaxing issue in Opera + function close() { + t.editor.windowManager.close(window); + tinymce = tinyMCE = t.editor = t.params = t.dom = t.dom.doc = null; // Cleanup + } + + if (tinymce.isOpera) { + t.getWin().setTimeout(close, 0); + } else { + close(); + } + }, + + // Internal functions + + _restoreSelection: function () { + var e = window.event.srcElement; + + if (e.nodeName == 'INPUT' && (e.type == 'submit' || e.type == 'button')) { + tinyMCEPopup.restoreSelection(); + } + }, + + /* _restoreSelection : function() { + var e = window.event.srcElement; + + // If user focus a non text input or textarea + if ((e.nodeName != 'INPUT' && e.nodeName != 'TEXTAREA') || e.type != 'text') + tinyMCEPopup.restoreSelection(); + },*/ + + _onDOMLoaded: function () { + var t = tinyMCEPopup, ti = document.title, h, nv; + + // Translate page + if (t.features.translate_i18n !== false) { + var map = { + "update": "Ok", + "insert": "Ok", + "cancel": "Cancel", + "not_set": "--", + "class_name": "Class name", + "browse": "Browse" + }; + + var langCode = (tinymce.settings ? tinymce.settings : t.editor.settings).language || 'en'; + for (var key in map) { + tinymce.i18n.data[langCode + "." + key] = tinymce.i18n.translate(map[key]); + } + + h = document.body.innerHTML; + + // Replace a=x with a="x" in IE + if (tinymce.isIE) { + h = h.replace(/ (value|title|alt)=([^"][^\s>]+)/gi, ' $1="$2"'); + } + + document.dir = t.editor.getParam('directionality', ''); + + if ((nv = t.editor.translate(h)) && nv != h) { + document.body.innerHTML = nv; + } + + if ((nv = t.editor.translate(ti)) && nv != ti) { + document.title = ti = nv; + } + } + + if (!t.editor.getParam('browser_preferred_colors', false) || !t.isWindow) { + t.dom.addClass(document.body, 'forceColors'); + } + + document.body.style.display = ''; + + // Restore selection in IE when focus is placed on a non textarea or input element of the type text + if (tinymce.Env.ie) { + if (tinymce.Env.ie < 11) { + document.attachEvent('onmouseup', tinyMCEPopup._restoreSelection); + + // Add base target element for it since it would fail with modal dialogs + t.dom.add(t.dom.select('head')[0], 'base', { target: '_self' }); + } else { + document.addEventListener('mouseup', tinyMCEPopup._restoreSelection, false); + } + } + + t.restoreSelection(); + t.resizeToInnerSize(); + + // Set inline title + if (!t.isWindow) { + t.editor.windowManager.setTitle(window, ti); + } else { + window.focus(); + } + + if (!tinymce.isIE && !t.isWindow) { + t.dom.bind(document, 'focus', function () { + t.editor.windowManager.focus(t.id); + }); + } + + // Patch for accessibility + tinymce.each(t.dom.select('select'), function (e) { + e.onkeydown = tinyMCEPopup._accessHandler; + }); + + // Call onInit + // Init must be called before focus so the selection won't get lost by the focus call + tinymce.each(t.listeners, function (o) { + o.func.call(o.scope, t.editor); + }); + + // Move focus to window + if (t.getWindowArg('mce_auto_focus', true)) { + window.focus(); + + // Focus element with mceFocus class + tinymce.each(document.forms, function (f) { + tinymce.each(f.elements, function (e) { + if (t.dom.hasClass(e, 'mceFocus') && !e.disabled) { + e.focus(); + return false; // Break loop + } + }); + }); + } + + document.onkeyup = tinyMCEPopup._closeWinKeyHandler; + + if ('textContent' in document) { + t.uiWindow.getEl('head').firstChild.textContent = document.title; + } else { + t.uiWindow.getEl('head').firstChild.innerText = document.title; + } + }, + + _accessHandler: function (e) { + e = e || window.event; + + if (e.keyCode == 13 || e.keyCode == 32) { + var elm = e.target || e.srcElement; + + if (elm.onchange) { + elm.onchange(); + } + + return tinymce.dom.Event.cancel(e); + } + }, + + _closeWinKeyHandler: function (e) { + e = e || window.event; + + if (e.keyCode == 27) { + tinyMCEPopup.close(); + } + }, + + _eventProxy: function (id) { + return function (evt) { + tinyMCEPopup.dom.events.callNativeHandler(id, evt); + }; + } }; tinyMCEPopup.init(); -tinymce.util.Dispatcher = function(scope) { - this.scope = scope || this; - this.listeners = []; +tinymce.util.Dispatcher = function (scope) { + this.scope = scope || this; + this.listeners = []; - this.add = function(callback, scope) { - this.listeners.push({cb : callback, scope : scope || this.scope}); + this.add = function (callback, scope) { + this.listeners.push({ cb: callback, scope: scope || this.scope }); - return callback; - }; + return callback; + }; - this.addToTop = function(callback, scope) { - var self = this, listener = {cb : callback, scope : scope || self.scope}; + this.addToTop = function (callback, scope) { + var self = this, listener = { cb: callback, scope: scope || self.scope }; - // Create new listeners if addToTop is executed in a dispatch loop - if (self.inDispatch) { - self.listeners = [listener].concat(self.listeners); - } else { - self.listeners.unshift(listener); - } + // Create new listeners if addToTop is executed in a dispatch loop + if (self.inDispatch) { + self.listeners = [listener].concat(self.listeners); + } else { + self.listeners.unshift(listener); + } - return callback; - }; + return callback; + }; - this.remove = function(callback) { - var listeners = this.listeners, output = null; + this.remove = function (callback) { + var listeners = this.listeners, output = null; - tinymce.each(listeners, function(listener, i) { - if (callback == listener.cb) { - output = listener; - listeners.splice(i, 1); - return false; - } - }); + tinymce.each(listeners, function (listener, i) { + if (callback == listener.cb) { + output = listener; + listeners.splice(i, 1); + return false; + } + }); - return output; - }; + return output; + }; - this.dispatch = function() { - var self = this, returnValue, args = arguments, i, listeners = self.listeners, listener; + this.dispatch = function () { + var self = this, returnValue, args = arguments, i, listeners = self.listeners, listener; - self.inDispatch = true; - - // Needs to be a real loop since the listener count might change while looping - // And this is also more efficient - for (i = 0; i < listeners.length; i++) { - listener = listeners[i]; - returnValue = listener.cb.apply(listener.scope, args.length > 0 ? args : [listener.scope]); + self.inDispatch = true; - if (returnValue === false) { - break; - } - } + // Needs to be a real loop since the listener count might change while looping + // And this is also more efficient + for (i = 0; i < listeners.length; i++) { + listener = listeners[i]; + returnValue = listener.cb.apply(listener.scope, args.length > 0 ? args : [listener.scope]); - self.inDispatch = false; + if (returnValue === false) { + break; + } + } - return returnValue; - }; + self.inDispatch = false; + + return returnValue; + }; }; diff --git a/e107_plugins/tinymce4/plugins/compat3x/utils/editable_selects.js b/e107_plugins/tinymce4/plugins/compat3x/utils/editable_selects.js index 8d30787d5..3dd44a8f1 100644 --- a/e107_plugins/tinymce4/plugins/compat3x/utils/editable_selects.js +++ b/e107_plugins/tinymce4/plugins/compat3x/utils/editable_selects.js @@ -1,70 +1,72 @@ /** * editable_selects.js * - * Copyright, Moxiecode Systems AB * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ var TinyMCE_EditableSelects = { - editSelectElm : null, + editSelectElm : null, - init : function() { - var nl = document.getElementsByTagName("select"), i, d = document, o; + init : function () { + var nl = document.getElementsByTagName("select"), i, d = document, o; - for (i=0; i'; - h += ' '; + h += ''; + h += ' '; - return h; + return h; } function updateColor(img_id, form_element_id) { - document.getElementById(img_id).style.backgroundColor = document.forms[0].elements[form_element_id].value; + document.getElementById(img_id).style.backgroundColor = document.forms[0].elements[form_element_id].value; } function setBrowserDisabled(id, state) { - var img = document.getElementById(id); - var lnk = document.getElementById(id + "_link"); + var img = document.getElementById(id); + var lnk = document.getElementById(id + "_link"); - if (lnk) { - if (state) { - lnk.setAttribute("realhref", lnk.getAttribute("href")); - lnk.removeAttribute("href"); - tinyMCEPopup.dom.addClass(img, 'disabled'); - } else { - if (lnk.getAttribute("realhref")) - lnk.setAttribute("href", lnk.getAttribute("realhref")); + if (lnk) { + if (state) { + lnk.setAttribute("realhref", lnk.getAttribute("href")); + lnk.removeAttribute("href"); + tinyMCEPopup.dom.addClass(img, 'disabled'); + } else { + if (lnk.getAttribute("realhref")) { + lnk.setAttribute("href", lnk.getAttribute("realhref")); + } - tinyMCEPopup.dom.removeClass(img, 'disabled'); - } - } + tinyMCEPopup.dom.removeClass(img, 'disabled'); + } + } } function getBrowserHTML(id, target_form_element, type, prefix) { - var option = prefix + "_" + type + "_browser_callback", cb, html; + var option = prefix + "_" + type + "_browser_callback", cb, html; - cb = tinyMCEPopup.getParam(option, tinyMCEPopup.getParam("file_browser_callback")); + cb = tinyMCEPopup.getParam(option, tinyMCEPopup.getParam("file_browser_callback")); - if (!cb) - return ""; + if (!cb) { + return ""; + } - html = ""; - html += ''; - html += ' '; + html = ""; + html += ''; + html += ' '; - return html; + return html; } function openBrowser(img_id, target_form_element, type, option) { - var img = document.getElementById(img_id); + var img = document.getElementById(img_id); - if (img.className != "mceButtonDisabled") - tinyMCEPopup.openBrowser(target_form_element, type, option); + if (img.className != "mceButtonDisabled") { + tinyMCEPopup.openBrowser(target_form_element, type, option); + } } function selectByValue(form_obj, field_name, value, add_custom, ignore_case) { - if (!form_obj || !form_obj.elements[field_name]) - return; + if (!form_obj || !form_obj.elements[field_name]) { + return; + } - if (!value) - value = ""; + if (!value) { + value = ""; + } - var sel = form_obj.elements[field_name]; + var sel = form_obj.elements[field_name]; - var found = false; - for (var i=0; i parseInt(v)) - st = this.mark(f, n); - } - } + if (isNaN(v) || parseInt(n.value) < parseInt(v)) { + st = this.mark(f, n); + } + } - return st; - }, + if (this.hasClass(n, s.max_cls, true)) { + v = this.getNum(n, s.max_cls); - hasClass : function(n, c, d) { - return new RegExp('\\b' + c + (d ? '[0-9]+' : '') + '\\b', 'g').test(n.className); - }, + if (isNaN(v) || parseInt(n.value) > parseInt(v)) { + st = this.mark(f, n); + } + } + } - getNum : function(n, c) { - c = n.className.match(new RegExp('\\b' + c + '([0-9]+)\\b', 'g'))[0]; - c = c.replace(/[^0-9]/g, ''); + return st; + }, - return c; - }, + hasClass : function (n, c, d) { + return new RegExp('\\b' + c + (d ? '[0-9]+' : '') + '\\b', 'g').test(n.className); + }, - addClass : function(n, c, b) { - var o = this.removeClass(n, c); - n.className = b ? c + (o != '' ? (' ' + o) : '') : (o != '' ? (o + ' ') : '') + c; - }, + getNum : function (n, c) { + c = n.className.match(new RegExp('\\b' + c + '([0-9]+)\\b', 'g'))[0]; + c = c.replace(/[^0-9]/g, ''); - removeClass : function(n, c) { - c = n.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' '); - return n.className = c != ' ' ? c : ''; - }, + return c; + }, - tags : function(f, s) { - return f.getElementsByTagName(s); - }, + addClass : function (n, c, b) { + var o = this.removeClass(n, c); + n.className = b ? c + (o !== '' ? (' ' + o) : '') : (o !== '' ? (o + ' ') : '') + c; + }, - mark : function(f, n) { - var s = this.settings; + removeClass : function (n, c) { + c = n.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' '); + return n.className = c !== ' ' ? c : ''; + }, - this.addClass(n, s.invalid_cls); - n.setAttribute('aria-invalid', 'true'); - this.markLabels(f, n, s.invalid_cls); + tags : function (f, s) { + return f.getElementsByTagName(s); + }, - return false; - }, + mark : function (f, n) { + var s = this.settings; - markLabels : function(f, n, ic) { - var nl, i; + this.addClass(n, s.invalid_cls); + n.setAttribute('aria-invalid', 'true'); + this.markLabels(f, n, s.invalid_cls); - nl = this.tags(f, "label"); - for (i=0; i Date: Thu, 10 May 2018 09:29:51 +0200 Subject: [PATCH 21/59] Delete en.js --- e107_plugins/tinymce4/langs/en.js | 179 ------------------------------ 1 file changed, 179 deletions(-) delete mode 100644 e107_plugins/tinymce4/langs/en.js diff --git a/e107_plugins/tinymce4/langs/en.js b/e107_plugins/tinymce4/langs/en.js deleted file mode 100644 index a588b8874..000000000 --- a/e107_plugins/tinymce4/langs/en.js +++ /dev/null @@ -1,179 +0,0 @@ -tinymce.addI18n('en_GB',{ -"Cut": "Cut", -"Header 2": "Header 2", -"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.", -"Div": "Div", -"Paste": "Paste", -"Close": "Close", -"Font Family": "Font Family", -"Pre": "Pre", -"Align right": "Align right", -"New document": "New document", -"Blockquote": "Blockquote", -"Numbered list": "Numbered list", -"Increase indent": "Increase indent", -"Formats": "Formats", -"Headers": "Headers", -"Select all": "Select all", -"Header 3": "Header 3", -"Blocks": "Blocks", -"Undo": "Undo", -"Strikethrough": "Strike-through", -"Bullet list": "Bullet list", -"Header 1": "Header 1", -"Superscript": "Superscript", -"Clear formatting": "Clear formatting", -"Font Sizes": "Font Sizes", -"Subscript": "Subscript", -"Header 6": "Header 6", -"Redo": "Redo", -"Paragraph": "Paragraph", -"Ok": "Ok", -"Bold": "Bold", -"Code": "Code", -"Italic": "Italic", -"Align center": "Align centre", -"Header 5": "Header 5", -"Decrease indent": "Decrease indent", -"Header 4": "Header 4", -"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.", -"Underline": "Underline", -"Cancel": "Cancel", -"Justify": "Justify", -"Inline": "Inline", -"Copy": "Copy", -"Align left": "Align left", -"Visual aids": "Visual aids", -"Lower Greek": "Lower Greek", -"Square": "Square", -"Default": "Default", -"Lower Alpha": "Lower Alpha", -"Circle": "Circle", -"Disc": "Disc", -"Upper Alpha": "Upper Alpha", -"Upper Roman": "Upper Roman", -"Lower Roman": "Lower Roman", -"Name": "Name", -"Anchor": "Anchor", -"You have unsaved changes are you sure you want to navigate away?": "You have unsaved changes are you sure you want to navigate away?", -"Restore last draft": "Restore last draft", -"Special character": "Special character", -"Source code": "Source code", -"Right to left": "Right to left", -"Left to right": "Left to right", -"Emoticons": "Emoticons", -"Robots": "Robots", -"Document properties": "Document properties", -"Title": "Title", -"Keywords": "Keywords", -"Encoding": "Encoding", -"Description": "Description", -"Author": "Author", -"Fullscreen": "Full-screen", -"Horizontal line": "Horizontal line", -"Horizontal space": "Horizontal space", -"Insert\/edit image": "Insert\/edit image", -"General": "General", -"Advanced": "Advanced", -"Source": "Source", -"Border": "Border", -"Constrain proportions": "Constrain proportions", -"Vertical space": "Vertical space", -"Image description": "Image description", -"Style": "Style", -"Dimensions": "Dimensions", -"Insert image": "Insert image", -"Insert date\/time": "Insert date\/time", -"Remove link": "Remove link", -"Url": "URL", -"Text to display": "Text to display", -"Anchors": "Anchors", -"Insert link": "Insert link", -"New window": "New window", -"None": "None", -"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?", -"Target": "Target", -"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?", -"Insert\/edit link": "Insert\/edit link", -"Insert\/edit video": "Insert\/edit video", -"Poster": "Poster", -"Alternative source": "Alternative source", -"Paste your embed code below:": "Paste your embed code below:", -"Insert video": "Insert video", -"Embed": "Embed", -"Nonbreaking space": "Non-breaking space", -"Page break": "Page break", -"Paste as text": "Paste as text", -"Preview": "Preview", -"Print": "Print", -"Save": "Save", -"Could not find the specified string.": "Could not find the specified string.", -"Replace": "Replace", -"Next": "Next", -"Whole words": "Whole words", -"Find and replace": "Find and replace", -"Replace with": "Replace with", -"Find": "Find", -"Replace all": "Replace all", -"Match case": "Match case", -"Prev": "Prev", -"Spellcheck": "Spell-check", -"Finish": "Finish", -"Ignore all": "Ignore all", -"Ignore": "Ignore", -"Insert row before": "Insert row before", -"Rows": "Rows", -"Height": "Height", -"Paste row after": "Paste row after", -"Alignment": "Alignment", -"Column group": "Column group", -"Row": "Row", -"Insert column before": "Insert column before", -"Split cell": "Split cell", -"Cell padding": "Cell padding", -"Cell spacing": "Cell spacing", -"Row type": "Row type", -"Insert table": "Insert table", -"Body": "Body", -"Caption": "Caption", -"Footer": "Footer", -"Delete row": "Delete row", -"Paste row before": "Paste row before", -"Scope": "Scope", -"Delete table": "Delete table", -"Header cell": "Header cell", -"Column": "Column", -"Cell": "Cell", -"Header": "Header", -"Cell type": "Cell type", -"Copy row": "Copy row", -"Row properties": "Row properties", -"Table properties": "Table properties", -"Row group": "Row group", -"Right": "Right", -"Insert column after": "Insert column after", -"Cols": "Cols", -"Insert row after": "Insert row after", -"Width": "Width", -"Cell properties": "Cell properties", -"Left": "Left", -"Cut row": "Cut row", -"Delete column": "Delete column", -"Center": "Centre", -"Merge cells": "Merge cells", -"Insert template": "Insert template", -"Templates": "Templates", -"Background color": "Background colour", -"Text color": "Text colour", -"Show blocks": "Show blocks", -"Show invisible characters": "Show invisible characters", -"Words: {0}": "Words: {0}", -"Insert": "Insert", -"File": "File", -"Edit": "Edit", -"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help", -"Tools": "Tools", -"View": "View", -"Table": "Table", -"Format": "Format" -}); \ No newline at end of file From 129ac9436d61eb449ad726944bd932d62ea84988 Mon Sep 17 00:00:00 2001 From: Cameron Date: Fri, 11 May 2018 08:39:01 -0700 Subject: [PATCH 22/59] Renamed date class and included BC fix. --- e107_handlers/date_handler.php | 30 +++++++++++++++++++----------- e107_handlers/e107_class.php | 7 ++++--- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/e107_handlers/date_handler.php b/e107_handlers/date_handler.php index 34aa2b104..ecbbbd530 100644 --- a/e107_handlers/date_handler.php +++ b/e107_handlers/date_handler.php @@ -16,7 +16,7 @@ if (!defined('e107_INIT')) { exit; } e107::includeLan(e_LANGUAGEDIR.e_LANGUAGE."/lan_date.php"); -class convert +class e_date { function __construct() @@ -81,8 +81,7 @@ class convert /** * Return an array of language terms representing months * @param $type string : month, month-short, day, day-short, day-shortest - * @return array - * TODO Cache! + * @return array|bool */ public function terms($type='month') { @@ -642,24 +641,22 @@ class convert } - - /** * This work of Lionel SAURON (http://sauron.lionel.free.fr:80) is licensed under the * Creative Commons Attribution-Noncommercial-Share Alike 2.0 France License. * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/2.0/fr/ * or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. - * + * * http://snipplr.com/view/4964/emulate-php-5-for-backwards-compatibility/ - * + * * Parse a date generated with strftime(). - * - * @author Lionel SAURON and reworked by e107 Inc. for month names. + * + * @author Lionel SAURON and reworked by e107 Inc. for month names. * @version 1.0 * @public * * @param string $str date string to parse (e.g. returned from strftime()). - * @param string $sFormat strftime format used to create the date + * @param $format * @return array|bool Returns an array with the $str parsed, or false on error. */ public function strptime($str, $format) @@ -919,4 +916,15 @@ class convert } -?> \ No newline at end of file + + +/** + * BC Fix convert + */ +class convert extends e_date +{ + + + + +} \ No newline at end of file diff --git a/e107_handlers/e107_class.php b/e107_handlers/e107_class.php index 49113de2b..73340f44b 100755 --- a/e107_handlers/e107_class.php +++ b/e107_handlers/e107_class.php @@ -160,7 +160,8 @@ class e107 protected static $_known_handlers = array( 'UserHandler' => '{e_HANDLER}user_handler.php', 'comment' => '{e_HANDLER}comment_class.php', - 'convert' => '{e_HANDLER}date_handler.php', + 'e_date' => '{e_HANDLER}date_handler.php', + 'convert' => '{e_HANDLER}date_handler.php', // BC Fix. 'db' => '{e_HANDLER}mysql_class.php', 'e107Email' => '{e_HANDLER}mail.php', 'e107_event' => '{e_HANDLER}event_class.php', @@ -1588,7 +1589,7 @@ class e107 */ public static function getDateConvert() { - return self::getSingleton('convert', true); + return self::getSingleton('e_date', true); } /** @@ -1598,7 +1599,7 @@ class e107 */ public static function getDate() { - return self::getSingleton('convert', true); + return self::getSingleton('e_date', true); } From 0fd399528ae9fe31dee576fa98af31952e0fb023 Mon Sep 17 00:00:00 2001 From: Cameron Date: Fri, 11 May 2018 14:52:55 -0700 Subject: [PATCH 23/59] Issue #3124 Fix for TinyMce language path. --- e107_plugins/tinymce4/wysiwyg.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e107_plugins/tinymce4/wysiwyg.php b/e107_plugins/tinymce4/wysiwyg.php index 68a876fdc..646d7750b 100644 --- a/e107_plugins/tinymce4/wysiwyg.php +++ b/e107_plugins/tinymce4/wysiwyg.php @@ -240,7 +240,7 @@ class wysiwyg 'Danish' => 'da', // 'Divehi' => 'dv', 'Dutch' => 'nl', - 'English' => 'en', // Default language file. + 'English' => 'en_GB', // Default language file. // 'English (Canada)' => 'en_CA', // 'English (United Kingdom)' => 'en_GB', 'Esperanto' => 'eo', From bf9cf05b0e159e4ee83a776982459363af78f93a Mon Sep 17 00:00:00 2001 From: Cameron Date: Fri, 11 May 2018 14:58:04 -0700 Subject: [PATCH 24/59] Renamed date handler to e_date. BC support added. --- e107_admin/prefs.php | 2 +- .../shortcodes/batch/news_shortcodes.php | 2 +- e107_handlers/date_handler.php | 13 +- e107_handlers/e107_class.php | 2 +- news.php | 1293 +---------------- search.php | 2 +- 6 files changed, 15 insertions(+), 1299 deletions(-) diff --git a/e107_admin/prefs.php b/e107_admin/prefs.php index c7588b68b..dd3cb3d59 100644 --- a/e107_admin/prefs.php +++ b/e107_admin/prefs.php @@ -643,7 +643,7 @@ $text .= " "; // Date options. -$ga = new convert(); +$ga = e107::getDate(); $date1 = $ga->convert_date(time(), "short"); $date2 = $ga->convert_date(time(), "long"); $date3 = $ga->convert_date(time(), "forum"); diff --git a/e107_core/shortcodes/batch/news_shortcodes.php b/e107_core/shortcodes/batch/news_shortcodes.php index 8685222f2..b157d1812 100644 --- a/e107_core/shortcodes/batch/news_shortcodes.php +++ b/e107_core/shortcodes/batch/news_shortcodes.php @@ -1116,7 +1116,7 @@ class news_shortcodes extends e_shortcode { $news_item = $this->news_item; $param = $this->param; - $con = new convert; + $con = e107::getDate(); $news_item['news_start'] = (isset($news_item['news_start']) && $news_item['news_start'] ? str_replace(' - 00:00:00', '', $con->convert_date($news_item['news_start'], 'long')) : LAN_NEWS_19); $news_item['news_end'] = (isset($news_item['news_end']) && $news_item['news_end'] ? ' to '.str_replace(' - 00:00:00', '', $con->convert_date($news_item['news_end'], 'long')) : ''); $info = $news_item['news_render_type'] == 1 ? LAN_NEWS_9 : ''; diff --git a/e107_handlers/date_handler.php b/e107_handlers/date_handler.php index ecbbbd530..2dc70aa75 100644 --- a/e107_handlers/date_handler.php +++ b/e107_handlers/date_handler.php @@ -227,7 +227,8 @@ class e_date /** - * Converts to new date-mask format or vice-versa when $legacy is TRUE + * Converts to new date-mask format or vice-versa when $legacy is TRUE + * @see https://github.com/AuspeXeu/bootstrap-datetimepicker */ function toMask($mask, $legacy = false) { @@ -258,13 +259,15 @@ class e_date $s = array_keys($convert); $r = array_values($convert); - if(strpos($mask, '%') === FALSE && $legacy == TRUE) + if(strpos($mask, '%') === false && $legacy === true) { - return str_replace($r, $s,$mask); + $ret = str_replace($r, $s,$mask); + return str_replace('%%p', '%P', $ret); // quick fix. } - elseif(strpos($mask,'%')!==FALSE) + elseif(strpos($mask,'%')!==false) { - return str_replace($s,$r, $mask); + return str_replace($s,$r, $mask); + } return $mask; diff --git a/e107_handlers/e107_class.php b/e107_handlers/e107_class.php index 73340f44b..049200bae 100755 --- a/e107_handlers/e107_class.php +++ b/e107_handlers/e107_class.php @@ -161,7 +161,7 @@ class e107 'UserHandler' => '{e_HANDLER}user_handler.php', 'comment' => '{e_HANDLER}comment_class.php', 'e_date' => '{e_HANDLER}date_handler.php', - 'convert' => '{e_HANDLER}date_handler.php', // BC Fix. + 'convert' => '{e_HANDLER}date_handler.php', // BC Fix. 'db' => '{e_HANDLER}mysql_class.php', 'e107Email' => '{e_HANDLER}mail.php', 'e107_event' => '{e_HANDLER}event_class.php', diff --git a/news.php b/news.php index 224bc5f33..434e3a8b7 100644 --- a/news.php +++ b/news.php @@ -20,1296 +20,9 @@ */ require_once("class2.php"); +require_once(e_PLUGIN."news/news.php"); +exit; -if(!deftrue('e_LEGACY_NEWS')) // subject to removal at any time. -{ - require_once(e_PLUGIN."news/news.php"); - exit; -} -// --------------------- everything below this point will be removed in future -------------------------- - - -e107::includeLan(e_LANGUAGEDIR.e_LANGUAGE.'/lan_'.e_PAGE); - -require_once(e_HANDLER."news_class.php"); -//require_once(e_HANDLER."comment_class.php"); -//$cobj = new comment; - -if (isset($NEWSHEADER)) -{ - require_once(HEADERF); - require_once(FOOTERF); - exit; -} - -e107::includeLan(e_LANGUAGEDIR.e_LANGUAGE.'/lan_news.php'); // Temporary - -$cacheString = 'news.php_default_'; -$action = ''; -$sub_action = ''; -$order = 'news_datestamp'; -$newsfrom = 0; - -if (!defined('ITEMVIEW')) -{ - define('ITEMVIEW', varset($pref['newsposts'],15)); -} - -// ?all and ?cat.x and ?tag are the same listing functions - just filtered differently. -// NEWSLIST_LIMIT is suitable for all - -if(!defined("NEWSLIST_LIMIT")) -{ - define("NEWSLIST_LIMIT", varset($pref['news_list_limit'],15)); -} - -$defTemplate = e107::getPref('news_default_template'); - -if (e_QUERY) //TODO add support for $_GET['cat'] and $_GET['mode'] and phase-out the x.x.x format. -{ - - $tmp = explode(".",e_QUERY); - $action = $tmp[0]; // At least one parameter here - $sub_action = varset($tmp[1],''); // Usually a numeric category, or numeric news item number, but don't presume yet - // $id = varset($tmp[2],''); // ID of specific news item where required - $newsfrom = intval(varset($tmp[2],0)); // Item number for first item on multi-page lists - $cacheString = 'news.php_'.e_QUERY; -} -else -{ - - $opt = array('default'=>'', 'list'=>'all'); - $action = varset($opt[$defTemplate],''); -} - -//$newsfrom = (!is_numeric($action) || !e_QUERY ? 0 : ($action ? $action : e_QUERY)); - -// Usually the first query parameter is the action. -// For any of the 'list' modes (inc month, day), the action being second is a legacy situation -// .... which can hopefully go sometime -//SecretR: Gone, gone... -if (is_numeric($action) && isset($tmp[1]) && (($tmp[1] == 'list') || ($tmp[1] == 'month') || ($tmp[1] == 'day'))) -{ - $action = $tmp[1]; - $sub_action = varset($tmp[0],''); -} - - - -if ($action == 'all' || $action == 'cat') -{ - $sub_action = intval(varset($tmp[1],0)); -} - - - - - -/* -Variables Used: -$action - the basic display format/filter -$sub_action - category number or news item number -$newsfrom - first item number in list (default 0) - derived from nextprev -$order - sets the listing order for 'list' format -*/ - - -$ix = new news; -$nobody_regexp = "'(^|,)(".str_replace(",", "|", e_UC_NOBODY).")(,|$)'"; - -// URL settings (nextprev) - $newsUrlparms = array('page' => '--FROM--'); - if($sub_action) - { - - switch ($action) - { - case 'list': - $newsUrlparms['id'] = $sub_action; - $newsRoute = 'list/category'; - break; - - case 'cat': - $newsUrlparms['id'] = $sub_action; - $newsRoute = 'list/short'; - break; - - case 'day': - case 'month': - $newsUrlparms['id'] = $sub_action; - $newsRoute = 'list/'.$action; - break; - - default: - $newsRoute = 'list/items'; - break; - } - } - elseif($action == 'all') - { - $newsRoute = 'list/all'; - $newsUrlparms['id'] = $sub_action; - } - else - { - $newsRoute = 'list/items'; - } - - - - $newsRoute = 'news/'.$newsRoute; - - - - -if(vartrue($_GET['tag']) || substr($action,0,4) == 'tag=') -{ - - $newsRoute = 'news/list/tag'; - if(!vartrue($_GET['tag'])) - { - list($action,$word) = explode("=",$action,2); - $_GET['tag'] = $word; - unset($word,$tmp); - } - - $newsUrlparms['tag'] = $tp->filter($_GET['tag']); - $newsfrom = intval(varset($_GET['page'],0)); -} - -if(!empty($_GET['author']) || substr($action,0,4) == 'author=') -{ - - $newsRoute = 'news/list/author'; - if(!vartrue($_GET['author'])) - { - list($action,$author) = explode("=",$action,2); - $_GET['author'] = $author; - unset($author,$tmp); - } - - $newsUrlparms['author'] = $tp->filter($_GET['author']); - $newsfrom = intval(varset($_GET['page'],0)); - -} - - -if(e_DEBUG === 'news') -{ - echo "

    "; - echo "

    SEF Debug Info

    "; - echo "action= ".$action." "; - echo "
    route= ".$newsRoute." "; - echo "
    e_QUERY= ".e_QUERY." "; - - echo "
    _GET= ".print_r($_GET,true); - echo "
    "; -} - -//------------------------------------------------------ -// DISPLAY NEWS IN 'CATEGORY' LIST FORMAT HERE -//------------------------------------------------------ -// Just title and a few other details - -if ($action == 'cat' || $action == 'all' || !empty($_GET['tag']) || !empty($_GET['author'])) -{ // --> Cache - if($newsCachedPage = checkCache($cacheString)) - { - require_once(HEADERF); - renderCache($newsCachedPage, TRUE); - } - // <-- Cache - - - $category = intval($sub_action); - if ($action == 'cat' && $category != 0) - { - $gen = new convert; - $sql->select("news_category", "*", "category_id='{$category}'"); - $row = $sql->fetch(); - extract($row); // still required for the table-render. :( - } - - //XXX These are all correctly using LIST templates. - - if ($action == 'all') // show archive of all news items using list-style template. - { - $renTypeQry = ''; - - if(!empty($pref['news_list_templates']) && is_array($pref['news_list_templates'])) - { - $renTypeQry = " AND (n.news_render_type REGEXP '(^|,)(".implode("|", $pref['news_list_templates']).")(,|$)')"; - } - - // $news_total = $sql->count("news", "(*)", "WHERE news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (news_class REGEXP ".$nobody_regexp.") AND news_start < ".time()." AND (news_end=0 || news_end>".time().")". str_replace("n.news", "news", $renTypeQry)); - $query = " - SELECT SQL_CALC_FOUND_ROWS n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, nc.category_icon, - nc.category_meta_keywords, nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - WHERE n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") AND n.news_start < ".time()." - AND (n.news_end=0 || n.news_end>".time().") "; - - $query .= $renTypeQry; - - $query .= " - ORDER BY n.news_sticky DESC, n.news_datestamp DESC - LIMIT ".intval($newsfrom).",".deftrue('NEWSALL_LIMIT', NEWSLIST_LIMIT); // NEWSALL_LIMIT just for BC. NEWSLIST_LIMIT is sufficient. - $category_name = ($defTemplate == 'list') ? PAGE_NAME : "All"; - unset($renTypeQry); - } - elseif ($action == 'cat') // show archive of all news items in a particular category using list-style template. - { - - // $news_total = $sql->count("news", "(*)", "WHERE news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (news_class REGEXP ".$nobody_regexp.") AND news_start < ".time()." AND (news_end=0 || news_end>".time().") AND news_category=".intval($sub_action)); - - $query = " - SELECT SQL_CALC_FOUND_ROWS n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, nc.category_icon, nc.category_meta_keywords, - nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - WHERE n.news_category=".intval($sub_action)." - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().") - AND n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") - ORDER BY n.news_datestamp DESC - LIMIT ".intval($newsfrom).",".NEWSLIST_LIMIT; - } - elseif(vartrue($_GET['tag'])) - { - $tagsearch = e107::getParser()->filter($_GET['tag']); - - $query = " - SELECT SQL_CALC_FOUND_ROWS n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, nc.category_icon, nc.category_meta_keywords, - nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - WHERE n.news_meta_keywords LIKE '%".$tagsearch."%' - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().") - AND n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") - ORDER BY n.news_datestamp DESC - LIMIT ".intval($newsfrom).",".NEWSLIST_LIMIT; - $category_name = 'Tag: "'.$tagsearch.'"'; - - } - elseif(!empty($_GET['author'])) - { - $authorSearch = e107::getParser()->filter($_GET['author']); - - $query = " - SELECT SQL_CALC_FOUND_ROWS n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, nc.category_icon, nc.category_meta_keywords, - nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - WHERE u.user_name = '".$authorSearch."' - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().") - AND n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") - ORDER BY n.news_datestamp DESC - LIMIT ".intval($newsfrom).",".NEWSLIST_LIMIT; - $category_name = 'Author: "'.$authorSearch.'"'; - - - - } - - $newsList = array(); - - if($sql->gen($query)) - { - $news_total = $sql->foundRows(); - $newsList = $sql->db_getList(); - $ogImageCount = 0; - foreach($newsList as $row) - { - if(!empty($row['news_thumbnail'])) - { - $iurl = (substr($row['news_thumbnail'],0,3)=="{e_") ? $row['news_thumbnail'] : SITEURL.e_IMAGE."newspost_images/".$news['news_thumbnail']; - $tmp = explode(",", $iurl); - - if($tp->isImage($tmp[0])) - { - if($ogImageCount > 6) - { - break; - } - - e107::meta('og:image',$tp->thumbUrl($tmp[0],'w=500',false,true) ); - $ogImageCount++; - - } - } - - } - } - - - if($action == 'cat') - { - setNewsFrontMeta($newsList[1], 'category'); - } -// elseif($category_name) -// { -// define('e_PAGETITLE', $tp->toHTML($category_name,FALSE,'TITLE')); -// } -e107::getDebug()->log("PageTitle: ".e_PAGETITLE); - $currentNewsAction = $action; - require_once(HEADERF); - $action = $currentNewsAction; - - if(deftrue('BOOTSTRAP')) // v2.x - { - $template = e107::getTemplate('news', 'news', 'list'); - } - else // v1.x - { - if(empty($NEWSLISTSTYLE)) - { - $NEWSLISTSTYLE = " -
    -
    ".$frm->text('download_security_expression', $pref['download_security_expression'], 1024)."
    ".LAN_DL_SECURITY_NGINX_SECURELINKMD5_EXPRESSION_HELP."
    + + ".LAN_DL_SECURITY_NGINX_SUPPORTED_VARIABLES_TOGGLE." + +
    ".DOWLAN_160." - ".$this->mirror_order_options_html($pref)."
    - -
    - {NEWS_CATEGORY_ICON} - - {NEWSTITLELINK=extend} -
    - {NEWS_SUMMARY} - - {NEWS_DATE} - {NEWSCOMMENTS} - -
    - {SETIMAGE: w=55&h=55&crop=1} - {NEWSTHUMBNAIL} -
    -
    \n"; - } - - $template = array('start'=>'', 'item'=>$NEWSLISTSTYLE, 'end'=>''); - - } - - // Legacy Styling.. - $param = array(); - $param['itemlink'] = (defined("NEWSLIST_ITEMLINK")) ? NEWSLIST_ITEMLINK : ""; - $param['thumbnail'] =(defined("NEWSLIST_THUMB")) ? NEWSLIST_THUMB : "border:0px"; - $param['catlink'] = (defined("NEWSLIST_CATLINK")) ? NEWSLIST_CATLINK : ""; - $param['caticon'] = (defined("NEWSLIST_CATICON")) ? NEWSLIST_CATICON : defset('ICONSTYLE',''); - $param['current_action'] = $action; - $param['template_key'] = 'list'; - - // NEW - allow news batch shortcode override (e.g. e107::getScBatch('news', 'myplugin', true); ) - e107::getEvent()->trigger('news_list_parse', $newsList); - - $text = ''; - - if(vartrue($template['start'])) - { - $text .= $tp->parseTemplate($template['start'], true); - } - - if(!empty($newsList)) - { - foreach($newsList as $row) - { - $text .= $ix->render_newsitem($row, 'return', '', $template['item'], $param); - } - } - else // No News - empty. - { - $text .= "
    ".(strstr(e_QUERY, "month") ? LAN_NEWS_462 : LAN_NEWS_83)."
    "; - } - - if(vartrue($template['end'])) - { - $text .= $tp->parseTemplate($template['end'], true); - } - - $icon = ($row['category_icon']) ? "" : ""; - - // Deprecated. - // $parms = $news_total.",".$amount.",".$newsfrom.",".$e107->url->getUrl('core:news', 'main', "action=nextprev&to_action={$action}&subaction={$category}"); - // $parms = $news_total.",".$amount.",".$newsfrom.",".e_SELF.'?'.$action.".".$category.".[FROM]"; - // - // $text .= "
    ".$tp->parseTemplate("{NEXTPREV={$parms}}")."
    "; - - $amount = NEWSLIST_LIMIT; - $nitems = defined('NEWS_NEXTPREV_NAVCOUNT') ? '&navcount='.NEWS_NEXTPREV_NAVCOUNT : '' ; - $url = rawurlencode(e107::getUrl()->create($newsRoute, $newsUrlparms)); - $parms = 'tmpl_prefix='.deftrue('NEWS_NEXTPREV_TMPL', 'default').'&total='.$news_total.'&amount='.$amount.'¤t='.$newsfrom.$nitems.'&url='.$url; - - - // e107::getDebug()->log($newsUrlparms); - - $text .= $tp->parseTemplate("{NEXTPREV={$parms}}"); - - if(varset($template['caption'])) // v2.x - { - $NEWSLISTTITLE = str_replace("{NEWSCATEGORY}",$tp->toHTML($category_name,FALSE,'TITLE'), $template['caption']); - } - elseif(!$NEWSLISTTITLE) // default - { - $NEWSLISTTITLE = LAN_NEWS_82." '".$tp->toHTML($category_name,FALSE,'TITLE')."'"; - } - else // v1.x - { - $NEWSLISTTITLE = str_replace("{NEWSCATEGORY}",$tp->toHTML($category_name,FALSE,'TITLE'),$NEWSLISTTITLE); - } - - if($defTemplate != 'list') - { - $text .= ""; - } - - ob_start(); - $ns->tablerender($NEWSLISTTITLE, $text, 'news'); - $cache_data = ob_get_flush(); - setNewsCache($cacheString, $cache_data); - require_once(FOOTERF); - exit; -} - - - -//------------------------------------------------------ -// DISPLAY SINGLE ITEM IN EXTENDED FORMAT HERE -//------------------------------------------------------ -if ($action == 'extend') -{ // --> Cache - if($newsCachedPage = checkCache($cacheString)) - { - require_once(HEADERF); - renderCache($newsCachedPage, TRUE); // This exits if cache used - } - // <-- Cache - - if(isset($pref['trackbackEnabled']) && $pref['trackbackEnabled']) - { - $query = " - SELECT COUNT(tb.trackback_pid) AS tb_count, n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, - nc.category_icon, nc.category_meta_keywords, nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - LEFT JOIN #trackback AS tb ON tb.trackback_pid = n.news_id - WHERE n.news_id=".intval($sub_action)." AND n.news_class REGEXP '".e_CLASS_REGEXP."' - AND NOT (n.news_class REGEXP ".$nobody_regexp.") - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().") - GROUP by n.news_id"; - } - else - { - $query = " - SELECT n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, nc.category_icon, nc.category_meta_keywords, - nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - WHERE n.news_class REGEXP '".e_CLASS_REGEXP."' - AND NOT (n.news_class REGEXP ".$nobody_regexp.") - AND n.news_start < ".time()." - AND (n.news_end=0 || n.news_end>".time().") - AND n.news_id=".intval($sub_action); - } - if ($sql->gen($query)) - { - $news = $sql->fetch(); - $id = $news['news_category']; // Use category of this news item to generate next/prev links - - e107::getEvent()->trigger('user_news_item_viewed', $news); - - //***NEW [SecretR] - comments handled inside now - e107::setRegistry('news/page_allow_comments', !$news['news_allow_comments']); - if(!$news['news_allow_comments'] && isset($_POST['commentsubmit'])) - { - $pid = intval(varset($_POST['pid'], 0)); // ID of the specific comment being edited (nested comments - replies) - - $clean_authorname = $_POST['author_name']; - $clean_comment = $_POST['comment']; - $clean_subject = $_POST['subject']; - - e107::getSingleton('comment')->enter_comment($clean_authorname, $clean_comment, 'news', $sub_action, $pid, $clean_subject); - } - - //More SEO - setNewsFrontMeta($news); - /* - if($news['news_title']) - { - if($pref['meta_news_summary'] && $news['news_title']) - { - define("META_DESCRIPTION",SITENAME.": ".$news['news_title']." - ".$news['news_summary']); - } - define("e_PAGETITLE",$news['news_title']); - }*/ - /* FIXME - better implementation: cache, shortcodes, do it inside the model/shortcode class itself. - if (TRUE) - { - // Added by nlStart - show links to previous and next news - if (!isset($news['news_extended'])) $news['news_extended'] = ''; - $news['news_extended'].=""; - $prev_query = "SELECT news_id, news_title FROM `#news` - WHERE `news_id` < ".intval($sub_action)." AND `news_category`=".$id." AND `news_class` REGEXP '".e_CLASS_REGEXP."' - AND NOT (`news_class` REGEXP ".$nobody_regexp.") - AND `news_start` < ".time()." AND (`news_end`=0 || `news_end` > ".time().') ORDER BY `news_id` DESC LIMIT 1'; - $sql->db_Select_gen($prev_query); - $prev_news = $sql->db_Fetch(); - if ($prev_news) - { - $news['news_extended'].=""; - } - $next_query = "SELECT news_id, news_title FROM `#news` AS n - WHERE `news_id` > ".intval($sub_action)." AND `news_category` = ".$id." AND `news_class` REGEXP '".e_CLASS_REGEXP."' - AND NOT (`news_class` REGEXP ".$nobody_regexp.") - AND `news_start` < ".time()." AND (`news_end`=0 || `news_end` > ".time().') ORDER BY `news_id` ASC LIMIT 1'; - $sql->db_Select_gen($next_query); - $next_news = $sql->db_Fetch(); - if ($next_news) - { - $news['news_extended'].=""; - } - $news['news_extended'].="

    "; - }*/ - - $currentNewsAction = $action; - require_once(HEADERF); - $action = $currentNewsAction; - - $param = array(); - $param['current_action'] = $action; - $param['template_key'] = 'view'; - - if(vartrue($NEWSSTYLE)) - { - $template = $NEWSSTYLE; - } - elseif(function_exists("news_style")) // BC - { - $template = news_style($news, 'extend', $param); - } - else - { - $tmp = e107::getTemplate('news', 'news', 'view'); - $template = $tmp['item']; - unset($tmp); - } - ob_start(); - $ix->render_newsitem($news, 'extend', '', $template, $param); - if(e107::getRegistry('news/page_allow_comments')) - { - global $comment_edit_query; //FIXME - kill me - $comment_edit_query = 'comment.news.'.$news['news_id']; - e107::getSingleton('comment')->compose_comment('news', 'comment', $news['news_id'], null, $news['news_title'], FALSE); - } - $cache_data = ob_get_contents(); - ob_end_flush(); - setNewsCache($cacheString, $cache_data); - require_once(FOOTERF); - exit; - } - else - { - // $action = 'default'; - - //XXX item not found, redirect to avoid messing up search-engine data. - $defaultUrl = e107::getUrl()->create('news/list/items'); - e107::getRedirect()->go($defaultUrl, null, 301); - exit; - - } -} - - -//------------------------------------------------------ -// DISPLAY NEWS IN LIST FORMAT HERE -//------------------------------------------------------ -// Show title, author, first part of news item... -if (empty($order)) -{ - $order = 'news_datestamp'; -} -$order = $tp -> toDB($order, true); /// @todo - try not to use toDB() - triggers prefilter - -$interval = $pref['newsposts']; - - - -switch ($action) -{ - case "list" : - $sub_action = intval($sub_action); - // $news_total = $sql->db_Count("news", "(*)", "WHERE news_category={$sub_action} AND news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (news_class REGEXP ".$nobody_regexp.") AND news_start < ".time()." AND (news_end=0 || news_end>".time().")"); - $query = " - SELECT SQL_CALC_FOUND_ROWS n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, - nc.category_icon, nc.category_meta_keywords, nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - WHERE n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().") - AND n.news_category={$sub_action} - ORDER BY n.news_sticky DESC,".$order." DESC LIMIT ".intval($newsfrom).",".ITEMVIEW; - - $noNewsMessage = LAN_NEWS_463; - break; - - - case "item" : - $sub_action = intval($sub_action); - $news_total = 1; - if(isset($pref['trackbackEnabled']) && $pref['trackbackEnabled']) - { - $query = " - SELECT COUNT(tb.trackback_pid) AS tb_count, n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, - nc.category_icon, nc.category_meta_keywords, nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - LEFT JOIN #trackback AS tb ON tb.trackback_pid = n.news_id - WHERE n.news_id={$sub_action} AND n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().") - GROUP by n.news_id"; - } - else - { - $query = " - SELECT n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, nc.category_icon, - nc.category_meta_keywords, nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - WHERE n.news_id={$sub_action} AND n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().")"; - } - - $noNewsMessage = LAN_NEWS_83; - break; - - - case "month" : - case "day" : - $item = $tp -> toDB($sub_action).'20000101'; - $year = substr($item, 0, 4); - $month = substr($item, 4,2); - if ($action == 'day') - { - $day = substr($item, 6, 2); - $lastday = $day; - } - else - { // A month's worth - $day = 1; - $lastday = date("t", $startdate); - } - - $startdate = mktime(0, 0, 0, $month, $day, $year); - $enddate = mktime(23, 59, 59, $month, $lastday, $year); - - $query = " - SELECT SQL_CALC_FOUND_ROWS n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, - nc.category_icon, nc.category_meta_keywords, nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - WHERE n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().") - AND (FIND_IN_SET('0', n.news_render_type) OR FIND_IN_SET(1, n.news_render_type)) AND n.news_datestamp BETWEEN {$startdate} AND {$enddate} - ORDER BY ".$order." DESC LIMIT ".intval($newsfrom).",".ITEMVIEW; - - $noNewsMessage = LAN_NEWS_462; - - break; - - case 'default' : - default : - //$action = ''; - $cacheString = 'news.php_default_'; // Make sure its sensible - // $news_total = $sql->db_Count("news", "(*)", "WHERE news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (news_class REGEXP ".$nobody_regexp.") AND news_start < ".time()." AND (news_end=0 || news_end>".time().") AND news_render_type<2" ); - - if(!isset($pref['newsposts_archive'])) - { - $pref['newsposts_archive'] = 0; - } - $interval = $pref['newsposts']-$pref['newsposts_archive']; // Number of 'full' posts to show - - // Get number of news item to show - if(isset($pref['trackbackEnabled']) && $pref['trackbackEnabled']) { - $query = " - SELECT SQL_CALC_FOUND_ROWS COUNT(tb.trackback_pid) AS tb_count, n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, - nc.category_name, nc.category_sef, nc.category_icon, nc.category_meta_keywords, nc.category_meta_description, - COUNT(*) AS tbcount - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - LEFT JOIN #trackback AS tb ON tb.trackback_pid = n.news_id - WHERE n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().") - AND (FIND_IN_SET('0', n.news_render_type) OR FIND_IN_SET(1, n.news_render_type)) - GROUP by n.news_id - ORDER BY news_sticky DESC, ".$order." DESC LIMIT ".intval($newsfrom).",".ITEMVIEW; - } - else - { - $query = " - SELECT SQL_CALC_FOUND_ROWS n.*, u.user_id, u.user_name, u.user_customtitle, nc.category_id, nc.category_name, nc.category_sef, nc.category_icon, - nc.category_meta_keywords, nc.category_meta_description - FROM #news AS n - LEFT JOIN #user AS u ON n.news_author = u.user_id - LEFT JOIN #news_category AS nc ON n.news_category = nc.category_id - WHERE n.news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (n.news_class REGEXP ".$nobody_regexp.") - AND n.news_start < ".time()." AND (n.news_end=0 || n.news_end>".time().") - AND (FIND_IN_SET('0', n.news_render_type) OR FIND_IN_SET(1, n.news_render_type)) - ORDER BY n.news_sticky DESC, ".$order." DESC LIMIT ".intval($newsfrom).",".ITEMVIEW; - } - - $noNewsMessage = LAN_NEWS_83; -} // END - switch($action) - - -if($newsCachedPage = checkCache($cacheString)) // normal news front-page - with cache. -{ - require_once(HEADERF); - - if(!$action) - { - // Removed, themes should use {FEATUREBOX} shortcode instead - // if (isset($pref['fb_active'])) - // { - // require_once(e_PLUGIN."featurebox/featurebox.php"); - // } - // Removed, legacy - // if (isset($pref['nfp_display']) && $pref['nfp_display'] == 1) - // { - // require_once(e_PLUGIN."newforumposts_main/newforumposts_main.php"); - // } - - } - - //news archive - if ($action != "item" && $action != 'list' && $pref['newsposts_archive']) { - if ($sql->db_Select_gen($query)) { - $newsAr = $sql -> db_getList(); - if($newsarchive = checkCache('newsarchive')){ - $newsCachedPage = $newsCachedPage.$newsarchive; - }else{ - show_newsarchive($newsAr,$interval); - } - } - } - renderCache($newsCachedPage, TRUE); -} - - -if (!($news_total = $sql->gen($query))) -{ // No news items - require_once(HEADERF); - echo "
    ".$noNewsMessage."
    "; - require_once(FOOTERF); - exit; -} - -$newsAr = $sql -> db_getList(); -$news_total=$sql->total_results; -// Get number of entries -//$sql -> db_Select_gen("SELECT FOUND_ROWS()"); -$frows = $sql -> db_Fetch(); -//$news_total = $frows[0]; - -//echo "
    Total ".$news_total." items found, ".count($newsAr)." displayed, Interval = {$interval}

    "; - -$p_title = ($action == "item") ? $newsAr[1]['news_title'] : $tp->toHTML($newsAr[1]['category_name'],FALSE,'TITLE'); - -switch($action) -{ - case 'item': - setNewsFrontMeta($newsAr[1]); - break; - - case 'list': - default: - setNewsFrontMeta($newsAr[1], 'list'); - break; -} - -/*if($action != "" && !is_numeric($action)) -{ -if($action == "item" && $pref['meta_news_summary'] && $newsAr[1]['news_title']) -{ -define("META_DESCRIPTION",SITENAME.": ".$newsAr[1]['news_title']." - ".$newsAr[1]['news_summary']); -} -define("e_PAGETITLE", $p_title); -}*/ - -$currentNewsAction = $action; -require_once(HEADERF); -$action = $currentNewsAction; - -if(!$action) -{ - // Removed, themes should use {FEATUREBOX} shortcode instead - // if (isset($pref['fb_active'])){ // --->feature box - // require_once(e_PLUGIN."featurebox/featurebox.php"); - // } - - // Removed, legacy - // if (isset($pref['nfp_display']) && $pref['nfp_display'] == 1){ - // require_once(e_PLUGIN."newforumposts_main/newforumposts_main.php"); - // } -} - -if(isset($pref['news_unstemplate']) && $pref['news_unstemplate'] && file_exists(THEME."news_template.php")) -{ - // theme specific template required ... - require_once(THEME."news_template.php"); - - if($ALTERNATECLASS1) - { - return TRUE; - } - - $newscolumns = (isset($NEWSCOLUMNS) ? $NEWSCOLUMNS : 1); - $newspercolumn = (isset($NEWSITEMSPERCOLUMN) ? $NEWSITEMSPERCOLUMN : 10); - $newsdata = array(); - $loop = 1; - $param = array(); - $param['current_action'] = $action; - foreach($newsAr as $news) { - - if(is_array($ALTERNATECLASSES)) { - $newsdata[$loop] .= "
    ".$ix->render_newsitem($news, "return", '', '', $param)."
    "; - $ALTERNATECLASSES = array_reverse($ALTERNATECLASSES); - } else { - $newsdata[$loop] .= $ix->render_newsitem($news, 'return', '', '', $param); - } - $loop ++; - if($loop > $newscolumns) { - $loop = 1; - } - } - $loop = 1; - foreach($newsdata as $data) { - $var = "ITEMS{$loop}"; - $$var = $data; - $loop ++; - } - $text = preg_replace("/\{(.*?)\}/e", '$\1', $NEWSCLAYOUT); - - require_once(HEADERF); - // Deprecated - // $parms = $news_total.",".ITEMVIEW.",".$newsfrom.",".$e107->url->getUrl('core:news', 'main', "action=nextprev&to_action=".($action ? $action : 'default' )."&subaction=".($sub_action ? $sub_action : "0")); - - $sub_action = intval($sub_action); - // $parms = $news_total.",".ITEMVIEW.",".$newsfrom.",".e_SELF.'?'.($action ? $action : 'default' ).($sub_action ? ".".$sub_action : ".0").".[FROM]"; - - $amount = ITEMVIEW; - $nitems = defined('NEWS_NEXTPREV_NAVCOUNT') ? '&navcount='.NEWS_NEXTPREV_NAVCOUNT : '' ; - $url = rawurlencode(e107::getUrl()->create($newsRoute, $newsUrlparms)); - $parms = 'tmpl_prefix='.deftrue('NEWS_NEXTPREV_TMPL', 'default').'&total='.$news_total.'&amount='.$amount.'¤t='.$newsfrom.$nitems.'&url='.$url; - - $text .= $tp->parseTemplate("{NEXTPREV={$parms}}"); - - // $nextprev = $tp->parseTemplate("{NEXTPREV={$parms}}"); - // $text .= ($nextprev ? "
    ".$nextprev."
    " : ""); - // $text=''.$text.'
    '.$nextprev.'
    '; - - echo $text; - setNewsCache($cacheString, $text); -} -else -{ - ob_start(); - - $newpostday = 0; - $thispostday = 0; - $pref['newsHeaderDate'] = 1; - $gen = new convert(); - /* - if(vartrue($NEWSLISTSTYLE)) $template = $NEWSLISTSTYLE; v1.x doesn't do this.. so no point doing it here. - else - { - $tmp = e107::getTemplate('news', 'news', 'list'); - $template = $tmp['item']; - unset($tmp); - } - */ - if (!defined("DATEHEADERCLASS")) { - define("DATEHEADERCLASS", "nextprev"); - // if not defined in the theme, default class nextprev will be used for new date header - } - - // #### normal newsitems, rendered via render_newsitem(), the $query is changed above (no other changes made) --------- - $param = array(); - $param['current_action'] = $action; - $param['template_key'] = 'default'; - - // Get Correct Template - // XXX we use $NEWSLISTSTYLE above - correct as we are currently in list mode - XXX No this is not NEWSLISTSTYLE - which provides only summaries. - // TODO requires BC testing if we comment this one - if(vartrue($NEWSSTYLE)) - { - $template = $NEWSSTYLE; - } - else - { - $tmp = e107::getTemplate('news', 'news', 'default'); // default - we show the full items, except for the 'extended' part.. - $template = $tmp['item']; - unset($tmp); - } - - - - - - // NEW - news category title when in list - if($sub_action && 'list' == $action && vartrue($newsAr[1]['category_name'])) - { - // we know category name - pass it to the nexprev url - $category_name = $newsAr[1]['category_name']; - if(vartrue($newsAr[1]['category_sef'])) $newsUrlparms['name'] = $newsAr[1]['category_sef']; - if(!isset($NEWSLISTCATTITLE)) - { - $NEWSLISTCATTITLE = "

    ".$tp->toHTML($category_name,FALSE,'TITLE')."

    "; - } - else - { - $NEWSLISTCATTITLE = str_replace("{NEWSCATEGORY}",$tp->toHTML($category_name,FALSE,'TITLE'),$NEWSLISTCATTITLE); - } - echo $NEWSLISTCATTITLE; - } - - $i= 1; - - $socialInstalled = e107::isInstalled('social'); - - while(isset($newsAr[$i]) && $i <= $interval) - { - $news = $newsAr[$i]; - - // Set the Values for the social shortcode usage. - if($socialInstalled == true) - { - $socialArray = array('url'=>e107::getUrl()->create('news/view/item', $news, 'full=1'), 'title'=>$tp->toText($news['news_title']), 'tags'=>$news['news_meta_keywords']); - $socialObj = e107::getScBatch('social'); - - if(is_object($socialObj)) - { - $socialObj->setVars($socialArray); - } - } - - if(function_exists("news_style")) // BC - { - $template = news_style($news, $action, $param); - } - - - // render new date header if pref selected ... - $thispostday = strftime("%j", $news['news_datestamp']); - if ($newpostday != $thispostday && (isset($pref['news_newdateheader']) && $pref['news_newdateheader'])) - { - echo "
    ".strftime("%A %d %B %Y", $news['news_datestamp'])."
    "; - } - $newpostday = $thispostday; - $news['category_id'] = $news['news_category']; - if ($action == "item") - { - unset($news['news_render_type']); - e107::getEvent()->trigger('user_news_item_viewed', $news); - //e107::getDebug()->log($news); - } - // $template = false; - $ix->render_newsitem($news, 'default', '', $template, $param); - - - $i++; - } - - $amount = ITEMVIEW; - $nitems = defined('NEWS_NEXTPREV_NAVCOUNT') ? '&navcount='.NEWS_NEXTPREV_NAVCOUNT : '' ; - $url = rawurlencode(e107::getUrl()->create($newsRoute, $newsUrlparms)); - // Example of passing route data instead building the URL outside the shortcode - for a reference only - // $url = rawurlencode('url::'.$newsRoute.'::'.http_build_query($newsUrlparms, null, '&')); - $parms = 'tmpl_prefix='.deftrue('NEWS_NEXTPREV_TMPL', 'default').'&total='.$news_total.'&amount='.$amount.'¤t='.$newsfrom.$nitems.'&url='.$url; - - echo $tp->parseTemplate("{NEXTPREV={$parms}}"); - - // $parms = $news_total.",".ITEMVIEW.",".$newsfrom.",".e_SELF.'?'.($action ? $action : 'default' ).($sub_action ? ".".$sub_action : ".0").".[FROM]"; - // $nextprev = $tp->parseTemplate("{NEXTPREV={$parms}}"); - // echo ($nextprev ? "
    ".$nextprev."
    " : ""); - - $cache_data = ob_get_clean(); - require_once(HEADERF); - echo $cache_data; - setNewsCache($cacheString, $cache_data); -} - -// ##### -------------------------------------------------------------------------------------------------------------- - -function show_newsarchive($newsAr, $i = 1) -{ - global $ns, $gen, $pref, $tp, $news_archive_shortcodes, $NEWSARCHIVE, $news2; - - // do not show the news archive on the news.php?item.X page (but only on the news mainpage) - require_once(e_CORE.'shortcodes/batch/news_archives.php'); - - $textnewsarchive = ''; - ob_start(); - - $i++; // First entry to show - while(isset($newsAr[$i])) - { - $news2 = $newsAr[$i]; - // Code from Lisa - // copied from the rss creation, but added here to make sure the url for the newsitem is to the news.php?item.X - // instead of the actual hyperlink that may have been added to a newstitle on creation - $search = array(); - $replace = array(); - $search[0] = "/\(.*?)<\/a>/si"; - $replace[0] = '\\2'; - $search[1] = "/\(.*?)<\/a>/si"; - $replace[1] = '\\2'; - $search[2] = "/\(.*?)<\/a>/si"; - $replace[2] = '\\2'; - $search[3] = "/\(.*?)<\/a>/si"; - $replace[3] = '\\2'; - $search[4] = "/\(.*?)<\/a>/si"; - $replace[4] = '\\2'; - $news2['news_title'] = preg_replace($search, $replace, $news2['news_title']); - // End of code from Lisa - - $gen = new convert; - $news2['news_datestamp'] = $gen->convert_date($news2['news_datestamp'], "short"); - - - if(!$NEWSARCHIVE){ - $NEWSARCHIVE ="
    - - - - -
    -
    {ARCHIVE_BULLET} {ARCHIVE_LINK} {ARCHIVE_AUTHOR} @ ({ARCHIVE_DATESTAMP}) ({ARCHIVE_CATEGORY})
    -
    -
    "; - } - - $textnewsarchive .= $tp->parseTemplate($NEWSARCHIVE, FALSE, $news_archive_shortcodes); - $i++; - } - $ns->tablerender($pref['newsposts_archive_title'], $textnewsarchive, 'news_archive'); - $newsarchive = ob_get_contents(); - ob_end_flush(); // dump collected data - setNewsCache('newsarchive', $newsarchive); -} - -// #### new: news archive --------------------------------------------------------------------------------------------- -if ($action != "item" && $action != 'list' && $pref['newsposts_archive']) -{ - show_newsarchive($newsAr,$interval); -} -// #### END ----------------------------------------------------------------------------------------------------------- - -if ($action != "item") { - if (is_numeric($action)){ - $action = ""; - } - // $parms = $news_total.",".ITEMVIEW.",".$newsfrom.",".e_SELF.'?'."[FROM].".$action.(isset($sub_action) ? ".".$sub_action : ""); - // $nextprev = $tp->parseTemplate("{NEXTPREV={$parms}}"); - // echo ($nextprev ? "
    ".$nextprev."
    " : ""); -} - -if(is_dir("remotefile")) { - require_once(e_HANDLER."file_class.php"); - $file = new e_file; - // $reject = array('$.','$..','/','CVS','thumbs.db','*._$', 'index', 'null*', 'Readme.txt'); - // $crem = $file -> get_files(e_BASE."remotefile", "", $reject); - $crem = $file -> get_files(e_BASE."remotefile", '~Readme\.txt'); - if(count($crem)) { - foreach($crem as $loadrem) { - if(strstr($loadrem['fname'], "load_")) { - require_once(e_BASE."remotefile/".$loadrem['fname']); - } - } - } -} - -if (isset($pref['nfp_display']) && $pref['nfp_display'] == 2 && is_readable(e_PLUGIN."newforumposts_main/newforumposts_main.php")) -{ - require_once(e_PLUGIN."newforumposts_main/newforumposts_main.php"); -} - -render_newscats(); - -require_once(FOOTERF); - - -// ========================================================================= -function setNewsCache($cache_tag, $cache_data) { - global $e107cache; - $e107cache->set($cache_tag, $cache_data); - $e107cache->set($cache_tag."_title", defined("e_PAGETITLE") ? e_PAGETITLE : ''); - $e107cache->set($cache_tag."_diz", defined("META_DESCRIPTION") ? META_DESCRIPTION : ''); -} - -function checkCache($cacheString){ - global $pref,$e107cache; - $cache_data = $e107cache->retrieve($cacheString); - $cache_title = $e107cache->retrieve($cacheString."_title"); - $cache_diz = $e107cache->retrieve($cacheString."_diz"); - $etitle = ($cache_title != "e_PAGETITLE") ? $cache_title : ""; - $ediz = ($cache_diz != "META_DESCRIPTION") ? $cache_diz : ""; - if($etitle){ - define(e_PAGETITLE,$etitle); - } - if($ediz){ - define("META_DESCRIPTION",$ediz); - } - if ($cache_data) { - return $cache_data; - } else { - return false; - } -} - -function renderCache($cache, $nfp = FALSE){ - global $pref,$tp,$sql,$CUSTOMFOOTER, $FOOTER,$cust_footer,$ph; - global $db_debug,$ns,$eTimingStart, $error_handler, $db_time, $sql2, $mySQLserver, $mySQLuser, $mySQLpassword, $mySQLdefaultdb,$e107; - echo $cache; - if (isset($nfp) && isset($pref['nfp_display']) && $pref['nfp_display'] == 2) { - require_once(e_PLUGIN."newforumposts_main/newforumposts_main.php"); - } - render_newscats(); - require_once(FOOTERF); - exit; -} - -function render_newscats(){ // -- CNN Style Categories. ---- - $tp = e107::getParser(); - $ns = e107::getRender(); - $pref = e107::getPref(); - - if (isset($pref['news_cats']) && $pref['news_cats'] == '1') - { - $text3 = $tp->toHTML("{NEWS_CATEGORIES}", TRUE, 'TITLE'); - $ns->tablerender(LAN_NEWS_23, $text3, 'news_cat'); - } -} - -function setNewsFrontMeta($news, $type='news') -{ - - $tp = e107::getParser(); - - if($type == 'news') - { - if($news['news_title'] && !defined('e_PAGETITLE')) - { - define('e_PAGETITLE', $news['news_title']); - e107::meta('og:title',$news['news_title']); - e107::meta('og:type','article'); - } - - if($news['news_meta_description'] && !defined('META_DESCRIPTION')) - { - e107::meta('description',$news['news_meta_description']); - e107::meta('og:description',$news['news_meta_description']); - //define('META_DESCRIPTION', $news['news_meta_description']); // deprecated - } - elseif($news['news_summary']) // BC compatibility - { - e107::meta('og:description',$news['news_summary']); - } - - // include news-thumbnail/image in meta. - always put this one first. - if($news['news_thumbnail']) - { - $iurl = (substr($news['news_thumbnail'],0,3)=="{e_") ? $news['news_thumbnail'] : SITEURL.e_IMAGE."newspost_images/".$news['news_thumbnail']; - $tmp = explode(",", $iurl); - foreach($tmp as $mimg) - { - if(substr($mimg,-8) == '.youtube') - { - continue; - } - e107::meta('og:image',$tp->thumbUrl($tmp[0],'w=500',false,true) ); - // e107::meta('og:image',$mimg); - } - - } - - // grab all images in news-body and add to meta. - $images = e107::getBB()->getContent('img',$news['news_body'],SITEURL.e_IMAGE."newspost_images/"); - $c =1; - foreach($images as $im) - { - if($c == 4){ break; } - e107::meta('og:image',$im); - $c++; - } - - // grab all youtube videos in news-body and add thumbnails to meta. - $youtube = e107::getBB()->getContent('youtube',$news['news_body']); - $c = 1; - foreach($youtube as $yt) - { - if($c == 3){ break; } - list($img,$tmp) = explode("?",$yt); - e107::meta('og:image',"http://img.youtube.com/vi/".$img."/0.jpg"); - $c++; - } - - - - $url = e107::getUrl()->create('news/view/item', $news,'full=1'); - e107::meta('og:url',$url); - - e107::meta('article:section',$news['category_name']); - - if($news['news_meta_keywords'] && !defined('META_KEYWORDS')) - { - e107::meta('keywords',$news['news_meta_keywords']); - $tmp = explode(",",$news['news_meta_keywords']); - foreach($tmp as $t) - { - e107::meta('article:tag', trim($t)); - } - - // define('META_KEYWORDS', $news['news_meta_keywords']); // deprecated - } - - - /* Facebook reference. - * http://developers.facebook.com/docs/opengraph/objects/builtin/ - */ - - return; - } - - - - if($news['category_name'] && !defined('e_PAGETITLE') && $type == 'category') - { - define('e_PAGETITLE', $tp->toHtml($news['category_name'],false,'TITLE_PLAIN')); - } - - if($news['category_meta_keywords'] && !defined('META_KEYWORDS')) - { - define('META_KEYWORDS', $news['category_meta_keywords']); - } - - if($news['category_meta_description'] && !defined('META_DESCRIPTION')) - { - define('META_DESCRIPTION', $news['category_meta_description']); - } - - - -} - - -?> +?> \ No newline at end of file diff --git a/search.php b/search.php index 00572b115..5aac25d26 100644 --- a/search.php +++ b/search.php @@ -1084,7 +1084,7 @@ if (check_class($search_prefs['google'])) { if ($perform_search) { - $con = new convert; + $con = e107::getDate(); $sch = new e_search; From 6b925a6f76d9ec48f1a052fbbcbdabf722fbb7dc Mon Sep 17 00:00:00 2001 From: Cameron Date: Fri, 11 May 2018 17:39:26 -0700 Subject: [PATCH 25/59] Issue #3104 - Library CSS order fix. --- e107_core/templates/header_default.php | 3 ++- e107_handlers/js_manager.php | 27 ++++++++++++++++++++++++++ e107_handlers/library_manager.php | 5 +++-- e107_themes/bootstrap4/theme.php | 2 +- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/e107_core/templates/header_default.php b/e107_core/templates/header_default.php index 286fb31cc..869a3f546 100644 --- a/e107_core/templates/header_default.php +++ b/e107_core/templates/header_default.php @@ -172,6 +172,7 @@ echo "".(defined('e_PAGETITLE') ? e_PAGETITLE.' - ' : (defined('PAGE_NAME // D: Register CSS // $e_js = e107::getJs(); + $e_pref = e107::getConfig('core'); // Other Meta tags. @@ -315,7 +316,7 @@ else -$CSSORDER = deftrue('CSSORDER') ? explode(",",CSSORDER) : array('other','core','plugin','theme','inline'); +$CSSORDER = deftrue('CSSORDER') ? explode(",",CSSORDER) : array('library', 'other','core','plugin','theme','inline'); foreach($CSSORDER as $val) diff --git a/e107_handlers/js_manager.php b/e107_handlers/js_manager.php index 1ee36df99..f44cf1e5f 100644 --- a/e107_handlers/js_manager.php +++ b/e107_handlers/js_manager.php @@ -358,6 +358,21 @@ class e_jsmanager return $this; } + /** + * Add CSS file(s) for inclusion in site header in the 'library' category. + * + * @param string|array $file_path path, shortcodes usage is prefered + * @param string $media any valid media attribute string - http://www.w3schools.com/TAGS/att_link_media.asp + * @return e_jsmanager + */ + public function libraryCSS($file_path, $media = 'all', $preComment = '', $postComment = '') + { + $this->addJs('library_css', $file_path, $media, $preComment, $postComment); + return $this; + } + + + /** * Add CSS file(s) for inclusion in site header * @@ -962,6 +977,13 @@ class e_jsmanager $runtime = true; break; + case 'library_css': + $file_path = $runtime_location.$this->_sep.$tp->createConstants($file_path, 'mix').$this->_sep.$pre.$this->_sep.$post; + if(!isset($this->_e_css['library'])) $this->_e_css['library'] = array(); + $registry = &$this->_e_css['library']; + $runtime = true; + break; + case 'inline_css': // no zones, TODO - media? $this->_e_css_src[] = $file_path; return $this; @@ -1129,6 +1151,11 @@ class e_jsmanager unset($this->_e_css['other']); break; + case 'library_css': + $this->renderFile(varset($this->_e_css['library'], array()), $external, 'Library CSS', $mod, false); + unset($this->_e_css['library']); + break; + case 'inline_css': $this->renderInline($this->_e_css_src, 'Inline CSS', 'css'); $this->_e_css_src = array(); diff --git a/e107_handlers/library_manager.php b/e107_handlers/library_manager.php index 57be5a1f0..8ff92d68a 100755 --- a/e107_handlers/library_manager.php +++ b/e107_handlers/library_manager.php @@ -300,7 +300,7 @@ class core_library ), 'css' => array( 'dist/css/bootstrap.min.css' => array( - 'zone' => 2, + 'zone' => 1, ), ), ), @@ -1724,7 +1724,8 @@ class e_library_manager } elseif($type == 'css') { - e107::css($options['type'], $data, null); + e107::getJs()->libraryCSS($data); // load before others. + // e107::css($options['type'], $data, null); } $count++; } diff --git a/e107_themes/bootstrap4/theme.php b/e107_themes/bootstrap4/theme.php index 1cf1cbb08..7439e1185 100644 --- a/e107_themes/bootstrap4/theme.php +++ b/e107_themes/bootstrap4/theme.php @@ -7,7 +7,7 @@ if ( ! defined('e107_INIT')) { exit(); } e107::meta('viewport', 'width=device-width, initial-scale=1.0'); //e107::meta('apple-mobile-web-app-capable','yes'); - +e107::css("url", "https://bootswatch.com/4/slate/bootstrap.min.css" ); $HEADER = array(); $FOOTER = array(); From 07d30296dc9c117b1bac0cfaa5cf34962b9b4184 Mon Sep 17 00:00:00 2001 From: Cameron <e107inc@gmail.com> Date: Fri, 11 May 2018 17:55:10 -0700 Subject: [PATCH 26/59] Issue #2630 Check for PDO MySQL module during install. --- install.php | 1 + 1 file changed, 1 insertion(+) diff --git a/install.php b/install.php index 3002519b5..252cf97b9 100644 --- a/install.php +++ b/install.php @@ -885,6 +885,7 @@ class e_install */ $extensionCheck = array( + 'pdo' => array('label'=> "PDO (MySQL)", 'status' => extension_loaded('pdo_mysql'), 'url'=> ''), 'xml' => array('label'=> LANINS_050, 'status' => function_exists('utf8_encode'), 'url'=> 'http://php.net/manual/en/ref.xml.php'), 'exif' => array('label'=> LANINS_048, 'status' => function_exists('exif_imagetype'), 'url'=> 'http://php.net/manual/en/book.exif.php'), 'curl' => array('label'=> 'Curl Library', 'status' => function_exists('curl_version'), 'url'=> 'http://php.net/manual/en/book.curl.php'), From 6413157b5ed10bd8f47b19b6c4b333913f029d38 Mon Sep 17 00:00:00 2001 From: rica-carv <rica-carv@users.noreply.github.com> Date: Sat, 12 May 2018 13:13:13 +0100 Subject: [PATCH 27/59] #3123 patch #3123 patch --- e107_plugins/forum/templates/forum_viewforum_template.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e107_plugins/forum/templates/forum_viewforum_template.php b/e107_plugins/forum/templates/forum_viewforum_template.php index 9c84889b5..77cf88cab 100644 --- a/e107_plugins/forum/templates/forum_viewforum_template.php +++ b/e107_plugins/forum/templates/forum_viewforum_template.php @@ -345,7 +345,7 @@ $FORUM_VIEWFORUM_TEMPLATE['divider-normal'] = "<tr><th colspan='2'>".LAN_FORUM_ $FORUM_VIEWFORUM_TEMPLATE['divider-important'] = "<tr><th colspan='2'>".LAN_FORUM_1006."</th><th class='text-center'>".LAN_FORUM_0003."</th><th class='hidden-xs text-center'>".LAN_FORUM_1005."</th><th class='hidden-xs'>".LAN_FORUM_0004."</th></tr>"; $FORUM_VIEWFORUM_TEMPLATE['divider-normal'] = "<tr><th colspan='2'>".LAN_FORUM_1007."</th><th class='text-center' >".LAN_FORUM_0003."</th><th class='hidden-xs text-center'>".LAN_FORUM_1005."</th><th class='hidden-xs'>".LAN_FORUM_0004."</th></tr>"; -$SC_WRAPPER['VIEWABLE_BY'] = "<div class='panel panel-default' style='margin-top:10px'><div class='panel-heading'>".LAN_FORUM_8012."</div><div class='panel-body'>{---}</div></div></div>"; +$SC_WRAPPER['VIEWABLE_BY'] = "<div class='panel panel-default' style='margin-top:10px'><div class='panel-heading'>".LAN_FORUM_8012."</div><div class='panel-body'>{---}</div></div>"; $FORUM_VIEWFORUM_TEMPLATE['footer'] = "</table> <div class='row row-fluid'> From ac959243747dcee5e3a54041e78a0e9c81b1c817 Mon Sep 17 00:00:00 2001 From: Cameron <e107inc@gmail.com> Date: Sat, 12 May 2018 10:22:58 -0700 Subject: [PATCH 28/59] Issue #3104 Library CSS fix for admin area. --- e107_admin/header.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/e107_admin/header.php b/e107_admin/header.php index dd858f6b2..f0ad7092d 100644 --- a/e107_admin/header.php +++ b/e107_admin/header.php @@ -165,6 +165,7 @@ echo "<title>".(defined("e_PAGETITLE") ? e_PAGETITLE." - " : (defined("PAGE_NAME echo "<!-- *CSS* -->\n"; $e_js = e107::getJs(); + // Core CSS - XXX awaiting for path changes if (!isset($no_core_css) || !$no_core_css) { @@ -267,9 +268,13 @@ unset($e_headers); // ################### RENDER CSS +echo "\n<!-- Library CSS -->\n"; + +$e_js->renderJs('library_css', false, 'css', false); + // Other CSS - from unknown location, different from core/theme/plugin location or backward compatibility $e_js->renderJs('other_css', false, 'css', false); -echo "\n<!-- footer_other_css -->\n"; +echo "\n<!-- footer_other_css -->\n"; // substituted in footer when detected. // Core CSS $e_js->renderJs('core_css', false, 'css', false); From ac4b505ceb0b59f94c1e95afb0e01e5bcd8fd5a7 Mon Sep 17 00:00:00 2001 From: Cameron <e107inc@gmail.com> Date: Sat, 12 May 2018 11:45:55 -0700 Subject: [PATCH 29/59] Issue #3104 Library CSS fix for late calls. (eg. bootstrap-switch ) --- e107_admin/footer.php | 8 ++++++++ e107_admin/header.php | 1 + e107_core/templates/footer_default.php | 2 +- e107_handlers/js_manager.php | 1 + 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/e107_admin/footer.php b/e107_admin/footer.php index dacce49e9..1132b3868 100644 --- a/e107_admin/footer.php +++ b/e107_admin/footer.php @@ -367,6 +367,14 @@ echo "</body></html>"; // SecretR - EXPERIMENT! SEND CSS data to header. Performance tests in progress. $tmp = array(); $e_js = e107::getJs(); + +$tmp0 = $e_js->renderJs('library_css', false, 'css', true); +if($tmp0) +{ + $tmp['search'][] = '<!-- footer_library_css -->'; + $tmp['replace'][] = $tmp0; +} + // Other CSS - from unknown location, different from core/theme/plugin location or backward compatibility $tmp1 = $e_js->renderJs('other_css', false, 'css', true); if($tmp1) diff --git a/e107_admin/header.php b/e107_admin/header.php index f0ad7092d..4b705759e 100644 --- a/e107_admin/header.php +++ b/e107_admin/header.php @@ -271,6 +271,7 @@ unset($e_headers); echo "\n<!-- Library CSS -->\n"; $e_js->renderJs('library_css', false, 'css', false); +echo "\n<!-- footer_library_css -->\n"; // substituted in footer when detected. // Other CSS - from unknown location, different from core/theme/plugin location or backward compatibility $e_js->renderJs('other_css', false, 'css', false); diff --git a/e107_core/templates/footer_default.php b/e107_core/templates/footer_default.php index 3fafe674e..ad9656fd6 100644 --- a/e107_core/templates/footer_default.php +++ b/e107_core/templates/footer_default.php @@ -305,7 +305,7 @@ if(deftrue('e_DEVELOPER')) { echo "\n\n<!-- ======= [JSManager] FOOTER: Remaining CSS ======= -->"; } -$CSSORDER = deftrue('CSSORDER') ? explode(",",CSSORDER) : array('other','core','plugin','theme'); // INLINE CSS in Body not supported by HTML5. . +$CSSORDER = deftrue('CSSORDER') ? explode(",",CSSORDER) : array('library','other','core','plugin','theme'); // INLINE CSS in Body not supported by HTML5. . foreach($CSSORDER as $val) { diff --git a/e107_handlers/js_manager.php b/e107_handlers/js_manager.php index f44cf1e5f..e21211d90 100644 --- a/e107_handlers/js_manager.php +++ b/e107_handlers/js_manager.php @@ -979,6 +979,7 @@ class e_jsmanager case 'library_css': $file_path = $runtime_location.$this->_sep.$tp->createConstants($file_path, 'mix').$this->_sep.$pre.$this->_sep.$post; + // e107::getDebug()->log($file_path); if(!isset($this->_e_css['library'])) $this->_e_css['library'] = array(); $registry = &$this->_e_css['library']; $runtime = true; From 34b422ff5857e4b64ea8b3b6350dfff13e1088ff Mon Sep 17 00:00:00 2001 From: Achim Ennenbach <achim@simsync.de> Date: Tue, 15 May 2018 21:54:43 +0200 Subject: [PATCH 30/59] fixed orphaned . (dot) in convert_date --- e107_handlers/date_handler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e107_handlers/date_handler.php b/e107_handlers/date_handler.php index 34aa2b104..e2f404d5a 100644 --- a/e107_handlers/date_handler.php +++ b/e107_handlers/date_handler.php @@ -173,7 +173,7 @@ class convert break; case 'inputtime': - $mask .= e107::getPref('inputtime', '%H:%M'); + $mask = e107::getPref('inputtime', '%H:%M'); break; case 'forum': // DEPRECATED - temporary here from BC reasons only From 6203233f302ea7005c105960543f5549ff8162b2 Mon Sep 17 00:00:00 2001 From: Achim Ennenbach <achim@simsync.de> Date: Tue, 15 May 2018 22:00:47 +0200 Subject: [PATCH 31/59] fixed issue in strptime with wrong monthname on windows --- e107_handlers/date_handler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e107_handlers/date_handler.php b/e107_handlers/date_handler.php index e2f404d5a..2afbb6d7c 100644 --- a/e107_handlers/date_handler.php +++ b/e107_handlers/date_handler.php @@ -791,7 +791,7 @@ class convert $unxTimestamp = mktime($vals['tm_hour'], $vals['tm_min'], $vals['tm_sec'], ($vals['tm_mon'] + 1), $vals['tm_mday'], ($vals['tm_year'] + 1900)); - $vals['tm_fmon'] = strftime('%B', mktime($vals['tm_hour'], $vals['tm_min'], $vals['tm_sec'], $vals['tm_mon'])); + $vals['tm_fmon'] = strftime('%B', mktime($vals['tm_hour'], $vals['tm_min'], $vals['tm_sec'], $vals['tm_mon'] + 1)); $vals['tm_wday'] = (int) strftime('%w', $unxTimestamp); // Days since Sunday (0-6) $vals['tm_yday'] = (strftime('%j', $unxTimestamp) - 1); // Days since January 1 (0-365) From fc2873f46baba3536cdb7e5cacbb2a5754e84748 Mon Sep 17 00:00:00 2001 From: Achim Ennenbach <achim@simsync.de> Date: Tue, 15 May 2018 22:21:05 +0200 Subject: [PATCH 32/59] closes e107inc/e107#3063 added option be able to set a different pattern added additional options do define step, min, max value and decimals --- e107_handlers/form_handler.php | 72 ++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/e107_handlers/form_handler.php b/e107_handlers/form_handler.php index a3c267c7b..a2737b506 100644 --- a/e107_handlers/form_handler.php +++ b/e107_handlers/form_handler.php @@ -820,7 +820,22 @@ class e_form } - + /** + * Create a input [type number] + * + * Additional options: + * - decimals: default 0; defines the number of decimals allowed in this field (0 = only integers; 1 = integers & floats with 1 decimal e.g. 4.1, etc.) + * - step: default 1; defines the step for the spinner and the max. number of decimals. If decimals is given, step will be ignored + * - min: default 0; minimum value allowed + * - max: default empty; maximum value allowed + * - pattern: default empty; allows to define an complex input pattern + * + * @param string $name + * @param integer $value + * @param integer $maxlength + * @param array $options decimals, step, min, max, pattern + * @return string + */ function number($name, $value=0, $maxlength = 200, $options = array()) { if(is_string($options)) parse_str($options, $options); @@ -852,15 +867,64 @@ class e_form $mlength = vartrue($maxlength) ? "maxlength=".$maxlength : ""; - $min = isset($options['min']) ? 'min="'.$options['min'].'"' : ''; - $max = isset($options['max']) ? 'max="'.$options['max'].'"' : ''; + // Always define the min. parameter + // defaults to 0 + // setting the min option to a negative value allows negative inputs + $min = " min='".varsettrue($options['min'], '0')."'"; + $max = isset($options['max']) ? " max='".$options['max']."'" : ''; + if (varsettrue($options['pattern'])) + { + $pattern = ' pattern="'.trim($options['pattern']).'"'; + } + else + { + $options['pattern'] = '^'; + // ^\-?[0-9]*\.?[0-9]{0,2} + if (varset($options['min'], 0) < 0) + { + $options['pattern'] .= '\-?'; + } + $options['pattern'] .= '[0-9]*'; + + // Integer & Floaat/Double value handling + if (isset($options['decimals'])) + { + if (intval($options['decimals']) > 0) + { + $options['pattern'] .= '\.?[0-9]{0,'.intval($options['decimals']).'}'; + } + + // defined the step based on number of decimals + // 2 = 0.01 > allows integers and float numbers with up to 2 decimals (3.1 = OK; 3.12 = OK; 3.123 = NOK) + // 1 = 0.1 > allows integers and float numbers with up to 2 decimals (3.1 = OK; 3.12 = NOK) + // 0 = 1 > allows only integers, no float values + if (intval($options['decimals']) <= 0) + { + $step = "step='1'"; + } + else + { + $step = "step='0." . str_pad(1, intval($options['decimals']), 0, STR_PAD_LEFT) . "'"; + } + } + else + { + // decimal option not defined + // check for step option (1, 0.1, 0.01, and so on) + // or set default step 1 (integers only) + $step = "step='" . varsettrue($options['step'], '1') . "'"; + } + + $pattern = ' pattern="'.$options['pattern'].'"'; + } $options = $this->format_options('text', $name, $options); //never allow id in format name-value for text fields if(THEME_LEGACY === false) { - return "<input pattern='[0-9]*' type='number' name='{$name}' value='{$value}' {$mlength} {$min} {$max} ".$this->get_attributes($options, $name)." />"; + // return "<input pattern='[0-9]*' type='number' name='{$name}' value='{$value}' {$mlength} {$step} {$min} {$max} ".$this->get_attributes($options, $name)." />"; + return "<input type='number' name='{$name}' {$min} {$max} {$step} value='{$value}' {$pattern}".$this->get_attributes($options, $name)." />"; } return $this->text($name, $value, $maxlength, $options); From b1473ed9194ac9baa281078984e14d4cd139ef4d Mon Sep 17 00:00:00 2001 From: Achim Ennenbach <achim@simsync.de> Date: Tue, 15 May 2018 22:56:13 +0200 Subject: [PATCH 33/59] removed orphaned variable --- e107_handlers/form_handler.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/e107_handlers/form_handler.php b/e107_handlers/form_handler.php index a2737b506..25df0ea42 100644 --- a/e107_handlers/form_handler.php +++ b/e107_handlers/form_handler.php @@ -865,7 +865,8 @@ class e_form $options['class'] .= " form-control"; $options['type'] ='number'; - $mlength = vartrue($maxlength) ? "maxlength=".$maxlength : ""; + // Not used anymore + //$mlength = vartrue($maxlength) ? "maxlength=".$maxlength : ""; // Always define the min. parameter // defaults to 0 From d7e3caae83e2feed06b68d5f4a91a234913211e1 Mon Sep 17 00:00:00 2001 From: Cameron <e107inc@gmail.com> Date: Wed, 23 May 2018 16:29:37 -0700 Subject: [PATCH 34/59] Admin-ui: Improved adminMenu highlighting when custom uri in use. Plugin Builder: added menu divider example. --- e107_admin/plugin.php | 4 +++- e107_handlers/admin_ui.php | 23 +++++++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/e107_admin/plugin.php b/e107_admin/plugin.php index fba364e94..38416524d 100755 --- a/e107_admin/plugin.php +++ b/e107_admin/plugin.php @@ -5122,7 +5122,9 @@ $text .= " "; } $text .= " - // 'main/custom' => array('caption'=> 'Custom Page', 'perm' => 'P') + // 'main/div0' => array('divider'=> true), + // 'main/custom' => array('caption'=> 'Custom Page', 'perm' => 'P'), + ); protected \$adminMenuAliases = array( diff --git a/e107_handlers/admin_ui.php b/e107_handlers/admin_ui.php index 425da2e45..2ab8383ca 100755 --- a/e107_handlers/admin_ui.php +++ b/e107_handlers/admin_ui.php @@ -1479,6 +1479,7 @@ class e_admin_dispatcher $tp = e107::getParser(); $var = array(); $selected = false; + foreach($this->adminMenu as $key => $val) { @@ -1516,6 +1517,12 @@ class e_admin_dispatcher case 'uri': $k2 = 'link'; $v = $tp->replaceConstants($v, 'abs'); + + if(!empty($v) && (e_REQUEST_URI === $v)) + { + $selected = $key; + } + break; default: @@ -1880,6 +1887,8 @@ class e_admin_controller $data = $_dispatcher->getPageTitles(); $search = $this->getMode().'/'.$this->getAction(); + + if(isset($data[$search])) { $res['caption'] = $data[$search]; @@ -2152,9 +2161,9 @@ class e_admin_controller return $response; } - if($action != 'Prefs' && $action != 'Create' && $action !='Edit' && $action != 'List') // Custom Page method in use, so add the title. + if($action != 'Prefs' && $action != 'Create' && $action !='Edit' && $action != 'List') // Custom Page method in use, so add the title. { - $this->addTitle(); + $this->addTitle(); } @@ -2164,6 +2173,9 @@ class e_admin_controller { $this->addTitle('#'.$this->getId()); // Inform user of which record is being edited. } + + + ob_start(); //catch any output $ret = $this->{$actionName}(); @@ -5478,6 +5490,13 @@ class e_admin_ui extends e_admin_controller_ui $this->getTreeModel()->setParam('db_query', $this->_modifyListQry(false, false, false, false, $this->listQry))->load(); $this->addTitle(); + + if($this->getQuery('filter_options')) + { + // var_dump($this); + // $this->addTitle("to-do"); // display filter option when active. + } + } /** From aa53328ef0fe5d68f6de0205da4339d97795644f Mon Sep 17 00:00:00 2001 From: Cameron <e107inc@gmail.com> Date: Wed, 23 May 2018 17:02:33 -0700 Subject: [PATCH 35/59] Issue #2222 - User Ranks experimental admin area moved to stable. --- e107_admin/users.php | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/e107_admin/users.php b/e107_admin/users.php index acb83eaf8..aa02fc828 100644 --- a/e107_admin/users.php +++ b/e107_admin/users.php @@ -60,7 +60,7 @@ class users_admin extends e_admin_dispatcher 'main/list' => array('caption'=> LAN_MANAGE, 'perm' => '0|4'), 'main/add' => array('caption'=> LAN_USER_QUICKADD, 'perm' => '4|U0|U1'), 'main/prefs' => array('caption'=> LAN_OPTIONS, 'perm' => '4|U2'), - 'main/ranks' => array('caption'=> LAN_USER_RANKS, 'perm' => '4|U3'), + 'ranks/list' => array('caption'=> LAN_USER_RANKS, 'perm' => '4|U3'), 'main/maintenance' => array('caption'=> LAN_MAINTENANCE, 'perms'=>'4') // 'ranks/list' => array('caption'=> LAN_USER_RANKS, 'perm' => '4|U3') ); @@ -86,11 +86,6 @@ class users_admin extends e_admin_dispatcher function init() { - if(E107_DEBUG_LEVEL > 0) - { - $this->adminMenu['ranks/list'] = array('caption'=> LAN_USER_RANKS. " (experimental)", 'perm' => '4|U3'); - } - $JS = <<<JS @@ -470,7 +465,7 @@ class users_admin_ui extends e_admin_ui } - public function afterDelete($deletedData,$id=null) + public function afterDelete($deletedData, $id=null, $deleted_check) { if(!empty($id)) { @@ -2860,10 +2855,10 @@ class users_admin_form_ui extends e_admin_form_ui } unset($tmp); - natsort($imageList); + // natsort($imageList); } - public function afterDelete($data) + public function afterDelete($data, $id, $deleted_check) { e107::getCache()->clear_sys('nomd5_user_ranks'); } From 25310a901b7176f1ed5e45c98b11c7e7928a125f Mon Sep 17 00:00:00 2001 From: Nick Liu <deltik@gmx.com> Date: Wed, 23 May 2018 19:33:35 -0500 Subject: [PATCH 36/59] Downloads plugin compatibility with PHP 5.4, 5.5 - FIX: Avoided use of PHP 5.6 feature in Downloads plugin's NginxSecureLinkMd5Decorator Fixes: #3135 --- .../download/handlers/NginxSecureLinkMd5Decorator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php b/e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php index 7e36cbace..a3b62c955 100644 --- a/e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php +++ b/e107_plugins/download/handlers/NginxSecureLinkMd5Decorator.php @@ -6,14 +6,14 @@ class NginxSecureLinkMd5Decorator implements SecureLinkDecorator protected $url = null; protected $prefs = array(); - const SUPPORTED_VARIABLES = array( + public static $SUPPORTED_VARIABLES = array( '$secure_link_expires', '$uri', '$remote_addr' ); static function supported_variables() { - return self::SUPPORTED_VARIABLES; + return self::$SUPPORTED_VARIABLES; } function __construct($url, $preferences) From 0c1ab458358eefdb0200bce482fec867b6b88d5d Mon Sep 17 00:00:00 2001 From: Cameron <e107inc@gmail.com> Date: Wed, 23 May 2018 18:47:34 -0700 Subject: [PATCH 37/59] Form Handler Fixed drop-down 'empty' value check. --- e107_handlers/form_handler.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/e107_handlers/form_handler.php b/e107_handlers/form_handler.php index 3ec0daece..2fbb883fb 100644 --- a/e107_handlers/form_handler.php +++ b/e107_handlers/form_handler.php @@ -874,7 +874,7 @@ class e_form $min = " min='".varsettrue($options['min'], '0')."'"; $max = isset($options['max']) ? " max='".$options['max']."'" : ''; - if (varsettrue($options['pattern'])) + if (!empty($options['pattern'])) { $pattern = ' pattern="'.trim($options['pattern']).'"'; } @@ -925,7 +925,7 @@ class e_form if(THEME_LEGACY === false) { // return "<input pattern='[0-9]*' type='number' name='{$name}' value='{$value}' {$mlength} {$step} {$min} {$max} ".$this->get_attributes($options, $name)." />"; - return "<input type='number' name='{$name}' {$min} {$max} {$step} value='{$value}' {$pattern}".$this->get_attributes($options, $name)." />"; + return "<input type='number' name='{$name}' {$min} {$max} {$step} value='{$value}' ".$this->get_attributes($options, $name)." />"; } return $this->text($name, $value, $maxlength, $options); @@ -5723,15 +5723,13 @@ class e_form $eloptions = vartrue($parms['__options'], array()); } - $value = (isset($eloptions['empty']) && empty($value)) ? $eloptions['empty'] : $value; + $value = (isset($eloptions['empty']) && ($value === null)) ? $eloptions['empty'] : $value; if(is_string($eloptions)) parse_str($eloptions, $eloptions); if($attributes['type'] === 'comma') $eloptions['multiple'] = true; unset($parms['__options']); if(vartrue($eloptions['multiple']) && !is_array($value)) $value = explode(',', $value); - - // Allow Ajax API. if(!empty($ajaxParms)) { From b06d67d0a1399a865dafab43d1bcaa0698fdbfe9 Mon Sep 17 00:00:00 2001 From: Cameron <e107inc@gmail.com> Date: Thu, 24 May 2018 07:39:54 -0700 Subject: [PATCH 38/59] Date handler. Reduce usage of strptime(). Date format conversion from strftime() > DateTime added to toMask() method. --- e107_handlers/date_handler.php | 81 ++++++++++++++++++++++++++++------ 1 file changed, 67 insertions(+), 14 deletions(-) diff --git a/e107_handlers/date_handler.php b/e107_handlers/date_handler.php index 35fb1e102..fc6d65a8b 100644 --- a/e107_handlers/date_handler.php +++ b/e107_handlers/date_handler.php @@ -224,18 +224,26 @@ class e_date return is_numeric($string) ? $this->convert_date($string, $mask) : $this->toTime($string, $mask); } - + + + /** * Converts to new date-mask format or vice-versa when $legacy is TRUE + * + * string $mask + * string|bool $legacy false= strftime > datetimepicker, true = datetimepicker > strftime, 'DateTime' = strftime > DateTime format. + * @see https://secure.php.net/manual/en/function.strftime.php * @see https://github.com/AuspeXeu/bootstrap-datetimepicker + * @see https://secure.php.net/manual/en/datetime.createfromformat.php */ function toMask($mask, $legacy = false) { + //strftime() -> datetimepicker format. $convert = array( - '%Y' => 'yyyy', // jquery-ui docs say 'yy' but yy produces '13' instead of '2013' - '%d' => 'dd', - '%m' => 'mm', + '%Y' => 'yyyy', // Year 4-digits '2013' + '%d' => 'dd', // day of the month 2-digits + '%m' => 'mm', // month number 2-digits '%B' => 'MM', // Full month name, based on the locale '%A' => 'DD', // A full textual representation of the day @@ -250,12 +258,46 @@ class e_date '%M' => 'ii', // Two digit representation of the minute '%S' => 'ss', // Two digit representation of the second '%P' => 'p', // %P lower-case 'am' or 'pm' based on the given time - '%p' => 'P', // %p UPPER-CASE 'AM' or 'PM' based on the given time + '%p' => 'P', // %p UPPER-CASE 'AM' or 'PM' based on the given time '%T' => 'hh:mm:ss', '%r' => "hh:mmm:ss TT" // 12 hour format ); - + + // strftime() > DateTime:: + if($legacy === 'DateTime') + { + $convert = array( + '%Y' => 'Y', // Year 4-digits '2013' + '%d' => 'd', // Two-digit day of the month (with leading zeros) (01 through 31) + '%e' => 'j', // Day of the month, with a space preceding single digits. Not implemented on Windows with strftime. + '%m' => 'm', // Two digit representation of the month (01 throught 12) + '%B' => 'F', // Full month name, based on the locale + '%A' => 'l', // A full textual representation of the day + + '%y' => 'y', + '%a' => 'D', // An abbreviated textual representation of the day + '%b' => 'M', // Abbreviated month name, based on the locale + '%h' => 'M', // Abbreviated month name, based on the locale (an alias of %b) + + '%k' => 'G', // Hour in 24-hour format, with a space preceding single digits (0 through 23) + '%I' => 'h', // Two digit representation of the hour in 12-hour format ( 01 through 12) + '%l' => 'g', // 12 hour format - no leading zero (1 through 12) + '%H' => 'H', // Two digit representation of the hour in 24-hour format (00 through 23) + + '%M' => 'i', // Two digit representation of the minute (00 through 59) + '%S' => 's', // Two digit representation of the second (00 through 59) + '%P' => 'a', // lower-case 'am' or 'pm' based on the given time + '%p' => 'A', // UPPER-CASE 'AM' or 'PM' based on the given time + '%Z' => 'e', // The time zone abbreviation. Not implemented as described on Windows with strftime. + + // TODO Add anything that is missing. + // '%T' => 'hh:mm:ss', + // '%r' => "hh:mmm:ss TT" // 12 hour format + ); + } + + $s = array_keys($convert); $r = array_values($convert); @@ -359,8 +401,24 @@ class e_date $mask = e107::getPref('inputtime', '%H:%M'); break; } - - // also in php compat handler for plugins that might use it. + + // convert to PHP 5+ @see https://secure.php.net/manual/en/datetime.createfromformat.php + $newMask = $this->toMask($mask, 'DateTime'); + $tdata = date_parse_from_format($newMask, $date_string); + + return mktime( + $tdata['hour'], + $tdata['minute'], + $tdata['second'], + $tdata['month'] , + $tdata['day'], + $tdata['year'] + ); + + + // also in php compat handler for plugins that might use it. + + /* $tdata = $this->strptime($date_string, $mask); @@ -387,14 +445,9 @@ class e_date $tdata['tm_mday'], ($tdata['tm_year'] + 1900) ); - - - // echo "<br />UNIX=".$unxTimestamp - TIMEOFFSET; - // echo "<br />".date("l, d M Y g:i A",$unxTimestamp); - - // var_dump($tdata, $date_string, $this->convert_date($unxTimestamp, $mask), $unxTimestamp); return $unxTimestamp; + */ } // ----------------------- From 8a6f1f5199b6e75526b8eed94db7ce60b561abb7 Mon Sep 17 00:00:00 2001 From: Achim Ennenbach <achim@simsync.de> Date: Thu, 24 May 2018 21:25:51 +0200 Subject: [PATCH 39/59] Fix for missing entries in strptime result array on Windows --- .gitignore | 2 ++ e107_handlers/date_handler.php | 27 ++++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index b9b73c25d..37bc22dc7 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ e107_core/override # Ignore Vim swap files *.swp *.swo +e107.htaccess +e107InstallLog.log diff --git a/e107_handlers/date_handler.php b/e107_handlers/date_handler.php index fc6d65a8b..b9e5a0b0d 100644 --- a/e107_handlers/date_handler.php +++ b/e107_handlers/date_handler.php @@ -840,10 +840,31 @@ class e_date #-- calculate wday/yday //$vals['tm_mon'] = $vals['tm_mon'] + 1; // returns months from 0 - 11 so we need to +1 - - + + if (!isset($vals['tm_sec'])) + { + $vals['tm_sec'] = 0; + } + + if (!isset($vals['tm_min'])) + { + $vals['tm_min'] = 0; + } + + if (!isset($vals['tm_hour'])) + { + $vals['tm_hour'] = 0; + } + + + if (!isset($vals['unparsed'])) + { + $vals['unparsed'] = ''; + } + $unxTimestamp = mktime($vals['tm_hour'], $vals['tm_min'], $vals['tm_sec'], ($vals['tm_mon'] + 1), $vals['tm_mday'], ($vals['tm_year'] + 1900)); - + + $vals['tm_amon'] = strftime('%b', mktime($vals['tm_hour'], $vals['tm_min'], $vals['tm_sec'], $vals['tm_mon'] + 1)); $vals['tm_fmon'] = strftime('%B', mktime($vals['tm_hour'], $vals['tm_min'], $vals['tm_sec'], $vals['tm_mon'] + 1)); $vals['tm_wday'] = (int) strftime('%w', $unxTimestamp); // Days since Sunday (0-6) $vals['tm_yday'] = (strftime('%j', $unxTimestamp) - 1); // Days since January 1 (0-365) From 171a914acf4a7ac19a536d9f570c7ff5a416b331 Mon Sep 17 00:00:00 2001 From: Cameron <e107inc@gmail.com> Date: Thu, 24 May 2018 13:05:43 -0700 Subject: [PATCH 40/59] Experimental e_user.php code added. --- e107_plugins/_blank/e_user.php | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/e107_plugins/_blank/e_user.php b/e107_plugins/_blank/e_user.php index 546355081..cc7056ff5 100644 --- a/e107_plugins/_blank/e_user.php +++ b/e107_plugins/_blank/e_user.php @@ -25,16 +25,29 @@ class _blank_user // plugin-folder + '_user' } - - function fields() + /** + * Experimental and subject to change without notice. + * @return mixed + */ + function delete() { - $fields = array( - - - + $config['user'] = array( + 'user_name' => 'Deleted User', + 'user_loginname' => '', + 'user_email' => '', + 'user_ip' => '', + // etc. + 'WHERE' => 'user_id = '.USERID, + 'MODE' => 'update' ); + $config['user_extended'] = array( + 'WHERE' => 'user_extended_id = '.USERID, + 'MODE' => 'delete' + ); + + return $config; } From 8327acb33e767008ee620ff0ca910dcbef6feee2 Mon Sep 17 00:00:00 2001 From: Cameron <e107inc@gmail.com> Date: Thu, 24 May 2018 13:14:48 -0700 Subject: [PATCH 41/59] Tweak e_user.php --- e107_plugins/_blank/e_user.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/e107_plugins/_blank/e_user.php b/e107_plugins/_blank/e_user.php index cc7056ff5..42e96bd2f 100644 --- a/e107_plugins/_blank/e_user.php +++ b/e107_plugins/_blank/e_user.php @@ -26,16 +26,17 @@ class _blank_user // plugin-folder + '_user' /** - * Experimental and subject to change without notice. + * Experimental and subject to change without notice. * @return mixed */ function delete() { $config['user'] = array( - 'user_name' => 'Deleted User', - 'user_loginname' => '', - 'user_email' => '', + 'user_id' => '[primary]', + 'user_name' => '[unique]', + 'user_loginname' => '[unique]', + 'user_email' => '[unique]', 'user_ip' => '', // etc. 'WHERE' => 'user_id = '.USERID, From 998a8fe7c3269b72c287c852ec6e540310409dad Mon Sep 17 00:00:00 2001 From: Cameron <e107inc@gmail.com> Date: Thu, 24 May 2018 15:16:02 -0700 Subject: [PATCH 42/59] JS datetimepicker() updated to latest version. Fixed datetimepicker() to respect the e107 timezone setting while saving as UTC. ie (admin > prefs > Date Display Options ) or the user's timezone setting (usersettings.php when the timezone user-extended field is enabled) . --- class2.php | 3 +++ e107_handlers/form_handler.php | 4 ++-- .../css/bootstrap-datetimepicker.min.css | 2 +- .../js/bootstrap-datetimepicker.init.js | 18 +++++++++++++++--- .../js/bootstrap-datetimepicker.min.js | 2 +- 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/class2.php b/class2.php index f6b227d73..bbe5494b1 100755 --- a/class2.php +++ b/class2.php @@ -1957,6 +1957,9 @@ function init_session() unset($tz); } +e107::getDebug()->log("Timezone: ".USERTIMEZONE); // remove later on. + + define('USERIP', e107::getIPHandler()->getIP(FALSE)); define('POST_REFERER', md5($user->getToken())); diff --git a/e107_handlers/form_handler.php b/e107_handlers/form_handler.php index 2fbb883fb..28734d472 100644 --- a/e107_handlers/form_handler.php +++ b/e107_handlers/form_handler.php @@ -1499,11 +1499,11 @@ class e_form if(vartrue($options['inline'])) { $text .= "<div class='{$class}' id='inline-{$id}' data-date-format='{$dformat}' data-date-ampm='{$ampm}' data-date-firstday='{$firstDay}'></div>"; - $text .= "<input type='hidden' name='{$name}' id='{$id}' value='{$value}' data-date-format='{$dformat}' data-date-ampm='{$ampm}' data-date-firstday='{$firstDay}' />"; + $text .= "<input type='hidden' name='{$name}' id='{$id}' value='{$value}' data-date-format='{$dformat}' data-date-ampm='{$ampm}' data-date-firstday='{$firstDay}' data-date-timezone-offset='".date('Z')."' />"; } else { - $text .= "<input class='{$class} input-".$xsize." form-control' type='text' size='{$size}' id='e-datepicker-{$id}' value='{$value}' data-date-unix ='{$useUnix}' data-date-format='{$dformat}' data-date-ampm='{$ampm}' data-date-language='".e_LAN."' data-date-firstday='{$firstDay}' {$required} {$disabled} />"; + $text .= "<input class='{$class} input-".$xsize." form-control' type='text' size='{$size}' id='e-datepicker-{$id}' value='{$value}' data-date-unix ='{$useUnix}' data-date-format='{$dformat}' data-date-ampm='{$ampm}' data-date-language='".e_LAN."' data-date-firstday='{$firstDay}' {$required} {$disabled} data-date-timezone-offset='".date('Z')."' />"; $ftype = (!empty($options['debug'])) ? 'text' : 'hidden'; $text .= "<input type='{$ftype}' name='{$name}' id='{$id}' value='{$hiddenValue}' />"; } diff --git a/e107_web/js/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css b/e107_web/js/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css index d0f3dff66..78485fee7 100644 --- a/e107_web/js/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css +++ b/e107_web/js/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css @@ -6,4 +6,4 @@ * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * - */.datetimepicker{padding:4px;margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;direction:ltr}.datetimepicker-inline{width:220px}.datetimepicker.datetimepicker-rtl{direction:rtl}.datetimepicker.datetimepicker-rtl table tr td span{float:right}.datetimepicker-dropdown,.datetimepicker-dropdown-left{top:0;left:0}[class*=" datetimepicker-dropdown"]:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,0.2);position:absolute}[class*=" datetimepicker-dropdown"]:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute}[class*=" datetimepicker-dropdown-top"]:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-top:7px solid #ccc;border-top-color:rgba(0,0,0,0.2);border-bottom:0}[class*=" datetimepicker-dropdown-top"]:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #fff;border-bottom:0}.datetimepicker-dropdown-bottom-left:before{top:-7px;right:6px}.datetimepicker-dropdown-bottom-left:after{top:-6px;right:7px}.datetimepicker-dropdown-bottom-right:before{top:-7px;left:6px}.datetimepicker-dropdown-bottom-right:after{top:-6px;left:7px}.datetimepicker-dropdown-top-left:before{bottom:-7px;right:6px}.datetimepicker-dropdown-top-left:after{bottom:-6px;right:7px}.datetimepicker-dropdown-top-right:before{bottom:-7px;left:6px}.datetimepicker-dropdown-top-right:after{bottom:-6px;left:7px}.datetimepicker>div{display:none}.datetimepicker.minutes div.datetimepicker-minutes{display:block}.datetimepicker.hours div.datetimepicker-hours{display:block}.datetimepicker.days div.datetimepicker-days{display:block}.datetimepicker.months div.datetimepicker-months{display:block}.datetimepicker.years div.datetimepicker-years{display:block}.datetimepicker table{margin:0}.datetimepicker td,.datetimepicker th{text-align:center;width:20px;height:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;border:0}.table-striped .datetimepicker table tr td,.table-striped .datetimepicker table tr th{background-color:transparent}.datetimepicker table tr td.minute:hover{background:#eee;cursor:pointer}.datetimepicker table tr td.hour:hover{background:#eee;cursor:pointer}.datetimepicker table tr td.day:hover{background:#eee;cursor:pointer}.datetimepicker table tr td.old,.datetimepicker table tr td.new{color:#999}.datetimepicker table tr td.disabled,.datetimepicker table tr td.disabled:hover{background:0;color:#999;cursor:default}.datetimepicker table tr td.today,.datetimepicker table tr td.today:hover,.datetimepicker table tr td.today.disabled,.datetimepicker table tr td.today.disabled:hover{background-color:#fde19a;background-image:-moz-linear-gradient(top,#fdd49a,#fdf59a);background-image:-ms-linear-gradient(top,#fdd49a,#fdf59a);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fdd49a),to(#fdf59a));background-image:-webkit-linear-gradient(top,#fdd49a,#fdf59a);background-image:-o-linear-gradient(top,#fdd49a,#fdf59a);background-image:linear-gradient(top,#fdd49a,#fdf59a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a',endColorstr='#fdf59a',GradientType=0);border-color:#fdf59a #fdf59a #fbed50;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.datetimepicker table tr td.today:hover,.datetimepicker table tr td.today:hover:hover,.datetimepicker table tr td.today.disabled:hover,.datetimepicker table tr td.today.disabled:hover:hover,.datetimepicker table tr td.today:active,.datetimepicker table tr td.today:hover:active,.datetimepicker table tr td.today.disabled:active,.datetimepicker table tr td.today.disabled:hover:active,.datetimepicker table tr td.today.active,.datetimepicker table tr td.today:hover.active,.datetimepicker table tr td.today.disabled.active,.datetimepicker table tr td.today.disabled:hover.active,.datetimepicker table tr td.today.disabled,.datetimepicker table tr td.today:hover.disabled,.datetimepicker table tr td.today.disabled.disabled,.datetimepicker table tr td.today.disabled:hover.disabled,.datetimepicker table tr td.today[disabled],.datetimepicker table tr td.today:hover[disabled],.datetimepicker table tr td.today.disabled[disabled],.datetimepicker table tr td.today.disabled:hover[disabled]{background-color:#fdf59a}.datetimepicker table tr td.today:active,.datetimepicker table tr td.today:hover:active,.datetimepicker table tr td.today.disabled:active,.datetimepicker table tr td.today.disabled:hover:active,.datetimepicker table tr td.today.active,.datetimepicker table tr td.today:hover.active,.datetimepicker table tr td.today.disabled.active,.datetimepicker table tr td.today.disabled:hover.active{background-color:#fbf069}.datetimepicker table tr td.active,.datetimepicker table tr td.active:hover,.datetimepicker table tr td.active.disabled,.datetimepicker table tr td.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-ms-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(top,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc',endColorstr='#0044cc',GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datetimepicker table tr td.active:hover,.datetimepicker table tr td.active:hover:hover,.datetimepicker table tr td.active.disabled:hover,.datetimepicker table tr td.active.disabled:hover:hover,.datetimepicker table tr td.active:active,.datetimepicker table tr td.active:hover:active,.datetimepicker table tr td.active.disabled:active,.datetimepicker table tr td.active.disabled:hover:active,.datetimepicker table tr td.active.active,.datetimepicker table tr td.active:hover.active,.datetimepicker table tr td.active.disabled.active,.datetimepicker table tr td.active.disabled:hover.active,.datetimepicker table tr td.active.disabled,.datetimepicker table tr td.active:hover.disabled,.datetimepicker table tr td.active.disabled.disabled,.datetimepicker table tr td.active.disabled:hover.disabled,.datetimepicker table tr td.active[disabled],.datetimepicker table tr td.active:hover[disabled],.datetimepicker table tr td.active.disabled[disabled],.datetimepicker table tr td.active.disabled:hover[disabled]{background-color:#04c}.datetimepicker table tr td.active:active,.datetimepicker table tr td.active:hover:active,.datetimepicker table tr td.active.disabled:active,.datetimepicker table tr td.active.disabled:hover:active,.datetimepicker table tr td.active.active,.datetimepicker table tr td.active:hover.active,.datetimepicker table tr td.active.disabled.active,.datetimepicker table tr td.active.disabled:hover.active{background-color:#039}.datetimepicker table tr td span{display:block;width:23%;height:54px;line-height:54px;float:left;margin:1%;cursor:pointer;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.datetimepicker .datetimepicker-hours span{height:26px;line-height:26px}.datetimepicker .datetimepicker-hours table tr td span.hour_am,.datetimepicker .datetimepicker-hours table tr td span.hour_pm{width:14.6%}.datetimepicker .datetimepicker-hours fieldset legend,.datetimepicker .datetimepicker-minutes fieldset legend{margin-bottom:inherit;line-height:30px}.datetimepicker .datetimepicker-minutes span{height:26px;line-height:26px}.datetimepicker table tr td span:hover{background:#eee}.datetimepicker table tr td span.disabled,.datetimepicker table tr td span.disabled:hover{background:0;color:#999;cursor:default}.datetimepicker table tr td span.active,.datetimepicker table tr td span.active:hover,.datetimepicker table tr td span.active.disabled,.datetimepicker table tr td span.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-ms-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(top,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc',endColorstr='#0044cc',GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datetimepicker table tr td span.active:hover,.datetimepicker table tr td span.active:hover:hover,.datetimepicker table tr td span.active.disabled:hover,.datetimepicker table tr td span.active.disabled:hover:hover,.datetimepicker table tr td span.active:active,.datetimepicker table tr td span.active:hover:active,.datetimepicker table tr td span.active.disabled:active,.datetimepicker table tr td span.active.disabled:hover:active,.datetimepicker table tr td span.active.active,.datetimepicker table tr td span.active:hover.active,.datetimepicker table tr td span.active.disabled.active,.datetimepicker table tr td span.active.disabled:hover.active,.datetimepicker table tr td span.active.disabled,.datetimepicker table tr td span.active:hover.disabled,.datetimepicker table tr td span.active.disabled.disabled,.datetimepicker table tr td span.active.disabled:hover.disabled,.datetimepicker table tr td span.active[disabled],.datetimepicker table tr td span.active:hover[disabled],.datetimepicker table tr td span.active.disabled[disabled],.datetimepicker table tr td span.active.disabled:hover[disabled]{background-color:#04c}.datetimepicker table tr td span.active:active,.datetimepicker table tr td span.active:hover:active,.datetimepicker table tr td span.active.disabled:active,.datetimepicker table tr td span.active.disabled:hover:active,.datetimepicker table tr td span.active.active,.datetimepicker table tr td span.active:hover.active,.datetimepicker table tr td span.active.disabled.active,.datetimepicker table tr td span.active.disabled:hover.active{background-color:#039}.datetimepicker table tr td span.old{color:#999}.datetimepicker th.switch{width:145px}.datetimepicker th span.glyphicon{pointer-events:none}.datetimepicker thead tr:first-child th,.datetimepicker tfoot th{cursor:pointer}.datetimepicker thead tr:first-child th:hover,.datetimepicker tfoot th:hover{background:#eee}.input-append.date .add-on i,.input-prepend.date .add-on i,.input-group.date .input-group-addon span{cursor:pointer;width:14px;height:14px} \ No newline at end of file + */.datetimepicker{padding:4px;margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;direction:ltr}.datetimepicker-inline{width:220px}.datetimepicker.datetimepicker-rtl{direction:rtl}.datetimepicker.datetimepicker-rtl table tr td span{float:right}.datetimepicker-dropdown,.datetimepicker-dropdown-left{top:0;left:0}[class*=" datetimepicker-dropdown"]:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,0.2);position:absolute}[class*=" datetimepicker-dropdown"]:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute}[class*=" datetimepicker-dropdown-top"]:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-top:7px solid #ccc;border-top-color:rgba(0,0,0,0.2);border-bottom:0}[class*=" datetimepicker-dropdown-top"]:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #fff;border-bottom:0}.datetimepicker-dropdown-bottom-left:before{top:-7px;right:6px}.datetimepicker-dropdown-bottom-left:after{top:-6px;right:7px}.datetimepicker-dropdown-bottom-right:before{top:-7px;left:6px}.datetimepicker-dropdown-bottom-right:after{top:-6px;left:7px}.datetimepicker-dropdown-top-left:before{bottom:-7px;right:6px}.datetimepicker-dropdown-top-left:after{bottom:-6px;right:7px}.datetimepicker-dropdown-top-right:before{bottom:-7px;left:6px}.datetimepicker-dropdown-top-right:after{bottom:-6px;left:7px}.datetimepicker>div{display:none}.datetimepicker.minutes div.datetimepicker-minutes{display:block}.datetimepicker.hours div.datetimepicker-hours{display:block}.datetimepicker.days div.datetimepicker-days{display:block}.datetimepicker.months div.datetimepicker-months{display:block}.datetimepicker.years div.datetimepicker-years{display:block}.datetimepicker table{margin:0}.datetimepicker td,.datetimepicker th{text-align:center;width:20px;height:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;border:0}.table-striped .datetimepicker table tr td,.table-striped .datetimepicker table tr th{background-color:transparent}.datetimepicker table tr td.minute:hover{background:#eee;cursor:pointer}.datetimepicker table tr td.hour:hover{background:#eee;cursor:pointer}.datetimepicker table tr td.day:hover{background:#eee;cursor:pointer}.datetimepicker table tr td.old,.datetimepicker table tr td.new{color:#999}.datetimepicker table tr td.disabled,.datetimepicker table tr td.disabled:hover{background:0;color:#999;cursor:default}.datetimepicker table tr td.today,.datetimepicker table tr td.today:hover,.datetimepicker table tr td.today.disabled,.datetimepicker table tr td.today.disabled:hover{background-color:#fde19a;background-image:-moz-linear-gradient(top,#fdd49a,#fdf59a);background-image:-ms-linear-gradient(top,#fdd49a,#fdf59a);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fdd49a),to(#fdf59a));background-image:-webkit-linear-gradient(top,#fdd49a,#fdf59a);background-image:-o-linear-gradient(top,#fdd49a,#fdf59a);background-image:linear-gradient(to bottom,#fdd49a,#fdf59a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a',endColorstr='#fdf59a',GradientType=0);border-color:#fdf59a #fdf59a #fbed50;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.datetimepicker table tr td.today:hover,.datetimepicker table tr td.today:hover:hover,.datetimepicker table tr td.today.disabled:hover,.datetimepicker table tr td.today.disabled:hover:hover,.datetimepicker table tr td.today:active,.datetimepicker table tr td.today:hover:active,.datetimepicker table tr td.today.disabled:active,.datetimepicker table tr td.today.disabled:hover:active,.datetimepicker table tr td.today.active,.datetimepicker table tr td.today:hover.active,.datetimepicker table tr td.today.disabled.active,.datetimepicker table tr td.today.disabled:hover.active,.datetimepicker table tr td.today.disabled,.datetimepicker table tr td.today:hover.disabled,.datetimepicker table tr td.today.disabled.disabled,.datetimepicker table tr td.today.disabled:hover.disabled,.datetimepicker table tr td.today[disabled],.datetimepicker table tr td.today:hover[disabled],.datetimepicker table tr td.today.disabled[disabled],.datetimepicker table tr td.today.disabled:hover[disabled]{background-color:#fdf59a}.datetimepicker table tr td.today:active,.datetimepicker table tr td.today:hover:active,.datetimepicker table tr td.today.disabled:active,.datetimepicker table tr td.today.disabled:hover:active,.datetimepicker table tr td.today.active,.datetimepicker table tr td.today:hover.active,.datetimepicker table tr td.today.disabled.active,.datetimepicker table tr td.today.disabled:hover.active{background-color:#fbf069}.datetimepicker table tr td.active,.datetimepicker table tr td.active:hover,.datetimepicker table tr td.active.disabled,.datetimepicker table tr td.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-ms-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc',endColorstr='#0044cc',GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datetimepicker table tr td.active:hover,.datetimepicker table tr td.active:hover:hover,.datetimepicker table tr td.active.disabled:hover,.datetimepicker table tr td.active.disabled:hover:hover,.datetimepicker table tr td.active:active,.datetimepicker table tr td.active:hover:active,.datetimepicker table tr td.active.disabled:active,.datetimepicker table tr td.active.disabled:hover:active,.datetimepicker table tr td.active.active,.datetimepicker table tr td.active:hover.active,.datetimepicker table tr td.active.disabled.active,.datetimepicker table tr td.active.disabled:hover.active,.datetimepicker table tr td.active.disabled,.datetimepicker table tr td.active:hover.disabled,.datetimepicker table tr td.active.disabled.disabled,.datetimepicker table tr td.active.disabled:hover.disabled,.datetimepicker table tr td.active[disabled],.datetimepicker table tr td.active:hover[disabled],.datetimepicker table tr td.active.disabled[disabled],.datetimepicker table tr td.active.disabled:hover[disabled]{background-color:#04c}.datetimepicker table tr td.active:active,.datetimepicker table tr td.active:hover:active,.datetimepicker table tr td.active.disabled:active,.datetimepicker table tr td.active.disabled:hover:active,.datetimepicker table tr td.active.active,.datetimepicker table tr td.active:hover.active,.datetimepicker table tr td.active.disabled.active,.datetimepicker table tr td.active.disabled:hover.active{background-color:#039}.datetimepicker table tr td span{display:block;width:23%;height:54px;line-height:54px;float:left;margin:1%;cursor:pointer;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.datetimepicker .datetimepicker-hours span{height:26px;line-height:26px}.datetimepicker .datetimepicker-hours table tr td span.hour_am,.datetimepicker .datetimepicker-hours table tr td span.hour_pm{width:14.6%}.datetimepicker .datetimepicker-hours fieldset legend,.datetimepicker .datetimepicker-minutes fieldset legend{margin-bottom:inherit;line-height:30px}.datetimepicker .datetimepicker-minutes span{height:26px;line-height:26px}.datetimepicker table tr td span:hover{background:#eee}.datetimepicker table tr td span.disabled,.datetimepicker table tr td span.disabled:hover{background:0;color:#999;cursor:default}.datetimepicker table tr td span.active,.datetimepicker table tr td span.active:hover,.datetimepicker table tr td span.active.disabled,.datetimepicker table tr td span.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-ms-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc',endColorstr='#0044cc',GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datetimepicker table tr td span.active:hover,.datetimepicker table tr td span.active:hover:hover,.datetimepicker table tr td span.active.disabled:hover,.datetimepicker table tr td span.active.disabled:hover:hover,.datetimepicker table tr td span.active:active,.datetimepicker table tr td span.active:hover:active,.datetimepicker table tr td span.active.disabled:active,.datetimepicker table tr td span.active.disabled:hover:active,.datetimepicker table tr td span.active.active,.datetimepicker table tr td span.active:hover.active,.datetimepicker table tr td span.active.disabled.active,.datetimepicker table tr td span.active.disabled:hover.active,.datetimepicker table tr td span.active.disabled,.datetimepicker table tr td span.active:hover.disabled,.datetimepicker table tr td span.active.disabled.disabled,.datetimepicker table tr td span.active.disabled:hover.disabled,.datetimepicker table tr td span.active[disabled],.datetimepicker table tr td span.active:hover[disabled],.datetimepicker table tr td span.active.disabled[disabled],.datetimepicker table tr td span.active.disabled:hover[disabled]{background-color:#04c}.datetimepicker table tr td span.active:active,.datetimepicker table tr td span.active:hover:active,.datetimepicker table tr td span.active.disabled:active,.datetimepicker table tr td span.active.disabled:hover:active,.datetimepicker table tr td span.active.active,.datetimepicker table tr td span.active:hover.active,.datetimepicker table tr td span.active.disabled.active,.datetimepicker table tr td span.active.disabled:hover.active{background-color:#039}.datetimepicker table tr td span.old{color:#999}.datetimepicker th.switch{width:145px}.datetimepicker th span.glyphicon{pointer-events:none}.datetimepicker thead tr:first-child th,.datetimepicker tfoot th{cursor:pointer}.datetimepicker thead tr:first-child th:hover,.datetimepicker tfoot th:hover{background:#eee}.input-append.date .add-on i,.input-prepend.date .add-on i,.input-group.date .input-group-addon span{cursor:pointer;width:14px;height:14px} \ No newline at end of file diff --git a/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.init.js b/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.init.js index 21aa00543..4afe4e763 100755 --- a/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.init.js +++ b/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.init.js @@ -36,7 +36,7 @@ var e107 = e107 || {'settings': {}, 'behaviors': {}}; autoclose: true, format: $item.attr("data-date-format"), weekStart: $item.attr("data-date-firstday"), - language: $item.attr("data-date-language") + language: $item.attr("data-date-language"), }).on("changeDate", function (ev) { var useUnix = $(this).attr("data-date-unix"); var newValue = ""; @@ -49,7 +49,11 @@ var e107 = e107 || {'settings': {}, 'behaviors': {}}; newValue = $("#" + ev.target.id).val(); } - $(newTarget).val(newValue); + // make sure a UTC datestamp is saved + offset = parseInt($item.attr("data-date-timezone-offset")); + newOffsetValue = newValue + offset; + + $(newTarget).val(newOffsetValue); }); }); @@ -62,6 +66,7 @@ var e107 = e107 || {'settings': {}, 'behaviors': {}}; weekStart: $item.attr("data-date-firstday"), showMeridian: $item.attr("data-date-ampm"), language: $item.attr("data-date-language") + }).on("changeDate", function (ev) { var useUnix = $(this).attr("data-date-unix"); var newValue = ""; @@ -74,7 +79,14 @@ var e107 = e107 || {'settings': {}, 'behaviors': {}}; newValue = $("#" + ev.target.id).val(); } - $(newTarget).val(newValue); + // make sure a UTC datestamp is saved + offset = parseInt($item.attr("data-date-timezone-offset")); + newOffsetValue = newValue + offset; + + $(newTarget).val(newOffsetValue); + + console.log( newOffsetValue); // remove later. + }) }); } diff --git a/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js b/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js index 512fcbbb9..eba15ce5d 100644 --- a/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js +++ b/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js @@ -1 +1 @@ -(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{if(typeof exports==="object"){a(require("jquery"))}else{a(jQuery)}}}(function(f,c){if(!("indexOf" in Array.prototype)){Array.prototype.indexOf=function(k,j){if(j===c){j=0}if(j<0){j+=this.length}if(j<0){j=0}for(var l=this.length;j<l;j++){if(j in this&&this[j]===k){return j}}return -1}}function e(l){var k=f(l);var j=k.add(k.parents());var m=false;j.each(function(){if(f(this).css("position")==="fixed"){m=true;return false}});return m}function h(){return new Date(Date.UTC.apply(Date,arguments))}function d(){var j=new Date();return h(j.getUTCFullYear(),j.getUTCMonth(),j.getUTCDate(),j.getUTCHours(),j.getUTCMinutes(),j.getUTCSeconds(),0)}var i=function(l,k){var n=this;this.element=f(l);this.container=k.container||"body";this.language=k.language||this.element.data("date-language")||"en";this.language=this.language in a?this.language:this.language.split("-")[0];this.language=this.language in a?this.language:"en";this.isRTL=a[this.language].rtl||false;this.formatType=k.formatType||this.element.data("format-type")||"standard";this.format=g.parseFormat(k.format||this.element.data("date-format")||a[this.language].format||g.getDefaultFormat(this.formatType,"input"),this.formatType);this.isInline=false;this.isVisible=false;this.isInput=this.element.is("input");this.fontAwesome=k.fontAwesome||this.element.data("font-awesome")||false;this.bootcssVer=k.bootcssVer||(this.isInput?(this.element.is(".form-control")?3:2):(this.bootcssVer=this.element.is(".input-group")?3:2));this.component=this.element.is(".date")?(this.bootcssVer==3?this.element.find(".input-group-addon .glyphicon-th, .input-group-addon .glyphicon-time, .input-group-addon .glyphicon-remove, .input-group-addon .glyphicon-calendar, .input-group-addon .fa-calendar, .input-group-addon .fa-clock-o").parent():this.element.find(".add-on .icon-th, .add-on .icon-time, .add-on .icon-calendar, .add-on .fa-calendar, .add-on .fa-clock-o").parent()):false;this.componentReset=this.element.is(".date")?(this.bootcssVer==3?this.element.find(".input-group-addon .glyphicon-remove, .input-group-addon .fa-times").parent():this.element.find(".add-on .icon-remove, .add-on .fa-times").parent()):false;this.hasInput=this.component&&this.element.find("input").length;if(this.component&&this.component.length===0){this.component=false}this.linkField=k.linkField||this.element.data("link-field")||false;this.linkFormat=g.parseFormat(k.linkFormat||this.element.data("link-format")||g.getDefaultFormat(this.formatType,"link"),this.formatType);this.minuteStep=k.minuteStep||this.element.data("minute-step")||5;this.pickerPosition=k.pickerPosition||this.element.data("picker-position")||"bottom-right";this.showMeridian=k.showMeridian||this.element.data("show-meridian")||false;this.initialDate=k.initialDate||new Date();this.zIndex=k.zIndex||this.element.data("z-index")||c;this.title=typeof k.title==="undefined"?false:k.title;this.icons={leftArrow:this.fontAwesome?"fa-arrow-left":(this.bootcssVer===3?"glyphicon-arrow-left":"icon-arrow-left"),rightArrow:this.fontAwesome?"fa-arrow-right":(this.bootcssVer===3?"glyphicon-arrow-right":"icon-arrow-right")};this.icontype=this.fontAwesome?"fa":"glyphicon";this._attachEvents();this.clickedOutside=function(o){if(f(o.target).closest(".datetimepicker").length===0){n.hide()}};this.formatViewType="datetime";if("formatViewType" in k){this.formatViewType=k.formatViewType}else{if("formatViewType" in this.element.data()){this.formatViewType=this.element.data("formatViewType")}}this.minView=0;if("minView" in k){this.minView=k.minView}else{if("minView" in this.element.data()){this.minView=this.element.data("min-view")}}this.minView=g.convertViewMode(this.minView);this.maxView=g.modes.length-1;if("maxView" in k){this.maxView=k.maxView}else{if("maxView" in this.element.data()){this.maxView=this.element.data("max-view")}}this.maxView=g.convertViewMode(this.maxView);this.wheelViewModeNavigation=false;if("wheelViewModeNavigation" in k){this.wheelViewModeNavigation=k.wheelViewModeNavigation}else{if("wheelViewModeNavigation" in this.element.data()){this.wheelViewModeNavigation=this.element.data("view-mode-wheel-navigation")}}this.wheelViewModeNavigationInverseDirection=false;if("wheelViewModeNavigationInverseDirection" in k){this.wheelViewModeNavigationInverseDirection=k.wheelViewModeNavigationInverseDirection}else{if("wheelViewModeNavigationInverseDirection" in this.element.data()){this.wheelViewModeNavigationInverseDirection=this.element.data("view-mode-wheel-navigation-inverse-dir")}}this.wheelViewModeNavigationDelay=100;if("wheelViewModeNavigationDelay" in k){this.wheelViewModeNavigationDelay=k.wheelViewModeNavigationDelay}else{if("wheelViewModeNavigationDelay" in this.element.data()){this.wheelViewModeNavigationDelay=this.element.data("view-mode-wheel-navigation-delay")}}this.startViewMode=2;if("startView" in k){this.startViewMode=k.startView}else{if("startView" in this.element.data()){this.startViewMode=this.element.data("start-view")}}this.startViewMode=g.convertViewMode(this.startViewMode);this.viewMode=this.startViewMode;this.viewSelect=this.minView;if("viewSelect" in k){this.viewSelect=k.viewSelect}else{if("viewSelect" in this.element.data()){this.viewSelect=this.element.data("view-select")}}this.viewSelect=g.convertViewMode(this.viewSelect);this.forceParse=true;if("forceParse" in k){this.forceParse=k.forceParse}else{if("dateForceParse" in this.element.data()){this.forceParse=this.element.data("date-force-parse")}}var m=this.bootcssVer===3?g.templateV3:g.template;while(m.indexOf("{iconType}")!==-1){m=m.replace("{iconType}",this.icontype)}while(m.indexOf("{leftArrow}")!==-1){m=m.replace("{leftArrow}",this.icons.leftArrow)}while(m.indexOf("{rightArrow}")!==-1){m=m.replace("{rightArrow}",this.icons.rightArrow)}this.picker=f(m).appendTo(this.isInline?this.element:this.container).on({click:f.proxy(this.click,this),mousedown:f.proxy(this.mousedown,this)});if(this.wheelViewModeNavigation){if(f.fn.mousewheel){this.picker.on({mousewheel:f.proxy(this.mousewheel,this)})}else{console.log("Mouse Wheel event is not supported. Please include the jQuery Mouse Wheel plugin before enabling this option")}}if(this.isInline){this.picker.addClass("datetimepicker-inline")}else{this.picker.addClass("datetimepicker-dropdown-"+this.pickerPosition+" dropdown-menu")}if(this.isRTL){this.picker.addClass("datetimepicker-rtl");var j=this.bootcssVer===3?".prev span, .next span":".prev i, .next i";this.picker.find(j).toggleClass(this.icons.leftArrow+" "+this.icons.rightArrow)}f(document).on("mousedown",this.clickedOutside);this.autoclose=false;if("autoclose" in k){this.autoclose=k.autoclose}else{if("dateAutoclose" in this.element.data()){this.autoclose=this.element.data("date-autoclose")}}this.keyboardNavigation=true;if("keyboardNavigation" in k){this.keyboardNavigation=k.keyboardNavigation}else{if("dateKeyboardNavigation" in this.element.data()){this.keyboardNavigation=this.element.data("date-keyboard-navigation")}}this.todayBtn=(k.todayBtn||this.element.data("date-today-btn")||false);this.clearBtn=(k.clearBtn||this.element.data("date-clear-btn")||false);this.todayHighlight=(k.todayHighlight||this.element.data("date-today-highlight")||false);this.weekStart=((k.weekStart||this.element.data("date-weekstart")||a[this.language].weekStart||0)%7);this.weekEnd=((this.weekStart+6)%7);this.startDate=-Infinity;this.endDate=Infinity;this.datesDisabled=[];this.daysOfWeekDisabled=[];this.setStartDate(k.startDate||this.element.data("date-startdate"));this.setEndDate(k.endDate||this.element.data("date-enddate"));this.setDatesDisabled(k.datesDisabled||this.element.data("date-dates-disabled"));this.setDaysOfWeekDisabled(k.daysOfWeekDisabled||this.element.data("date-days-of-week-disabled"));this.setMinutesDisabled(k.minutesDisabled||this.element.data("date-minute-disabled"));this.setHoursDisabled(k.hoursDisabled||this.element.data("date-hour-disabled"));this.fillDow();this.fillMonths();this.update();this.showMode();if(this.isInline){this.show()}};i.prototype={constructor:i,_events:[],_attachEvents:function(){this._detachEvents();if(this.isInput){this._events=[[this.element,{focus:f.proxy(this.show,this),keyup:f.proxy(this.update,this),keydown:f.proxy(this.keydown,this)}]]}else{if(this.component&&this.hasInput){this._events=[[this.element.find("input"),{focus:f.proxy(this.show,this),keyup:f.proxy(this.update,this),keydown:f.proxy(this.keydown,this)}],[this.component,{click:f.proxy(this.show,this)}]];if(this.componentReset){this._events.push([this.componentReset,{click:f.proxy(this.reset,this)}])}}else{if(this.element.is("div")){this.isInline=true}else{this._events=[[this.element,{click:f.proxy(this.show,this)}]]}}}for(var j=0,k,l;j<this._events.length;j++){k=this._events[j][0];l=this._events[j][1];k.on(l)}},_detachEvents:function(){for(var j=0,k,l;j<this._events.length;j++){k=this._events[j][0];l=this._events[j][1];k.off(l)}this._events=[]},show:function(j){this.picker.show();this.height=this.component?this.component.outerHeight():this.element.outerHeight();if(this.forceParse){this.update()}this.place();f(window).on("resize",f.proxy(this.place,this));if(j){j.stopPropagation();j.preventDefault()}this.isVisible=true;this.element.trigger({type:"show",date:this.date})},hide:function(j){if(!this.isVisible){return}if(this.isInline){return}this.picker.hide();f(window).off("resize",this.place);this.viewMode=this.startViewMode;this.showMode();if(!this.isInput){f(document).off("mousedown",this.hide)}if(this.forceParse&&(this.isInput&&this.element.val()||this.hasInput&&this.element.find("input").val())){this.setValue()}this.isVisible=false;this.element.trigger({type:"hide",date:this.date})},remove:function(){this._detachEvents();f(document).off("mousedown",this.clickedOutside);this.picker.remove();delete this.picker;delete this.element.data().datetimepicker},getDate:function(){var j=this.getUTCDate();return new Date(j.getTime()+(j.getTimezoneOffset()*60000))},getUTCDate:function(){return this.date},setDate:function(j){this.setUTCDate(new Date(j.getTime()-(j.getTimezoneOffset()*60000)))},setUTCDate:function(j){if(j>=this.startDate&&j<=this.endDate){this.date=j;this.setValue();this.viewDate=this.date;this.fill()}else{this.element.trigger({type:"outOfRange",date:j,startDate:this.startDate,endDate:this.endDate})}},setFormat:function(k){this.format=g.parseFormat(k,this.formatType);var j;if(this.isInput){j=this.element}else{if(this.component){j=this.element.find("input")}}if(j&&j.val()){this.setValue()}},setValue:function(){var j=this.getFormattedDate();if(!this.isInput){if(this.component){this.element.find("input").val(j)}this.element.data("date",j)}else{this.element.val(j)}if(this.linkField){f("#"+this.linkField).val(this.getFormattedDate(this.linkFormat))}},getFormattedDate:function(j){if(j==c){j=this.format}return g.formatDate(this.date,j,this.language,this.formatType)},setStartDate:function(j){this.startDate=j||-Infinity;if(this.startDate!==-Infinity){this.startDate=g.parseDate(this.startDate,this.format,this.language,this.formatType)}this.update();this.updateNavArrows()},setEndDate:function(j){this.endDate=j||Infinity;if(this.endDate!==Infinity){this.endDate=g.parseDate(this.endDate,this.format,this.language,this.formatType)}this.update();this.updateNavArrows()},setDatesDisabled:function(j){this.datesDisabled=j||[];if(!f.isArray(this.datesDisabled)){this.datesDisabled=this.datesDisabled.split(/,\s*/)}this.datesDisabled=f.map(this.datesDisabled,function(k){return g.parseDate(k,this.format,this.language,this.formatType).toDateString()});this.update();this.updateNavArrows()},setTitle:function(j,k){return this.picker.find(j).find("th:eq(1)").text(this.title===false?k:this.title)},setDaysOfWeekDisabled:function(j){this.daysOfWeekDisabled=j||[];if(!f.isArray(this.daysOfWeekDisabled)){this.daysOfWeekDisabled=this.daysOfWeekDisabled.split(/,\s*/)}this.daysOfWeekDisabled=f.map(this.daysOfWeekDisabled,function(k){return parseInt(k,10)});this.update();this.updateNavArrows()},setMinutesDisabled:function(j){this.minutesDisabled=j||[];if(!f.isArray(this.minutesDisabled)){this.minutesDisabled=this.minutesDisabled.split(/,\s*/)}this.minutesDisabled=f.map(this.minutesDisabled,function(k){return parseInt(k,10)});this.update();this.updateNavArrows()},setHoursDisabled:function(j){this.hoursDisabled=j||[];if(!f.isArray(this.hoursDisabled)){this.hoursDisabled=this.hoursDisabled.split(/,\s*/)}this.hoursDisabled=f.map(this.hoursDisabled,function(k){return parseInt(k,10)});this.update();this.updateNavArrows()},place:function(){if(this.isInline){return}if(!this.zIndex){var k=0;f("div").each(function(){var p=parseInt(f(this).css("zIndex"),10);if(p>k){k=p}});this.zIndex=k+10}var o,n,m,l;if(this.container instanceof f){l=this.container.offset()}else{l=f(this.container).offset()}if(this.component){o=this.component.offset();m=o.left;if(this.pickerPosition=="bottom-left"||this.pickerPosition=="top-left"){m+=this.component.outerWidth()-this.picker.outerWidth()}}else{o=this.element.offset();m=o.left;if(this.pickerPosition=="bottom-left"||this.pickerPosition=="top-left"){m+=this.element.outerWidth()-this.picker.outerWidth()}}var j=document.body.clientWidth||window.innerWidth;if(m+220>j){m=j-220}if(this.component){n=n-l.top+169;m=m-l.left+210}else{if(this.pickerPosition=="top-left"||this.pickerPosition=="top-right"){n=o.top-this.picker.outerHeight()}else{n=o.top+this.height}}this.picker.css({top:n,left:m,zIndex:this.zIndex})},update:function(){var j,k=false;if(arguments&&arguments.length&&(typeof arguments[0]==="string"||arguments[0] instanceof Date)){j=arguments[0];k=true}else{j=(this.isInput?this.element.val():this.element.find("input").val())||this.element.data("date")||this.initialDate;if(typeof j=="string"||j instanceof String){j=j.replace(/^\s+|\s+$/g,"")}}if(!j){j=new Date();k=false}this.date=g.parseDate(j,this.format,this.language,this.formatType);if(k){this.setValue()}if(this.date<this.startDate){this.viewDate=new Date(this.startDate)}else{if(this.date>this.endDate){this.viewDate=new Date(this.endDate)}else{this.viewDate=new Date(this.date)}}this.fill()},fillDow:function(){var j=this.weekStart,k="<tr>";while(j<this.weekStart+7){k+='<th class="dow">'+a[this.language].daysMin[(j++)%7]+"</th>"}k+="</tr>";this.picker.find(".datetimepicker-days thead").append(k)},fillMonths:function(){var k="",j=0;while(j<12){k+='<span class="month">'+a[this.language].monthsShort[j++]+"</span>"}this.picker.find(".datetimepicker-months td").html(k)},fill:function(){if(this.date==null||this.viewDate==null){return}var H=new Date(this.viewDate),u=H.getUTCFullYear(),I=H.getUTCMonth(),n=H.getUTCDate(),D=H.getUTCHours(),y=H.getUTCMinutes(),z=this.startDate!==-Infinity?this.startDate.getUTCFullYear():-Infinity,E=this.startDate!==-Infinity?this.startDate.getUTCMonth()+1:-Infinity,q=this.endDate!==Infinity?this.endDate.getUTCFullYear():Infinity,A=this.endDate!==Infinity?this.endDate.getUTCMonth()+1:Infinity,r=(new h(this.date.getUTCFullYear(),this.date.getUTCMonth(),this.date.getUTCDate())).valueOf(),G=new Date();this.setTitle(".datetimepicker-days",a[this.language].months[I]+" "+u);if(this.formatViewType=="time"){var k=this.getFormattedDate();this.setTitle(".datetimepicker-hours",k);this.setTitle(".datetimepicker-minutes",k)}else{this.setTitle(".datetimepicker-hours",n+" "+a[this.language].months[I]+" "+u);this.setTitle(".datetimepicker-minutes",n+" "+a[this.language].months[I]+" "+u)}this.picker.find("tfoot th.today").text(a[this.language].today||a.en.today).toggle(this.todayBtn!==false);this.picker.find("tfoot th.clear").text(a[this.language].clear||a.en.clear).toggle(this.clearBtn!==false);this.updateNavArrows();this.fillMonths();var K=h(u,I-1,28,0,0,0,0),C=g.getDaysInMonth(K.getUTCFullYear(),K.getUTCMonth());K.setUTCDate(C);K.setUTCDate(C-(K.getUTCDay()-this.weekStart+7)%7);var j=new Date(K);j.setUTCDate(j.getUTCDate()+42);j=j.valueOf();var s=[];var v;while(K.valueOf()<j){if(K.getUTCDay()==this.weekStart){s.push("<tr>")}v="";if(K.getUTCFullYear()<u||(K.getUTCFullYear()==u&&K.getUTCMonth()<I)){v+=" old"}else{if(K.getUTCFullYear()>u||(K.getUTCFullYear()==u&&K.getUTCMonth()>I)){v+=" new"}}if(this.todayHighlight&&K.getUTCFullYear()==G.getFullYear()&&K.getUTCMonth()==G.getMonth()&&K.getUTCDate()==G.getDate()){v+=" today"}if(K.valueOf()==r){v+=" active"}if((K.valueOf()+86400000)<=this.startDate||K.valueOf()>this.endDate||f.inArray(K.getUTCDay(),this.daysOfWeekDisabled)!==-1||f.inArray(K.toDateString(),this.datesDisabled)!==-1){v+=" disabled"}s.push('<td class="day'+v+'">'+K.getUTCDate()+"</td>");if(K.getUTCDay()==this.weekEnd){s.push("</tr>")}K.setUTCDate(K.getUTCDate()+1)}this.picker.find(".datetimepicker-days tbody").empty().append(s.join(""));s=[];var w="",F="",t="";var l=this.hoursDisabled||[];for(var B=0;B<24;B++){if(l.indexOf(B)!==-1){continue}var x=h(u,I,n,B);v="";if((x.valueOf()+3600000)<=this.startDate||x.valueOf()>this.endDate){v+=" disabled"}else{if(D==B){v+=" active"}}if(this.showMeridian&&a[this.language].meridiem.length==2){F=(B<12?a[this.language].meridiem[0]:a[this.language].meridiem[1]);if(F!=t){if(t!=""){s.push("</fieldset>")}s.push('<fieldset class="hour"><legend>'+F.toUpperCase()+"</legend>")}t=F;w=(B%12?B%12:12);s.push('<span class="hour'+v+" hour_"+(B<12?"am":"pm")+'">'+w+"</span>");if(B==23){s.push("</fieldset>")}}else{w=B+":00";s.push('<span class="hour'+v+'">'+w+"</span>")}}this.picker.find(".datetimepicker-hours td").html(s.join(""));s=[];w="",F="",t="";var m=this.minutesDisabled||[];for(var B=0;B<60;B+=this.minuteStep){if(m.indexOf(B)!==-1){continue}var x=h(u,I,n,D,B,0);v="";if(x.valueOf()<this.startDate||x.valueOf()>this.endDate){v+=" disabled"}else{if(Math.floor(y/this.minuteStep)==Math.floor(B/this.minuteStep)){v+=" active"}}if(this.showMeridian&&a[this.language].meridiem.length==2){F=(D<12?a[this.language].meridiem[0]:a[this.language].meridiem[1]);if(F!=t){if(t!=""){s.push("</fieldset>")}s.push('<fieldset class="minute"><legend>'+F.toUpperCase()+"</legend>")}t=F;w=(D%12?D%12:12);s.push('<span class="minute'+v+'">'+w+":"+(B<10?"0"+B:B)+"</span>");if(B==59){s.push("</fieldset>")}}else{w=B+":00";s.push('<span class="minute'+v+'">'+D+":"+(B<10?"0"+B:B)+"</span>")}}this.picker.find(".datetimepicker-minutes td").html(s.join(""));var L=this.date.getUTCFullYear();var p=this.setTitle(".datetimepicker-months",u).end().find("span").removeClass("active");if(L==u){var o=p.length-12;p.eq(this.date.getUTCMonth()+o).addClass("active")}if(u<z||u>q){p.addClass("disabled")}if(u==z){p.slice(0,E+1).addClass("disabled")}if(u==q){p.slice(A).addClass("disabled")}s="";u=parseInt(u/10,10)*10;var J=this.setTitle(".datetimepicker-years",u+"-"+(u+9)).end().find("td");u-=1;for(var B=-1;B<11;B++){s+='<span class="year'+(B==-1||B==10?" old":"")+(L==u?" active":"")+(u<z||u>q?" disabled":"")+'">'+u+"</span>";u+=1}J.html(s);this.place()},updateNavArrows:function(){var n=new Date(this.viewDate),l=n.getUTCFullYear(),m=n.getUTCMonth(),k=n.getUTCDate(),j=n.getUTCHours();switch(this.viewMode){case 0:if(this.startDate!==-Infinity&&l<=this.startDate.getUTCFullYear()&&m<=this.startDate.getUTCMonth()&&k<=this.startDate.getUTCDate()&&j<=this.startDate.getUTCHours()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(this.endDate!==Infinity&&l>=this.endDate.getUTCFullYear()&&m>=this.endDate.getUTCMonth()&&k>=this.endDate.getUTCDate()&&j>=this.endDate.getUTCHours()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 1:if(this.startDate!==-Infinity&&l<=this.startDate.getUTCFullYear()&&m<=this.startDate.getUTCMonth()&&k<=this.startDate.getUTCDate()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(this.endDate!==Infinity&&l>=this.endDate.getUTCFullYear()&&m>=this.endDate.getUTCMonth()&&k>=this.endDate.getUTCDate()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 2:if(this.startDate!==-Infinity&&l<=this.startDate.getUTCFullYear()&&m<=this.startDate.getUTCMonth()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(this.endDate!==Infinity&&l>=this.endDate.getUTCFullYear()&&m>=this.endDate.getUTCMonth()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 3:case 4:if(this.startDate!==-Infinity&&l<=this.startDate.getUTCFullYear()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(this.endDate!==Infinity&&l>=this.endDate.getUTCFullYear()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break}},mousewheel:function(k){k.preventDefault();k.stopPropagation();if(this.wheelPause){return}this.wheelPause=true;var j=k.originalEvent;var m=j.wheelDelta;var l=m>0?1:(m===0)?0:-1;if(this.wheelViewModeNavigationInverseDirection){l=-l}this.showMode(l);setTimeout(f.proxy(function(){this.wheelPause=false},this),this.wheelViewModeNavigationDelay)},click:function(n){n.stopPropagation();n.preventDefault();var o=f(n.target).closest("span, td, th, legend");if(o.is("."+this.icontype)){o=f(o).parent().closest("span, td, th, legend")}if(o.length==1){if(o.is(".disabled")){this.element.trigger({type:"outOfRange",date:this.viewDate,startDate:this.startDate,endDate:this.endDate});return}switch(o[0].nodeName.toLowerCase()){case"th":switch(o[0].className){case"switch":this.showMode(1);break;case"prev":case"next":var j=g.modes[this.viewMode].navStep*(o[0].className=="prev"?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveHour(this.viewDate,j);break;case 1:this.viewDate=this.moveDate(this.viewDate,j);break;case 2:this.viewDate=this.moveMonth(this.viewDate,j);break;case 3:case 4:this.viewDate=this.moveYear(this.viewDate,j);break}this.fill();this.element.trigger({type:o[0].className+":"+this.convertViewModeText(this.viewMode),date:this.viewDate,startDate:this.startDate,endDate:this.endDate});break;case"clear":this.reset();if(this.autoclose){this.hide()}break;case"today":var k=new Date();k=h(k.getFullYear(),k.getMonth(),k.getDate(),k.getHours(),k.getMinutes(),k.getSeconds(),0);if(k<this.startDate){k=this.startDate}else{if(k>this.endDate){k=this.endDate}}this.viewMode=this.startViewMode;this.showMode(0);this._setDate(k);this.fill();if(this.autoclose){this.hide()}break}break;case"span":if(!o.is(".disabled")){var q=this.viewDate.getUTCFullYear(),p=this.viewDate.getUTCMonth(),r=this.viewDate.getUTCDate(),s=this.viewDate.getUTCHours(),l=this.viewDate.getUTCMinutes(),t=this.viewDate.getUTCSeconds();if(o.is(".month")){this.viewDate.setUTCDate(1);p=o.parent().find("span").index(o);r=this.viewDate.getUTCDate();this.viewDate.setUTCMonth(p);this.element.trigger({type:"changeMonth",date:this.viewDate});if(this.viewSelect>=3){this._setDate(h(q,p,r,s,l,t,0))}}else{if(o.is(".year")){this.viewDate.setUTCDate(1);q=parseInt(o.text(),10)||0;this.viewDate.setUTCFullYear(q);this.element.trigger({type:"changeYear",date:this.viewDate});if(this.viewSelect>=4){this._setDate(h(q,p,r,s,l,t,0))}}else{if(o.is(".hour")){s=parseInt(o.text(),10)||0;if(o.hasClass("hour_am")||o.hasClass("hour_pm")){if(s==12&&o.hasClass("hour_am")){s=0}else{if(s!=12&&o.hasClass("hour_pm")){s+=12}}}this.viewDate.setUTCHours(s);this.element.trigger({type:"changeHour",date:this.viewDate});if(this.viewSelect>=1){this._setDate(h(q,p,r,s,l,t,0))}}else{if(o.is(".minute")){l=parseInt(o.text().substr(o.text().indexOf(":")+1),10)||0;this.viewDate.setUTCMinutes(l);this.element.trigger({type:"changeMinute",date:this.viewDate});if(this.viewSelect>=0){this._setDate(h(q,p,r,s,l,t,0))}}}}}if(this.viewMode!=0){var m=this.viewMode;this.showMode(-1);this.fill();if(m==this.viewMode&&this.autoclose){this.hide()}}else{this.fill();if(this.autoclose){this.hide()}}}break;case"td":if(o.is(".day")&&!o.is(".disabled")){var r=parseInt(o.text(),10)||1;var q=this.viewDate.getUTCFullYear(),p=this.viewDate.getUTCMonth(),s=this.viewDate.getUTCHours(),l=this.viewDate.getUTCMinutes(),t=this.viewDate.getUTCSeconds();if(o.is(".old")){if(p===0){p=11;q-=1}else{p-=1}}else{if(o.is(".new")){if(p==11){p=0;q+=1}else{p+=1}}}this.viewDate.setUTCFullYear(q);this.viewDate.setUTCMonth(p,r);this.element.trigger({type:"changeDay",date:this.viewDate});if(this.viewSelect>=2){this._setDate(h(q,p,r,s,l,t,0))}}var m=this.viewMode;this.showMode(-1);this.fill();if(m==this.viewMode&&this.autoclose){this.hide()}break}}},_setDate:function(j,l){if(!l||l=="date"){this.date=j}if(!l||l=="view"){this.viewDate=j}this.fill();this.setValue();var k;if(this.isInput){k=this.element}else{if(this.component){k=this.element.find("input")}}if(k){k.change();if(this.autoclose&&(!l||l=="date")){}}this.element.trigger({type:"changeDate",date:this.getDate()});if(j==null){this.date=this.viewDate}},moveMinute:function(k,j){if(!j){return k}var l=new Date(k.valueOf());l.setUTCMinutes(l.getUTCMinutes()+(j*this.minuteStep));return l},moveHour:function(k,j){if(!j){return k}var l=new Date(k.valueOf());l.setUTCHours(l.getUTCHours()+j);return l},moveDate:function(k,j){if(!j){return k}var l=new Date(k.valueOf());l.setUTCDate(l.getUTCDate()+j);return l},moveMonth:function(j,k){if(!k){return j}var n=new Date(j.valueOf()),r=n.getUTCDate(),o=n.getUTCMonth(),m=Math.abs(k),q,p;k=k>0?1:-1;if(m==1){p=k==-1?function(){return n.getUTCMonth()==o}:function(){return n.getUTCMonth()!=q};q=o+k;n.setUTCMonth(q);if(q<0||q>11){q=(q+12)%12}}else{for(var l=0;l<m;l++){n=this.moveMonth(n,k)}q=n.getUTCMonth();n.setUTCDate(r);p=function(){return q!=n.getUTCMonth()}}while(p()){n.setUTCDate(--r);n.setUTCMonth(q)}return n},moveYear:function(k,j){return this.moveMonth(k,j*12)},dateWithinRange:function(j){return j>=this.startDate&&j<=this.endDate},keydown:function(n){if(this.picker.is(":not(:visible)")){if(n.keyCode==27){this.show()}return}var p=false,k,q,o,r,j;switch(n.keyCode){case 27:this.hide();n.preventDefault();break;case 37:case 39:if(!this.keyboardNavigation){break}k=n.keyCode==37?-1:1;viewMode=this.viewMode;if(n.ctrlKey){viewMode+=2}else{if(n.shiftKey){viewMode+=1}}if(viewMode==4){r=this.moveYear(this.date,k);j=this.moveYear(this.viewDate,k)}else{if(viewMode==3){r=this.moveMonth(this.date,k);j=this.moveMonth(this.viewDate,k)}else{if(viewMode==2){r=this.moveDate(this.date,k);j=this.moveDate(this.viewDate,k)}else{if(viewMode==1){r=this.moveHour(this.date,k);j=this.moveHour(this.viewDate,k)}else{if(viewMode==0){r=this.moveMinute(this.date,k);j=this.moveMinute(this.viewDate,k)}}}}}if(this.dateWithinRange(r)){this.date=r;this.viewDate=j;this.setValue();this.update();n.preventDefault();p=true}break;case 38:case 40:if(!this.keyboardNavigation){break}k=n.keyCode==38?-1:1;viewMode=this.viewMode;if(n.ctrlKey){viewMode+=2}else{if(n.shiftKey){viewMode+=1}}if(viewMode==4){r=this.moveYear(this.date,k);j=this.moveYear(this.viewDate,k)}else{if(viewMode==3){r=this.moveMonth(this.date,k);j=this.moveMonth(this.viewDate,k)}else{if(viewMode==2){r=this.moveDate(this.date,k*7);j=this.moveDate(this.viewDate,k*7)}else{if(viewMode==1){if(this.showMeridian){r=this.moveHour(this.date,k*6);j=this.moveHour(this.viewDate,k*6)}else{r=this.moveHour(this.date,k*4);j=this.moveHour(this.viewDate,k*4)}}else{if(viewMode==0){r=this.moveMinute(this.date,k*4);j=this.moveMinute(this.viewDate,k*4)}}}}}if(this.dateWithinRange(r)){this.date=r;this.viewDate=j;this.setValue();this.update();n.preventDefault();p=true}break;case 13:if(this.viewMode!=0){var m=this.viewMode;this.showMode(-1);this.fill();if(m==this.viewMode&&this.autoclose){this.hide()}}else{this.fill();if(this.autoclose){this.hide()}}n.preventDefault();break;case 9:this.hide();break}if(p){var l;if(this.isInput){l=this.element}else{if(this.component){l=this.element.find("input")}}if(l){l.change()}this.element.trigger({type:"changeDate",date:this.getDate()})}},showMode:function(j){if(j){var k=Math.max(0,Math.min(g.modes.length-1,this.viewMode+j));if(k>=this.minView&&k<=this.maxView){this.element.trigger({type:"changeMode",date:this.viewDate,oldViewMode:this.viewMode,newViewMode:k});this.viewMode=k}}this.picker.find(">div").hide().filter(".datetimepicker-"+g.modes[this.viewMode].clsName).css("display","block");this.updateNavArrows()},reset:function(j){this._setDate(null,"date")},convertViewModeText:function(j){switch(j){case 4:return"decade";case 3:return"year";case 2:return"month";case 1:return"day";case 0:return"hour"}}};var b=f.fn.datetimepicker;f.fn.datetimepicker=function(l){var j=Array.apply(null,arguments);j.shift();var k;this.each(function(){var o=f(this),n=o.data("datetimepicker"),m=typeof l=="object"&&l;if(!n){o.data("datetimepicker",(n=new i(this,f.extend({},f.fn.datetimepicker.defaults,m))))}if(typeof l=="string"&&typeof n[l]=="function"){k=n[l].apply(n,j);if(k!==c){return false}}});if(k!==c){return k}else{return this}};f.fn.datetimepicker.defaults={};f.fn.datetimepicker.Constructor=i;var a=f.fn.datetimepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],meridiem:["am","pm"],suffix:["st","nd","rd","th"],today:"Today",clear:"Clear"}};var g={modes:[{clsName:"minutes",navFnc:"Hours",navStep:1},{clsName:"hours",navFnc:"Date",navStep:1},{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(j){return(((j%4===0)&&(j%100!==0))||(j%400===0))},getDaysInMonth:function(j,k){return[31,(g.isLeapYear(j)?29:28),31,30,31,30,31,31,30,31,30,31][k]},getDefaultFormat:function(j,k){if(j=="standard"){if(k=="input"){return"yyyy-mm-dd hh:ii"}else{return"yyyy-mm-dd hh:ii:ss"}}else{if(j=="php"){if(k=="input"){return"Y-m-d H:i"}else{return"Y-m-d H:i:s"}}else{throw new Error("Invalid format type.")}}},validParts:function(j){if(j=="standard"){return/t|hh?|HH?|p|P|ii?|ss?|dd?|DD?|mm?|MM?|yy(?:yy)?/g}else{if(j=="php"){return/[dDjlNwzFmMnStyYaABgGhHis]/g}else{throw new Error("Invalid format type.")}}},nonpunctuation:/[^ -\/:-@\[-`{-~\t\n\rTZ]+/g,parseFormat:function(m,k){var j=m.replace(this.validParts(k),"\0").split("\0"),l=m.match(this.validParts(k));if(!j||!j.length||!l||l.length==0){throw new Error("Invalid date format.")}return{separators:j,parts:l}},parseDate:function(n,w,q,u){if(n instanceof Date){var y=new Date(n.valueOf()-n.getTimezoneOffset()*60000);y.setMilliseconds(0);return y}if(/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(n)){w=this.parseFormat("yyyy-mm-dd",u)}if(/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(n)){w=this.parseFormat("yyyy-mm-dd hh:ii",u)}if(/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(n)){w=this.parseFormat("yyyy-mm-dd hh:ii:ss",u)}if(/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(n)){var z=/([-+]\d+)([dmwy])/,o=n.match(/([-+]\d+)([dmwy])/g),j,m;n=new Date();for(var p=0;p<o.length;p++){j=z.exec(o[p]);m=parseInt(j[1]);switch(j[2]){case"d":n.setUTCDate(n.getUTCDate()+m);break;case"m":n=i.prototype.moveMonth.call(i.prototype,n,m);break;case"w":n.setUTCDate(n.getUTCDate()+m*7);break;case"y":n=i.prototype.moveYear.call(i.prototype,n,m);break}}return h(n.getUTCFullYear(),n.getUTCMonth(),n.getUTCDate(),n.getUTCHours(),n.getUTCMinutes(),n.getUTCSeconds(),0)}var o=n&&n.toString().match(this.nonpunctuation)||[],n=new Date(0,0,0,0,0,0,0),t={},v=["hh","h","ii","i","ss","s","yyyy","yy","M","MM","m","mm","D","DD","d","dd","H","HH","p","P"],x={hh:function(B,s){return B.setUTCHours(s)},h:function(B,s){return B.setUTCHours(s)},HH:function(B,s){return B.setUTCHours(s==12?0:s)},H:function(B,s){return B.setUTCHours(s==12?0:s)},ii:function(B,s){return B.setUTCMinutes(s)},i:function(B,s){return B.setUTCMinutes(s)},ss:function(B,s){return B.setUTCSeconds(s)},s:function(B,s){return B.setUTCSeconds(s)},yyyy:function(B,s){return B.setUTCFullYear(s)},yy:function(B,s){return B.setUTCFullYear(2000+s)},m:function(B,s){s-=1;while(s<0){s+=12}s%=12;B.setUTCMonth(s);while(B.getUTCMonth()!=s){if(isNaN(B.getUTCMonth())){return B}else{B.setUTCDate(B.getUTCDate()-1)}}return B},d:function(B,s){return B.setUTCDate(s)},p:function(B,s){return B.setUTCHours(s==1?B.getUTCHours()+12:B.getUTCHours())}},l,r,j;x.M=x.MM=x.mm=x.m;x.dd=x.d;x.P=x.p;n=h(n.getFullYear(),n.getMonth(),n.getDate(),n.getHours(),n.getMinutes(),n.getSeconds());if(o.length==w.parts.length){for(var p=0,k=w.parts.length;p<k;p++){l=parseInt(o[p],10);j=w.parts[p];if(isNaN(l)){switch(j){case"MM":r=f(a[q].months).filter(function(){var s=this.slice(0,o[p].length),B=o[p].slice(0,s.length);return s==B});l=f.inArray(r[0],a[q].months)+1;break;case"M":r=f(a[q].monthsShort).filter(function(){var s=this.slice(0,o[p].length),B=o[p].slice(0,s.length);return s.toLowerCase()==B.toLowerCase()});l=f.inArray(r[0],a[q].monthsShort)+1;break;case"p":case"P":l=f.inArray(o[p].toLowerCase(),a[q].meridiem);break}}t[j]=l}for(var p=0,A;p<v.length;p++){A=v[p];if(A in t&&!isNaN(t[A])){x[A](n,t[A])}}}return n},formatDate:function(j,o,q,m){if(j==null){return""}var p;if(m=="standard"){p={t:j.getTime(),yy:j.getUTCFullYear().toString().substring(2),yyyy:j.getUTCFullYear(),m:j.getUTCMonth()+1,M:a[q].monthsShort[j.getUTCMonth()],MM:a[q].months[j.getUTCMonth()],d:j.getUTCDate(),D:a[q].daysShort[j.getUTCDay()],DD:a[q].days[j.getUTCDay()],p:(a[q].meridiem.length==2?a[q].meridiem[j.getUTCHours()<12?0:1]:""),h:j.getUTCHours(),i:j.getUTCMinutes(),s:j.getUTCSeconds()};if(a[q].meridiem.length==2){p.H=(p.h%12==0?12:p.h%12)}else{p.H=p.h}p.HH=(p.H<10?"0":"")+p.H;p.P=p.p.toUpperCase();p.hh=(p.h<10?"0":"")+p.h;p.ii=(p.i<10?"0":"")+p.i;p.ss=(p.s<10?"0":"")+p.s;p.dd=(p.d<10?"0":"")+p.d;p.mm=(p.m<10?"0":"")+p.m}else{if(m=="php"){p={y:j.getUTCFullYear().toString().substring(2),Y:j.getUTCFullYear(),F:a[q].months[j.getUTCMonth()],M:a[q].monthsShort[j.getUTCMonth()],n:j.getUTCMonth()+1,t:g.getDaysInMonth(j.getUTCFullYear(),j.getUTCMonth()),j:j.getUTCDate(),l:a[q].days[j.getUTCDay()],D:a[q].daysShort[j.getUTCDay()],w:j.getUTCDay(),N:(j.getUTCDay()==0?7:j.getUTCDay()),S:(j.getUTCDate()%10<=a[q].suffix.length?a[q].suffix[j.getUTCDate()%10-1]:""),a:(a[q].meridiem.length==2?a[q].meridiem[j.getUTCHours()<12?0:1]:""),g:(j.getUTCHours()%12==0?12:j.getUTCHours()%12),G:j.getUTCHours(),i:j.getUTCMinutes(),s:j.getUTCSeconds()};p.m=(p.n<10?"0":"")+p.n;p.d=(p.j<10?"0":"")+p.j;p.A=p.a.toString().toUpperCase();p.h=(p.g<10?"0":"")+p.g;p.H=(p.G<10?"0":"")+p.G;p.i=(p.i<10?"0":"")+p.i;p.s=(p.s<10?"0":"")+p.s}else{throw new Error("Invalid format type.")}}var j=[],n=f.extend([],o.separators);for(var l=0,k=o.parts.length;l<k;l++){if(n.length){j.push(n.shift())}j.push(p[o.parts[l]])}if(n.length){j.push(n.shift())}return j.join("")},convertViewMode:function(j){switch(j){case 4:case"decade":j=4;break;case 3:case"year":j=3;break;case 2:case"month":j=2;break;case 1:case"day":j=1;break;case 0:case"hour":j=0;break}return j},headTemplate:'<thead><tr><th class="prev"><i class="{iconType} {leftArrow}"/></th><th colspan="5" class="switch"></th><th class="next"><i class="{iconType} {rightArrow}"/></th></tr></thead>',headTemplateV3:'<thead><tr><th class="prev"><span class="{iconType} {leftArrow}"></span> </th><th colspan="5" class="switch"></th><th class="next"><span class="{iconType} {rightArrow}"></span> </th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr><tr><th colspan="7" class="clear"></th></tr></tfoot>'};g.template='<div class="datetimepicker"><div class="datetimepicker-minutes"><table class=" table-condensed">'+g.headTemplate+g.contTemplate+g.footTemplate+'</table></div><div class="datetimepicker-hours"><table class=" table-condensed">'+g.headTemplate+g.contTemplate+g.footTemplate+'</table></div><div class="datetimepicker-days"><table class=" table-condensed">'+g.headTemplate+"<tbody></tbody>"+g.footTemplate+'</table></div><div class="datetimepicker-months"><table class="table-condensed">'+g.headTemplate+g.contTemplate+g.footTemplate+'</table></div><div class="datetimepicker-years"><table class="table-condensed">'+g.headTemplate+g.contTemplate+g.footTemplate+"</table></div></div>";g.templateV3='<div class="datetimepicker"><div class="datetimepicker-minutes"><table class=" table-condensed">'+g.headTemplateV3+g.contTemplate+g.footTemplate+'</table></div><div class="datetimepicker-hours"><table class=" table-condensed">'+g.headTemplateV3+g.contTemplate+g.footTemplate+'</table></div><div class="datetimepicker-days"><table class=" table-condensed">'+g.headTemplateV3+"<tbody></tbody>"+g.footTemplate+'</table></div><div class="datetimepicker-months"><table class="table-condensed">'+g.headTemplateV3+g.contTemplate+g.footTemplate+'</table></div><div class="datetimepicker-years"><table class="table-condensed">'+g.headTemplateV3+g.contTemplate+g.footTemplate+"</table></div></div>";f.fn.datetimepicker.DPGlobal=g;f.fn.datetimepicker.noConflict=function(){f.fn.datetimepicker=b;return this};f(document).on("focus.datetimepicker.data-api click.datetimepicker.data-api",'[data-provide="datetimepicker"]',function(k){var j=f(this);if(j.data("datetimepicker")){return}k.preventDefault();j.datetimepicker("show")});f(function(){f('[data-provide="datetimepicker-inline"]').datetimepicker()})})); \ No newline at end of file +(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{if(typeof exports==="object"){a(require("jquery"))}else{a(jQuery)}}}(function(d,f){if(!("indexOf" in Array.prototype)){Array.prototype.indexOf=function(k,j){if(j===f){j=0}if(j<0){j+=this.length}if(j<0){j=0}for(var l=this.length;j<l;j++){if(j in this&&this[j]===k){return j}}return -1}}function a(){var q,k,p,l,j,n,m,o;k=(new Date()).toString();p=((m=k.split("(")[1])!=null?m.slice(0,-1):0)||k.split(" ");if(p instanceof Array){n=[];for(var l=0,j=p.length;l<j;l++){o=p[l];if((q=(m=o.match(/\b[A-Z]+\b/))!==null)?m[0]:0){n.push(q)}}p=n.pop()}return p}function h(){return new Date(Date.UTC.apply(Date,arguments))}var g=function(k,j){var m=this;this.element=d(k);this.container=j.container||"body";this.language=j.language||this.element.data("date-language")||"en";this.language=this.language in e?this.language:this.language.split("-")[0];this.language=this.language in e?this.language:"en";this.isRTL=e[this.language].rtl||false;this.formatType=j.formatType||this.element.data("format-type")||"standard";this.format=c.parseFormat(j.format||this.element.data("date-format")||e[this.language].format||c.getDefaultFormat(this.formatType,"input"),this.formatType);this.isInline=false;this.isVisible=false;this.isInput=this.element.is("input");this.fontAwesome=j.fontAwesome||this.element.data("font-awesome")||false;this.bootcssVer=j.bootcssVer||(this.isInput?(this.element.is(".form-control")?3:2):(this.bootcssVer=this.element.is(".input-group")?3:2));this.component=this.element.is(".date")?(this.bootcssVer===3?this.element.find(".input-group-addon .glyphicon-th, .input-group-addon .glyphicon-time, .input-group-addon .glyphicon-remove, .input-group-addon .glyphicon-calendar, .input-group-addon .fa-calendar, .input-group-addon .fa-clock-o").parent():this.element.find(".add-on .icon-th, .add-on .icon-time, .add-on .icon-calendar, .add-on .fa-calendar, .add-on .fa-clock-o").parent()):false;this.componentReset=this.element.is(".date")?(this.bootcssVer===3?this.element.find(".input-group-addon .glyphicon-remove, .input-group-addon .fa-times").parent():this.element.find(".add-on .icon-remove, .add-on .fa-times").parent()):false;this.hasInput=this.component&&this.element.find("input").length;if(this.component&&this.component.length===0){this.component=false}this.linkField=j.linkField||this.element.data("link-field")||false;this.linkFormat=c.parseFormat(j.linkFormat||this.element.data("link-format")||c.getDefaultFormat(this.formatType,"link"),this.formatType);this.minuteStep=j.minuteStep||this.element.data("minute-step")||5;this.pickerPosition=j.pickerPosition||this.element.data("picker-position")||"bottom-right";this.showMeridian=j.showMeridian||this.element.data("show-meridian")||false;this.initialDate=j.initialDate||new Date();this.zIndex=j.zIndex||this.element.data("z-index")||f;this.title=typeof j.title==="undefined"?false:j.title;this.timezone=j.timezone||a();this.icons={leftArrow:this.fontAwesome?"fa-arrow-left":(this.bootcssVer===3?"glyphicon-arrow-left":"icon-arrow-left"),rightArrow:this.fontAwesome?"fa-arrow-right":(this.bootcssVer===3?"glyphicon-arrow-right":"icon-arrow-right")};this.icontype=this.fontAwesome?"fa":"glyphicon";this._attachEvents();this.clickedOutside=function(n){if(d(n.target).closest(".datetimepicker").length===0){m.hide()}};this.formatViewType="datetime";if("formatViewType" in j){this.formatViewType=j.formatViewType}else{if("formatViewType" in this.element.data()){this.formatViewType=this.element.data("formatViewType")}}this.minView=0;if("minView" in j){this.minView=j.minView}else{if("minView" in this.element.data()){this.minView=this.element.data("min-view")}}this.minView=c.convertViewMode(this.minView);this.maxView=c.modes.length-1;if("maxView" in j){this.maxView=j.maxView}else{if("maxView" in this.element.data()){this.maxView=this.element.data("max-view")}}this.maxView=c.convertViewMode(this.maxView);this.wheelViewModeNavigation=false;if("wheelViewModeNavigation" in j){this.wheelViewModeNavigation=j.wheelViewModeNavigation}else{if("wheelViewModeNavigation" in this.element.data()){this.wheelViewModeNavigation=this.element.data("view-mode-wheel-navigation")}}this.wheelViewModeNavigationInverseDirection=false;if("wheelViewModeNavigationInverseDirection" in j){this.wheelViewModeNavigationInverseDirection=j.wheelViewModeNavigationInverseDirection}else{if("wheelViewModeNavigationInverseDirection" in this.element.data()){this.wheelViewModeNavigationInverseDirection=this.element.data("view-mode-wheel-navigation-inverse-dir")}}this.wheelViewModeNavigationDelay=100;if("wheelViewModeNavigationDelay" in j){this.wheelViewModeNavigationDelay=j.wheelViewModeNavigationDelay}else{if("wheelViewModeNavigationDelay" in this.element.data()){this.wheelViewModeNavigationDelay=this.element.data("view-mode-wheel-navigation-delay")}}this.startViewMode=2;if("startView" in j){this.startViewMode=j.startView}else{if("startView" in this.element.data()){this.startViewMode=this.element.data("start-view")}}this.startViewMode=c.convertViewMode(this.startViewMode);this.viewMode=this.startViewMode;this.viewSelect=this.minView;if("viewSelect" in j){this.viewSelect=j.viewSelect}else{if("viewSelect" in this.element.data()){this.viewSelect=this.element.data("view-select")}}this.viewSelect=c.convertViewMode(this.viewSelect);this.forceParse=true;if("forceParse" in j){this.forceParse=j.forceParse}else{if("dateForceParse" in this.element.data()){this.forceParse=this.element.data("date-force-parse")}}var l=this.bootcssVer===3?c.templateV3:c.template;while(l.indexOf("{iconType}")!==-1){l=l.replace("{iconType}",this.icontype)}while(l.indexOf("{leftArrow}")!==-1){l=l.replace("{leftArrow}",this.icons.leftArrow)}while(l.indexOf("{rightArrow}")!==-1){l=l.replace("{rightArrow}",this.icons.rightArrow)}this.picker=d(l).appendTo(this.isInline?this.element:this.container).on({click:d.proxy(this.click,this),mousedown:d.proxy(this.mousedown,this)});if(this.wheelViewModeNavigation){if(d.fn.mousewheel){this.picker.on({mousewheel:d.proxy(this.mousewheel,this)})}else{console.log("Mouse Wheel event is not supported. Please include the jQuery Mouse Wheel plugin before enabling this option")}}if(this.isInline){this.picker.addClass("datetimepicker-inline")}else{this.picker.addClass("datetimepicker-dropdown-"+this.pickerPosition+" dropdown-menu")}if(this.isRTL){this.picker.addClass("datetimepicker-rtl");var i=this.bootcssVer===3?".prev span, .next span":".prev i, .next i";this.picker.find(i).toggleClass(this.icons.leftArrow+" "+this.icons.rightArrow)}d(document).on("mousedown touchend",this.clickedOutside);this.autoclose=false;if("autoclose" in j){this.autoclose=j.autoclose}else{if("dateAutoclose" in this.element.data()){this.autoclose=this.element.data("date-autoclose")}}this.keyboardNavigation=true;if("keyboardNavigation" in j){this.keyboardNavigation=j.keyboardNavigation}else{if("dateKeyboardNavigation" in this.element.data()){this.keyboardNavigation=this.element.data("date-keyboard-navigation")}}this.todayBtn=(j.todayBtn||this.element.data("date-today-btn")||false);this.clearBtn=(j.clearBtn||this.element.data("date-clear-btn")||false);this.todayHighlight=(j.todayHighlight||this.element.data("date-today-highlight")||false);this.weekStart=0;if(typeof j.weekStart!=="undefined"){this.weekStart=j.weekStart}else{if(typeof this.element.data("date-weekstart")!=="undefined"){this.weekStart=this.element.data("date-weekstart")}else{if(typeof e[this.language].weekStart!=="undefined"){this.weekStart=e[this.language].weekStart}}}this.weekStart=this.weekStart%7;this.weekEnd=((this.weekStart+6)%7);this.onRenderDay=function(n){var p=(j.onRenderDay||function(){return[]})(n);if(typeof p==="string"){p=[p]}var o=["day"];return o.concat((p?p:[]))};this.onRenderHour=function(n){var p=(j.onRenderHour||function(){return[]})(n);var o=["hour"];if(typeof p==="string"){p=[p]}return o.concat((p?p:[]))};this.onRenderMinute=function(n){var p=(j.onRenderMinute||function(){return[]})(n);var o=["minute"];if(typeof p==="string"){p=[p]}if(n<this.startDate||n>this.endDate){o.push("disabled")}else{if(Math.floor(this.date.getUTCMinutes()/this.minuteStep)===Math.floor(n.getUTCMinutes()/this.minuteStep)){o.push("active")}}return o.concat((p?p:[]))};this.onRenderYear=function(o){var q=(j.onRenderYear||function(){return[]})(o);var p=["year"];if(typeof q==="string"){q=[q]}if(this.date.getUTCFullYear()===o.getUTCFullYear()){p.push("active")}var n=o.getUTCFullYear();var r=this.endDate.getUTCFullYear();if(o<this.startDate||n>r){p.push("disabled")}return p.concat((q?q:[]))};this.onRenderMonth=function(n){var p=(j.onRenderMonth||function(){return[]})(n);var o=["month"];if(typeof p==="string"){p=[p]}return o.concat((p?p:[]))};this.startDate=new Date(-8639968443048000);this.endDate=new Date(8639968443048000);this.datesDisabled=[];this.daysOfWeekDisabled=[];this.setStartDate(j.startDate||this.element.data("date-startdate"));this.setEndDate(j.endDate||this.element.data("date-enddate"));this.setDatesDisabled(j.datesDisabled||this.element.data("date-dates-disabled"));this.setDaysOfWeekDisabled(j.daysOfWeekDisabled||this.element.data("date-days-of-week-disabled"));this.setMinutesDisabled(j.minutesDisabled||this.element.data("date-minute-disabled"));this.setHoursDisabled(j.hoursDisabled||this.element.data("date-hour-disabled"));this.fillDow();this.fillMonths();this.update();this.showMode();if(this.isInline){this.show()}};g.prototype={constructor:g,_events:[],_attachEvents:function(){this._detachEvents();if(this.isInput){this._events=[[this.element,{focus:d.proxy(this.show,this),keyup:d.proxy(this.update,this),keydown:d.proxy(this.keydown,this)}]]}else{if(this.component&&this.hasInput){this._events=[[this.element.find("input"),{focus:d.proxy(this.show,this),keyup:d.proxy(this.update,this),keydown:d.proxy(this.keydown,this)}],[this.component,{click:d.proxy(this.show,this)}]];if(this.componentReset){this._events.push([this.componentReset,{click:d.proxy(this.reset,this)}])}}else{if(this.element.is("div")){this.isInline=true}else{this._events=[[this.element,{click:d.proxy(this.show,this)}]]}}}for(var j=0,k,l;j<this._events.length;j++){k=this._events[j][0];l=this._events[j][1];k.on(l)}},_detachEvents:function(){for(var j=0,k,l;j<this._events.length;j++){k=this._events[j][0];l=this._events[j][1];k.off(l)}this._events=[]},show:function(i){this.picker.show();this.height=this.component?this.component.outerHeight():this.element.outerHeight();if(this.forceParse){this.update()}this.place();d(window).on("resize",d.proxy(this.place,this));if(i){i.stopPropagation();i.preventDefault()}this.isVisible=true;this.element.trigger({type:"show",date:this.date})},hide:function(){if(!this.isVisible){return}if(this.isInline){return}this.picker.hide();d(window).off("resize",this.place);this.viewMode=this.startViewMode;this.showMode();if(!this.isInput){d(document).off("mousedown",this.hide)}if(this.forceParse&&(this.isInput&&this.element.val()||this.hasInput&&this.element.find("input").val())){this.setValue()}this.isVisible=false;this.element.trigger({type:"hide",date:this.date})},remove:function(){this._detachEvents();d(document).off("mousedown",this.clickedOutside);this.picker.remove();delete this.picker;delete this.element.data().datetimepicker},getDate:function(){var i=this.getUTCDate();if(i===null){return null}return new Date(i.getTime()+(i.getTimezoneOffset()*60000))},getUTCDate:function(){return this.date},getInitialDate:function(){return this.initialDate},setInitialDate:function(i){this.initialDate=i},setDate:function(i){this.setUTCDate(new Date(i.getTime()-(i.getTimezoneOffset()*60000)))},setUTCDate:function(i){if(i>=this.startDate&&i<=this.endDate){this.date=i;this.setValue();this.viewDate=this.date;this.fill()}else{this.element.trigger({type:"outOfRange",date:i,startDate:this.startDate,endDate:this.endDate})}},setFormat:function(j){this.format=c.parseFormat(j,this.formatType);var i;if(this.isInput){i=this.element}else{if(this.component){i=this.element.find("input")}}if(i&&i.val()){this.setValue()}},setValue:function(){var i=this.getFormattedDate();if(!this.isInput){if(this.component){this.element.find("input").val(i)}this.element.data("date",i)}else{this.element.val(i)}if(this.linkField){d("#"+this.linkField).val(this.getFormattedDate(this.linkFormat))}},getFormattedDate:function(i){i=i||this.format;return c.formatDate(this.date,i,this.language,this.formatType,this.timezone)},setStartDate:function(i){this.startDate=i||this.startDate;if(this.startDate.valueOf()!==8639968443048000){this.startDate=c.parseDate(this.startDate,this.format,this.language,this.formatType,this.timezone)}this.update();this.updateNavArrows()},setEndDate:function(i){this.endDate=i||this.endDate;if(this.endDate.valueOf()!==8639968443048000){this.endDate=c.parseDate(this.endDate,this.format,this.language,this.formatType,this.timezone)}this.update();this.updateNavArrows()},setDatesDisabled:function(j){this.datesDisabled=j||[];if(!d.isArray(this.datesDisabled)){this.datesDisabled=this.datesDisabled.split(/,\s*/)}var i=this;this.datesDisabled=d.map(this.datesDisabled,function(k){return c.parseDate(k,i.format,i.language,i.formatType,i.timezone).toDateString()});this.update();this.updateNavArrows()},setTitle:function(i,j){return this.picker.find(i).find("th:eq(1)").text(this.title===false?j:this.title)},setDaysOfWeekDisabled:function(i){this.daysOfWeekDisabled=i||[];if(!d.isArray(this.daysOfWeekDisabled)){this.daysOfWeekDisabled=this.daysOfWeekDisabled.split(/,\s*/)}this.daysOfWeekDisabled=d.map(this.daysOfWeekDisabled,function(j){return parseInt(j,10)});this.update();this.updateNavArrows()},setMinutesDisabled:function(i){this.minutesDisabled=i||[];if(!d.isArray(this.minutesDisabled)){this.minutesDisabled=this.minutesDisabled.split(/,\s*/)}this.minutesDisabled=d.map(this.minutesDisabled,function(j){return parseInt(j,10)});this.update();this.updateNavArrows()},setHoursDisabled:function(i){this.hoursDisabled=i||[];if(!d.isArray(this.hoursDisabled)){this.hoursDisabled=this.hoursDisabled.split(/,\s*/)}this.hoursDisabled=d.map(this.hoursDisabled,function(j){return parseInt(j,10)});this.update();this.updateNavArrows()},place:function(){if(this.isInline){return}if(!this.zIndex){var j=0;d("div").each(function(){var o=parseInt(d(this).css("zIndex"),10);if(o>j){j=o}});this.zIndex=j+10}var n,m,l,k;if(this.container instanceof d){k=this.container.offset()}else{k=d(this.container).offset()}if(this.component){n=this.component.offset();l=n.left;if(this.pickerPosition==="bottom-left"||this.pickerPosition==="top-left"){l+=this.component.outerWidth()-this.picker.outerWidth()}}else{n=this.element.offset();l=n.left;if(this.pickerPosition==="bottom-left"||this.pickerPosition==="top-left"){l+=this.element.outerWidth()-this.picker.outerWidth()}}var i=document.body.clientWidth||window.innerWidth;if(l+220>i){l=i-220}if(this.pickerPosition==="top-left"||this.pickerPosition==="top-right"){m=n.top-this.picker.outerHeight()}else{m=n.top+this.height}m=m-k.top;l=l-k.left;this.picker.css({top:m,left:l,zIndex:this.zIndex})},hour_minute:"^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]",update:function(){var i,j=false;if(arguments&&arguments.length&&(typeof arguments[0]==="string"||arguments[0] instanceof Date)){i=arguments[0];j=true}else{i=(this.isInput?this.element.val():this.element.find("input").val())||this.element.data("date")||this.initialDate;if(typeof i==="string"){i=i.replace(/^\s+|\s+$/g,"")}}if(!i){i=new Date();j=false}if(typeof i==="string"){if(new RegExp(this.hour_minute).test(i)||new RegExp(this.hour_minute+":[0-5][0-9]").test(i)){i=this.getDate()}}this.date=c.parseDate(i,this.format,this.language,this.formatType,this.timezone);if(j){this.setValue()}if(this.date<this.startDate){this.viewDate=new Date(this.startDate)}else{if(this.date>this.endDate){this.viewDate=new Date(this.endDate)}else{this.viewDate=new Date(this.date)}}this.fill()},fillDow:function(){var i=this.weekStart,j="<tr>";while(i<this.weekStart+7){j+='<th class="dow">'+e[this.language].daysMin[(i++)%7]+"</th>"}j+="</tr>";this.picker.find(".datetimepicker-days thead").append(j)},fillMonths:function(){var l="";var m=new Date(this.viewDate);for(var k=0;k<12;k++){m.setUTCMonth(k);var j=this.onRenderMonth(m);l+='<span class="'+j.join(" ")+'">'+e[this.language].monthsShort[k]+"</span>"}this.picker.find(".datetimepicker-months td").html(l)},fill:function(){if(!this.date||!this.viewDate){return}var E=new Date(this.viewDate),t=E.getUTCFullYear(),G=E.getUTCMonth(),n=E.getUTCDate(),A=E.getUTCHours(),w=this.startDate.getUTCFullYear(),B=this.startDate.getUTCMonth(),p=this.endDate.getUTCFullYear(),x=this.endDate.getUTCMonth()+1,q=(new h(this.date.getUTCFullYear(),this.date.getUTCMonth(),this.date.getUTCDate())).valueOf(),D=new Date();this.setTitle(".datetimepicker-days",e[this.language].months[G]+" "+t);if(this.formatViewType==="time"){var k=this.getFormattedDate();this.setTitle(".datetimepicker-hours",k);this.setTitle(".datetimepicker-minutes",k)}else{this.setTitle(".datetimepicker-hours",n+" "+e[this.language].months[G]+" "+t);this.setTitle(".datetimepicker-minutes",n+" "+e[this.language].months[G]+" "+t)}this.picker.find("tfoot th.today").text(e[this.language].today||e.en.today).toggle(this.todayBtn!==false);this.picker.find("tfoot th.clear").text(e[this.language].clear||e.en.clear).toggle(this.clearBtn!==false);this.updateNavArrows();this.fillMonths();var I=h(t,G-1,28,0,0,0,0),z=c.getDaysInMonth(I.getUTCFullYear(),I.getUTCMonth());I.setUTCDate(z);I.setUTCDate(z-(I.getUTCDay()-this.weekStart+7)%7);var j=new Date(I);j.setUTCDate(j.getUTCDate()+42);j=j.valueOf();var r=[];var F;while(I.valueOf()<j){if(I.getUTCDay()===this.weekStart){r.push("<tr>")}F=this.onRenderDay(I);if(I.getUTCFullYear()<t||(I.getUTCFullYear()===t&&I.getUTCMonth()<G)){F.push("old")}else{if(I.getUTCFullYear()>t||(I.getUTCFullYear()===t&&I.getUTCMonth()>G)){F.push("new")}}if(this.todayHighlight&&I.getUTCFullYear()===D.getFullYear()&&I.getUTCMonth()===D.getMonth()&&I.getUTCDate()===D.getDate()){F.push("today")}if(I.valueOf()===q){F.push("active")}if((I.valueOf()+86400000)<=this.startDate||I.valueOf()>this.endDate||d.inArray(I.getUTCDay(),this.daysOfWeekDisabled)!==-1||d.inArray(I.toDateString(),this.datesDisabled)!==-1){F.push("disabled")}r.push('<td class="'+F.join(" ")+'">'+I.getUTCDate()+"</td>");if(I.getUTCDay()===this.weekEnd){r.push("</tr>")}I.setUTCDate(I.getUTCDate()+1)}this.picker.find(".datetimepicker-days tbody").empty().append(r.join(""));r=[];var u="",C="",s="";var l=this.hoursDisabled||[];E=new Date(this.viewDate);for(var y=0;y<24;y++){E.setUTCHours(y);F=this.onRenderHour(E);if(l.indexOf(y)!==-1){F.push("disabled")}var v=h(t,G,n,y);if((v.valueOf()+3600000)<=this.startDate||v.valueOf()>this.endDate){F.push("disabled")}else{if(A===y){F.push("active")}}if(this.showMeridian&&e[this.language].meridiem.length===2){C=(y<12?e[this.language].meridiem[0]:e[this.language].meridiem[1]);if(C!==s){if(s!==""){r.push("</fieldset>")}r.push('<fieldset class="hour"><legend>'+C.toUpperCase()+"</legend>")}s=C;u=(y%12?y%12:12);if(y<12){F.push("hour_am")}else{F.push("hour_pm")}r.push('<span class="'+F.join(" ")+'">'+u+"</span>");if(y===23){r.push("</fieldset>")}}else{u=y+":00";r.push('<span class="'+F.join(" ")+'">'+u+"</span>")}}this.picker.find(".datetimepicker-hours td").html(r.join(""));r=[];u="";C="";s="";var m=this.minutesDisabled||[];E=new Date(this.viewDate);for(var y=0;y<60;y+=this.minuteStep){if(m.indexOf(y)!==-1){continue}E.setUTCMinutes(y);E.setUTCSeconds(0);F=this.onRenderMinute(E);if(this.showMeridian&&e[this.language].meridiem.length===2){C=(A<12?e[this.language].meridiem[0]:e[this.language].meridiem[1]);if(C!==s){if(s!==""){r.push("</fieldset>")}r.push('<fieldset class="minute"><legend>'+C.toUpperCase()+"</legend>")}s=C;u=(A%12?A%12:12);r.push('<span class="'+F.join(" ")+'">'+u+":"+(y<10?"0"+y:y)+"</span>");if(y===59){r.push("</fieldset>")}}else{u=y+":00";r.push('<span class="'+F.join(" ")+'">'+A+":"+(y<10?"0"+y:y)+"</span>")}}this.picker.find(".datetimepicker-minutes td").html(r.join(""));var J=this.date.getUTCFullYear();var o=this.setTitle(".datetimepicker-months",t).end().find(".month").removeClass("active");if(J===t){o.eq(this.date.getUTCMonth()).addClass("active")}if(t<w||t>p){o.addClass("disabled")}if(t===w){o.slice(0,B).addClass("disabled")}if(t===p){o.slice(x).addClass("disabled")}r="";t=parseInt(t/10,10)*10;var H=this.setTitle(".datetimepicker-years",t+"-"+(t+9)).end().find("td");t-=1;E=new Date(this.viewDate);for(var y=-1;y<11;y++){E.setUTCFullYear(t);F=this.onRenderYear(E);if(y===-1||y===10){F.push(b)}r+='<span class="'+F.join(" ")+'">'+t+"</span>";t+=1}H.html(r);this.place()},updateNavArrows:function(){var m=new Date(this.viewDate),k=m.getUTCFullYear(),l=m.getUTCMonth(),j=m.getUTCDate(),i=m.getUTCHours();switch(this.viewMode){case 0:if(k<=this.startDate.getUTCFullYear()&&l<=this.startDate.getUTCMonth()&&j<=this.startDate.getUTCDate()&&i<=this.startDate.getUTCHours()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()&&l>=this.endDate.getUTCMonth()&&j>=this.endDate.getUTCDate()&&i>=this.endDate.getUTCHours()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 1:if(k<=this.startDate.getUTCFullYear()&&l<=this.startDate.getUTCMonth()&&j<=this.startDate.getUTCDate()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()&&l>=this.endDate.getUTCMonth()&&j>=this.endDate.getUTCDate()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 2:if(k<=this.startDate.getUTCFullYear()&&l<=this.startDate.getUTCMonth()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()&&l>=this.endDate.getUTCMonth()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 3:case 4:if(k<=this.startDate.getUTCFullYear()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break}},mousewheel:function(j){j.preventDefault();j.stopPropagation();if(this.wheelPause){return}this.wheelPause=true;var i=j.originalEvent;var l=i.wheelDelta;var k=l>0?1:(l===0)?0:-1;if(this.wheelViewModeNavigationInverseDirection){k=-k}this.showMode(k);setTimeout(d.proxy(function(){this.wheelPause=false},this),this.wheelViewModeNavigationDelay)},click:function(m){m.stopPropagation();m.preventDefault();var n=d(m.target).closest("span, td, th, legend");if(n.is("."+this.icontype)){n=d(n).parent().closest("span, td, th, legend")}if(n.length===1){if(n.is(".disabled")){this.element.trigger({type:"outOfRange",date:this.viewDate,startDate:this.startDate,endDate:this.endDate});return}switch(n[0].nodeName.toLowerCase()){case"th":switch(n[0].className){case"switch":this.showMode(1);break;case"prev":case"next":var i=c.modes[this.viewMode].navStep*(n[0].className==="prev"?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveHour(this.viewDate,i);break;case 1:this.viewDate=this.moveDate(this.viewDate,i);break;case 2:this.viewDate=this.moveMonth(this.viewDate,i);break;case 3:case 4:this.viewDate=this.moveYear(this.viewDate,i);break}this.fill();this.element.trigger({type:n[0].className+":"+this.convertViewModeText(this.viewMode),date:this.viewDate,startDate:this.startDate,endDate:this.endDate});break;case"clear":this.reset();if(this.autoclose){this.hide()}break;case"today":var j=new Date();j=h(j.getFullYear(),j.getMonth(),j.getDate(),j.getHours(),j.getMinutes(),j.getSeconds(),0);if(j<this.startDate){j=this.startDate}else{if(j>this.endDate){j=this.endDate}}this.viewMode=this.startViewMode;this.showMode(0);this._setDate(j);this.fill();if(this.autoclose){this.hide()}break}break;case"span":if(!n.is(".disabled")){var p=this.viewDate.getUTCFullYear(),o=this.viewDate.getUTCMonth(),q=this.viewDate.getUTCDate(),r=this.viewDate.getUTCHours(),k=this.viewDate.getUTCMinutes(),s=this.viewDate.getUTCSeconds();if(n.is(".month")){this.viewDate.setUTCDate(1);o=n.parent().find("span").index(n);q=this.viewDate.getUTCDate();this.viewDate.setUTCMonth(o);this.element.trigger({type:"changeMonth",date:this.viewDate});if(this.viewSelect>=3){this._setDate(h(p,o,q,r,k,s,0))}}else{if(n.is(".year")){this.viewDate.setUTCDate(1);p=parseInt(n.text(),10)||0;this.viewDate.setUTCFullYear(p);this.element.trigger({type:"changeYear",date:this.viewDate});if(this.viewSelect>=4){this._setDate(h(p,o,q,r,k,s,0))}}else{if(n.is(".hour")){r=parseInt(n.text(),10)||0;if(n.hasClass("hour_am")||n.hasClass("hour_pm")){if(r===12&&n.hasClass("hour_am")){r=0}else{if(r!==12&&n.hasClass("hour_pm")){r+=12}}}this.viewDate.setUTCHours(r);this.element.trigger({type:"changeHour",date:this.viewDate});if(this.viewSelect>=1){this._setDate(h(p,o,q,r,k,s,0))}}else{if(n.is(".minute")){k=parseInt(n.text().substr(n.text().indexOf(":")+1),10)||0;this.viewDate.setUTCMinutes(k);this.element.trigger({type:"changeMinute",date:this.viewDate});if(this.viewSelect>=0){this._setDate(h(p,o,q,r,k,s,0))}}}}}if(this.viewMode!==0){var l=this.viewMode;this.showMode(-1);this.fill();if(l===this.viewMode&&this.autoclose){this.hide()}}else{this.fill();if(this.autoclose){this.hide()}}}break;case"td":if(n.is(".day")&&!n.is(".disabled")){var q=parseInt(n.text(),10)||1;var p=this.viewDate.getUTCFullYear(),o=this.viewDate.getUTCMonth(),r=this.viewDate.getUTCHours(),k=this.viewDate.getUTCMinutes(),s=this.viewDate.getUTCSeconds();if(n.is(".old")){if(o===0){o=11;p-=1}else{o-=1}}else{if(n.is(".new")){if(o===11){o=0;p+=1}else{o+=1}}}this.viewDate.setUTCFullYear(p);this.viewDate.setUTCMonth(o,q);this.element.trigger({type:"changeDay",date:this.viewDate});if(this.viewSelect>=2){this._setDate(h(p,o,q,r,k,s,0))}}var l=this.viewMode;this.showMode(-1);this.fill();if(l===this.viewMode&&this.autoclose){this.hide()}break}}},_setDate:function(i,k){if(!k||k==="date"){this.date=i}if(!k||k==="view"){this.viewDate=i}this.fill();this.setValue();var j;if(this.isInput){j=this.element}else{if(this.component){j=this.element.find("input")}}if(j){j.change()}this.element.trigger({type:"changeDate",date:this.getDate()});if(i===null){this.date=this.viewDate}},moveMinute:function(j,i){if(!i){return j}var k=new Date(j.valueOf());k.setUTCMinutes(k.getUTCMinutes()+(i*this.minuteStep));return k},moveHour:function(j,i){if(!i){return j}var k=new Date(j.valueOf());k.setUTCHours(k.getUTCHours()+i);return k},moveDate:function(j,i){if(!i){return j}var k=new Date(j.valueOf());k.setUTCDate(k.getUTCDate()+i);return k},moveMonth:function(j,k){if(!k){return j}var n=new Date(j.valueOf()),r=n.getUTCDate(),o=n.getUTCMonth(),m=Math.abs(k),q,p;k=k>0?1:-1;if(m===1){p=k===-1?function(){return n.getUTCMonth()===o}:function(){return n.getUTCMonth()!==q};q=o+k;n.setUTCMonth(q);if(q<0||q>11){q=(q+12)%12}}else{for(var l=0;l<m;l++){n=this.moveMonth(n,k)}q=n.getUTCMonth();n.setUTCDate(r);p=function(){return q!==n.getUTCMonth()}}while(p()){n.setUTCDate(--r);n.setUTCMonth(q)}return n},moveYear:function(j,i){return this.moveMonth(j,i*12)},dateWithinRange:function(i){return i>=this.startDate&&i<=this.endDate},keydown:function(o){if(this.picker.is(":not(:visible)")){if(o.keyCode===27){this.show()}return}var k=false,j,i,n;switch(o.keyCode){case 27:this.hide();o.preventDefault();break;case 37:case 39:if(!this.keyboardNavigation){break}j=o.keyCode===37?-1:1;var m=this.viewMode;if(o.ctrlKey){m+=2}else{if(o.shiftKey){m+=1}}if(m===4){i=this.moveYear(this.date,j);n=this.moveYear(this.viewDate,j)}else{if(m===3){i=this.moveMonth(this.date,j);n=this.moveMonth(this.viewDate,j)}else{if(m===2){i=this.moveDate(this.date,j);n=this.moveDate(this.viewDate,j)}else{if(m===1){i=this.moveHour(this.date,j);n=this.moveHour(this.viewDate,j)}else{if(m===0){i=this.moveMinute(this.date,j);n=this.moveMinute(this.viewDate,j)}}}}}if(this.dateWithinRange(i)){this.date=i;this.viewDate=n;this.setValue();this.update();o.preventDefault();k=true}break;case 38:case 40:if(!this.keyboardNavigation){break}j=o.keyCode===38?-1:1;m=this.viewMode;if(o.ctrlKey){m+=2}else{if(o.shiftKey){m+=1}}if(m===4){i=this.moveYear(this.date,j);n=this.moveYear(this.viewDate,j)}else{if(m===3){i=this.moveMonth(this.date,j);n=this.moveMonth(this.viewDate,j)}else{if(m===2){i=this.moveDate(this.date,j*7);n=this.moveDate(this.viewDate,j*7)}else{if(m===1){if(this.showMeridian){i=this.moveHour(this.date,j*6);n=this.moveHour(this.viewDate,j*6)}else{i=this.moveHour(this.date,j*4);n=this.moveHour(this.viewDate,j*4)}}else{if(m===0){i=this.moveMinute(this.date,j*4);n=this.moveMinute(this.viewDate,j*4)}}}}}if(this.dateWithinRange(i)){this.date=i;this.viewDate=n;this.setValue();this.update();o.preventDefault();k=true}break;case 13:if(this.viewMode!==0){var p=this.viewMode;this.showMode(-1);this.fill();if(p===this.viewMode&&this.autoclose){this.hide()}}else{this.fill();if(this.autoclose){this.hide()}}o.preventDefault();break;case 9:this.hide();break}if(k){var l;if(this.isInput){l=this.element}else{if(this.component){l=this.element.find("input")}}if(l){l.change()}this.element.trigger({type:"changeDate",date:this.getDate()})}},showMode:function(i){if(i){var j=Math.max(0,Math.min(c.modes.length-1,this.viewMode+i));if(j>=this.minView&&j<=this.maxView){this.element.trigger({type:"changeMode",date:this.viewDate,oldViewMode:this.viewMode,newViewMode:j});this.viewMode=j}}this.picker.find(">div").hide().filter(".datetimepicker-"+c.modes[this.viewMode].clsName).css("display","block");this.updateNavArrows()},reset:function(){this._setDate(null,"date")},convertViewModeText:function(i){switch(i){case 4:return"decade";case 3:return"year";case 2:return"month";case 1:return"day";case 0:return"hour"}}};var b=d.fn.datetimepicker;d.fn.datetimepicker=function(k){var i=Array.apply(null,arguments);i.shift();var j;this.each(function(){var n=d(this),m=n.data("datetimepicker"),l=typeof k==="object"&&k;if(!m){n.data("datetimepicker",(m=new g(this,d.extend({},d.fn.datetimepicker.defaults,l))))}if(typeof k==="string"&&typeof m[k]==="function"){j=m[k].apply(m,i);if(j!==f){return false}}});if(j!==f){return j}else{return this}};d.fn.datetimepicker.defaults={};d.fn.datetimepicker.Constructor=g;var e=d.fn.datetimepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],meridiem:["am","pm"],suffix:["st","nd","rd","th"],today:"Today",clear:"Clear"}};var c={modes:[{clsName:"minutes",navFnc:"Hours",navStep:1},{clsName:"hours",navFnc:"Date",navStep:1},{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(i){return(((i%4===0)&&(i%100!==0))||(i%400===0))},getDaysInMonth:function(i,j){return[31,(c.isLeapYear(i)?29:28),31,30,31,30,31,31,30,31,30,31][j]},getDefaultFormat:function(i,j){if(i==="standard"){if(j==="input"){return"yyyy-mm-dd hh:ii"}else{return"yyyy-mm-dd hh:ii:ss"}}else{if(i==="php"){if(j==="input"){return"Y-m-d H:i"}else{return"Y-m-d H:i:s"}}else{throw new Error("Invalid format type.")}}},validParts:function(i){if(i==="standard"){return/t|hh?|HH?|p|P|z|Z|ii?|ss?|dd?|DD?|mm?|MM?|yy(?:yy)?/g}else{if(i==="php"){return/[dDjlNwzFmMnStyYaABgGhHis]/g}else{throw new Error("Invalid format type.")}}},nonpunctuation:/[^ -\/:-@\[-`{-~\t\n\rTZ]+/g,parseFormat:function(l,j){var i=l.replace(this.validParts(j),"\0").split("\0"),k=l.match(this.validParts(j));if(!i||!i.length||!k||k.length===0){throw new Error("Invalid date format.")}return{separators:i,parts:k}},parseDate:function(A,y,v,j,r){if(A instanceof Date){var u=new Date(A.valueOf()-A.getTimezoneOffset()*60000);u.setMilliseconds(0);return u}if(/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(A)){y=this.parseFormat("yyyy-mm-dd",j)}if(/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(A)){y=this.parseFormat("yyyy-mm-dd hh:ii",j)}if(/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(A)){y=this.parseFormat("yyyy-mm-dd hh:ii:ss",j)}if(/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(A)){var l=/([-+]\d+)([dmwy])/,q=A.match(/([-+]\d+)([dmwy])/g),t,p;A=new Date();for(var x=0;x<q.length;x++){t=l.exec(q[x]);p=parseInt(t[1]);switch(t[2]){case"d":A.setUTCDate(A.getUTCDate()+p);break;case"m":A=g.prototype.moveMonth.call(g.prototype,A,p);break;case"w":A.setUTCDate(A.getUTCDate()+p*7);break;case"y":A=g.prototype.moveYear.call(g.prototype,A,p);break}}return h(A.getUTCFullYear(),A.getUTCMonth(),A.getUTCDate(),A.getUTCHours(),A.getUTCMinutes(),A.getUTCSeconds(),0)}var q=A&&A.toString().match(this.nonpunctuation)||[],A=new Date(0,0,0,0,0,0,0),m={},z=["hh","h","ii","i","ss","s","yyyy","yy","M","MM","m","mm","D","DD","d","dd","H","HH","p","P","z","Z"],o={hh:function(s,i){return s.setUTCHours(i)},h:function(s,i){return s.setUTCHours(i)},HH:function(s,i){return s.setUTCHours(i===12?0:i)},H:function(s,i){return s.setUTCHours(i===12?0:i)},ii:function(s,i){return s.setUTCMinutes(i)},i:function(s,i){return s.setUTCMinutes(i)},ss:function(s,i){return s.setUTCSeconds(i)},s:function(s,i){return s.setUTCSeconds(i)},yyyy:function(s,i){return s.setUTCFullYear(i)},yy:function(s,i){return s.setUTCFullYear(2000+i)},m:function(s,i){i-=1;while(i<0){i+=12}i%=12;s.setUTCMonth(i);while(s.getUTCMonth()!==i){if(isNaN(s.getUTCMonth())){return s}else{s.setUTCDate(s.getUTCDate()-1)}}return s},d:function(s,i){return s.setUTCDate(i)},p:function(s,i){return s.setUTCHours(i===1?s.getUTCHours()+12:s.getUTCHours())},z:function(){return r}},B,k,t;o.M=o.MM=o.mm=o.m;o.dd=o.d;o.P=o.p;o.Z=o.z;A=h(A.getFullYear(),A.getMonth(),A.getDate(),A.getHours(),A.getMinutes(),A.getSeconds());if(q.length===y.parts.length){for(var x=0,w=y.parts.length;x<w;x++){B=parseInt(q[x],10);t=y.parts[x];if(isNaN(B)){switch(t){case"MM":k=d(e[v].months).filter(function(){var i=this.slice(0,q[x].length),s=q[x].slice(0,i.length);return i===s});B=d.inArray(k[0],e[v].months)+1;break;case"M":k=d(e[v].monthsShort).filter(function(){var i=this.slice(0,q[x].length),s=q[x].slice(0,i.length);return i.toLowerCase()===s.toLowerCase()});B=d.inArray(k[0],e[v].monthsShort)+1;break;case"p":case"P":B=d.inArray(q[x].toLowerCase(),e[v].meridiem);break;case"z":case"Z":r;break}}m[t]=B}for(var x=0,n;x<z.length;x++){n=z[x];if(n in m&&!isNaN(m[n])){o[n](A,m[n])}}}return A},formatDate:function(l,q,m,p,o){if(l===null){return""}var k;if(p==="standard"){k={t:l.getTime(),yy:l.getUTCFullYear().toString().substring(2),yyyy:l.getUTCFullYear(),m:l.getUTCMonth()+1,M:e[m].monthsShort[l.getUTCMonth()],MM:e[m].months[l.getUTCMonth()],d:l.getUTCDate(),D:e[m].daysShort[l.getUTCDay()],DD:e[m].days[l.getUTCDay()],p:(e[m].meridiem.length===2?e[m].meridiem[l.getUTCHours()<12?0:1]:""),h:l.getUTCHours(),i:l.getUTCMinutes(),s:l.getUTCSeconds(),z:o};if(e[m].meridiem.length===2){k.H=(k.h%12===0?12:k.h%12)}else{k.H=k.h}k.HH=(k.H<10?"0":"")+k.H;k.P=k.p.toUpperCase();k.Z=k.z;k.hh=(k.h<10?"0":"")+k.h;k.ii=(k.i<10?"0":"")+k.i;k.ss=(k.s<10?"0":"")+k.s;k.dd=(k.d<10?"0":"")+k.d;k.mm=(k.m<10?"0":"")+k.m}else{if(p==="php"){k={y:l.getUTCFullYear().toString().substring(2),Y:l.getUTCFullYear(),F:e[m].months[l.getUTCMonth()],M:e[m].monthsShort[l.getUTCMonth()],n:l.getUTCMonth()+1,t:c.getDaysInMonth(l.getUTCFullYear(),l.getUTCMonth()),j:l.getUTCDate(),l:e[m].days[l.getUTCDay()],D:e[m].daysShort[l.getUTCDay()],w:l.getUTCDay(),N:(l.getUTCDay()===0?7:l.getUTCDay()),S:(l.getUTCDate()%10<=e[m].suffix.length?e[m].suffix[l.getUTCDate()%10-1]:""),a:(e[m].meridiem.length===2?e[m].meridiem[l.getUTCHours()<12?0:1]:""),g:(l.getUTCHours()%12===0?12:l.getUTCHours()%12),G:l.getUTCHours(),i:l.getUTCMinutes(),s:l.getUTCSeconds()};k.m=(k.n<10?"0":"")+k.n;k.d=(k.j<10?"0":"")+k.j;k.A=k.a.toString().toUpperCase();k.h=(k.g<10?"0":"")+k.g;k.H=(k.G<10?"0":"")+k.G;k.i=(k.i<10?"0":"")+k.i;k.s=(k.s<10?"0":"")+k.s}else{throw new Error("Invalid format type.")}}var l=[],r=d.extend([],q.separators);for(var n=0,j=q.parts.length;n<j;n++){if(r.length){l.push(r.shift())}l.push(k[q.parts[n]])}if(r.length){l.push(r.shift())}return l.join("")},convertViewMode:function(i){switch(i){case 4:case"decade":i=4;break;case 3:case"year":i=3;break;case 2:case"month":i=2;break;case 1:case"day":i=1;break;case 0:case"hour":i=0;break}return i},headTemplate:'<thead><tr><th class="prev"><i class="{iconType} {leftArrow}"/></th><th colspan="5" class="switch"></th><th class="next"><i class="{iconType} {rightArrow}"/></th></tr></thead>',headTemplateV3:'<thead><tr><th class="prev"><span class="{iconType} {leftArrow}"></span> </th><th colspan="5" class="switch"></th><th class="next"><span class="{iconType} {rightArrow}"></span> </th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr><tr><th colspan="7" class="clear"></th></tr></tfoot>'};c.template='<div class="datetimepicker"><div class="datetimepicker-minutes"><table class=" table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-hours"><table class=" table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-days"><table class=" table-condensed">'+c.headTemplate+"<tbody></tbody>"+c.footTemplate+'</table></div><div class="datetimepicker-months"><table class="table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-years"><table class="table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+"</table></div></div>";c.templateV3='<div class="datetimepicker"><div class="datetimepicker-minutes"><table class=" table-condensed">'+c.headTemplateV3+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-hours"><table class=" table-condensed">'+c.headTemplateV3+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-days"><table class=" table-condensed">'+c.headTemplateV3+"<tbody></tbody>"+c.footTemplate+'</table></div><div class="datetimepicker-months"><table class="table-condensed">'+c.headTemplateV3+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-years"><table class="table-condensed">'+c.headTemplateV3+c.contTemplate+c.footTemplate+"</table></div></div>";d.fn.datetimepicker.DPGlobal=c;d.fn.datetimepicker.noConflict=function(){d.fn.datetimepicker=b;return this};d(document).on("focus.datetimepicker.data-api click.datetimepicker.data-api",'[data-provide="datetimepicker"]',function(j){var i=d(this);if(i.data("datetimepicker")){return}j.preventDefault();i.datetimepicker("show")});d(function(){d('[data-provide="datetimepicker-inline"]').datetimepicker()})})); \ No newline at end of file From d023cfc63cb23c9dea9cf4b2741628b49f04a7f3 Mon Sep 17 00:00:00 2001 From: Cameron <e107inc@gmail.com> Date: Fri, 25 May 2018 08:47:47 -0700 Subject: [PATCH 43/59] datepicker timezone fix. --- e107_handlers/form_handler.php | 4 ++-- .../js/bootstrap-datetimepicker.init.js | 14 ++------------ 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/e107_handlers/form_handler.php b/e107_handlers/form_handler.php index 28734d472..23826f581 100644 --- a/e107_handlers/form_handler.php +++ b/e107_handlers/form_handler.php @@ -1499,11 +1499,11 @@ class e_form if(vartrue($options['inline'])) { $text .= "<div class='{$class}' id='inline-{$id}' data-date-format='{$dformat}' data-date-ampm='{$ampm}' data-date-firstday='{$firstDay}'></div>"; - $text .= "<input type='hidden' name='{$name}' id='{$id}' value='{$value}' data-date-format='{$dformat}' data-date-ampm='{$ampm}' data-date-firstday='{$firstDay}' data-date-timezone-offset='".date('Z')."' />"; + $text .= "<input type='hidden' name='{$name}' id='{$id}' value='{$value}' data-date-format='{$dformat}' data-date-ampm='{$ampm}' data-date-firstday='{$firstDay}' />"; } else { - $text .= "<input class='{$class} input-".$xsize." form-control' type='text' size='{$size}' id='e-datepicker-{$id}' value='{$value}' data-date-unix ='{$useUnix}' data-date-format='{$dformat}' data-date-ampm='{$ampm}' data-date-language='".e_LAN."' data-date-firstday='{$firstDay}' {$required} {$disabled} data-date-timezone-offset='".date('Z')."' />"; + $text .= "<input class='{$class} input-".$xsize." form-control' type='text' size='{$size}' id='e-datepicker-{$id}' value='{$value}' data-date-unix ='{$useUnix}' data-date-format='{$dformat}' data-date-ampm='{$ampm}' data-date-language='".e_LAN."' data-date-firstday='{$firstDay}' {$required} {$disabled} />"; $ftype = (!empty($options['debug'])) ? 'text' : 'hidden'; $text .= "<input type='{$ftype}' name='{$name}' id='{$id}' value='{$hiddenValue}' />"; } diff --git a/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.init.js b/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.init.js index 4afe4e763..d00fb9f23 100755 --- a/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.init.js +++ b/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.init.js @@ -49,11 +49,7 @@ var e107 = e107 || {'settings': {}, 'behaviors': {}}; newValue = $("#" + ev.target.id).val(); } - // make sure a UTC datestamp is saved - offset = parseInt($item.attr("data-date-timezone-offset")); - newOffsetValue = newValue + offset; - - $(newTarget).val(newOffsetValue); + $(newTarget).val( newValue); }); }); @@ -79,13 +75,7 @@ var e107 = e107 || {'settings': {}, 'behaviors': {}}; newValue = $("#" + ev.target.id).val(); } - // make sure a UTC datestamp is saved - offset = parseInt($item.attr("data-date-timezone-offset")); - newOffsetValue = newValue + offset; - - $(newTarget).val(newOffsetValue); - - console.log( newOffsetValue); // remove later. + $(newTarget).val(newValue); }) }); From bab26e7762b74acf267c7cb634665e679e7feca3 Mon Sep 17 00:00:00 2001 From: Cameron <e107inc@gmail.com> Date: Fri, 25 May 2018 19:00:55 -0700 Subject: [PATCH 44/59] datetimepicker() assumes the timezone to be that of the browser, which can pose problems in some situations. Now we can set a different timezone for the datepicker input and the UTC value will be automatically adjusted. eg. writeParms = array(type='datetime', 'timezone'=>'America/Los_Angeles') --- e107_handlers/form_handler.php | 16 ++++++++++++++-- .../js/bootstrap-datetimepicker.init.js | 14 ++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/e107_handlers/form_handler.php b/e107_handlers/form_handler.php index 23826f581..2232669ed 100644 --- a/e107_handlers/form_handler.php +++ b/e107_handlers/form_handler.php @@ -1437,7 +1437,10 @@ class e_form * on Submit returns unix timestamp or string value. * @param string $name the name of the field * @param integer $datestamp UNIX timestamp - default value of the field - * @param array or str + * @param array or str + * @param string $options['type'] date or datetime + * @param string $options['format'] strftime format eg. '%Y-%m-%d' + * @param string $options['timezone'] eg. 'America/Los_Angeles' - intended timezone of the date/time entered. (offsets UTC value) * @example $frm->datepicker('my_field',time(),'type=date'); * @example $frm->datepicker('my_field',time(),'type=datetime&inline=1'); * @example $frm->datepicker('my_field',time(),'type=date&format=yyyy-mm-dd'); @@ -1493,6 +1496,15 @@ class e_form $firstDay = vartrue($options['firstDay']) ? $options['firstDay'] : 0; $xsize = (vartrue($options['size']) && !is_numeric($options['size'])) ? $options['size'] : 'xlarge'; $disabled = vartrue($options['disabled']) ? "disabled" : ""; + $timezone = ''; + + if(!empty($options['timezone'])) // since datetimepicker does not support timezones and assumes the browser timezone is the intended timezone. + { + date_default_timezone_set($options['timezone']); + $targetOffset = date('Z'); + date_default_timezone_set(USERTIMEZONE); + $timezone = "data-date-timezone-offset='".$targetOffset."'"; + } $text = ""; @@ -1503,7 +1515,7 @@ class e_form } else { - $text .= "<input class='{$class} input-".$xsize." form-control' type='text' size='{$size}' id='e-datepicker-{$id}' value='{$value}' data-date-unix ='{$useUnix}' data-date-format='{$dformat}' data-date-ampm='{$ampm}' data-date-language='".e_LAN."' data-date-firstday='{$firstDay}' {$required} {$disabled} />"; + $text .= "<input class='{$class} input-".$xsize." form-control' type='text' size='{$size}' id='e-datepicker-{$id}' value='{$value}' data-date-unix ='{$useUnix}' data-date-format='{$dformat}' data-date-ampm='{$ampm}' data-date-language='".e_LAN."' data-date-firstday='{$firstDay}' {$required} {$disabled} {$timezone} />"; $ftype = (!empty($options['debug'])) ? 'text' : 'hidden'; $text .= "<input type='{$ftype}' name='{$name}' id='{$id}' value='{$hiddenValue}' />"; } diff --git a/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.init.js b/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.init.js index d00fb9f23..6c872e12f 100755 --- a/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.init.js +++ b/e107_web/js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.init.js @@ -75,6 +75,20 @@ var e107 = e107 || {'settings': {}, 'behaviors': {}}; newValue = $("#" + ev.target.id).val(); } + offset = parseInt($item.attr("data-date-timezone-offset")); + + if(offset) // adjust UTC value to target timezone. ie. timezone other than the one of the browser. + { + browserOffset = ev.date.getTimezoneOffset() * 60; + relativeOffset = browserOffset + offset; + + console.log("Browser Offset: " + browserOffset); + console.log('Offset: ' + offset); + console.log('Relative Offset: ' + relativeOffset); + + newValue = newValue - relativeOffset; + } + $(newTarget).val(newValue); }) From a97d58ae44121f550d0d6cc6bc55df43a78cdcc5 Mon Sep 17 00:00:00 2001 From: Achim <SimSync@users.noreply.github.com> Date: Wed, 30 May 2018 12:32:32 +0200 Subject: [PATCH 45/59] Closes #2265 User Extended Field for Date does not allow entry This fix closes issue e107inc/e107#2265 which pops up only when the JS files are cached (compressed). There was a ";" missing at the end of the file after (jQuery). --- e107_web/js/password/jquery.pwdMeter.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/e107_web/js/password/jquery.pwdMeter.js b/e107_web/js/password/jquery.pwdMeter.js index 6876184a2..7026262ca 100644 --- a/e107_web/js/password/jquery.pwdMeter.js +++ b/e107_web/js/password/jquery.pwdMeter.js @@ -201,5 +201,9 @@ jQuery.fn.pwdMeter = function(options){ }); } - -})(jQuery) +/** + * ALLWAYS add a semicolon at the end, otherwise + * it may cause issues when js is cached! + * see issue e107inc/e107#2265 + */ +})(jQuery); From 7470aa4e0bfec7e4e9a816a815e8cdd11f1e05f2 Mon Sep 17 00:00:00 2001 From: Achim Ennenbach <achim@simsync.de> Date: Thu, 31 May 2018 20:48:03 +0200 Subject: [PATCH 46/59] Fixes #3154 Added missing 6th argument which throwed an exception --- comment.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/comment.php b/comment.php index d38a5b0f9..d17577a5a 100644 --- a/comment.php +++ b/comment.php @@ -140,7 +140,12 @@ if(e_AJAX_REQUEST) // TODO improve security $width = ($pid) ? 1 : 0; $ret['html'] = "\n<!-- Appended -->\n<li>"; - $ret['html'] .= e107::getComment()->render_comment($row,'comments','comment',intval($_POST['itemid']),$width); + + /** + * Fix for issue e107inc/e107#3154 (Comments not refreshing on submission) + * Missing 6th argument ($subject) caused an exception + */ + $ret['html'] .= e107::getComment()->render_comment($row,'comments','comment',intval($_POST['itemid']),$width, $tp->toDB($clean_subject)); $ret['html'] .= "</li>\n<!-- end Appended -->\n"; $ret['error'] = false; From 4978a0603d78efd452e988d18340ef5e0ec9d97c Mon Sep 17 00:00:00 2001 From: Achim Ennenbach <achim@simsync.de> Date: Thu, 31 May 2018 20:51:44 +0200 Subject: [PATCH 47/59] Fixes #3136 Tinymce introduced with version 4.7.10 an issue that prevents the e107 media manager to work correctly. Reverted back to Tinymce version 4.7.9 --- e107_plugins/tinymce4/e_footer.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/e107_plugins/tinymce4/e_footer.php b/e107_plugins/tinymce4/e_footer.php index 3ac55d28a..24c9c6dd7 100644 --- a/e107_plugins/tinymce4/e_footer.php +++ b/e107_plugins/tinymce4/e_footer.php @@ -23,7 +23,15 @@ if((e107::wysiwyg() === true && check_class($pref['post_html'])) || strpos(e_SEL // e107::js('footer', 'https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.5.3/tinymce.min.js'); - e107::js('footer', 'https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.7.12/tinymce.min.js'); + // e107::js('footer', 'https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.7.11/tinymce.min.js'); + /** + * tinymce 4.7.10 and newer do not work. + * Looks like an issue introduced with 4.7.10 + * Reverting back to 4.7.9 makes everything work in e107 + * Issue #3136 + */ + e107::js('footer', 'https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.7.9/tinymce.min.js'); + // e107::js('footer', "//cdn.tinymce.com/4/tinymce.min.js"); From 3a228c018145772177736cc8a87755f7f6f12944 Mon Sep 17 00:00:00 2001 From: Achim Ennenbach <achim@simsync.de> Date: Fri, 1 Jun 2018 18:16:48 +0200 Subject: [PATCH 48/59] Possible fix for issue e107inc/e107#3152 Makes the category field editable (dropdown) so a download category can be assigned. --- e107_admin/upload.php | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/e107_admin/upload.php b/e107_admin/upload.php index 0b854bfd1..dcef44605 100644 --- a/e107_admin/upload.php +++ b/e107_admin/upload.php @@ -204,7 +204,18 @@ class upload_ui extends e_admin_ui $this->getModel()->addValidationError(UPLLAN_62); $new_data['upload_active'] = 0; return $new_data; - } + } + // Make sure the upload_category contains only integers + if (substr($new_data['upload_category'], 0, 10) == 'download__') + { + $new_data['upload_category'] = intval(substr($new_data['upload_category'], 10)); + } + // Make sure the owner is not empty + if (trim($new_data['upload_owner']) == '') + { + $new_data['upload_owner'] = 'download'; + } + return $new_data; } /** @@ -262,7 +273,8 @@ class upload_ui extends e_admin_ui return 0; } - $owner = varset($upload['upload_owner'], 'download'); + // Make sure the owner is not empty + $owner = vartrue($upload['upload_owner'], 'download'); $uploadObj = e107::getAddon($owner,'e_upload'); @@ -371,7 +383,9 @@ class upload_form_ui extends e_admin_form_ui case 'write': $owner = $this->getController()->getModel()->get('upload_owner'); - return $value."-- ".$owner; // $this->radio_switch('upload_active', $value, LAN_ACCEPT, LAN_PENDING, $options); + //return $value."-- ".$owner; // $this->radio_switch('upload_active', $value, LAN_ACCEPT, LAN_PENDING, $options); + // make category editable instead of just displaying data + return e107::getForm()->select('upload_category', $opts, $value); break; case 'batch': From 8d41cd695662a18963e86cf59b9419e50d58f67a Mon Sep 17 00:00:00 2001 From: Achim Ennenbach <achim@simsync.de> Date: Fri, 1 Jun 2018 19:00:17 +0200 Subject: [PATCH 49/59] Fixes #3152 Made category editable (dropdown) Made screenshot not required on public upload --- e107_admin/upload.php | 15 ++++++--------- upload.php | 2 +- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/e107_admin/upload.php b/e107_admin/upload.php index dcef44605..da787ac2e 100644 --- a/e107_admin/upload.php +++ b/e107_admin/upload.php @@ -205,16 +205,13 @@ class upload_ui extends e_admin_ui $new_data['upload_active'] = 0; return $new_data; } + // Make sure the upload_category contains only integers - if (substr($new_data['upload_category'], 0, 10) == 'download__') - { - $new_data['upload_category'] = intval(substr($new_data['upload_category'], 10)); - } - // Make sure the owner is not empty - if (trim($new_data['upload_owner']) == '') - { - $new_data['upload_owner'] = 'download'; - } + // Make sure the owner correspondents to the category id + list($catOwner, $catID) = explode("__", $new_data['upload_category'], 2); + $new_data['upload_category'] = intval($catID); + $new_data['upload_owner'] = $catOwner; + return $new_data; } diff --git a/upload.php b/upload.php index 41e637902..e32f784de 100644 --- a/upload.php +++ b/upload.php @@ -107,7 +107,7 @@ class userUpload $catID = null; $catOwner = null; $file = null; - $image = null; + $image = ''; $filesize = 0; From a1469aad5e6ede17dbd4bd04e841471a29a4b49d Mon Sep 17 00:00:00 2001 From: Cameron <e107inc@gmail.com> Date: Tue, 5 Jun 2018 12:55:20 -0700 Subject: [PATCH 50/59] Issue #3175 GDPR work. --- .../batch/usersettings_shortcodes.php | 17 +++++++++++++++++ e107_core/templates/usersettings_template.php | 2 ++ e107_handlers/form_handler.php | 14 ++++++++++++-- e107_languages/English/lan_usersettings.php | 4 +++- e107_web/js/core/all.jquery.js | 13 +++++++++++++ usersettings.php | 7 ++++++- 6 files changed, 53 insertions(+), 4 deletions(-) diff --git a/e107_core/shortcodes/batch/usersettings_shortcodes.php b/e107_core/shortcodes/batch/usersettings_shortcodes.php index 29f36637a..b9994fee0 100755 --- a/e107_core/shortcodes/batch/usersettings_shortcodes.php +++ b/e107_core/shortcodes/batch/usersettings_shortcodes.php @@ -554,5 +554,22 @@ class usersettings_shortcodes extends e_shortcode } + function sc_deleteaccountbutton($parm=array()) + { + + if((int) $_GET['id'] !== USERID) + { + return null; + } + + $confirm = defset("LAN_USET_51", "Are you sure? This procedure cannot be reversed! Once completed all personal data that you have entered on this site will be permanently lost and you will no longer be able to login."); + $label = defset('LAN_USET_50', "Delete All Account Information"); + + $parm['confirm'] = $confirm; + + return e107::getForm()->button('delete_account',1, 'delete', $label, $parm); + + } + } ?> \ No newline at end of file diff --git a/e107_core/templates/usersettings_template.php b/e107_core/templates/usersettings_template.php index c5222a588..330f0ca4d 100755 --- a/e107_core/templates/usersettings_template.php +++ b/e107_core/templates/usersettings_template.php @@ -173,6 +173,7 @@ $USERSETTINGS_EDIT = " </table> <div> {UPDATESETTINGSBUTTON} + {DELETEACCOUNTBUTTON} </div> </div> "; @@ -303,6 +304,7 @@ $USERSETTINGS_TEMPLATE['edit'] = " <div class='form-group'> <div class='col-sm-offset-3 col-sm-9'> {UPDATESETTINGSBUTTON} + {DELETEACCOUNTBUTTON} </div> </div> diff --git a/e107_handlers/form_handler.php b/e107_handlers/form_handler.php index 2232669ed..906cbf7ca 100644 --- a/e107_handlers/form_handler.php +++ b/e107_handlers/form_handler.php @@ -3148,7 +3148,7 @@ class e_form return $text; } - + return $this->admin_button($name, $value, $action, $label, $options); @@ -3253,6 +3253,13 @@ class e_form $include = (deftrue("FONTAWESOME")) ? "data-loading-icon='fa-spinner' data-disable='true'" : ""; } + $confirmation = LAN_JSCONFIRM; + + if(!empty($options['confirm'])) + { + $confirmation = $options['confirm']; + } + $options = $this->format_options('admin_button', $name, $options); $options['class'] = vartrue($options['class']); @@ -3277,7 +3284,10 @@ class e_form case 'delete': case 'danger': - $options['other'] = 'data-confirm="'.LAN_JSCONFIRM.'"'; + + + + $options['other'] = 'data-confirm="'.$confirmation.'"'; break; case 'batch': diff --git a/e107_languages/English/lan_usersettings.php b/e107_languages/English/lan_usersettings.php index f5fb4bf54..2892622b0 100644 --- a/e107_languages/English/lan_usersettings.php +++ b/e107_languages/English/lan_usersettings.php @@ -145,4 +145,6 @@ define("LAN_CUSTOMTITLE", "Custom title"); define("LAN_USET_5", "Subscribed to"); define("LAN_USET_6", "Subscribe to our mailing-list(s) and/or sections of this site."); // define("LAN_USET_8", "Signature / Time zone"); -?> \ No newline at end of file + +define("LAN_USET_50", "Delete Account"); +define("LAN_USET_51", "Are you sure? This procedure cannot be reversed! Once completed, your account and any personal data that you have entered on this site will be permanently lost and you will no longer be able to login."); \ No newline at end of file diff --git a/e107_web/js/core/all.jquery.js b/e107_web/js/core/all.jquery.js index cf4c175ea..efa5ef078 100644 --- a/e107_web/js/core/all.jquery.js +++ b/e107_web/js/core/all.jquery.js @@ -788,6 +788,19 @@ $.ajaxSetup({ $(document).ready(function() { + + // Basic Delete Confirmation + $('input.delete,button.delete,a[data-confirm]').click(function(){ + answer = confirm($(this).attr("data-confirm")); + return answer; // answer is a boolean + }); + + $(".e-confirm").click(function(){ + answer = confirm($(this).attr("title")); + return answer; // answer is a boolean + }); + + //check all $("#check-all").click(function(event){ var val = $(this).val(), selector = '.field-spacer'; diff --git a/usersettings.php b/usersettings.php index 2f3f64b97..7cc9e50f8 100644 --- a/usersettings.php +++ b/usersettings.php @@ -69,7 +69,7 @@ class usersettings_front // Begin Usersettings rewrite. function __construct() { - if(deftrue('BOOTSTRAP')===3) + if(deftrue('BOOTSTRAP')) { $template = e107::getCoreTemplate('usersettings','', true, true); // always merge @@ -172,6 +172,11 @@ class usersettings_front // Begin Usersettings rewrite. $adminEdit = false; // @deprecated // FALSE if editing own data. TRUE if admin edit + if(!empty($_POST['delete_account'])) + { + echo e107::getMessage()->addWarning("This feature is currently under development. Your data has not been modified")->render(); // do not LAN. + } + /* todo subject of removal */ if(is_numeric(e_QUERY)) { // Trying to edit specific user record From eeaa9b22a84be84f7949f513a59ba2a8ca630abe Mon Sep 17 00:00:00 2001 From: Achim Ennenbach <achim@simsync.de> Date: Fri, 8 Jun 2018 22:59:24 +0200 Subject: [PATCH 51/59] New method to check table indexes --- e107_handlers/mysql_class.php | 71 +++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/e107_handlers/mysql_class.php b/e107_handlers/mysql_class.php index 5ac5a74bf..af93de116 100644 --- a/e107_handlers/mysql_class.php +++ b/e107_handlers/mysql_class.php @@ -2356,6 +2356,77 @@ class e_db_mysql } + /** + * Determines if a table index (key) exist. + * + * @param string $table - table name (no prefix) + * @param string $keyname - Name of the key to + * @param array $fields - OPTIONAL list of fieldnames, the index (key) must contain + * @param boolean $retinfo = FALSE - just returns true|false. TRUE - returns all key info + * @return array|boolean - FALSE on error, key information on success + */ + function index($table, $keyname, $fields=null, $retinfo = FALSE) + { + if(!$this->mySQLdefaultdb) + { + global $mySQLdefaultdb; + $this->mySQLdefaultdb = $mySQLdefaultdb; + } + + if(!$this->mySQLaccess) + { + global $db_ConnectionID; + $this->mySQLaccess = $db_ConnectionID; + } + + if (!empty($fields) && !is_array($fields)) + { + $fields = explode(',', str_replace(' ', '', $fields)); + } + elseif(empty($fields)) + { + $fields = array(); + } + + $check_field = count($fields) > 0; + + $info = array(); + $result = $this->gen("SHOW INDEX FROM ".$this->mySQLPrefix.$table); + if ($result && ($this->rowCount() > 0)) + { + $c=0; + while ($row = $this->fetch()) + { + // Check for match of key name - and allow that key might not be used + if($keyname == $row['Key_name']) + { + // a key can contain severeal fields which are returned as 1 row per field + if (!$check_field) + { // Check only for keyname + $info[] = $row; + } + elseif ($check_field && in_array($row['Column_name'], $fields)) + { // Check also for fieldnames + $info[] = $row; + } + $c++; + } + } + + if (count($info) > 0) + { + // Kex does not consist of all keys + if ($check_field && $c != count($fields)) return false; + // Return full information + if ($retinfo) return $info; + // Return only if index was found + return true; + } + } + return FALSE; + } + + /** * A pointer to mysql_real_escape_string() - see http://www.php.net/mysql_real_escape_string * From a7f1271eb450edc8d9ad3a8c194f98a1d4a60c73 Mon Sep 17 00:00:00 2001 From: Achim Ennenbach <achim@simsync.de> Date: Fri, 8 Jun 2018 23:02:36 +0200 Subject: [PATCH 52/59] Implemented upgrade_required() method as defined in forum_setup.php Added some documentation on how to check for tables, fields and indexes and how to remove fields and indexes --- e107_plugins/_blank/_blank_setup.php | 90 ++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/e107_plugins/_blank/_blank_setup.php b/e107_plugins/_blank/_blank_setup.php index d435b0a7e..5b937725d 100644 --- a/e107_plugins/_blank/_blank_setup.php +++ b/e107_plugins/_blank/_blank_setup.php @@ -78,6 +78,96 @@ if(!class_exists("_blank_setup")) // print_a($var); } + + /* + * Call During Upgrade Check. May be used to check for existance of tables etc and if not found return TRUE to call for an upgrade. + * + * @return bool true = upgrade required; false = upgrade not required + */ + function upgrade_required() + { + // Check if a specific table exists and if not, return true to force a db update + // In this example, it checks if the table "blank_table" exists +// if(!e107::getDb()->isTable('blank_table')) +// { +// return true; // true to trigger an upgrade alert, and false to not. +// } + + + // Check if a specific field exists in the specified table + // and if not return false to force a db update to add this field + // from the "_blank_sql.php" file + // In this case: Exists field "blank_id" in table "blank_table" +// if(!e107::getDb()->field('blank_table','blank_id')) +// { +// return true; // true to trigger an upgrade alert, and false to not. +// } + + + // In case you need to delete a field that is not used anymore, + // first check if the field exists, than run a sql command to drop (delete) the field + // !!! ATTENTION !!! + // !!! Deleting a field, deletes also the data stored in that field !!! + // !!! Make sure you know what you are doing !!! + // + // In this example, the field "blank_unused_field" from table "blank_table" + // isn't used anymore and will be deleted (dropped) if it still exists +// if(e107::getDb()->field('blank_table', 'blank_unused_field')) +// { + // this statement directly deletes the field, an additional + // db update isn't needed anymore, if this is the only change on the db/table. +// e107::getDb()->gen("ALTER TABLE `#blank_table` DROP `blank_unused_field` "); +// } + + + // In case you need to delete a index that is not used anymore, + // first check if the index exists, than run a sql command to drop (delete) the field + // Be aware, that deleting an index is not very harmfull, as the data of the + // index will be recreated when the index is added again. +// if(e107::getDb()->index('blank_table','blank_unused_index')) +// { + // this statement directly deletes the index, an additional + // db update isn't needed anymore, if this is the only change on the db/table. +// e107::getDb()->gen("ALTER TABLE `#blank_table` DROP INDEX `blank_unused_index` "); +// } + + // In case you need to check an index and which fields it is build of, + // use the fourth parameter to return the index definition. + // In this case, the index should be deleted if consists only of 1 field ("blank_fieldname"), +// if(e107::getDb()->index('blank_table','blank_unused_index', array('blank_fieldname'))) +// { + // this statement directly deletes the index, an additional + // db update isn't needed anymore, if this is the only change on the db/table. +// e107::getDb()->gen("ALTER TABLE `#blank_table` DROP INDEX `blank_unused_index` "); +// } + + + // In case you need to check an index and which fields it is build of, + // use the third parameter to return the index definition. + // In this case, the index should be deleted if consists only of 1 field ("blank_fieldname"), +// if ($index_def = e107::getDb()->index('blank_table','blank_unused_index', array('blank_fieldname'))) +// { + // Check if the key should be UNIQUE +// $unique = array_count_values(array_column($index_def, 'Non_unique')); +// if($unique[1] > 0) // Keys are not unique +// { + // this statement directly deletes the index, an additional + // db update isn't needed anymore, if this is the only change on the db/table. +// e107::getDb()->gen("ALTER TABLE `#blank_table` DROP INDEX `blank_unused_index` "); +// } +// } + + + $legacyMenuPref = e107::getConfig('menu')->getPref(); + if(isset($legacyMenuPref['newforumposts_caption'])) + { + + } + + return false; + } + + function upgrade_post($var) { // $sql = e107::getDb(); From 2b24346a8aa4bd3768095a50c7ad732a348cb6e6 Mon Sep 17 00:00:00 2001 From: Cameron <e107inc@gmail.com> Date: Fri, 8 Jun 2018 18:55:04 -0700 Subject: [PATCH 53/59] Form handler - select() - support for disabled items. --- e107_handlers/form_handler.php | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/e107_handlers/form_handler.php b/e107_handlers/form_handler.php index 906cbf7ca..fa95efc36 100644 --- a/e107_handlers/form_handler.php +++ b/e107_handlers/form_handler.php @@ -2714,6 +2714,7 @@ class e_form * @param boolean $selected [optional] * @param string|array $options [optional] * @param bool $options['useValues'] when true uses array values as the key. + * @param array $options['disabled'] list of $option_array keys which should be disabled. eg. array('key_1', 'key_2'); * @param bool|string $defaultBlank [optional] set to TRUE if the first entry should be blank, or to a string to use it for the blank description. * @return string HTML text for display */ @@ -2758,7 +2759,7 @@ class e_form $option_array = $new; } - $text .= $this->option_multi($option_array, $selected)."\n".$this->select_close(); + $text .= $this->option_multi($option_array, $selected, $options)."\n".$this->select_close(); return $text; } @@ -2940,11 +2941,13 @@ class e_form function option($option_title, $value, $selected = false, $options = '') { if(is_string($options)) parse_str($options, $options); - + if(false === $value) $value = ''; $options = $this->format_options('option', '', $options); $options['selected'] = $selected; //comes as separate argument just for convenience + + return "<option value='{$value}'".$this->get_attributes($options).">".defset($option_title, $option_title)."</option>"; } @@ -2966,18 +2969,24 @@ class e_form return $this->option('',''); } + $opts = $options; - foreach ($option_array as $value => $label) + foreach ((array) $option_array as $value => $label) { if(is_array($label)) { - $text .= $this->optgroup($value,$label,$selected,$options, 0); - + $text .= $this->optgroup($value, $label, $selected, $options, 0); } else { + $sel = is_array($selected) ? in_array($value, $selected) : ($value == $selected); - $text .= $this->option($label, $value, (is_array($selected) ? in_array($value, $selected) : $selected == $value), $options)."\n"; + if(!empty($options['disabled'])) + { + $opts['disabled'] = in_array($value, $options['disabled']); + } + + $text .= $this->option($label, $value, $sel, $opts)."\n"; } } @@ -2999,6 +3008,8 @@ class e_form $level++; $text = $this->optgroup_open($value, null, array('class'=>'level-'.$level)); + $opts = $options; + foreach($label as $val => $lab) { if(is_array($lab)) @@ -3007,7 +3018,12 @@ class e_form } else { - $text .= $this->option($lab, $val, (is_array($selected) ? in_array($val, $selected) : $selected == $val), $options)."\n"; + if(!empty($options['disabled'])) + { + $opts['disabled'] = in_array($val, $options['disabled']); + } + + $text .= $this->option($lab, $val, (is_array($selected) ? in_array($val, $selected) : $selected == $val), $opts)."\n"; } } From ff3dc03a817f4a976a892e427d2ca6d8cc9af5d7 Mon Sep 17 00:00:00 2001 From: oudoken <oudoken@gmail.com> Date: Tue, 12 Jun 2018 11:07:21 +0200 Subject: [PATCH 54/59] Issue #3151 add an e_end to plugin class --- e107_core/templates/footer_default.php | 16 ++++++++++++++++ e107_handlers/plugin_class.php | 6 ++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/e107_core/templates/footer_default.php b/e107_core/templates/footer_default.php index ad9656fd6..e75de9592 100644 --- a/e107_core/templates/footer_default.php +++ b/e107_core/templates/footer_default.php @@ -374,6 +374,22 @@ $show = deftrue('e_POWEREDBY_DISABLE') ? "none" : "block"; // Let search engines unset($show); echo "\n</body>\n</html>"; +//hook into the end of page buffering +//Load e_end.php files. +if (!empty($pref['e_end_list']) && is_array($pref['e_end_list'])) +{ + foreach($pref['e_end_list'] as $val) + { + $fname = e_PLUGIN.$val."/e_end.php"; // Do not place inside a function - BC $pref required. . + + if(is_readable($fname)) + { + + $ret = ($e107_debug || isset($_E107['debug'])) ? include_once($fname) : @include_once($fname); + } + } + unset($ret); +} // // I Send the buffered page data, along with appropriate headers diff --git a/e107_handlers/plugin_class.php b/e107_handlers/plugin_class.php index 4af32abcc..77b1000df 100644 --- a/e107_handlers/plugin_class.php +++ b/e107_handlers/plugin_class.php @@ -76,6 +76,7 @@ class e_plugin 'e_user', 'e_library', // For third-party libraries are defined by plugins/themes. 'e_gsitemap', + 'e_end', // hook into all page at the end ); @@ -1069,6 +1070,7 @@ class e107plugin 'e_user', 'e_library', // For third-party libraries are defined by plugins/themes. 'e_gsitemap', + 'e_end', // hook into all page at the end ); @@ -1114,8 +1116,8 @@ class e107plugin 'e_upload' => "Use data from your plugin in the user upload form.", 'e_user' => "Have your plugin include data on the user-profile page.", 'e_library' => "Include a third-party library", - 'e_parse' => "Hook into e107's text/html parser" - + 'e_parse' => "Hook into e107's text/html parser", + 'e_end' => "Hook into all page at the end" ); From fbdbd4b1cacb1435d6fe8992aaea3e5230d60bea Mon Sep 17 00:00:00 2001 From: oudoken <oudoken@gmail.com> Date: Tue, 12 Jun 2018 18:09:00 +0200 Subject: [PATCH 55/59] Issue #3151 add an e_end to plugin class V2 renamed based on Cameron suggestion --- e107_core/templates/footer_default.php | 10 +++++----- e107_handlers/plugin_class.php | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/e107_core/templates/footer_default.php b/e107_core/templates/footer_default.php index e75de9592..bf734657a 100644 --- a/e107_core/templates/footer_default.php +++ b/e107_core/templates/footer_default.php @@ -374,13 +374,13 @@ $show = deftrue('e_POWEREDBY_DISABLE') ? "none" : "block"; // Let search engines unset($show); echo "\n</body>\n</html>"; -//hook into the end of page buffering -//Load e_end.php files. -if (!empty($pref['e_end_list']) && is_array($pref['e_end_list'])) +//hook into the end of page (usefull for example for capturing output buffering) +//Load e_output.php files. +if (!empty($pref['e_output_list']) && is_array($pref['e_output_list'])) { - foreach($pref['e_end_list'] as $val) + foreach($pref['e_output_list'] as $val) { - $fname = e_PLUGIN.$val."/e_end.php"; // Do not place inside a function - BC $pref required. . + $fname = e_PLUGIN.$val."/e_output.php"; // Do not place inside a function - BC $pref required. . if(is_readable($fname)) { diff --git a/e107_handlers/plugin_class.php b/e107_handlers/plugin_class.php index 77b1000df..7c5200d1b 100644 --- a/e107_handlers/plugin_class.php +++ b/e107_handlers/plugin_class.php @@ -76,7 +76,7 @@ class e_plugin 'e_user', 'e_library', // For third-party libraries are defined by plugins/themes. 'e_gsitemap', - 'e_end', // hook into all page at the end + 'e_output', //hook into all pages at the end (after closing </html>) ); @@ -1070,7 +1070,7 @@ class e107plugin 'e_user', 'e_library', // For third-party libraries are defined by plugins/themes. 'e_gsitemap', - 'e_end', // hook into all page at the end + 'e_output', //hook into all pages at the end (after closing </html>) ); @@ -1117,7 +1117,7 @@ class e107plugin 'e_user' => "Have your plugin include data on the user-profile page.", 'e_library' => "Include a third-party library", 'e_parse' => "Hook into e107's text/html parser", - 'e_end' => "Hook into all page at the end" + 'e_output' => "Hook into all pages at the end (after closing </html>)" ); From a56ffe0e58b61c12ce9006690fc85e52f359fcf9 Mon Sep 17 00:00:00 2001 From: Tijn Kuyper <Moc@users.noreply.github.com> Date: Wed, 13 Jun 2018 14:48:36 +0200 Subject: [PATCH 56/59] Allow for copying forum categories in admin area --- e107_plugins/forum/forum_admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e107_plugins/forum/forum_admin.php b/e107_plugins/forum/forum_admin.php index c39c1af50..102ed1e5a 100644 --- a/e107_plugins/forum/forum_admin.php +++ b/e107_plugins/forum/forum_admin.php @@ -116,7 +116,7 @@ if(!deftrue('OLD_FORUMADMIN')) protected $pid = 'forum_id'; protected $perPage = 30; protected $batchDelete = true; - // protected $batchCopy = true; + protected $batchCopy = true; protected $sortField = 'forum_order'; protected $sortParent = 'forum_parent'; protected $orderStep = 50; From 52e02087aec189c62228fe3541af09653b293afa Mon Sep 17 00:00:00 2001 From: Cameron <e107inc@gmail.com> Date: Thu, 14 Jun 2018 17:03:03 -0700 Subject: [PATCH 57/59] Issue #3096 - user theme preference check. --- e107_handlers/e107_class.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/e107_handlers/e107_class.php b/e107_handlers/e107_class.php index 049200bae..8e98213d1 100755 --- a/e107_handlers/e107_class.php +++ b/e107_handlers/e107_class.php @@ -2609,7 +2609,7 @@ class e107 */ public static function getThemeInfo($for = true, $path = '') { - global $user_pref; // FIXME - user model, kill user_pref global + // global $user_pref; // FIXME - user model, kill user_pref global if(true === $for) { @@ -2629,7 +2629,8 @@ class e107 } else { - $for = isset($user_pref['sitetheme']) ? $user_pref['sitetheme'] : self::getPref('sitetheme'); + $user_pref = self::getUser()->getPref(); + $for = !empty($user_pref['sitetheme']) ? $user_pref['sitetheme'] : self::getPref('sitetheme'); } break; From 4f568aec52162d0a24d46c56f296180f9ba0a32b Mon Sep 17 00:00:00 2001 From: Achim Ennenbach <achim@simsync.de> Date: Fri, 15 Jun 2018 18:58:15 +0200 Subject: [PATCH 58/59] Added a help block at the beginning of the file, which informs about how it works and what is supported. --- e107_plugins/_blank/blank_sql.php | 45 +++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/e107_plugins/_blank/blank_sql.php b/e107_plugins/_blank/blank_sql.php index 3a0c771c5..3ab5902ee 100644 --- a/e107_plugins/_blank/blank_sql.php +++ b/e107_plugins/_blank/blank_sql.php @@ -1,3 +1,48 @@ +/** + * e107 website system + * + * Copyright (C) 2008-2013 e107 Inc (e107.org) + * Released under the terms and conditions of the + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) + * + * INFORMATION + * + * BEFORE DOING ANY DATABASE CHANGES OR UPDATES, CREATE A FRESH BACKUP!!! + * + * Add the SQL statements for your table here. + * Make sure that you do not add the e107 table prefix (by default e107) to the table name!! + * This file will be analyzed on plugin install and missing tables will be installed automatically. + * To check if the table structure is still valid, run the "Tools -> Database -> Check for Updates" command. + * Any differences between the defined structure here and the table structure on the server will than be detected. + * In another step, you are able to update the table structure to the latest version from this file! + * + * + * For the moment, the following operations are supported: + * ------------------------------------------------------- + * - Create table + * - Change field type, field size, field null or not, field default value + * - Add index + * + * + * What is currently NOT supported: + * -------------------------------- + * - Rename table (by renaming the tablename, e.g. "blank" > "blank2"). The renamed table will be considered as new! + * - Drop a table (e.g. if you remove the "blank" table definition from this file, the table will NOT be deleted from the database!) + * - Rename or drop a field (a renamed field will be considered new, a missing field definition will NOT be recognized at all!) + * - Change an index/key (e.g. the change is recognized, but leads to an error message and the change is not applied) + * - Rename or drop an index/key (Rename is recognized as a new index and the missing index is not recognized at all!) + * - A field definition containing "NULL DEFAULT NULL". The "Check for updates" method will always detect a change, + * but fails silently when trying to update. In that case remove the first "NULL" and run the the "Check for updates" again. + * + * + * How to rename or drop tables, fields and indexes or modify indexes: + * ------------------------------------------------------------------- + * There are methods that can be used to detect tables, fields and indexes. Some examples of how to use them + * can be found in the "_blank_setup.php". There are also examples on how to drop a field or index or to check for specific properties. + * Other examples can be found also in the "forum_setup.php" + */ + + CREATE TABLE blank ( `blank_id` int(10) NOT NULL AUTO_INCREMENT, `blank_icon` varchar(255) NOT NULL, From e1920c740a57b0cd6a36b993e64f21b6073bb2e8 Mon Sep 17 00:00:00 2001 From: Achim Ennenbach <achim@simsync.de> Date: Fri, 15 Jun 2018 19:05:15 +0200 Subject: [PATCH 59/59] toMySQL() added keyname to index if available getIndex() now supports also the INDEX keyword --- e107_handlers/db_verify_class.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/e107_handlers/db_verify_class.php b/e107_handlers/db_verify_class.php index 6418be6bc..338235091 100755 --- a/e107_handlers/db_verify_class.php +++ b/e107_handlers/db_verify_class.php @@ -641,7 +641,10 @@ class db_verify // print_a($data); if($data['type']) { - return $data['type']." (".$data['field'].");"; + //return $data['type']." (".$data['field'].");"; + // Check if index keyname exists and add backticks + $keyname = (!empty($data['keyname']) ? " `".$data['keyname']."`" : ""); + return $data['type'] . $keyname . " (" . $data['field'] . ");"; } else { @@ -919,9 +922,15 @@ class db_verify function getIndex($data, $print = false) { // $regex = "/(?:(PRIMARY|UNIQUE|FULLTEXT))?[\s]*?KEY (?: ?`?([\w]*)`?)[\s]* ?(?:\([\s]?`?([\w,]*[\s]?)`?\))?,?/i"; - $regex = "/(?:(PRIMARY|UNIQUE|FULLTEXT|FOREIGN))?[\s]*?KEY (?: ?`?([\w]*)`?)[\s]* ?(?:\([\s]?([\w\s,`]*[\s]?)`?\))?,?/i"; + // $regex = "/(?:(PRIMARY|UNIQUE|FULLTEXT|FOREIGN))?[\s]*?KEY (?: ?`?([\w]*)`?)[\s]* ?(?:\([\s]?([\w\s,`]*[\s]?)`?\))?,?/i"; + $regex = "/(?:(PRIMARY|UNIQUE|FULLTEXT|FOREIGN))?[\s]*?(INDEX|KEY) (?: ?`?([\w]*)`?)[\s]* ?(?:\([\s]?([\w\s,`]*[\s]?)`?\))?,?/i"; preg_match_all($regex,$data,$m); - + + if (count($m) > 0) + { + unset($m[2]); + $m = array_combine(range(0, count($m)-1), array_values($m)); + } $ret = array(); if($print) @@ -933,6 +942,7 @@ class db_verify $fieldReplace = array("`"," "); + foreach($m[3] as $k=>$val) { if(!$val) continue;