\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "Original"
+msgstr "Translated"
+
+msgid "Original with string: %1"
+msgstr "Translated with string: %1"
+
+#msgid ""
+#msgstr ""
diff --git a/test/includes/locale/ja_JP/LC_MESSAGES/frontend.mo b/test/includes/locale/ja_JP/LC_MESSAGES/frontend.mo
new file mode 100644
index 0000000..1e0a4ff
Binary files /dev/null and b/test/includes/locale/ja_JP/LC_MESSAGES/frontend.mo differ
diff --git a/test/includes/templates/frontend/test.full.tpl b/test/includes/templates/frontend/test.full.tpl
new file mode 100644
index 0000000..a031e5b
--- /dev/null
+++ b/test/includes/templates/frontend/test.full.tpl
@@ -0,0 +1,98 @@
+
+
+
+ {$HTML_TITLE}
+
+ {popup_init src="./js/overlib/overlib.js"}
+
+
+BASE: {$BASE}
+
+
+ SMARTY_TEST: {$SMARTY_TEST}
+
+
+ TEST INSTALL {$TEST_INSTALL}
+
+
+ MERGE DATA: {$adm_set}
+
+This is a test for Smarty 5
+
+ POPUP HERE (hover mouse)
+
+
+ POPUP PLUGIN HERE (hover mouse)
+
+
+ Outside translation test
+ TRANSLATION CLASS (OUT): {$TRANSLATE_TEST}
+ TRANSLATION CLASS (OUT FUNCTION): {$TRANSLATE_TEST_FUNCTION}
+ TRANSLATION CLASS (SMARTY): {$TRANSLATE_TEST_SMARTY}
+
+
+ Translate Test with replace:
+ ORIGINAL: Original with string: %1 ({$replace})
+ TRANSLATED: {t 1=$replace}Original with string: %1{/t}
+ TRANSLATED (escape): {t escape=on 1=$replace}Original with string: %1{/t}
+ {capture assign="extra_title"}{t}INPUT TEST{/t}{/capture}
+ Capture test: {$extra_title}
+ {section name=plural_test start=0 loop=3}
+ Plural test {$smarty.section.plural_test.index}: {t count=$smarty.section.plural_test.index plural="multi"}single{/t}
+ {/section}
+
+
+ Plugin Test:
+ ORIGINAL: Original with string: %1 ({$replace})
+ TRANSLATED: {tp 1=$replace}Original with string: %1{/tp}
+
+
+ Variable variables:
+ Test: {$test}
+ Foo: {$foo}
+ {assign var="bar" value="test"}
+ vFoo ($test = $foo = bar): {$test|getvar}
+ vFoo ($bar = $test = foo): {$bar|getvar}
+
+
+
+
+ Some content here or asdfasdfasf
+
+
+ TRANSLATION SMARTY: {t}I should be translated{/t}
+
+
+
+
+
LOOP TEST
+{section name=page_list start=1 loop=$loop_start+1}
+
LOOP OUTPUT: {$smarty.section.page_list.index}
+{/section}
+
+
+
+
+
+
+
+
+ {html_radios name="radio_test" options=$radio_test selected=$radio_test_selected}
+
+
+ {html_checkboxes name="checkbox_test" options=$checkbox_test selected=$checkbox_test_selected}
+
+
+ {html_checkboxes name="checkbox_test_pos" options=$checkbox_test selected=$checkbox_test_pos_selected pos=$checkbox_test_pos}
+
+
+{$lang_ex}
+
+
+
+
+
diff --git a/test/includes/templates/frontend/test.simple.tpl b/test/includes/templates/frontend/test.simple.tpl
new file mode 100644
index 0000000..a312ca0
--- /dev/null
+++ b/test/includes/templates/frontend/test.simple.tpl
@@ -0,0 +1,90 @@
+
+
+
+ {$HTML_TITLE}
+
+
+
+BASE: {$BASE}
+
+
+ SMARTY_TEST: {$SMARTY_TEST}
+
+
+ TEST INSTALL {$TEST_INSTALL}
+
+
+ MERGE DATA: {$adm_set}
+
+
+ Outside translation test
+ TRANSLATION CLASS (OUT): {$TRANSLATE_TEST}
+ TRANSLATION CLASS (OUT FUNCTION): {$TRANSLATE_TEST_FUNCTION}
+ TRANSLATION CLASS (SMARTY): {$TRANSLATE_TEST_SMARTY}
+
+
+ Translate Test with replace:
+ ORIGINAL: Original with string: %1 ({$replace})
+ TRANSLATED: {t 1=$replace}Original with string: %1{/t}
+ TRANSLATED (escape): {t escape=on 1=$replace}Original with string: %1{/t}
+ {capture assign="extra_title"}{t}INPUT TEST{/t}{/capture}
+ Capture test: {$extra_title}
+ {section name=plural_test start=0 loop=3}
+ Plural test {$smarty.section.plural_test.index}: {t count=$smarty.section.plural_test.index plural="multi"}single{/t}
+ {/section}
+
+
+ Plugin Test:
+ ORIGINAL: Original with string: %1 ({$replace})
+ TRANSLATED: {tp 1=$replace}Original with string: %1{/tp}
+
+
+ Variable variables:
+ Test: {$test}
+ Foo: {$foo}
+ {assign var="bar" value="test"}
+ vFoo ($test = $foo = bar): {$test|getvar}
+ vFoo ($bar = $test = foo): {$bar|getvar}
+
+
+
+
+ Some content here or asdfasdfasf
+
+
+ TRANSLATION SMARTY: {t}I should be translated{/t}
+
+
+
+
+
LOOP TEST
+{section name=page_list start=1 loop=$loop_start+1}
+
LOOP OUTPUT: {$smarty.section.page_list.index}
+{/section}
+
+
+
+
+
+
+
+
+ {html_radios name="radio_test" options=$radio_test selected=$radio_test_selected}
+
+
+ {html_checkboxes name="checkbox_test" options=$checkbox_test selected=$checkbox_test_selected}
+
+
+ {html_checkboxes name="checkbox_test_pos" options=$checkbox_test selected=$checkbox_test_pos_selected pos=$checkbox_test_pos}
+
+
+{$lang_ex}
+
+
+
+
+
diff --git a/test/index.php b/test/index.php
new file mode 100644
index 0000000..20dbd9c
--- /dev/null
+++ b/test/index.php
@@ -0,0 +1,144 @@
+setTemplateDir('includes/templates/frontend');
+// $smarty_ml->setConfigDir('configs');
+// $smarty_ml->setCompileDir('templates_c');
+// $smarty_ml->setCacheDir('cache');
+// $smarty_ml->setSmartyPaths();
+// $smarty_ml->setSmartyVarsFrontend();
+// $smarty_ml->renderSmarty();
+
+$locale = $l10n->getLocaleAsArray();
+\CoreLibs\Language\L10n::loadFunctions();
+_setlocale(LC_MESSAGES, $locale['locale']);
+_textdomain($locale['domain']);
+_bindtextdomain($locale['domain'], $locale['path']);
+_bind_textdomain_codeset($locale['domain'], $locale['encoding']);
+
+$template_name = "test.full.tpl";
+// $template_name = "test.simple.tpl";
+
+$CACHE_ID = 'SmartyV5Test';
+$COMPILE_ID = 'SmartyV5Test';
+
+// $smarty = \Smarty::__construct();
+$smarty = new \Smarty\Smarty();
+$smarty->setTemplateDir('includes/templates/frontend');
+$smarty->setConfigDir('configs');
+$smarty->setCompileDir('templates_c');
+$smarty->setCacheDir('cache');
+
+$smarty->setEscapeHtml(true);
+$smarty->registerPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'getvar', [&$smarty, 'getTemplateVars']);
+
+require 'plugins/block.t.php';
+$smarty->registerPlugin(\Smarty\Smarty::PLUGIN_BLOCK, 'tp', 'smarty_block_t');
+require 'plugins/function.popup_init.php';
+require 'plugins/function.popup.php';
+$smarty->registerPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, 'popinit', 'smarty_function_popup_init');
+$smarty->registerPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, 'pop', 'smarty_function_popup');
+
+// $smarty->testInstall();
+
+$CONTENT_DATA = [
+ 'BASE' => BASE,
+ // 'TEST_INSTALL' => $smarty->testInstall(),
+ 'HTML_TITLE' => 'Smarty v5 tst',
+ // smarty test
+ 'SMARTY_TEST' => 'Test Data',
+ 'TRANSLATE_TEST' => $l10n->__('Are we translated?'),
+ 'TRANSLATE_TEST_FUNCTION' => _gettext('Are we translated?'),
+ 'TRANSLATE_TEST_SMARTY' => $l10n->__('Are we translated?'),
+ 'replace' => 'Replaced',
+ // variable variables
+ 'test' => 'foo',
+ 'foo' => 'bar',
+ // loop
+ 'loop_start' => 5,
+ // drop down test with optgroups
+ 'drop_down_test' => [
+ 'foo' => 'Foo',
+ 'bar' => 'Bar',
+ 'foobar' => 'Foo Bar',
+ ],
+ 'drop_down_test_selected' => 'bar',
+ 'drop_down_test_nested' => [
+ '' => '選択してください',
+ '4/25(木)' => [
+ '4/25(木) 11:00-11:50' => '4/25(木) 11:00-11:50',
+ '4/25(木) 12:20-13:00' => '4/25(木) 12:20-13:00'
+ ],
+ '4/26(金)' => [
+ '4/26(金) 11:00-11:50' => '4/26(金) 11:00-11:50',
+ '4/26(金) 12:20-13:00' => '4/26(金) 12:20-13:00'
+ ],
+ '4/27(土)' => [
+ '4/27(土) 11:00-11:50' => '4/27(土) 11:00-11:50',
+ '4/27(土) 12:20-13:00' => '4/27(土) 12:20-13:00'
+ ],
+ ],
+ 'drop_down_test_nested_selected' => '',
+ 'radio_test' => [
+ '0' => 'On',
+ '1' => 'Off',
+ '-1' => 'Undefined'
+ ],
+ 'radio_test_selected' => -1,
+ 'checkbox_test' => [
+ '0' => 'On',
+ '1' => 'Off',
+ '-1' => 'Undefined'
+ ],
+ 'checkbox_test_pos' => [
+ '0' => 'A',
+ '1' => 'B'
+ ],
+ 'checkbox_test_selected' => ['1', '-1'],
+ 'checkbox_test_pos_selected' => ['0', '-1'],
+];
+
+foreach ($CONTENT_DATA as $key => $value) {
+ $smarty->assign($key, $value);
+}
+
+file_put_contents('tmp/' . $template_name . '.html', $smarty->fetch(
+ $template_name,
+ $CACHE_ID,
+ $COMPILE_ID
+));
+// write to display
+$smarty->display(
+ $template_name,
+ $CACHE_ID,
+ $COMPILE_ID
+);
+
+// __END__
diff --git a/test/js/overlib/overlib.js b/test/js/overlib/overlib.js
new file mode 100644
index 0000000..7f20694
--- /dev/null
+++ b/test/js/overlib/overlib.js
@@ -0,0 +1,1491 @@
+//\/////
+//\ overLIB 4.21 - You may not remove or change this notice.
+//\ Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\
+//\ Contributors are listed on the homepage.
+//\ This file might be old, always check for the latest version at:
+//\ http://www.bosrup.com/web/overlib/
+//\
+//\ Please read the license agreement (available through the link above)
+//\ before using overLIB. Direct any licensing questions to erik@bosrup.com.
+//\
+//\ Do not sell this as your own work or remove this copyright notice.
+//\ For full details on copying or changing this script please read the
+//\ license agreement at the link above. Please give credit on sites that
+//\ use overLIB and submit changes of the script so other people can use
+//\ them as well.
+// $Revision: 3159 $ $Date: 2010-09-02 11:58:10 +0900 (Thu, 02 Sep 2010) $
+//\/////
+//\mini
+
+////////
+// PRE-INIT
+// Ignore these lines, configuration is below.
+////////
+var olLoaded = 0;var pmStart = 10000000; var pmUpper = 10001000; var pmCount = pmStart+1; var pmt=''; var pms = new Array(); var olInfo = new Info('4.21', 1);
+var FREPLACE = 0; var FBEFORE = 1; var FAFTER = 2; var FALTERNATE = 3; var FCHAIN=4;
+var olHideForm=0; // parameter for hiding SELECT and ActiveX elements in IE5.5+
+var olHautoFlag = 0; // flags for over-riding VAUTO and HAUTO if corresponding
+var olVautoFlag = 0; // positioning commands are used on the command line
+var hookPts = new Array(), postParse = new Array(), cmdLine = new Array(), runTime = new Array();
+// for plugins
+registerCommands('donothing,inarray,caparray,sticky,background,noclose,caption,left,right,center,offsetx,offsety,fgcolor,bgcolor,textcolor,capcolor,closecolor,width,border,cellpad,status,autostatus,autostatuscap,height,closetext,snapx,snapy,fixx,fixy,relx,rely,fgbackground,bgbackground,padx,pady,fullhtml,above,below,capicon,textfont,captionfont,closefont,textsize,captionsize,closesize,timeout,function,delay,hauto,vauto,closeclick,wrap,followmouse,mouseoff,closetitle,cssoff,compatmode,cssclass,fgclass,bgclass,textfontclass,captionfontclass,closefontclass');
+
+////////
+// DEFAULT CONFIGURATION
+// Settings you want everywhere are set here. All of this can also be
+// changed on your html page or through an overLIB call.
+////////
+if (typeof ol_fgcolor=='undefined') var ol_fgcolor="#CCCCFF";
+if (typeof ol_bgcolor=='undefined') var ol_bgcolor="#333399";
+if (typeof ol_textcolor=='undefined') var ol_textcolor="#000000";
+if (typeof ol_capcolor=='undefined') var ol_capcolor="#FFFFFF";
+if (typeof ol_closecolor=='undefined') var ol_closecolor="#9999FF";
+if (typeof ol_textfont=='undefined') var ol_textfont="Verdana,Arial,Helvetica";
+if (typeof ol_captionfont=='undefined') var ol_captionfont="Verdana,Arial,Helvetica";
+if (typeof ol_closefont=='undefined') var ol_closefont="Verdana,Arial,Helvetica";
+if (typeof ol_textsize=='undefined') var ol_textsize="1";
+if (typeof ol_captionsize=='undefined') var ol_captionsize="1";
+if (typeof ol_closesize=='undefined') var ol_closesize="1";
+if (typeof ol_width=='undefined') var ol_width="200";
+if (typeof ol_border=='undefined') var ol_border="1";
+if (typeof ol_cellpad=='undefined') var ol_cellpad=2;
+if (typeof ol_offsetx=='undefined') var ol_offsetx=10;
+if (typeof ol_offsety=='undefined') var ol_offsety=10;
+if (typeof ol_text=='undefined') var ol_text="Default Text";
+if (typeof ol_cap=='undefined') var ol_cap="";
+if (typeof ol_sticky=='undefined') var ol_sticky=0;
+if (typeof ol_background=='undefined') var ol_background="";
+if (typeof ol_close=='undefined') var ol_close="Close";
+if (typeof ol_hpos=='undefined') var ol_hpos=RIGHT;
+if (typeof ol_status=='undefined') var ol_status="";
+if (typeof ol_autostatus=='undefined') var ol_autostatus=0;
+if (typeof ol_height=='undefined') var ol_height=-1;
+if (typeof ol_snapx=='undefined') var ol_snapx=0;
+if (typeof ol_snapy=='undefined') var ol_snapy=0;
+if (typeof ol_fixx=='undefined') var ol_fixx=-1;
+if (typeof ol_fixy=='undefined') var ol_fixy=-1;
+if (typeof ol_relx=='undefined') var ol_relx=null;
+if (typeof ol_rely=='undefined') var ol_rely=null;
+if (typeof ol_fgbackground=='undefined') var ol_fgbackground="";
+if (typeof ol_bgbackground=='undefined') var ol_bgbackground="";
+if (typeof ol_padxl=='undefined') var ol_padxl=1;
+if (typeof ol_padxr=='undefined') var ol_padxr=1;
+if (typeof ol_padyt=='undefined') var ol_padyt=1;
+if (typeof ol_padyb=='undefined') var ol_padyb=1;
+if (typeof ol_fullhtml=='undefined') var ol_fullhtml=0;
+if (typeof ol_vpos=='undefined') var ol_vpos=BELOW;
+if (typeof ol_aboveheight=='undefined') var ol_aboveheight=0;
+if (typeof ol_capicon=='undefined') var ol_capicon="";
+if (typeof ol_frame=='undefined') var ol_frame=self;
+if (typeof ol_timeout=='undefined') var ol_timeout=0;
+if (typeof ol_function=='undefined') var ol_function=null;
+if (typeof ol_delay=='undefined') var ol_delay=0;
+if (typeof ol_hauto=='undefined') var ol_hauto=0;
+if (typeof ol_vauto=='undefined') var ol_vauto=0;
+if (typeof ol_closeclick=='undefined') var ol_closeclick=0;
+if (typeof ol_wrap=='undefined') var ol_wrap=0;
+if (typeof ol_followmouse=='undefined') var ol_followmouse=1;
+if (typeof ol_mouseoff=='undefined') var ol_mouseoff=0;
+if (typeof ol_closetitle=='undefined') var ol_closetitle='Close';
+if (typeof ol_compatmode=='undefined') var ol_compatmode=0;
+if (typeof ol_css=='undefined') var ol_css=CSSOFF;
+if (typeof ol_fgclass=='undefined') var ol_fgclass="";
+if (typeof ol_bgclass=='undefined') var ol_bgclass="";
+if (typeof ol_textfontclass=='undefined') var ol_textfontclass="";
+if (typeof ol_captionfontclass=='undefined') var ol_captionfontclass="";
+if (typeof ol_closefontclass=='undefined') var ol_closefontclass="";
+
+////////
+// ARRAY CONFIGURATION
+////////
+
+// You can use these arrays to store popup text here instead of in the html.
+if (typeof ol_texts=='undefined') var ol_texts = new Array("Text 0", "Text 1");
+if (typeof ol_caps=='undefined') var ol_caps = new Array("Caption 0", "Caption 1");
+
+////////
+// END OF CONFIGURATION
+// Don't change anything below this line, all configuration is above.
+////////
+
+
+
+
+
+////////
+// INIT
+////////
+// Runtime variables init. Don't change for config!
+var o3_text="";
+var o3_cap="";
+var o3_sticky=0;
+var o3_background="";
+var o3_close="Close";
+var o3_hpos=RIGHT;
+var o3_offsetx=2;
+var o3_offsety=2;
+var o3_fgcolor="";
+var o3_bgcolor="";
+var o3_textcolor="";
+var o3_capcolor="";
+var o3_closecolor="";
+var o3_width=100;
+var o3_border=1;
+var o3_cellpad=2;
+var o3_status="";
+var o3_autostatus=0;
+var o3_height=-1;
+var o3_snapx=0;
+var o3_snapy=0;
+var o3_fixx=-1;
+var o3_fixy=-1;
+var o3_relx=null;
+var o3_rely=null;
+var o3_fgbackground="";
+var o3_bgbackground="";
+var o3_padxl=0;
+var o3_padxr=0;
+var o3_padyt=0;
+var o3_padyb=0;
+var o3_fullhtml=0;
+var o3_vpos=BELOW;
+var o3_aboveheight=0;
+var o3_capicon="";
+var o3_textfont="Verdana,Arial,Helvetica";
+var o3_captionfont="Verdana,Arial,Helvetica";
+var o3_closefont="Verdana,Arial,Helvetica";
+var o3_textsize="1";
+var o3_captionsize="1";
+var o3_closesize="1";
+var o3_frame=self;
+var o3_timeout=0;
+var o3_timerid=0;
+var o3_allowmove=0;
+var o3_function=null;
+var o3_delay=0;
+var o3_delayid=0;
+var o3_hauto=0;
+var o3_vauto=0;
+var o3_closeclick=0;
+var o3_wrap=0;
+var o3_followmouse=1;
+var o3_mouseoff=0;
+var o3_closetitle='';
+var o3_compatmode=0;
+var o3_css=CSSOFF;
+var o3_fgclass="";
+var o3_bgclass="";
+var o3_textfontclass="";
+var o3_captionfontclass="";
+var o3_closefontclass="";
+
+// Display state variables
+var o3_x = 0;
+var o3_y = 0;
+var o3_showingsticky = 0;
+var o3_removecounter = 0;
+
+// Our layer
+var over = null;
+var fnRef, hoveringSwitch = false;
+var olHideDelay;
+
+// Decide browser version
+var isMac = (navigator.userAgent.indexOf("Mac") != -1);
+var olOp = (navigator.userAgent.toLowerCase().indexOf('opera') > -1 && document.createTextNode); // Opera 7
+var olNs4 = (navigator.appName=='Netscape' && parseInt(navigator.appVersion) == 4);
+var olNs6 = (document.getElementById) ? true : false;
+var olKq = (olNs6 && /konqueror/i.test(navigator.userAgent));
+var olIe4 = (document.all) ? true : false;
+var olIe5 = false;
+var olIe55 = false; // Added additional variable to identify IE5.5+
+var docRoot = 'document.body';
+
+// Resize fix for NS4.x to keep track of layer
+if (olNs4) {
+ var oW = window.innerWidth;
+ var oH = window.innerHeight;
+ window.onresize = function() { if (oW != window.innerWidth || oH != window.innerHeight) location.reload(); }
+}
+
+// Microsoft Stupidity Check(tm).
+if (olIe4) {
+ var agent = navigator.userAgent;
+ if (/MSIE/.test(agent)) {
+ var versNum = parseFloat(agent.match(/MSIE[ ](\d\.\d+)\.*/i)[1]);
+ if (versNum >= 5){
+ olIe5=true;
+ olIe55=(versNum>=5.5&&!olOp) ? true : false;
+ if (olNs6) olNs6=false;
+ }
+ }
+ if (olNs6) olIe4 = false;
+}
+
+// Check for compatability mode.
+if (document.compatMode && document.compatMode == 'CSS1Compat') {
+ docRoot= ((olIe4 && !olOp) ? 'document.documentElement' : docRoot);
+}
+
+// Add window onload handlers to indicate when all modules have been loaded
+// For Netscape 6+ and Mozilla, uses addEventListener method on the window object
+// For IE it uses the attachEvent method of the window object and for Netscape 4.x
+// it sets the window.onload handler to the OLonload_handler function for Bubbling
+if(window.addEventListener) window.addEventListener("load",OLonLoad_handler,false);
+else if (window.attachEvent) window.attachEvent("onload",OLonLoad_handler);
+
+var capExtent;
+
+////////
+// PUBLIC FUNCTIONS
+////////
+
+// overlib(arg0,...,argN)
+// Loads parameters into global runtime variables.
+function overlib() {
+ if (!olLoaded || isExclusive(overlib.arguments)) return true;
+ if (olCheckMouseCapture) olMouseCapture();
+ if (over) {
+ over = (typeof over.id != 'string') ? o3_frame.document.all['overDiv'] : over;
+ cClick();
+ }
+
+ // Load defaults to runtime.
+ olHideDelay=0;
+ o3_text=ol_text;
+ o3_cap=ol_cap;
+ o3_sticky=ol_sticky;
+ o3_background=ol_background;
+ o3_close=ol_close;
+ o3_hpos=ol_hpos;
+ o3_offsetx=ol_offsetx;
+ o3_offsety=ol_offsety;
+ o3_fgcolor=ol_fgcolor;
+ o3_bgcolor=ol_bgcolor;
+ o3_textcolor=ol_textcolor;
+ o3_capcolor=ol_capcolor;
+ o3_closecolor=ol_closecolor;
+ o3_width=ol_width;
+ o3_border=ol_border;
+ o3_cellpad=ol_cellpad;
+ o3_status=ol_status;
+ o3_autostatus=ol_autostatus;
+ o3_height=ol_height;
+ o3_snapx=ol_snapx;
+ o3_snapy=ol_snapy;
+ o3_fixx=ol_fixx;
+ o3_fixy=ol_fixy;
+ o3_relx=ol_relx;
+ o3_rely=ol_rely;
+ o3_fgbackground=ol_fgbackground;
+ o3_bgbackground=ol_bgbackground;
+ o3_padxl=ol_padxl;
+ o3_padxr=ol_padxr;
+ o3_padyt=ol_padyt;
+ o3_padyb=ol_padyb;
+ o3_fullhtml=ol_fullhtml;
+ o3_vpos=ol_vpos;
+ o3_aboveheight=ol_aboveheight;
+ o3_capicon=ol_capicon;
+ o3_textfont=ol_textfont;
+ o3_captionfont=ol_captionfont;
+ o3_closefont=ol_closefont;
+ o3_textsize=ol_textsize;
+ o3_captionsize=ol_captionsize;
+ o3_closesize=ol_closesize;
+ o3_timeout=ol_timeout;
+ o3_function=ol_function;
+ o3_delay=ol_delay;
+ o3_hauto=ol_hauto;
+ o3_vauto=ol_vauto;
+ o3_closeclick=ol_closeclick;
+ o3_wrap=ol_wrap;
+ o3_followmouse=ol_followmouse;
+ o3_mouseoff=ol_mouseoff;
+ o3_closetitle=ol_closetitle;
+ o3_css=ol_css;
+ o3_compatmode=ol_compatmode;
+ o3_fgclass=ol_fgclass;
+ o3_bgclass=ol_bgclass;
+ o3_textfontclass=ol_textfontclass;
+ o3_captionfontclass=ol_captionfontclass;
+ o3_closefontclass=ol_closefontclass;
+
+ setRunTimeVariables();
+
+ fnRef = '';
+
+ // Special for frame support, over must be reset...
+ o3_frame = ol_frame;
+
+ if(!(over=createDivContainer())) return false;
+
+ parseTokens('o3_', overlib.arguments);
+ if (!postParseChecks()) return false;
+
+ if (o3_delay == 0) {
+ return runHook("olMain", FREPLACE);
+ } else {
+ o3_delayid = setTimeout("runHook('olMain', FREPLACE)", o3_delay);
+ return false;
+ }
+}
+
+// Clears popups if appropriate
+function nd(time) {
+ if (olLoaded && !isExclusive()) {
+ hideDelay(time); // delay popup close if time specified
+
+ if (o3_removecounter >= 1) { o3_showingsticky = 0 };
+
+ if (o3_showingsticky == 0) {
+ o3_allowmove = 0;
+ if (over != null && o3_timerid == 0) runHook("hideObject", FREPLACE, over);
+ } else {
+ o3_removecounter++;
+ }
+ }
+
+ return true;
+}
+
+// The Close onMouseOver function for stickies
+function cClick() {
+ if (olLoaded) {
+ runHook("hideObject", FREPLACE, over);
+ o3_showingsticky = 0;
+ }
+ return false;
+}
+
+// Method for setting page specific defaults.
+function overlib_pagedefaults() {
+ parseTokens('ol_', overlib_pagedefaults.arguments);
+}
+
+
+////////
+// OVERLIB MAIN FUNCTION
+////////
+
+// This function decides what it is we want to display and how we want it done.
+function olMain() {
+ var layerhtml, styleType;
+ runHook("olMain", FBEFORE);
+
+ if (o3_background!="" || o3_fullhtml) {
+ // Use background instead of box.
+ layerhtml = runHook('ol_content_background', FALTERNATE, o3_css, o3_text, o3_background, o3_fullhtml);
+ } else {
+ // They want a popup box.
+ styleType = (pms[o3_css-1-pmStart] == "cssoff" || pms[o3_css-1-pmStart] == "cssclass");
+
+ // Prepare popup background
+ if (o3_fgbackground != "") o3_fgbackground = "background=\""+o3_fgbackground+"\"";
+ if (o3_bgbackground != "") o3_bgbackground = (styleType ? "background=\""+o3_bgbackground+"\"" : o3_bgbackground);
+
+ // Prepare popup colors
+ if (o3_fgcolor != "") o3_fgcolor = (styleType ? "bgcolor=\""+o3_fgcolor+"\"" : o3_fgcolor);
+ if (o3_bgcolor != "") o3_bgcolor = (styleType ? "bgcolor=\""+o3_bgcolor+"\"" : o3_bgcolor);
+
+ // Prepare popup height
+ if (o3_height > 0) o3_height = (styleType ? "height=\""+o3_height+"\"" : o3_height);
+ else o3_height = "";
+
+ // Decide which kinda box.
+ if (o3_cap=="") {
+ // Plain
+ layerhtml = runHook('ol_content_simple', FALTERNATE, o3_css, o3_text);
+ } else {
+ // With caption
+ if (o3_sticky) {
+ // Show close text
+ layerhtml = runHook('ol_content_caption', FALTERNATE, o3_css, o3_text, o3_cap, o3_close);
+ } else {
+ // No close text
+ layerhtml = runHook('ol_content_caption', FALTERNATE, o3_css, o3_text, o3_cap, "");
+ }
+ }
+ }
+
+ // We want it to stick!
+ if (o3_sticky) {
+ if (o3_timerid > 0) {
+ clearTimeout(o3_timerid);
+ o3_timerid = 0;
+ }
+ o3_showingsticky = 1;
+ o3_removecounter = 0;
+ }
+
+ // Created a separate routine to generate the popup to make it easier
+ // to implement a plugin capability
+ if (!runHook("createPopup", FREPLACE, layerhtml)) return false;
+
+ // Prepare status bar
+ if (o3_autostatus > 0) {
+ o3_status = o3_text;
+ if (o3_autostatus > 1) o3_status = o3_cap;
+ }
+
+ // When placing the layer the first time, even stickies may be moved.
+ o3_allowmove = 0;
+
+ // Initiate a timer for timeout
+ if (o3_timeout > 0) {
+ if (o3_timerid > 0) clearTimeout(o3_timerid);
+ o3_timerid = setTimeout("cClick()", o3_timeout);
+ }
+
+ // Show layer
+ runHook("disp", FREPLACE, o3_status);
+ runHook("olMain", FAFTER);
+
+ return (olOp && event && event.type == 'mouseover' && !o3_status) ? '' : (o3_status != '');
+}
+
+////////
+// LAYER GENERATION FUNCTIONS
+////////
+// These functions just handle popup content with tags that should adhere to the W3C standards specification.
+
+// Makes simple table without caption
+function ol_content_simple(text) {
+ var cpIsMultiple = /,/.test(o3_cellpad);
+ var txt = '| ' : ((!olNs4&&cpIsMultiple) ? ' style="'+setCellPadStr(o3_cellpad)+'">' : '>'))+(o3_textfontclass ? '' : wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass ? '' : wrapStr(1,o3_textsize))+' |
|
';
+
+ set_background("");
+ return txt;
+}
+
+// Makes table with caption and optional close link
+function ol_content_caption(text,title,close) {
+ var nameId, txt, cpIsMultiple = /,/.test(o3_cellpad);
+ var closing, closeevent;
+
+ closing = "";
+ closeevent = "onmouseover";
+ if (o3_closeclick == 1) closeevent = (o3_closetitle ? "title='" + o3_closetitle +"'" : "") + " onclick";
+ if (o3_capicon != "") {
+ nameId = ' hspace = \"5\"'+' align = \"middle\" alt = \"\"';
+ if (typeof o3_dragimg != 'undefined' && o3_dragimg) nameId =' hspace=\"5\"'+' name=\"'+o3_dragimg+'\" id=\"'+o3_dragimg+'\" align=\"middle\" alt=\"Drag Enabled\" title=\"Drag Enabled\"';
+ o3_capicon = '
';
+ }
+
+ if (close != "")
+ closing = ''+(o3_closefontclass ? '' : wrapStr(0,o3_closesize,'close'))+close+(o3_closefontclass ? '' : wrapStr(1,o3_closesize,'close'))+' | ';
+ txt = '| ' : '>')+(o3_captionfontclass ? '' : ''+wrapStr(0,o3_captionsize,'caption'))+o3_capicon+title+(o3_captionfontclass ? '' : wrapStr(1,o3_captionsize)+'')+' | '+closing+'
| ' :((!olNs4&&cpIsMultiple) ? ' style="'+setCellPadStr(o3_cellpad)+'">' : '>'))+(o3_textfontclass ? '' : wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass ? '' : wrapStr(1,o3_textsize)) + ' |
|
';
+
+ set_background("");
+ return txt;
+}
+
+// Sets the background picture,padding and lots more. :)
+function ol_content_background(text,picture,hasfullhtml) {
+ if (hasfullhtml) {
+ txt=text;
+ } else {
+ txt=' |
| '+(o3_textfontclass ? '' : wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass ? '' : wrapStr(1,o3_textsize))+' | |
|
';
+ }
+
+ set_background(picture);
+ return txt;
+}
+
+// Loads a picture into the div.
+function set_background(pic) {
+ if (pic == "") {
+ if (olNs4) {
+ over.background.src = null;
+ } else if (over.style) {
+ over.style.backgroundImage = "none";
+ }
+ } else {
+ if (olNs4) {
+ over.background.src = pic;
+ } else if (over.style) {
+ over.style.width=o3_width + 'px';
+ over.style.backgroundImage = "url("+pic+")";
+ }
+ }
+}
+
+////////
+// HANDLING FUNCTIONS
+////////
+var olShowId=-1;
+
+// Displays the popup
+function disp(statustext) {
+ runHook("disp", FBEFORE);
+
+ if (o3_allowmove == 0) {
+ runHook("placeLayer", FREPLACE);
+ (olNs6&&olShowId<0) ? olShowId=setTimeout("runHook('showObject', FREPLACE, over)", 1) : runHook("showObject", FREPLACE, over);
+ o3_allowmove = (o3_sticky || o3_followmouse==0) ? 0 : 1;
+ }
+
+ runHook("disp", FAFTER);
+
+ if (statustext != "") self.status = statustext;
+}
+
+// Creates the actual popup structure
+function createPopup(lyrContent){
+ runHook("createPopup", FBEFORE);
+
+ if (o3_wrap) {
+ var wd,ww,theObj = (olNs4 ? over : over.style);
+ theObj.top = theObj.left = ((olIe4&&!olOp) ? 0 : -10000) + (!olNs4 ? 'px' : 0);
+ layerWrite(lyrContent);
+ wd = (olNs4 ? over.clip.width : over.offsetWidth);
+ if (wd > (ww=windowWidth())) {
+ lyrContent=lyrContent.replace(/\ /g, ' ');
+ o3_width=ww;
+ o3_wrap=0;
+ }
+ }
+
+ layerWrite(lyrContent);
+
+ // Have to set o3_width for placeLayer() routine if o3_wrap is turned on
+ if (o3_wrap) o3_width=(olNs4 ? over.clip.width : over.offsetWidth);
+
+ runHook("createPopup", FAFTER, lyrContent);
+
+ return true;
+}
+
+// Decides where we want the popup.
+function placeLayer() {
+ var placeX, placeY, widthFix = 0;
+
+ // HORIZONTAL PLACEMENT, re-arranged to work in Safari
+ if (o3_frame.innerWidth) widthFix=18;
+ iwidth = windowWidth();
+
+ // Horizontal scroll offset
+ winoffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollLeft') : o3_frame.pageXOffset;
+
+ placeX = runHook('horizontalPlacement',FCHAIN,iwidth,winoffset,widthFix);
+
+ // VERTICAL PLACEMENT, re-arranged to work in Safari
+ if (o3_frame.innerHeight) {
+ iheight=o3_frame.innerHeight;
+ } else if (eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientHeight=='number'")&&eval('o3_frame.'+docRoot+'.clientHeight')) {
+ iheight=eval('o3_frame.'+docRoot+'.clientHeight');
+ }
+
+ // Vertical scroll offset
+ scrolloffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollTop') : o3_frame.pageYOffset;
+ placeY = runHook('verticalPlacement',FCHAIN,iheight,scrolloffset);
+
+ // Actually move the object.
+ repositionTo(over, placeX, placeY);
+}
+
+// Moves the layer
+function olMouseMove(e) {
+ var e = (e) ? e : event;
+
+ if (e.pageX) {
+ o3_x = e.pageX;
+ o3_y = e.pageY;
+ } else if (e.clientX) {
+ o3_x = eval('e.clientX+o3_frame.'+docRoot+'.scrollLeft');
+ o3_y = eval('e.clientY+o3_frame.'+docRoot+'.scrollTop');
+ }
+
+ if (o3_allowmove == 1) runHook("placeLayer", FREPLACE);
+
+ // MouseOut handler
+ if (hoveringSwitch && !olNs4 && runHook("cursorOff", FREPLACE)) {
+ (olHideDelay ? hideDelay(olHideDelay) : cClick());
+ hoveringSwitch = !hoveringSwitch;
+ }
+}
+
+// Fake function for 3.0 users.
+function no_overlib() { return ver3fix; }
+
+// Capture the mouse and chain other scripts.
+function olMouseCapture() {
+ capExtent = document;
+ var fN, str = '', l, k, f, wMv, sS, mseHandler = olMouseMove;
+ var re = /function[ ]*(\w*)\(/;
+
+ wMv = (!olIe4 && window.onmousemove);
+ if (document.onmousemove || wMv) {
+ if (wMv) capExtent = window;
+ f = capExtent.onmousemove.toString();
+ fN = f.match(re);
+ if (fN == null) {
+ str = f+'(e); ';
+ } else if (fN[1] == 'anonymous' || fN[1] == 'olMouseMove' || (wMv && fN[1] == 'onmousemove')) {
+ if (!olOp && wMv) {
+ l = f.indexOf('{')+1;
+ k = f.lastIndexOf('}');
+ sS = f.substring(l,k);
+ if ((l = sS.indexOf('(')) != -1) {
+ sS = sS.substring(0,l).replace(/^\s+/,'').replace(/\s+$/,'');
+ if (eval("typeof " + sS + " == 'undefined'")) window.onmousemove = null;
+ else str = sS + '(e);';
+ }
+ }
+ if (!str) {
+ olCheckMouseCapture = false;
+ return;
+ }
+ } else {
+ if (fN[1]) str = fN[1]+'(e); ';
+ else {
+ l = f.indexOf('{')+1;
+ k = f.lastIndexOf('}');
+ str = f.substring(l,k) + '\n';
+ }
+ }
+ str += 'olMouseMove(e); ';
+ mseHandler = new Function('e', str);
+ }
+
+ capExtent.onmousemove = mseHandler;
+ if (olNs4) capExtent.captureEvents(Event.MOUSEMOVE);
+}
+
+////////
+// PARSING FUNCTIONS
+////////
+
+// Does the actual command parsing.
+function parseTokens(pf, ar) {
+ // What the next argument is expected to be.
+ var v, i, mode=-1, par = (pf != 'ol_');
+ var fnMark = (par && !ar.length ? 1 : 0);
+
+ for (i = 0; i < ar.length; i++) {
+ if (mode < 0) {
+ // Arg is maintext,unless its a number between pmStart and pmUpper
+ // then its a command.
+ if (typeof ar[i] == 'number' && ar[i] > pmStart && ar[i] < pmUpper) {
+ fnMark = (par ? 1 : 0);
+ i--; // backup one so that the next block can parse it
+ } else {
+ switch(pf) {
+ case 'ol_':
+ ol_text = ar[i].toString();
+ break;
+ default:
+ o3_text=ar[i].toString();
+ }
+ }
+ mode = 0;
+ } else {
+ // Note: NS4 doesn't like switch cases with vars.
+ if (ar[i] >= pmCount || ar[i]==DONOTHING) { continue; }
+ if (ar[i]==INARRAY) { fnMark = 0; eval(pf+'text=ol_texts['+ar[++i]+'].toString()'); continue; }
+ if (ar[i]==CAPARRAY) { eval(pf+'cap=ol_caps['+ar[++i]+'].toString()'); continue; }
+ if (ar[i]==STICKY) { if (pf!='ol_') eval(pf+'sticky=1'); continue; }
+ if (ar[i]==BACKGROUND) { eval(pf+'background="'+ar[++i]+'"'); continue; }
+ if (ar[i]==NOCLOSE) { if (pf!='ol_') opt_NOCLOSE(); continue; }
+ if (ar[i]==CAPTION) { eval(pf+"cap='"+escSglQuote(ar[++i])+"'"); continue; }
+ if (ar[i]==CENTER || ar[i]==LEFT || ar[i]==RIGHT) { eval(pf+'hpos='+ar[i]); if(pf!='ol_') olHautoFlag=1; continue; }
+ if (ar[i]==OFFSETX) { eval(pf+'offsetx='+ar[++i]); continue; }
+ if (ar[i]==OFFSETY) { eval(pf+'offsety='+ar[++i]); continue; }
+ if (ar[i]==FGCOLOR) { eval(pf+'fgcolor="'+ar[++i]+'"'); continue; }
+ if (ar[i]==BGCOLOR) { eval(pf+'bgcolor="'+ar[++i]+'"'); continue; }
+ if (ar[i]==TEXTCOLOR) { eval(pf+'textcolor="'+ar[++i]+'"'); continue; }
+ if (ar[i]==CAPCOLOR) { eval(pf+'capcolor="'+ar[++i]+'"'); continue; }
+ if (ar[i]==CLOSECOLOR) { eval(pf+'closecolor="'+ar[++i]+'"'); continue; }
+ if (ar[i]==WIDTH) { eval(pf+'width='+ar[++i]); continue; }
+ if (ar[i]==BORDER) { eval(pf+'border='+ar[++i]); continue; }
+ if (ar[i]==CELLPAD) { i=opt_MULTIPLEARGS(++i,ar,(pf+'cellpad')); continue; }
+ if (ar[i]==STATUS) { eval(pf+"status='"+escSglQuote(ar[++i])+"'"); continue; }
+ if (ar[i]==AUTOSTATUS) { eval(pf +'autostatus=('+pf+'autostatus == 1) ? 0 : 1'); continue; }
+ if (ar[i]==AUTOSTATUSCAP) { eval(pf +'autostatus=('+pf+'autostatus == 2) ? 0 : 2'); continue; }
+ if (ar[i]==HEIGHT) { eval(pf+'height='+pf+'aboveheight='+ar[++i]); continue; } // Same param again.
+ if (ar[i]==CLOSETEXT) { eval(pf+"close='"+escSglQuote(ar[++i])+"'"); continue; }
+ if (ar[i]==SNAPX) { eval(pf+'snapx='+ar[++i]); continue; }
+ if (ar[i]==SNAPY) { eval(pf+'snapy='+ar[++i]); continue; }
+ if (ar[i]==FIXX) { eval(pf+'fixx='+ar[++i]); continue; }
+ if (ar[i]==FIXY) { eval(pf+'fixy='+ar[++i]); continue; }
+ if (ar[i]==RELX) { eval(pf+'relx='+ar[++i]); continue; }
+ if (ar[i]==RELY) { eval(pf+'rely='+ar[++i]); continue; }
+ if (ar[i]==FGBACKGROUND) { eval(pf+'fgbackground="'+ar[++i]+'"'); continue; }
+ if (ar[i]==BGBACKGROUND) { eval(pf+'bgbackground="'+ar[++i]+'"'); continue; }
+ if (ar[i]==PADX) { eval(pf+'padxl='+ar[++i]); eval(pf+'padxr='+ar[++i]); continue; }
+ if (ar[i]==PADY) { eval(pf+'padyt='+ar[++i]); eval(pf+'padyb='+ar[++i]); continue; }
+ if (ar[i]==FULLHTML) { if (pf!='ol_') eval(pf+'fullhtml=1'); continue; }
+ if (ar[i]==BELOW || ar[i]==ABOVE) { eval(pf+'vpos='+ar[i]); if (pf!='ol_') olVautoFlag=1; continue; }
+ if (ar[i]==CAPICON) { eval(pf+'capicon="'+ar[++i]+'"'); continue; }
+ if (ar[i]==TEXTFONT) { eval(pf+"textfont='"+escSglQuote(ar[++i])+"'"); continue; }
+ if (ar[i]==CAPTIONFONT) { eval(pf+"captionfont='"+escSglQuote(ar[++i])+"'"); continue; }
+ if (ar[i]==CLOSEFONT) { eval(pf+"closefont='"+escSglQuote(ar[++i])+"'"); continue; }
+ if (ar[i]==TEXTSIZE) { eval(pf+'textsize="'+ar[++i]+'"'); continue; }
+ if (ar[i]==CAPTIONSIZE) { eval(pf+'captionsize="'+ar[++i]+'"'); continue; }
+ if (ar[i]==CLOSESIZE) { eval(pf+'closesize="'+ar[++i]+'"'); continue; }
+ if (ar[i]==TIMEOUT) { eval(pf+'timeout='+ar[++i]); continue; }
+ if (ar[i]==FUNCTION) { if (pf=='ol_') { if (typeof ar[i+1]!='number') { v=ar[++i]; ol_function=(typeof v=='function' ? v : null); }} else {fnMark = 0; v = null; if (typeof ar[i+1]!='number') v = ar[++i]; opt_FUNCTION(v); } continue; }
+ if (ar[i]==DELAY) { eval(pf+'delay='+ar[++i]); continue; }
+ if (ar[i]==HAUTO) { eval(pf+'hauto=('+pf+'hauto == 0) ? 1 : 0'); continue; }
+ if (ar[i]==VAUTO) { eval(pf+'vauto=('+pf+'vauto == 0) ? 1 : 0'); continue; }
+ if (ar[i]==CLOSECLICK) { eval(pf +'closeclick=('+pf+'closeclick == 0) ? 1 : 0'); continue; }
+ if (ar[i]==WRAP) { eval(pf +'wrap=('+pf+'wrap == 0) ? 1 : 0'); continue; }
+ if (ar[i]==FOLLOWMOUSE) { eval(pf +'followmouse=('+pf+'followmouse == 1) ? 0 : 1'); continue; }
+ if (ar[i]==MOUSEOFF) { eval(pf +'mouseoff=('+pf+'mouseoff==0) ? 1 : 0'); v=ar[i+1]; if (pf != 'ol_' && eval(pf+'mouseoff') && typeof v == 'number' && (v < pmStart || v > pmUpper)) olHideDelay=ar[++i]; continue; }
+ if (ar[i]==CLOSETITLE) { eval(pf+"closetitle='"+escSglQuote(ar[++i])+"'"); continue; }
+ if (ar[i]==CSSOFF||ar[i]==CSSCLASS) { eval(pf+'css='+ar[i]); continue; }
+ if (ar[i]==COMPATMODE) { eval(pf+'compatmode=('+pf+'compatmode==0) ? 1 : 0'); continue; }
+ if (ar[i]==FGCLASS) { eval(pf+'fgclass="'+ar[++i]+'"'); continue; }
+ if (ar[i]==BGCLASS) { eval(pf+'bgclass="'+ar[++i]+'"'); continue; }
+ if (ar[i]==TEXTFONTCLASS) { eval(pf+'textfontclass="'+ar[++i]+'"'); continue; }
+ if (ar[i]==CAPTIONFONTCLASS) { eval(pf+'captionfontclass="'+ar[++i]+'"'); continue; }
+ if (ar[i]==CLOSEFONTCLASS) { eval(pf+'closefontclass="'+ar[++i]+'"'); continue; }
+ i = parseCmdLine(pf, i, ar);
+ }
+ }
+
+ if (fnMark && o3_function) o3_text = o3_function();
+
+ if ((pf == 'o3_') && o3_wrap) {
+ o3_width = 0;
+
+ var tReg=/<.*\n*>/ig;
+ if (!tReg.test(o3_text)) o3_text = o3_text.replace(/[ ]+/g, ' ');
+ if (!tReg.test(o3_cap))o3_cap = o3_cap.replace(/[ ]+/g, ' ');
+ }
+ if ((pf == 'o3_') && o3_sticky) {
+ if (!o3_close && (o3_frame != ol_frame)) o3_close = ol_close;
+ if (o3_mouseoff && (o3_frame == ol_frame)) opt_NOCLOSE(' ');
+ }
+}
+
+
+////////
+// LAYER FUNCTIONS
+////////
+
+// Writes to a layer
+function layerWrite(txt) {
+ txt += "\n";
+ if (olNs4) {
+ var lyr = o3_frame.document.layers['overDiv'].document
+ lyr.write(txt)
+ lyr.close()
+ } else if (typeof over.innerHTML != 'undefined') {
+ if (olIe5 && isMac) over.innerHTML = '';
+ over.innerHTML = txt;
+ } else {
+ range = o3_frame.document.createRange();
+ range.setStartAfter(over);
+ domfrag = range.createContextualFragment(txt);
+
+ while (over.hasChildNodes()) {
+ over.removeChild(over.lastChild);
+ }
+
+ over.appendChild(domfrag);
+ }
+}
+
+// Make an object visible
+function showObject(obj) {
+ runHook("showObject", FBEFORE);
+
+ var theObj=(olNs4 ? obj : obj.style);
+ theObj.visibility = 'visible';
+
+ runHook("showObject", FAFTER);
+}
+
+// Hides an object
+function hideObject(obj) {
+ runHook("hideObject", FBEFORE);
+
+ var theObj=(olNs4 ? obj : obj.style);
+ if (olNs6 && olShowId>0) { clearTimeout(olShowId); olShowId=0; }
+ theObj.visibility = 'hidden';
+ theObj.top = theObj.left = ((olIe4&&!olOp) ? 0 : -10000) + (!olNs4 ? 'px' : 0);
+
+ if (o3_timerid > 0) clearTimeout(o3_timerid);
+ if (o3_delayid > 0) clearTimeout(o3_delayid);
+
+ o3_timerid = 0;
+ o3_delayid = 0;
+ self.status = "";
+
+ if (obj.onmouseout||obj.onmouseover) {
+ if (olNs4) obj.releaseEvents(Event.MOUSEOUT || Event.MOUSEOVER);
+ obj.onmouseout = obj.onmouseover = null;
+ }
+
+ runHook("hideObject", FAFTER);
+}
+
+// Move a layer
+function repositionTo(obj, xL, yL) {
+ var theObj=(olNs4 ? obj : obj.style);
+ theObj.left = xL + (!olNs4 ? 'px' : 0);
+ theObj.top = yL + (!olNs4 ? 'px' : 0);
+}
+
+// Check position of cursor relative to overDiv DIVision; mouseOut function
+function cursorOff() {
+ var left = parseInt(over.style.left);
+ var top = parseInt(over.style.top);
+ var right = left + (over.offsetWidth >= parseInt(o3_width) ? over.offsetWidth : parseInt(o3_width));
+ var bottom = top + (over.offsetHeight >= o3_aboveheight ? over.offsetHeight : o3_aboveheight);
+
+ if (o3_x < left || o3_x > right || o3_y < top || o3_y > bottom) return true;
+
+ return false;
+}
+
+
+////////
+// COMMAND FUNCTIONS
+////////
+
+// Calls callme or the default function.
+function opt_FUNCTION(callme) {
+ o3_text = (callme ? (typeof callme=='string' ? (/.+\(.*\)/.test(callme) ? eval(callme) : callme) : callme()) : (o3_function ? o3_function() : 'No Function'));
+
+ return 0;
+}
+
+// Handle hovering
+function opt_NOCLOSE(unused) {
+ if (!unused) o3_close = "";
+
+ if (olNs4) {
+ over.captureEvents(Event.MOUSEOUT || Event.MOUSEOVER);
+ over.onmouseover = function () { if (o3_timerid > 0) { clearTimeout(o3_timerid); o3_timerid = 0; } }
+ over.onmouseout = function (e) { if (olHideDelay) hideDelay(olHideDelay); else cClick(e); }
+ } else {
+ over.onmouseover = function () {hoveringSwitch = true; if (o3_timerid > 0) { clearTimeout(o3_timerid); o3_timerid =0; } }
+ }
+
+ return 0;
+}
+
+// Function to scan command line arguments for multiples
+function opt_MULTIPLEARGS(i, args, parameter) {
+ var k=i, re, pV, str='';
+
+ for(k=i; kpmStart) break;
+ str += args[k] + ',';
+ }
+ if (str) str = str.substring(0,--str.length);
+
+ k--; // reduce by one so the for loop this is in works correctly
+ pV=(olNs4 && /cellpad/i.test(parameter)) ? str.split(',')[0] : str;
+ eval(parameter + '="' + pV + '"');
+
+ return k;
+}
+
+// Remove in texts when done.
+function nbspCleanup() {
+ if (o3_wrap) {
+ o3_text = o3_text.replace(/\ /g, ' ');
+ o3_cap = o3_cap.replace(/\ /g, ' ');
+ }
+}
+
+// Escape embedded single quotes in text strings
+function escSglQuote(str) {
+ return str.toString().replace(/'/g,"\\'");
+}
+
+// Onload handler for window onload event
+function OLonLoad_handler(e) {
+ var re = /\w+\(.*\)[;\s]+/g, olre = /overlib\(|nd\(|cClick\(/, fn, l, i;
+
+ if(!olLoaded) olLoaded=1;
+
+ // Remove it for Gecko based browsers
+ if(window.removeEventListener && e.eventPhase == 3) window.removeEventListener("load",OLonLoad_handler,false);
+ else if(window.detachEvent) { // and for IE and Opera 4.x but execute calls to overlib, nd, or cClick()
+ window.detachEvent("onload",OLonLoad_handler);
+ var fN = document.body.getAttribute('onload');
+ if (fN) {
+ fN=fN.toString().match(re);
+ if (fN && fN.length) {
+ for (i=0; i' : '') : '';
+ else {
+ fontStr='o3_'+whichString+'font';
+ fontColor='o3_'+((whichString=='caption')? 'cap' : whichString)+'color';
+ return (hasDims&&!olNs4) ? (isClose ? '' : '') : '
';
+ }
+}
+
+// Quotes Multi word font names; needed for CSS Standards adherence in font-family
+function quoteMultiNameFonts(theFont) {
+ var v, pM=theFont.split(',');
+ for (var i=0; i 0) clearTimeout(o3_timerid);
+
+ o3_timerid=setTimeout("cClick()",(o3_timeout=time));
+ }
+}
+
+// Was originally in the placeLayer() routine; separated out for future ease
+function horizontalPlacement(browserWidth, horizontalScrollAmount, widthFix) {
+ var placeX, iwidth=browserWidth, winoffset=horizontalScrollAmount;
+ var parsedWidth = parseInt(o3_width);
+
+ if (o3_fixx > -1 || o3_relx != null) {
+ // Fixed position
+ placeX=(o3_relx != null ? ( o3_relx < 0 ? winoffset +o3_relx+ iwidth - parsedWidth - widthFix : winoffset+o3_relx) : o3_fixx);
+ } else {
+ // If HAUTO, decide what to use.
+ if (o3_hauto == 1) {
+ if ((o3_x - winoffset) > (iwidth / 2)) {
+ o3_hpos = LEFT;
+ } else {
+ o3_hpos = RIGHT;
+ }
+ }
+
+ // From mouse
+ if (o3_hpos == CENTER) { // Center
+ placeX = o3_x+o3_offsetx-(parsedWidth/2);
+
+ if (placeX < winoffset) placeX = winoffset;
+ }
+
+ if (o3_hpos == RIGHT) { // Right
+ placeX = o3_x+o3_offsetx;
+
+ if ((placeX+parsedWidth) > (winoffset+iwidth - widthFix)) {
+ placeX = iwidth+winoffset - parsedWidth - widthFix;
+ if (placeX < 0) placeX = 0;
+ }
+ }
+ if (o3_hpos == LEFT) { // Left
+ placeX = o3_x-o3_offsetx-parsedWidth;
+ if (placeX < winoffset) placeX = winoffset;
+ }
+
+ // Snapping!
+ if (o3_snapx > 1) {
+ var snapping = placeX % o3_snapx;
+
+ if (o3_hpos == LEFT) {
+ placeX = placeX - (o3_snapx+snapping);
+ } else {
+ // CENTER and RIGHT
+ placeX = placeX+(o3_snapx - snapping);
+ }
+
+ if (placeX < winoffset) placeX = winoffset;
+ }
+ }
+
+ return placeX;
+}
+
+// was originally in the placeLayer() routine; separated out for future ease
+function verticalPlacement(browserHeight,verticalScrollAmount) {
+ var placeY, iheight=browserHeight, scrolloffset=verticalScrollAmount;
+ var parsedHeight=(o3_aboveheight ? parseInt(o3_aboveheight) : (olNs4 ? over.clip.height : over.offsetHeight));
+
+ if (o3_fixy > -1 || o3_rely != null) {
+ // Fixed position
+ placeY=(o3_rely != null ? (o3_rely < 0 ? scrolloffset+o3_rely+iheight - parsedHeight : scrolloffset+o3_rely) : o3_fixy);
+ } else {
+ // If VAUTO, decide what to use.
+ if (o3_vauto == 1) {
+ if ((o3_y - scrolloffset) > (iheight / 2) && o3_vpos == BELOW && (o3_y + parsedHeight + o3_offsety - (scrolloffset + iheight) > 0)) {
+ o3_vpos = ABOVE;
+ } else if (o3_vpos == ABOVE && (o3_y - (parsedHeight + o3_offsety) - scrolloffset < 0)) {
+ o3_vpos = BELOW;
+ }
+ }
+
+ // From mouse
+ if (o3_vpos == ABOVE) {
+ if (o3_aboveheight == 0) o3_aboveheight = parsedHeight;
+
+ placeY = o3_y - (o3_aboveheight+o3_offsety);
+ if (placeY < scrolloffset) placeY = scrolloffset;
+ } else {
+ // BELOW
+ placeY = o3_y+o3_offsety;
+ }
+
+ // Snapping!
+ if (o3_snapy > 1) {
+ var snapping = placeY % o3_snapy;
+
+ if (o3_aboveheight > 0 && o3_vpos == ABOVE) {
+ placeY = placeY - (o3_snapy+snapping);
+ } else {
+ placeY = placeY+(o3_snapy - snapping);
+ }
+
+ if (placeY < scrolloffset) placeY = scrolloffset;
+ }
+ }
+
+ return placeY;
+}
+
+// checks positioning flags
+function checkPositionFlags() {
+ if (olHautoFlag) olHautoFlag = o3_hauto=0;
+ if (olVautoFlag) olVautoFlag = o3_vauto=0;
+ return true;
+}
+
+// get Browser window width
+function windowWidth() {
+ var w;
+ if (o3_frame.innerWidth) w=o3_frame.innerWidth;
+ else if (eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientWidth=='number'")&&eval('o3_frame.'+docRoot+'.clientWidth'))
+ w=eval('o3_frame.'+docRoot+'.clientWidth');
+ return w;
+}
+
+// create the div container for popup content if it doesn't exist
+function createDivContainer(id,frm,zValue) {
+ id = (id || 'overDiv'), frm = (frm || o3_frame), zValue = (zValue || 3000);
+ var objRef, divContainer = layerReference(id);
+
+ if (divContainer == null) {
+ if (olNs4) {
+ divContainer = frm.document.layers[id] = new Layer(window.innerWidth, frm);
+ objRef = divContainer;
+ } else {
+ var body = (olIe4 ? frm.document.all.tags('BODY')[0] : frm.document.getElementsByTagName("BODY")[0]);
+ if (olIe4&&!document.getElementById) {
+ body.insertAdjacentHTML("beforeEnd",'');
+ divContainer=layerReference(id);
+ } else {
+ divContainer = frm.document.createElement("DIV");
+ divContainer.id = id;
+ body.appendChild(divContainer);
+ }
+ objRef = divContainer.style;
+ }
+
+ objRef.position = 'absolute';
+ objRef.visibility = 'hidden';
+ objRef.zIndex = zValue;
+ if (olIe4&&!olOp) objRef.left = objRef.top = '0px';
+ else objRef.left = objRef.top = -10000 + (!olNs4 ? 'px' : 0);
+ }
+
+ return divContainer;
+}
+
+// get reference to a layer with ID=id
+function layerReference(id) {
+ return (olNs4 ? o3_frame.document.layers[id] : (document.all ? o3_frame.document.all[id] : o3_frame.document.getElementById(id)));
+}
+////////
+// UTILITY FUNCTIONS
+////////
+
+// Checks if something is a function.
+function isFunction(fnRef) {
+ var rtn = true;
+
+ if (typeof fnRef == 'object') {
+ for (var i = 0; i < fnRef.length; i++) {
+ if (typeof fnRef[i]=='function') continue;
+ rtn = false;
+ break;
+ }
+ } else if (typeof fnRef != 'function') {
+ rtn = false;
+ }
+
+ return rtn;
+}
+
+// Converts an array into an argument string for use in eval.
+function argToString(array, strtInd, argName) {
+ var jS = strtInd, aS = '', ar = array;
+ argName=(argName ? argName : 'ar');
+
+ if (ar.length > jS) {
+ for (var k = jS; k < ar.length; k++) aS += argName+'['+k+'], ';
+ aS = aS.substring(0, aS.length-2);
+ }
+
+ return aS;
+}
+
+// Places a hook in the correct position in a hook point.
+function reOrder(hookPt, fnRef, order) {
+ var newPt = new Array(), match, i, j;
+
+ if (!order || typeof order == 'undefined' || typeof order == 'number') return hookPt;
+
+ if (typeof order=='function') {
+ if (typeof fnRef=='object') {
+ newPt = newPt.concat(fnRef);
+ } else {
+ newPt[newPt.length++]=fnRef;
+ }
+
+ for (i = 0; i < hookPt.length; i++) {
+ match = false;
+ if (typeof fnRef == 'function' && hookPt[i] == fnRef) {
+ continue;
+ } else {
+ for(j = 0; j < fnRef.length; j++) if (hookPt[i] == fnRef[j]) {
+ match = true;
+ break;
+ }
+ }
+ if (!match) newPt[newPt.length++] = hookPt[i];
+ }
+
+ newPt[newPt.length++] = order;
+
+ } else if (typeof order == 'object') {
+ if (typeof fnRef == 'object') {
+ newPt = newPt.concat(fnRef);
+ } else {
+ newPt[newPt.length++] = fnRef;
+ }
+
+ for (j = 0; j < hookPt.length; j++) {
+ match = false;
+ if (typeof fnRef == 'function' && hookPt[j] == fnRef) {
+ continue;
+ } else {
+ for (i = 0; i < fnRef.length; i++) if (hookPt[j] == fnRef[i]) {
+ match = true;
+ break;
+ }
+ }
+ if (!match) newPt[newPt.length++]=hookPt[j];
+ }
+
+ for (i = 0; i < newPt.length; i++) hookPt[i] = newPt[i];
+ newPt.length = 0;
+
+ for (j = 0; j < hookPt.length; j++) {
+ match = false;
+ for (i = 0; i < order.length; i++) {
+ if (hookPt[j] == order[i]) {
+ match = true;
+ break;
+ }
+ }
+ if (!match) newPt[newPt.length++] = hookPt[j];
+ }
+ newPt = newPt.concat(order);
+ }
+
+ hookPt = newPt;
+
+ return hookPt;
+}
+
+////////
+// PLUGIN ACTIVATION FUNCTIONS
+////////
+
+// Runs plugin functions to set runtime variables.
+function setRunTimeVariables(){
+ if (typeof runTime != 'undefined' && runTime.length) {
+ for (var k = 0; k < runTime.length; k++) {
+ runTime[k]();
+ }
+ }
+}
+
+// Runs plugin functions to parse commands.
+function parseCmdLine(pf, i, args) {
+ if (typeof cmdLine != 'undefined' && cmdLine.length) {
+ for (var k = 0; k < cmdLine.length; k++) {
+ var j = cmdLine[k](pf, i, args);
+ if (j >- 1) {
+ i = j;
+ break;
+ }
+ }
+ }
+
+ return i;
+}
+
+// Runs plugin functions to do things after parse.
+function postParseChecks(pf,args){
+ if (typeof postParse != 'undefined' && postParse.length) {
+ for (var k = 0; k < postParse.length; k++) {
+ if (postParse[k](pf,args)) continue;
+ return false; // end now since have an error
+ }
+ }
+ return true;
+}
+
+
+////////
+// PLUGIN REGISTRATION FUNCTIONS
+////////
+
+// Registers commands and creates constants.
+function registerCommands(cmdStr) {
+ if (typeof cmdStr!='string') return;
+
+ var pM = cmdStr.split(',');
+ pms = pms.concat(pM);
+
+ for (var i = 0; i< pM.length; i++) {
+ eval(pM[i].toUpperCase()+'='+pmCount++);
+ }
+}
+
+// Registers no-parameter commands
+function registerNoParameterCommands(cmdStr) {
+ if (!cmdStr && typeof cmdStr != 'string') return;
+ pmt=(!pmt) ? cmdStr : pmt + ',' + cmdStr;
+}
+
+// Register a function to hook at a certain point.
+function registerHook(fnHookTo, fnRef, hookType, optPm) {
+ var hookPt, last = typeof optPm;
+
+ if (fnHookTo == 'plgIn'||fnHookTo == 'postParse') return;
+ if (typeof hookPts[fnHookTo] == 'undefined') hookPts[fnHookTo] = new FunctionReference();
+
+ hookPt = hookPts[fnHookTo];
+
+ if (hookType != null) {
+ if (hookType == FREPLACE) {
+ hookPt.ovload = fnRef; // replace normal overlib routine
+ if (fnHookTo.indexOf('ol_content_') > -1) hookPt.alt[pms[CSSOFF-1-pmStart]]=fnRef;
+
+ } else if (hookType == FBEFORE || hookType == FAFTER) {
+ var hookPt=(hookType == 1 ? hookPt.before : hookPt.after);
+
+ if (typeof fnRef == 'object') {
+ hookPt = hookPt.concat(fnRef);
+ } else {
+ hookPt[hookPt.length++] = fnRef;
+ }
+
+ if (optPm) hookPt = reOrder(hookPt, fnRef, optPm);
+
+ } else if (hookType == FALTERNATE) {
+ if (last=='number') hookPt.alt[pms[optPm-1-pmStart]] = fnRef;
+ } else if (hookType == FCHAIN) {
+ hookPt = hookPt.chain;
+ if (typeof fnRef=='object') hookPt=hookPt.concat(fnRef); // add other functions
+ else hookPt[hookPt.length++]=fnRef;
+ }
+
+ return;
+ }
+}
+
+// Register a function that will set runtime variables.
+function registerRunTimeFunction(fn) {
+ if (isFunction(fn)) {
+ if (typeof fn == 'object') {
+ runTime = runTime.concat(fn);
+ } else {
+ runTime[runTime.length++] = fn;
+ }
+ }
+}
+
+// Register a function that will handle command parsing.
+function registerCmdLineFunction(fn){
+ if (isFunction(fn)) {
+ if (typeof fn == 'object') {
+ cmdLine = cmdLine.concat(fn);
+ } else {
+ cmdLine[cmdLine.length++] = fn;
+ }
+ }
+}
+
+// Register a function that does things after command parsing.
+function registerPostParseFunction(fn){
+ if (isFunction(fn)) {
+ if (typeof fn == 'object') {
+ postParse = postParse.concat(fn);
+ } else {
+ postParse[postParse.length++] = fn;
+ }
+ }
+}
+
+////////
+// PLUGIN REGISTRATION FUNCTIONS
+////////
+
+// Runs any hooks registered.
+function runHook(fnHookTo, hookType) {
+ var l = hookPts[fnHookTo], k, rtnVal = null, optPm, arS, ar = runHook.arguments;
+
+ if (hookType == FREPLACE) {
+ arS = argToString(ar, 2);
+
+ if (typeof l == 'undefined' || !(l = l.ovload)) rtnVal = eval(fnHookTo+'('+arS+')');
+ else rtnVal = eval('l('+arS+')');
+
+ } else if (hookType == FBEFORE || hookType == FAFTER) {
+ if (typeof l != 'undefined') {
+ l=(hookType == 1 ? l.before : l.after);
+
+ if (l.length) {
+ arS = argToString(ar, 2);
+ for (var k = 0; k < l.length; k++) eval('l[k]('+arS+')');
+ }
+ }
+ } else if (hookType == FALTERNATE) {
+ optPm = ar[2];
+ arS = argToString(ar, 3);
+
+ if (typeof l == 'undefined' || (l = l.alt[pms[optPm-1-pmStart]]) == 'undefined') {
+ rtnVal = eval(fnHookTo+'('+arS+')');
+ } else {
+ rtnVal = eval('l('+arS+')');
+ }
+ } else if (hookType == FCHAIN) {
+ arS=argToString(ar,2);
+ l=l.chain;
+
+ for (k=l.length; k > 0; k--) if((rtnVal=eval('l[k-1]('+arS+')'))!=void(0)) break;
+ }
+
+ return rtnVal;
+}
+
+////////
+// OBJECT CONSTRUCTORS
+////////
+
+// Object for handling hooks.
+function FunctionReference() {
+ this.ovload = null;
+ this.before = new Array();
+ this.after = new Array();
+ this.alt = new Array();
+ this.chain = new Array();
+}
+
+// Object for simple access to the overLIB version used.
+// Examples: simpleversion:351 major:3 minor:5 revision:1
+function Info(version, prerelease) {
+ this.version = version;
+ this.prerelease = prerelease;
+
+ this.simpleversion = Math.round(this.version*100);
+ this.major = parseInt(this.simpleversion / 100);
+ this.minor = parseInt(this.simpleversion / 10) - this.major * 10;
+ this.revision = parseInt(this.simpleversion) - this.major * 100 - this.minor * 10;
+ this.meets = meets;
+}
+
+// checks for Core Version required
+function meets(reqdVersion) {
+ return (!reqdVersion) ? false : this.simpleversion >= Math.round(100*parseFloat(reqdVersion));
+}
+
+
+////////
+// STANDARD REGISTRATIONS
+////////
+registerHook("ol_content_simple", ol_content_simple, FALTERNATE, CSSOFF);
+registerHook("ol_content_caption", ol_content_caption, FALTERNATE, CSSOFF);
+registerHook("ol_content_background", ol_content_background, FALTERNATE, CSSOFF);
+registerHook("ol_content_simple", ol_content_simple, FALTERNATE, CSSCLASS);
+registerHook("ol_content_caption", ol_content_caption, FALTERNATE, CSSCLASS);
+registerHook("ol_content_background", ol_content_background, FALTERNATE, CSSCLASS);
+registerPostParseFunction(checkPositionFlags);
+registerHook("hideObject", nbspCleanup, FAFTER);
+registerHook("horizontalPlacement", horizontalPlacement, FCHAIN);
+registerHook("verticalPlacement", verticalPlacement, FCHAIN);
+if (olNs4||(olIe5&&isMac)||olKq) olLoaded=1;
+registerNoParameterCommands('sticky,autostatus,autostatuscap,fullhtml,hauto,vauto,closeclick,wrap,followmouse,mouseoff,compatmode');
+///////
+// ESTABLISH MOUSECAPTURING
+///////
+
+// Capture events, alt. diffuses the overlib function.
+var olCheckMouseCapture=true;
+if ((olNs4 || olNs6 || olIe4)) {
+ olMouseCapture();
+} else {
+ overlib = no_overlib;
+ nd = no_overlib;
+ ver3fix = true;
+}
diff --git a/src/plugins/block.t.php b/test/plugins/block.t.php
similarity index 70%
rename from src/plugins/block.t.php
rename to test/plugins/block.t.php
index ba62a09..d321953 100644
--- a/src/plugins/block.t.php
+++ b/test/plugins/block.t.php
@@ -15,7 +15,7 @@
* @author Sagi Bashari
* @copyright 2004 Sagi Bashari
* @copyright Elan Ruusamäe
- * @copyright Clemens Schwaighofer
+ * @copyright 2024 Clemens Schwaighofer
*/
/**
@@ -47,6 +47,17 @@ function smarty_gettext_strarg($str/*, $varargs... */)
return strtr($str, $tr);
}
+/**
+ * raise a notice for missing callable, indicates L10n functions where not loaded
+ *
+ * @param string $function
+ * @return void
+ */
+function reportL10nNotInitialized(string $function): void
+{
+ trigger_error("Missing " . $function . ", L10n::loadFunctions() called?", E_NOTICE);
+}
+
/**
* Smarty block function, provides gettext support for smarty.
*
@@ -64,103 +75,98 @@ function smarty_gettext_strarg($str/*, $varargs... */)
* - domain - Textdomain to be used, default if skipped (dgettext() instead of gettext())
* - context - gettext context. reserved for future use.
*
+ * @param array $params
+ * @param string $text
+ * @return string
*/
-
-// cs modified: __ calls instead of direct gettext calls
-
function smarty_block_t($params, $text)
{
if (!isset($text)) {
return $text;
}
- // set escape mode, default html escape
- if (isset($params['escape'])) {
- $escape = $params['escape'];
- unset($params['escape']);
- } else {
- $escape = 'html';
- }
+ $escape = 'html';
+ $plural = null;
+ $count = null;
+ $domain = null;
+ $context = null;
- // set plural parameters 'plural' and 'count'.
- if (isset($params['plural'])) {
- $plural = $params['plural'];
- unset($params['plural']);
-
- // set count
- if (isset($params['count'])) {
- $count = $params['count'];
- unset($params['count']);
+ foreach ($params as $_key => $_value) {
+ switch ($_key) {
+ // set escape mode, default html escape
+ case 'escape':
+ $escape = (string)$_value;
+ break;
+ // set plural parameters 'plural' and 'count'.
+ case 'plural':
+ $plural = $_value;
+ break;
+ // set count, only for plural, else ignored
+ case 'count':
+ $count = $_value;
+ break;
+ // get domain param
+ case 'domain':
+ $domain = (string)$_value;
+ break;
+ // get context param
+ case 'context':
+ $context = (string)$_value;
+ break;
}
}
- // get domain param
- if (isset($params['domain'])) {
- $domain = $params['domain'];
- unset($params['domain']);
- } else {
- $domain = null;
- }
-
- // get context param
- if (isset($params['context'])) {
- $context = $params['context'];
- unset($params['context']);
- } else {
- $context = null;
- }
-
// use plural if required parameters are set
if (isset($count) && isset($plural)) {
if (isset($domain) && isset($context)) {
if (is_callable('_dnpgettext')) {
$text = _dnpgettext($domain, $context, $text, $plural, $count);
- }/* elseif (is_callable('dnpgettext')) {
- $text = dnpgettext($domain, $context, $text, $plural, $count);
- } */
+ } else {
+ reportL10nNotInitialized('_dnpgettext');
+ }
} elseif (isset($domain)) {
if (is_callable('_dngettext')) {
$text = _dngettext($domain, $text, $plural, $count);
- } elseif (is_callable('dngettext')) {
- $text = dngettext($domain, $text, $plural, $count);
+ } else {
+ reportL10nNotInitialized('_dngettext');
}
} elseif (isset($context)) {
if (is_callable('_npgettext')) {
$text = _npgettext($context, $text, $plural, $count);
- }/* elseif (is_callable('npgettext')) {
- $text = npgettext($context, $text, $plural, $count);
- } */
+ } else {
+ reportL10nNotInitialized('_npgettext');
+ }
} else {
if (is_callable('_ngettext')) {
$text = _ngettext($text, $plural, $count);
- } elseif (is_callable('ngettext')) {
- $text = ngettext($text, $plural, $count);
+ } else {
+ reportL10nNotInitialized('_ngettext');
}
}
} else { // use normal
if (isset($domain) && isset($context)) {
if (is_callable('_dpgettext')) {
$text = _dpgettext($domain, $context, $text);
- }/* elseif (is_callable('dpgettext')) {
- $text = dpgettext($domain, $context, $text);
- } */
+ } else {
+ reportL10nNotInitialized('_dpgettext');
+ }
} elseif (isset($domain)) {
if (is_callable('_dgettext')) {
$text = _dgettext($domain, $text);
- } elseif (is_callable('dpgettext')) {
- $text = dgettext($domain, $text);
+ } else {
+ reportL10nNotInitialized('_dgettext');
}
} elseif (isset($context)) {
if (is_callable('_pgettext')) {
$text = _pgettext($context, $text);
- }/* elseif (is_callable('pgettext')) {
- $text = pgettext($context, $text);
- } */
+ } else {
+ reportL10nNotInitialized('_pgettext');
+ }
} else {
if (is_callable('_gettext')) {
$text = _gettext($text);
- } elseif (is_callable('gettext')) {
- $text = gettext($text);
+ } else {
+ reportL10nNotInitialized('_gettext');
}
}
}
diff --git a/test/plugins/function.popup.php b/test/plugins/function.popup.php
new file mode 100644
index 0000000..df40eea
--- /dev/null
+++ b/test/plugins/function.popup.php
@@ -0,0 +1,124 @@
+
+ * Name: popup
+ * Purpose: make text pop up in windows via overlib
+ * @author Monte Ohrt
+ * @author 2024 Clemens Schwaighofer
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_popup($params, &$smarty)
+{
+ $append = '';
+ foreach ($params as $_key => $_value) {
+ switch ($_key) {
+ case 'text':
+ case 'trigger':
+ case 'function':
+ case 'inarray':
+ $$_key = (string)$_value;
+ if ($_key == 'function' || $_key == 'inarray') {
+ $append .= ',' . strtoupper($_key) . ",'$_value'";
+ }
+ break;
+
+ case 'caption':
+ case 'closetext':
+ case 'status':
+ $append .= ',' . strtoupper($_key) . ",'" . str_replace("'", "\'", $_value) . "'";
+ break;
+
+ case 'fgcolor':
+ case 'bgcolor':
+ case 'textcolor':
+ case 'capcolor':
+ case 'closecolor':
+ case 'textfont':
+ case 'captionfont':
+ case 'closefont':
+ case 'fgbackground':
+ case 'bgbackground':
+ case 'caparray':
+ case 'capicon':
+ case 'background':
+ case 'frame':
+ $append .= ',' . strtoupper($_key) . ",'$_value'";
+ break;
+
+ case 'textsize':
+ case 'captionsize':
+ case 'closesize':
+ case 'width':
+ case 'height':
+ case 'border':
+ case 'offsetx':
+ case 'offsety':
+ case 'snapx':
+ case 'snapy':
+ case 'fixx':
+ case 'fixy':
+ case 'padx':
+ case 'pady':
+ case 'timeout':
+ case 'delay':
+ $append .= ',' . strtoupper($_key) . ",$_value";
+ break;
+
+ case 'sticky':
+ case 'left':
+ case 'right':
+ case 'center':
+ case 'above':
+ case 'below':
+ case 'noclose':
+ case 'autostatus':
+ case 'autostatuscap':
+ case 'fullhtml':
+ case 'hauto':
+ case 'vauto':
+ case 'mouseoff':
+ case 'followmouse':
+ case 'closeclick':
+ if ($_value) {
+ $append .= ',' . strtoupper($_key);
+ }
+ break;
+
+ default:
+ $smarty->trigger_error("[popup] unknown parameter $_key", E_USER_WARNING);
+ }
+ }
+
+ if (empty($text) && !isset($inarray) && empty($function)) {
+ $smarty->trigger_error("overlib: attribute 'text' or 'inarray' or 'function' required");
+ return false;
+ }
+
+ if (empty($trigger)) {
+ $trigger = "onmouseover";
+ }
+
+ $retval = $trigger
+ . '="return overlib(\'' . preg_replace(array("!'!", "![\r\n]!"), array("\'", '\r'), $text) . '\'';
+ $retval .= $append . ');"';
+ if ($trigger == 'onmouseover') {
+ $retval .= ' onmouseout="nd();"';
+ }
+
+
+ return $retval;
+}
+
+// __END__
diff --git a/test/plugins/function.popup_init.php b/test/plugins/function.popup_init.php
new file mode 100644
index 0000000..43598eb
--- /dev/null
+++ b/test/plugins/function.popup_init.php
@@ -0,0 +1,44 @@
+
+ * Name: popup_init
+ * Purpose: initialize overlib
+ * @author Monte Ohrt
+ * @author 2024 Clemens Schwaighofer
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_popup_init($params, &$smarty)
+{
+ /* $zindex = 1000;
+
+ if (!empty($params['zindex'])) {
+ $zindex = $params['zindex'];
+ } */
+
+ if (!empty($params['src'])) {
+ return str_replace(
+ [/*"{ZINDEX}", */"{SCRIPT_SOURCE}"],
+ [/*$zindex, */$params['src']],
+ //
+ <<
+ HTML
+ );
+ } else {
+ $smarty->trigger_error("popup_init: missing src parameter");
+ }
+}
+
+// __END__
diff --git a/test/tmp/.gitignore b/test/tmp/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/test/tmp/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/tools/phpunit b/tools/phpunit
new file mode 120000
index 0000000..f1897d5
--- /dev/null
+++ b/tools/phpunit
@@ -0,0 +1 @@
+/home/clemens/.phive/phars/phpunit-10.3.5.phar
\ No newline at end of file
diff --git a/update/ReadMe.md b/update/ReadMe.md
new file mode 100644
index 0000000..8a687d5
--- /dev/null
+++ b/update/ReadMe.md
@@ -0,0 +1,15 @@
+# Files in this folder must be copied or merged over
+
+The following files can be copied as is
+
+- `src/BlockHandler/T.php`
+- `src/FunctionHandler/Popup.php`
+- `src/FunctionHandler/PopupInit.php`
+
+The following files need to be checkd for changes.
+
+If no changes they can be copied, else merged
+
+- `src/FunctionHandler/HtmlCheckboxes.php`
+- `src/FunctionHandler/HtmlOptions.php`
+- `src/Extensions/DefaultExtensions.php`
diff --git a/update/src/BlockHandler/T.php b/update/src/BlockHandler/T.php
new file mode 100644
index 0000000..d04ea6a
--- /dev/null
+++ b/update/src/BlockHandler/T.php
@@ -0,0 +1,238 @@
+
+ * @throws \Smarty\Exception
+ */
+class T implements BlockHandlerInterface
+{
+ /**
+ * Replaces arguments in a string with their values.
+ * Arguments are represented by % followed by their number.
+ *
+ * @param string $str Source string
+ * @param mixed mixed Arguments, can be passed in an array or through single variables.
+ * @return string Modified string
+ */
+ private function smartyGettextStrArg($str/*, $varargs... */)
+ {
+ $tr = [];
+ $p = 0;
+
+ $nargs = func_num_args();
+ for ($i = 1; $i < $nargs; $i++) {
+ $arg = func_get_arg($i);
+
+ if (is_array($arg)) {
+ foreach ($arg as $aarg) {
+ $tr['%' . ++$p] = $aarg;
+ }
+ } else {
+ $tr['%' . ++$p] = $arg;
+ }
+ }
+
+ return strtr($str, $tr);
+ }
+
+ /**
+ * raise a notice for missing callable, indicates L10n functions where not loaded
+ *
+ * @param string $function
+ * @return void
+ */
+ private function reportL10nNotInitialized(string $function): void
+ {
+ trigger_error("Missing " . $function . ", L10n::loadFunctions() called?", E_NOTICE);
+ }
+
+ /**
+ * main handler
+ *
+ * @param array $params
+ * @param string $content
+ * @param Template $template
+ * @param boolean $repeat
+ * @return void
+ */
+ public function handle($params, $content, Template $template, &$repeat)
+ {
+ if (is_null($content)) {
+ return;
+ }
+
+ $escape = 'html';
+ $plural = null;
+ $count = null;
+ $domain = null;
+ $context = null;
+
+ foreach ($params as $_key => $_value) {
+ switch ($_key) {
+ // set escape mode, default html escape
+ case 'escape':
+ $escape = (string)$_value;
+ break;
+ // set plural parameters 'plural' and 'count'.
+ case 'plural':
+ $plural = $_value;
+ break;
+ // set count, only for plural, else ignored
+ case 'count':
+ $count = $_value;
+ break;
+ // get domain param
+ case 'domain':
+ $domain = (string)$_value;
+ break;
+ // get context param
+ case 'context':
+ $context = (string)$_value;
+ break;
+ }
+ }
+
+ // use plural if required parameters are set
+ if (isset($count) && isset($plural)) {
+ // plural calls
+ if (isset($domain) && isset($context)) {
+ if (is_callable('_dnpgettext')) {
+ $content = _dnpgettext($domain, $context, $content, $plural, $count);
+ } else {
+ $this->reportL10nNotInitialized('_dnpgettext');
+ }
+ } elseif (isset($domain)) {
+ if (is_callable('_dngettext')) {
+ $content = _dngettext($domain, $content, $plural, $count);
+ } else {
+ $this->reportL10nNotInitialized('_dngettext');
+ }
+ } elseif (isset($context)) {
+ if (is_callable('_npgettext')) {
+ $content = _npgettext($context, $content, $plural, $count);
+ } else {
+ $this->reportL10nNotInitialized('_npgettext');
+ }
+ } else {
+ if (is_callable('_ngettext')) {
+ $content = _ngettext($content, $plural, $count);
+ } else {
+ $this->reportL10nNotInitialized('_ngettext');
+ }
+ }
+ } else {
+ // use normal
+ if (isset($domain) && isset($context)) {
+ if (is_callable('_dpgettext')) {
+ $content = _dpgettext($domain, $context, $content);
+ } else {
+ $this->reportL10nNotInitialized('_dpgettext');
+ }
+ } elseif (isset($domain)) {
+ if (is_callable('_dgettext')) {
+ $content = _dgettext($domain, $content);
+ } else {
+ $this->reportL10nNotInitialized('_dgettext');
+ }
+ } elseif (isset($context)) {
+ if (is_callable('_pgettext')) {
+ $content = _pgettext($context, $content);
+ } else {
+ $this->reportL10nNotInitialized('_pgettext');
+ }
+ } else {
+ if (is_callable('_gettext')) {
+ $content = _gettext($content);
+ } else {
+ $this->reportL10nNotInitialized('_gettext');
+ }
+ }
+ }
+
+ // run strarg if there are parameters
+ if (count($params)) {
+ $content = $this->smartyGettextStrArg($content, $params);
+ }
+
+ switch ($escape) {
+ case 'html':
+ // default
+ $content = nl2br(htmlspecialchars($content));
+ break;
+ case 'javascript':
+ case 'js':
+ // javascript escape
+ $content = strtr(
+ $content,
+ [
+ '\\' => '\\\\',
+ "'" => "\\'",
+ '"' => '\\"',
+ "\r" => '\\r',
+ "\n" => '\\n',
+ '' => '<\/'
+ ]
+ );
+ break;
+ case 'url':
+ // url escape
+ $content = urlencode($content);
+ break;
+ // below is a list for explicit OFF
+ case 'no':
+ case 'off':
+ case 'false':
+ case '0':
+ case 0:
+ // explicit OFF
+ default:
+ break;
+ }
+
+ return $content;
+ }
+
+ public function isCacheable(): bool
+ {
+ return true;
+ }
+}
+
+// __END__
diff --git a/update/src/Extensions/DefaultExtension.php b/update/src/Extensions/DefaultExtension.php
new file mode 100644
index 0000000..156e4ec
--- /dev/null
+++ b/update/src/Extensions/DefaultExtension.php
@@ -0,0 +1,760 @@
+modifiers[$modifier])) {
+ return $this->modifiers[$modifier];
+ }
+
+ switch ($modifier) {
+ case 'cat': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\CatModifierCompiler(); break;
+ case 'count_characters': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\CountCharactersModifierCompiler(); break;
+ case 'count_paragraphs': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\CountParagraphsModifierCompiler(); break;
+ case 'count_sentences': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\CountSentencesModifierCompiler(); break;
+ case 'count_words': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\CountWordsModifierCompiler(); break;
+ case 'default': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\DefaultModifierCompiler(); break;
+ case 'empty': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\EmptyModifierCompiler(); break;
+ case 'escape': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\EscapeModifierCompiler(); break;
+ case 'from_charset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\FromCharsetModifierCompiler(); break;
+ case 'indent': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\IndentModifierCompiler(); break;
+ case 'is_array': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\IsArrayModifierCompiler(); break;
+ case 'isset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\IssetModifierCompiler(); break;
+ case 'json_encode': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\JsonEncodeModifierCompiler(); break;
+ case 'lower': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\LowerModifierCompiler(); break;
+ case 'nl2br': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\Nl2brModifierCompiler(); break;
+ case 'noprint': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\NoPrintModifierCompiler(); break;
+ case 'raw': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\RawModifierCompiler(); break;
+ case 'round': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\RoundModifierCompiler(); break;
+ case 'str_repeat': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StrRepeatModifierCompiler(); break;
+ case 'string_format': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StringFormatModifierCompiler(); break;
+ case 'strip': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StripModifierCompiler(); break;
+ case 'strip_tags': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StripTagsModifierCompiler(); break;
+ case 'strlen': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StrlenModifierCompiler(); break;
+ case 'substr': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\SubstrModifierCompiler(); break;
+ case 'to_charset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\ToCharsetModifierCompiler(); break;
+ case 'unescape': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\UnescapeModifierCompiler(); break;
+ case 'upper': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\UpperModifierCompiler(); break;
+ case 'wordwrap': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\WordWrapModifierCompiler(); break;
+ }
+
+ return $this->modifiers[$modifier] ?? null;
+ }
+
+ public function getModifierCallback(string $modifierName) {
+ switch ($modifierName) {
+ case 'capitalize': return [$this, 'smarty_modifier_capitalize'];
+ case 'count': return [$this, 'smarty_modifier_count'];
+ case 'date_format': return [$this, 'smarty_modifier_date_format'];
+ case 'debug_print_var': return [$this, 'smarty_modifier_debug_print_var'];
+ case 'escape': return [$this, 'smarty_modifier_escape'];
+ case 'explode': return [$this, 'smarty_modifier_explode'];
+ case 'implode': return [$this, 'smarty_modifier_implode'];
+ case 'in_array': return [$this, 'smarty_modifier_in_array'];
+ case 'join': return [$this, 'smarty_modifier_join'];
+ case 'mb_wordwrap': return [$this, 'smarty_modifier_mb_wordwrap'];
+ case 'number_format': return [$this, 'smarty_modifier_number_format'];
+ case 'regex_replace': return [$this, 'smarty_modifier_regex_replace'];
+ case 'replace': return [$this, 'smarty_modifier_replace'];
+ case 'spacify': return [$this, 'smarty_modifier_spacify'];
+ case 'split': return [$this, 'smarty_modifier_split'];
+ case 'truncate': return [$this, 'smarty_modifier_truncate'];
+ }
+ return null;
+ }
+
+ public function getFunctionHandler(string $functionName): ?\Smarty\FunctionHandler\FunctionHandlerInterface {
+
+ if (isset($this->functionHandlers[$functionName])) {
+ return $this->functionHandlers[$functionName];
+ }
+
+ switch ($functionName) {
+ case 'count': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Count(); break;
+ case 'counter': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Counter(); break;
+ case 'cycle': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Cycle(); break;
+ case 'fetch': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Fetch(); break;
+ case 'html_checkboxes': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlCheckboxes(); break;
+ case 'html_image': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlImage(); break;
+ case 'html_options': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlOptions(); break;
+ case 'html_radios': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlRadios(); break;
+ case 'html_select_date': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlSelectDate(); break;
+ case 'html_select_time': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlSelectTime(); break;
+ case 'html_table': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlTable(); break;
+ case 'mailto': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Mailto(); break;
+ case 'math': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Math(); break;
+ case 'popup_init': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\PopupInit(); break;
+ case 'popup': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Popup(); break;
+ }
+
+ return $this->functionHandlers[$functionName] ?? null;
+ }
+
+ public function getBlockHandler(string $blockTagName): ?\Smarty\BlockHandler\BlockHandlerInterface {
+
+ switch ($blockTagName) {
+ case 'textformat': $this->blockHandlers[$blockTagName] = new \Smarty\BlockHandler\TextFormat(); break;
+ case 't': $this->blockHandlers[$blockTagName] = new \Smarty\BlockHandler\T(); break;
+ }
+
+ return $this->blockHandlers[$blockTagName] ?? null;
+ }
+
+ /**
+ * Smarty spacify modifier plugin
+ * Type: modifier
+ * Name: spacify
+ * Purpose: add spaces between characters in a string
+ *
+ * @author Monte Ohrt
+ *
+ * @param string $string input string
+ * @param string $spacify_char string to insert between characters.
+ *
+ * @return string
+ */
+ public function smarty_modifier_spacify($string, $spacify_char = ' ')
+ {
+ // well… what about charsets besides latin and UTF-8?
+ return implode($spacify_char, preg_split('//' . \Smarty\Smarty::$_UTF8_MODIFIER, $string, -1, PREG_SPLIT_NO_EMPTY));
+ }
+
+ /**
+ * Smarty capitalize modifier plugin
+ * Type: modifier
+ * Name: capitalize
+ * Purpose: capitalize words in the string
+ * {@internal {$string|capitalize:true:true} is the fastest option for MBString enabled systems }}
+ *
+ * @param string $string string to capitalize
+ * @param boolean $uc_digits also capitalize "x123" to "X123"
+ * @param boolean $lc_rest capitalize first letters, lowercase all following letters "aAa" to "Aaa"
+ *
+ * @return string capitalized string
+ * @author Monte Ohrt
+ * @author Rodney Rehm
+ */
+ public function smarty_modifier_capitalize($string, $uc_digits = false, $lc_rest = false)
+ {
+ $string = (string) $string;
+
+ if ($lc_rest) {
+ // uppercase (including hyphenated words)
+ $upper_string = mb_convert_case($string, MB_CASE_TITLE, \Smarty\Smarty::$_CHARSET);
+ } else {
+ // uppercase word breaks
+ $upper_string = preg_replace_callback(
+ "!(^|[^\p{L}'])([\p{Ll}])!S" . \Smarty\Smarty::$_UTF8_MODIFIER,
+ function ($matches) {
+ return stripslashes($matches[1]) .
+ mb_convert_case(stripslashes($matches[2]), MB_CASE_UPPER, \Smarty\Smarty::$_CHARSET);
+ },
+ $string
+ );
+ }
+ // check uc_digits case
+ if (!$uc_digits) {
+ if (preg_match_all(
+ "!\b([\p{L}]*[\p{N}]+[\p{L}]*)\b!" . \Smarty\Smarty::$_UTF8_MODIFIER,
+ $string,
+ $matches,
+ PREG_OFFSET_CAPTURE
+ )
+ ) {
+ foreach ($matches[ 1 ] as $match) {
+ $upper_string =
+ substr_replace(
+ $upper_string,
+ mb_strtolower($match[ 0 ], \Smarty\Smarty::$_CHARSET),
+ $match[ 1 ],
+ strlen($match[ 0 ])
+ );
+ }
+ }
+ }
+ $upper_string =
+ preg_replace_callback(
+ "!((^|\s)['\"])(\w)!" . \Smarty\Smarty::$_UTF8_MODIFIER,
+ function ($matches) {
+ return stripslashes(
+ $matches[ 1 ]) . mb_convert_case(stripslashes($matches[ 3 ]),
+ MB_CASE_UPPER,
+ \Smarty\Smarty::$_CHARSET
+ );
+ },
+ $upper_string
+ );
+ return $upper_string;
+ }
+
+ /**
+ * Smarty count modifier plugin
+ * Type: modifier
+ * Name: count
+ * Purpose: counts all elements in an array or in a Countable object
+ * Input:
+ * - Countable|array: array or object to count
+ * - mode: int defaults to 0 for normal count mode, if set to 1 counts recursive
+ *
+ * @param mixed $arrayOrObject input array/object
+ * @param int $mode count mode
+ *
+ * @return int
+ */
+ public function smarty_modifier_count($arrayOrObject, $mode = 0) {
+ /*
+ * @see https://www.php.net/count
+ * > Prior to PHP 8.0.0, if the parameter was neither an array nor an object that implements the Countable interface,
+ * > 1 would be returned, unless value was null, in which case 0 would be returned.
+ */
+
+ if ($arrayOrObject instanceof \Countable || is_array($arrayOrObject)) {
+ return count($arrayOrObject, (int) $mode);
+ } elseif ($arrayOrObject === null) {
+ return 0;
+ }
+ return 1;
+ }
+
+ /**
+ * Smarty date_format modifier plugin
+ * Type: modifier
+ * Name: date_format
+ * Purpose: format datestamps via strftime
+ * Input:
+ * - string: input date string
+ * - format: strftime format for output
+ * - default_date: default date if $string is empty
+ *
+ * @author Monte Ohrt
+ *
+ * @param string $string input date string
+ * @param string $format strftime format for output
+ * @param string $default_date default date if $string is empty
+ * @param string $formatter either 'strftime' or 'auto'
+ *
+ * @return string |void
+ * @uses smarty_make_timestamp()
+ */
+ public function smarty_modifier_date_format($string, $format = null, $default_date = '', $formatter = 'auto')
+ {
+ if ($format === null) {
+ $format = \Smarty\Smarty::$_DATE_FORMAT;
+ }
+
+ if (!empty($string) && $string !== '0000-00-00' && $string !== '0000-00-00 00:00:00') {
+ $timestamp = smarty_make_timestamp($string);
+ } elseif (!empty($default_date)) {
+ $timestamp = smarty_make_timestamp($default_date);
+ } else {
+ return;
+ }
+ if ($formatter === 'strftime' || ($formatter === 'auto' && strpos($format, '%') !== false)) {
+ if (\Smarty\Smarty::$_IS_WINDOWS) {
+ $_win_from = array(
+ '%D',
+ '%h',
+ '%n',
+ '%r',
+ '%R',
+ '%t',
+ '%T'
+ );
+ $_win_to = array(
+ '%m/%d/%y',
+ '%b',
+ "\n",
+ '%I:%M:%S %p',
+ '%H:%M',
+ "\t",
+ '%H:%M:%S'
+ );
+ if (strpos($format, '%e') !== false) {
+ $_win_from[] = '%e';
+ $_win_to[] = sprintf('%\' 2d', date('j', $timestamp));
+ }
+ if (strpos($format, '%l') !== false) {
+ $_win_from[] = '%l';
+ $_win_to[] = sprintf('%\' 2d', date('h', $timestamp));
+ }
+ $format = str_replace($_win_from, $_win_to, $format);
+ }
+ // @ to suppress deprecation errors when running in PHP8.1 or higher.
+ return @strftime($format, $timestamp);
+ } else {
+ return date($format, $timestamp);
+ }
+ }
+
+ /**
+ * Smarty debug_print_var modifier plugin
+ * Type: modifier
+ * Name: debug_print_var
+ * Purpose: formats variable contents for display in the console
+ *
+ * @author Monte Ohrt
+ *
+ * @param array|object $var variable to be formatted
+ * @param int $max maximum recursion depth if $var is an array or object
+ * @param int $length maximum string length if $var is a string
+ * @param int $depth actual recursion depth
+ * @param array $objects processed objects in actual depth to prevent recursive object processing
+ *
+ * @return string
+ */
+ public function smarty_modifier_debug_print_var($var, $max = 10, $length = 40, $depth = 0, $objects = array())
+ {
+ $_replace = array("\n" => '\n', "\r" => '\r', "\t" => '\t');
+ switch (gettype($var)) {
+ case 'array':
+ $results = 'Array (' . count($var) . ')';
+ if ($depth === $max) {
+ break;
+ }
+ foreach ($var as $curr_key => $curr_val) {
+ $results .= '
' . str_repeat(' ', $depth * 2) . '' . strtr($curr_key, $_replace) .
+ ' => ' .
+ $this->smarty_modifier_debug_print_var($curr_val, $max, $length, ++$depth, $objects);
+ $depth--;
+ }
+ break;
+ case 'object':
+ $object_vars = get_object_vars($var);
+ $results = '' . get_class($var) . ' Object (' . count($object_vars) . ')';
+ if (in_array($var, $objects)) {
+ $results .= ' called recursive';
+ break;
+ }
+ if ($depth === $max) {
+ break;
+ }
+ $objects[] = $var;
+ foreach ($object_vars as $curr_key => $curr_val) {
+ $results .= '
' . str_repeat(' ', $depth * 2) . ' ->' . strtr($curr_key, $_replace) .
+ ' = ' . $this->smarty_modifier_debug_print_var($curr_val, $max, $length, ++$depth, $objects);
+ $depth--;
+ }
+ break;
+ case 'boolean':
+ case 'NULL':
+ case 'resource':
+ if (true === $var) {
+ $results = 'true';
+ } elseif (false === $var) {
+ $results = 'false';
+ } elseif (null === $var) {
+ $results = 'null';
+ } else {
+ $results = htmlspecialchars((string)$var);
+ }
+ $results = '' . $results . '';
+ break;
+ case 'integer':
+ case 'float':
+ $results = htmlspecialchars((string)$var);
+ break;
+ case 'string':
+ $results = strtr($var, $_replace);
+ if (mb_strlen($var, \Smarty\Smarty::$_CHARSET) > $length) {
+ $results = mb_substr($var, 0, $length - 3, \Smarty\Smarty::$_CHARSET) . '...';
+ }
+ $results = htmlspecialchars('"' . $results . '"', ENT_QUOTES, \Smarty\Smarty::$_CHARSET);
+ break;
+ case 'unknown type':
+ default:
+ $results = strtr((string)$var, $_replace);
+ if (mb_strlen($results, \Smarty\Smarty::$_CHARSET) > $length) {
+ $results = mb_substr($results, 0, $length - 3, \Smarty\Smarty::$_CHARSET) . '...';
+ }
+ $results = htmlspecialchars($results, ENT_QUOTES, \Smarty\Smarty::$_CHARSET);
+ }
+ return $results;
+ }
+
+ /**
+ * Smarty escape modifier plugin
+ * Type: modifier
+ * Name: escape
+ * Purpose: escape string for output
+ *
+ * @author Monte Ohrt
+ *
+ * @param string $string input string
+ * @param string $esc_type escape type
+ * @param string $char_set character set, used for htmlspecialchars() or htmlentities()
+ * @param boolean $double_encode encode already encoded entitites again, used for htmlspecialchars() or htmlentities()
+ *
+ * @return string escaped input string
+ */
+ public function smarty_modifier_escape($string, $esc_type = 'html', $char_set = null, $double_encode = true)
+ {
+ if (!$char_set) {
+ $char_set = \Smarty\Smarty::$_CHARSET;
+ }
+
+ $string = (string)$string;
+
+ switch ($esc_type) {
+ case 'html':
+ return htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode);
+ // no break
+ case 'htmlall':
+ $string = mb_convert_encoding($string, 'UTF-8', $char_set);
+ return htmlentities($string, ENT_QUOTES, 'UTF-8', $double_encode);
+ // no break
+ case 'url':
+ return rawurlencode($string);
+ case 'urlpathinfo':
+ return str_replace('%2F', '/', rawurlencode($string));
+ case 'quotes':
+ // escape unescaped single quotes
+ return preg_replace("%(?mb_to_unicode($string, \Smarty\Smarty::$_CHARSET) as $unicode) {
+ $return .= '' . strtoupper(dechex($unicode)) . ';';
+ }
+ return $return;
+ case 'decentity':
+ $return = '';
+ foreach ($this->mb_to_unicode($string, \Smarty\Smarty::$_CHARSET) as $unicode) {
+ $return .= '' . $unicode . ';';
+ }
+ return $return;
+ case 'javascript':
+ // escape quotes and backslashes, newlines, etc.
+ return strtr(
+ $string,
+ array(
+ '\\' => '\\\\',
+ "'" => "\\'",
+ '"' => '\\"',
+ "\r" => '\\r',
+ "\n" => '\\n',
+ '' => '<\/',
+ // see https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements
+ '