Index: branches/5.0.x/themes/default2009/platform/designs/default_design.des.tpl =================================================================== --- branches/5.0.x/themes/default2009/platform/designs/default_design.des.tpl (revision 12297) +++ branches/5.0.x/themes/default2009/platform/designs/default_design.des.tpl (revision 12298) @@ -1,123 +1,123 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <inp2:m_CheckSSL/> <inp2:m_include template="platform/elements/side_boxes.elm" strip_nl="1"/> <inp2:m_include template="platform/elements/content_boxes.elm" strip_nl="1"/> <inp2:m_include template="platform/elements/forms.elm" strip_nl="1"/> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <inp2:m_DefineElement name="cms_page_title"> <inp2:st_PageInfo type="htmlhead_title"/> </inp2:m_DefineElement> <title><inp2:m_GetConfig name="Site_Name"/> :: <inp2:m_RenderElement name="page_title" default_element="cms_page_title" no_editing="1"/></title> <!--## Include module specific HEADER (META INFORMATION inside) template ##--> <inp2:m_ModuleInclude template="elements/html_head.elm" in-portal_template="platform/elements/html_head.elm"/> <inp2:st_EditingScripts/> <!--## /Include module specific HEADER template ##--> </head> <body> <inp2:st_EditPage mode="start"/> <div align="left"> <div align="left" style="width:100%"> <table class="fullwidth"> <tr> <td> <inp2:m_include template="platform/elements/header.elm"/> </td> </tr> <tr> <td> <inp2:m_include template="platform/elements/menu.elm"/> </td> </tr> </table> <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/s.gif" width="1" height="1" alt=""/><br /> <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/grey_pix.gif" width="100%" height="1" alt=""/><br /> <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/s.gif" width="1" height="1" alt=""/><br /> <table class="fullwidth"> <tr> <!-- SIDEBAR --> <td style="width: 200px;" valign="top"> <inp2:m_DefineElement name="cms_sidebar"> <div class="movable-area"> <div class="movable-element"> <inp2:m_RenderElement name="platform/elements/side_boxes/login.elm" design="blue_box"/> </div> <div class="movable-element"> <inp2:m_RenderElement name="platform/elements/side_boxes/search.elm" design="blue_box"/> </div> </div> </inp2:m_DefineElement> - <inp2:m_RenderElement name="sidebar" default_element="cms_sidebar" layout_view="1"/> + <inp2:m_RenderElement name="sidebar" default_element="cms_sidebar"/> </td> <!-- /SIDEBAR --> <!-- SEPARATOR --> <td width="3" class="vertical-separator" style="width: 3px;"> <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/s.gif" width="3" height="1" alt=""/><br /> </td> <!-- /SEPARATOR --> <!-- CONTENT --> <td style="width: auto;" valign="top"> <inp2:m_DefineElement name="cms_content"> <div class="movable-area"> <div class="movable-element"> <inp2:m_include template="platform/elements/navigation_bar.elm"/> </div> <div class="movable-element"> <inp2:m_RenderElement design="content_box"> <inp2:m_Capture to_var="header"> <inp2:st_PageInfo type="title"/> </inp2:m_Capture> <inp2:st_ContentBlock num="1"/> </inp2:m_RenderElement> </div> </div> </inp2:m_DefineElement> - <inp2:m_RenderElement name="content" default_element="cms_content" layout_view="1"/> + <inp2:m_RenderElement name="content" default_element="cms_content"/> <br /> </td> <!-- /CONTENT --> <!--## REMOVE THIS LINE TO UNCOMMENT <!-- SEPARATOR --> <td width="3" class="vertical-separator"> <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/s.gif" width="3" height="1" alt=""/><br /> </td> <!-- /SEPARATOR --> <!-- RIGHT-SIDEBAR WITH BANNER --> <td style="width: 200px;" valign="top"> <div class="movable-area"> <div class="movable-element"> <inp2:m_include template="platform/elements/banners/banner_right.elm"/> </div> </div> </td> <!-- /RIGHT-SIDEBAR WITH BANNER --> REMOVE THIS LINE TO UNCOMMENT ##--> </tr> </table> <table class="fullwidth"> <tr> <td > <inp2:m_include template="platform/elements/footer.elm"/> </td> </tr> </table> </div> </div> <inp2:st_EditPage mode="end"/> </body> </html> \ No newline at end of file Index: branches/5.0.x/themes/default2009/platform/elements/side_boxes/search.elm.tpl =================================================================== --- branches/5.0.x/themes/default2009/platform/elements/side_boxes/search.elm.tpl (revision 12297) +++ branches/5.0.x/themes/default2009/platform/elements/side_boxes/search.elm.tpl (revision 12298) @@ -1,51 +1,51 @@ <inp2:m_Capture to_var="header"> <inp2:m_phrase name="lu_title_SearchBox"/> </inp2:m_Capture> <form method="post" action="<inp2:m_Link template="platform/search/search_results" pass_category="1"/>"> <inp2:m_GetFormHiddens template="platform/search/search_results"/> <table> <tr> <td colspan="2"> <input type="text" name="keywords" id="keywords" style="width: 155px;" class="input-text" value="" /> </td> </tr> <!--## Show only when not on home ##--> <inp2:m_if check="m_GetEquals" var="m_cat_id" value="0" inverse="1"> <tr> <td> <input type="radio" name="search_scope" id="search_scope_any" value="any" checked /> </td> <td> <label for="search_scope_any"><inp2:m_Phrase name="lu_AllWebsite"/></label> </td> </tr> <tr> <td> <input type="radio" name="search_scope" id="search_scope_category" value="category"/> </td> <td> <label for="search_scope_category"><inp2:m_Phrase name="lu_ThisCategory"/></label> </td> </tr> </inp2:m_if> <!--## // Show only when not on home ##--> </table> <br /> - <input class="button" type="submit" value="<inp2:m_Phrase label="lu_btn_FindIt"/>!" /> + <input class="button" type="submit" value="<inp2:m_Phrase label='lu_btn_FindIt' no_editing='1'/>!" /> <!--## <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/s.gif" alt="" width="1" height="10" border="0" /><br /> <table> <tr> <td width="10"> <input class="button" type="submit" style="width: 40px;" value="<inp2:m_Phrase label="lu_comm_Go"/>!" /> </td> <td align="left"> <a href="<inp2:m_Link template="platform/search/advanced_search" />" class="more-link"><inp2:m_Phrase label="lu_btn_AdvancedSearch"/></a> <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/side_link_str.gif" width="6" height="5" alt="" /><br /> </td> </tr> </table> ##--> </form> \ No newline at end of file Index: branches/5.0.x/themes/default2009/platform/elements/side_boxes/login.elm.tpl =================================================================== --- branches/5.0.x/themes/default2009/platform/elements/side_boxes/login.elm.tpl (revision 12297) +++ branches/5.0.x/themes/default2009/platform/elements/side_boxes/login.elm.tpl (revision 12298) @@ -1,125 +1,125 @@ <!-- LOGIN BOX TITLE --> <inp2:m_Capture to_var="header"> <table class="fullwidth"> <tr> <td class="side-box-title" align="left"> <inp2:m_phrase name="lu_title_LoginBox"/> </td> <td align="right" class="login-status"> <!-- IF LOGGED IN SHOW NAME --> <inp2:m_if check="m_LoggedIn"> <a href="<inp2:m_Link template="platform/my_account/my_profile" m_cat_id="0" m_cat_page="1"/>"><inp2:u_Field name="FirstName"/> <inp2:u_Field name="LastName"/></a><br /> <!-- /IF LOGGED IN SHOW NAME --> <inp2:m_else/> <table> <tr> <td width="11"> <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/not_logged.gif" alt="" width="11" height="11" border="0" /><br /> </td> <td class="login-status"> <inp2:m_Phrase label="lu_NotLoggedIn"/> </td> </tr> </table> </inp2:m_if> </td> </tr> </table> </inp2:m_Capture> <!-- /LOGIN BOX TITLE --> <!-- IF LOGGED! --> <inp2:m_if check="m_LoggedIn"> <table width="100%" style="border-width: 0px;"> <tr> <td colspan="2"><strong><inp2:m_phrase name="lu_section_MyAccount"/></strong></td> </tr> <!-- SHOW MY PROFILE --> <inp2:m_RenderElement name="box_element" template="platform/my_account/my_profile" title="lu_MyProfile"/> <!-- /SHOW MY PROFILE --> <!-- SHOW MY FAVORITES --> <inp2:m_RenderElement name="box_element" template="platform/my_account/my_favorites" title="lu_MyFavorites"/> <!-- /SHOW MY FAVORITES --> <!-- SHOW MY PREFERENCES --> <inp2:m_RenderElement name="box_element" template="platform/my_account/my_preferences" title="lu_MyPreferences"/> <!-- /SHOW MY PREFERENCES --> <!-- INCLUDE "themes/default2007/[MODULE_NAME]/my_account/my_items.elm.tpl" FOR EACH INSTALLED MODULE --> <inp2:m_ModuleInclude template="my_account/my_items.elm" place="sidebox" section="1"/> <!-- /INCLUDE "themes/[MODULE_NAME]/my_account/my_items.elm.tpl" FOR EACH INSTALLED MODULE --> <tr> <td> <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/menu-li-2-level.gif" alt="" width="4" height="4" border="0" /><br /> </td> <td> <a href="<inp2:u_LogoutLink template="index" />"><inp2:m_Phrase label="lu_logout"/></a> </td> </tr> <tr> <td colspan="2"> <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/s.gif" alt="" width="1" height="7" border="0" /><br /> </td> </tr> <tr> <td colspan="2"> <strong><inp2:m_phrase name="lu_section_MyItems"/></strong> </td> </tr> <inp2:m_ModuleInclude template="my_account/my_items.elm" place="sidebox" section="2"/> </table> <!-- /IF LOGGED --> <inp2:m_else/> <!-- IF NOT LOGGED IN! --> <form method="post" action="<inp2:m_FormAction />"> <inp2:m_if check="u_UseUsernames"> <inp2:m_phrase label="lu_username"/><br /> <input class="input-text" type="text" name="login" style="width:155px" /><br /> <inp2:m_else/> <inp2:m_phrase label="lu_email"/><br /> <input class="input-text" type="text" name="email" style="width:155px" /><br /> </inp2:m_if> <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/s.gif" width="1" height="5" alt=""/><br /> <inp2:m_Phrase label="lu_Password"/><br /> <input type="password" class="input-text" name="password" style="width:155px" /><br /> <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/s.gif" alt="" width="1" height="10" border="0" /><br /> <table> <tr> <td width="10"> - <input class="button" name="events[u][OnLogin]" type="submit" value="<inp2:m_Phrase label="lu_Login"/>" /><br /> + <input class="button" name="events[u][OnLogin]" type="submit" value="<inp2:m_Phrase label='lu_Login' no_editing='1'/>" /><br /> </td> <td align="left"> <input type="checkbox" name="cb_remember_login" value="1"/> <span class="remember-login"><inp2:m_Phrase label="lu_remember_login"/></span> </td> </tr> </table> <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/s.gif" alt="" width="5" height="5" border="0" /><br /> <inp2:m_if check="u_HasError" field="any"> <span class="field-error"><inp2:u_Error field="ValidateLogin"/></span><br /> </inp2:m_if> <inp2:m_if check="u_RegistrationEnabled"> <a href="<inp2:m_Link template="platform/login/register" m_cat_id="0" m_cat_page="1"/>" class="more-link" ><inp2:m_Phrase label="lu_Register"/></a> <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/side_link_str.gif" width="6" height="5" alt="" /><br /> </inp2:m_if> <a href="<inp2:m_Link template="platform/login/forgot_password" m_cat_id="0" m_cat_page="1"/>" class="more-link" ><inp2:m_Phrase label="lu_ForgotPassword"/>?</a> <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/side_link_str.gif" width="6" height="5" alt="" /> <input type="hidden" name="next_template" value="<inp2:m_get var="next_template"/>" /> <input type="hidden" name="pending_disabled_template" value="platform/login/login_pending_disabled" /> </form> </inp2:m_if> <!-- /IF NOT LOGGED IN --> Index: branches/5.0.x/themes/default2009/platform/elements/side_boxes/mailing_list.elm.tpl =================================================================== --- branches/5.0.x/themes/default2009/platform/elements/side_boxes/mailing_list.elm.tpl (revision 12297) +++ branches/5.0.x/themes/default2009/platform/elements/side_boxes/mailing_list.elm.tpl (revision 12298) @@ -1,21 +1,21 @@ -<inp2:m_Capture to_var="header"> - <inp2:m_phrase name="lu_title_MailingList"/> -</inp2:m_Capture> - -<inp2:m_Phrase label="lu_EnterEmailToSubscribe"/><br /> -<img src="<inp2:m_TemplatesBase module="In-Portal"/>img/s.gif" alt="" width="1" height="5" border="0" /><br /> - -<form method="POST" action="<inp2:m_FormAction />" name="mailing_list_form"> - <input type="text" name="subscriber_email" class="input-text" style="width: 155px;"/><br /> - <inp2:m_if check="u_HasError" field="any"> - <span class="field-error"><inp2:u_Error field="SubscribeEmail"/></span><br /> - </inp2:m_if> - - <br /> - <input class="button" name="events[u][OnSubscribeQuery]" type="submit" style="width: 90px;" value="<inp2:m_Phrase label="lu_btn_Subscribe"/>" /> - <input class="button" name="events[u][OnSubscribeQuery]" type="submit" style="width: 90px;" value="<inp2:m_Phrase label="lu_btn_Unsubscribe" />" /> - - <input type="text" style="display: none" /> - <input type="hidden" name="subscribe_template" value="platform/mailing_list/subscribe"/> - <input type="hidden" name="unsubscribe_template" value="platform/mailing_list/unsubscribe"/> -</form> +<inp2:m_Capture to_var="header"> + <inp2:m_phrase name="lu_title_MailingList"/> +</inp2:m_Capture> + +<inp2:m_Phrase label="lu_EnterEmailToSubscribe"/><br /> +<img src="<inp2:m_TemplatesBase module="In-Portal"/>img/s.gif" alt="" width="1" height="5" border="0" /><br /> + +<form method="POST" action="<inp2:m_FormAction />" name="mailing_list_form"> + <input type="text" name="subscriber_email" class="input-text" style="width: 155px;"/><br /> + <inp2:m_if check="u_HasError" field="any"> + <span class="field-error"><inp2:u_Error field="SubscribeEmail"/></span><br /> + </inp2:m_if> + + <br /> + <input class="button" name="events[u][OnSubscribeQuery]" type="submit" style="width: 90px;" value="<inp2:m_Phrase label='lu_btn_Subscribe' no_editing='1'/>" /> + <input class="button" name="events[u][OnSubscribeQuery]" type="submit" style="width: 90px;" value="<inp2:m_Phrase label='lu_btn_Unsubscribe' no_editing='1'/>" /> + + <input type="text" style="display: none" /> + <input type="hidden" name="subscribe_template" value="platform/mailing_list/subscribe"/> + <input type="hidden" name="unsubscribe_template" value="platform/mailing_list/unsubscribe"/> +</form> Index: branches/5.0.x/themes/default2009/platform/elements/side_boxes/recommend_site.elm.tpl =================================================================== --- branches/5.0.x/themes/default2009/platform/elements/side_boxes/recommend_site.elm.tpl (revision 12297) +++ branches/5.0.x/themes/default2009/platform/elements/side_boxes/recommend_site.elm.tpl (revision 12298) @@ -1,16 +1,16 @@ <inp2:m_Capture to_var="header"> <inp2:m_phrase name="lu_title_RecommendSite"/> </inp2:m_Capture> <inp2:m_Phrase label="lu_EnterEmailToRecommend"/><br /> <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/s.gif" alt="" width="1" height="5" border="0" /><br /> <form method="POST" action="<inp2:m_FormAction />"> <input type="text" class="input-text" name="friend_email" value="" style="width: 155px;" /><br /> <inp2:m_if check="u_HasError" field="any"> <span class="field-error"><inp2:u_Error field="Email"/></span><br /> </inp2:m_if> <br /> - <input class="button" name="events[u][OnRecommend]" type="submit" value="<inp2:m_Phrase label="lu_btn_Recommend"/>" /> + <input class="button" name="events[u][OnRecommend]" type="submit" value="<inp2:m_Phrase label='lu_btn_Recommend' no_editing='1'/>" /> <input type="hidden" name="template_success" value="platform/recommend/recommend" /> </form> \ No newline at end of file Index: branches/5.0.x/themes/default2009/platform/elements/html_head.elm.tpl =================================================================== --- branches/5.0.x/themes/default2009/platform/elements/html_head.elm.tpl (revision 12297) +++ branches/5.0.x/themes/default2009/platform/elements/html_head.elm.tpl (revision 12298) @@ -1,31 +1,31 @@ <!--## Meta Info (Keywords and Description) ##--> <meta http-equiv="Content-Type" content="text/html; charset=<inp2:lang.current_Field name="Charset"/>" /> <meta name="Description" content="<inp2:st_PageInfo type="meta_description"/>" /> <meta name="Keywords" content="<inp2:st_PageInfo type="meta_keywords"/>" /> <!--## /Meta Keywords and Description ##--> <inp2:theme.current_StylesheetFile/> <link rel="stylesheet" href="<inp2:m_TemplatesBase module='In-Portal'/>inc/jquery/thickbox/thickbox.css" type="text/css" media="screen" /> <link rel="stylesheet" rev="stylesheet" href="<inp2:m_TemplatesBase module='In-Portal'/>inc/styles.css" type="text/css" /> <script type="text/javascript" src="<inp2:m_TemplatesBase module='In-Portal'/>inc/script.js"></script> <script type="text/javascript" src="<inp2:m_TemplatesBase module='In-Portal'/>inc/ajax.js"></script> <script type="text/javascript" src="<inp2:m_TemplatesBase module='In-Portal'/>inc/calendar.js"></script> <script type="text/javascript">var inportalBase = '<inp2:m_TemplatesBase module="In-Portal"/>';</script> <script type="text/javascript" src="<inp2:m_TemplatesBase module='In-Portal'/>inc/jquery/jquery.pack.js"></script> <script type="text/javascript" src="<inp2:m_TemplatesBase module='In-Portal'/>inc/jquery/thickbox/thickbox.js"></script> <script type="text/javascript"> var aRatingManager = new RatingManager('<inp2:m_Link template="index" events[#PREFIX#]="OnMakeVote" rating="#VOTE#" id="#ID#" no_amp="1" size="#SIZE#"/>'); <inp2:m_DefineElement name="ml_selector_language_element"> <inp2:Field name="LanguageId"/>: {'on': '<inp2:Field name="IconURL" js_ecape="1"/>', 'off': '<inp2:Field name="IconDisabledURL" js_ecape="1"/>'} <inp2:m_ifnot check="m_Param" name="is_last">,</inp2:m_ifnot> </inp2:m_DefineElement> - var aMultiLanguageSelector = new MultiLanguageSelector({<inp2:lang.enabled_PrintList render_as="ml_selector_language_element" per_page="-1" strip_nl="2"/>}, <inp2:m_Get name="m_lang"/>); + var aMultiLanguageSelector = new MultiLanguageSelector({<inp2:lang.enabled_PrintList render_as="ml_selector_language_element" per_page="-1" no_editing="1" strip_nl="2"/>}, <inp2:m_Get name="m_lang"/>); </script> Index: branches/5.0.x/themes/default2009/platform/elements/menu.elm.tpl =================================================================== --- branches/5.0.x/themes/default2009/platform/elements/menu.elm.tpl (revision 12297) +++ branches/5.0.x/themes/default2009/platform/elements/menu.elm.tpl (revision 12298) @@ -1,104 +1,109 @@ <table class="menu-background fullwidth"> <tr> <td align="left"> <table style="width: auto;"> <tr> <td> <script type="text/javascript" src="<inp2:m_TemplatesBase module='In-Portal'/>inc/nlsmenu.js"></script> <script type="text/javascript" src="<inp2:m_TemplatesBase module='In-Portal'/>inc/nlsmenueffect.js"></script> <script type="text/javascript" src="<inp2:m_TemplatesBase module='In-Portal'/>inc/nlsmenuext_dyn.js"></script> <script type="text/javascript" src="<inp2:m_TemplatesBase module='In-Portal'/>inc/nlsmenuext_xml.js"></script> <link rel="StyleSheet" href="<inp2:m_TemplatesBase module='In-Portal'/>inc/dmenu.css" type="text/css" /> <div id="xmlMenuDiv"></div> <script type="text/javascript"> <inp2:m_DefineElement name="menu_xml" no_editing="1"> <menumgr id="mgr" flowoverformelement="false" defaulteffect="aoslide" icpath=""> <!--## USE droponclick="false" TO OPEN MENU ONMOUSE-OVER ##--> <menubar id="menubar" orient="H" showicon="true" showsubicon="false" stlprf="horz_" droponclick="true" > <items> <item id="sub-elem0" url="<inp2:m_Link template="index" m_cat_id="0" m_cat_page="1"/>" ico="['<inp2:m_TemplatesBase module="In-portal"/>img/menu_home.gif']" enb="true" title=""><![CDATA[<inp2:m_RootCategoryName/>]]></item> <inp2:m_Include template="platform/elements/menu_sections.xml" /> </items> </menubar> </menumgr> </inp2:m_DefineElement> <inp2:m_get name="m_cat_id" result_to_var="current_category"/> - addLoadEvent( + $(document).ready( function() { var menu_mgr = NlsMenuUtil.createFromXMLString('<inp2:m_RenderElement name="menu_xml" js_escape="1"/>'); // menu_mgr.renderMenus(); menu_mgr.renderMenubar('xmlMenuDiv'); + + <inp2:m_if check="m_GetConst" name="EDITING_MODE" equals_to="2"> + // make all spans with phrases clickable inside menus, that were just created + aTemplateManager.setupEditTranslationButtons('#xmlMenuDiv'); + </inp2:m_if> } ); </script> <noscript> <inp2:m_DefineElement name="static_top_menu_element"> <inp2:m_if check="m_Param" name="external_url"> <inp2:m_Param name="external_url" result_to_var="link"/> <inp2:m_else/> <inp2:m_Link template="$template" m_cat_id="$cat_id" m_cat_page="1" result_to_var="link"/> </inp2:m_if> <inp2:m_if check="m_Param" name="menu_icon"> <inp2:m_TemplatesBase result_to_var="module_path"/> <inp2:m_RenderElement name="menu_element" menu_href="$link" menu_title="$title" menu_icon_src="{$module_path}{$menu_icon}"/> <inp2:m_else/> <inp2:m_TemplatesBase module="In-Portal" result_to_var="module_path"/> <inp2:m_RenderElement name="menu_element" menu_href="$link" menu_title="$title" menu_icon_src="{$module_path}img/menu_inedit.gif"/> </inp2:m_if> </inp2:m_DefineElement> <table> <tr> <inp2:m_Link template="index" m_cat_id="0" m_cat_page="1" result_to_var="link"/> <inp2:m_RootCategoryName result_to_var="title"/> <inp2:m_TemplatesBase module="In-portal" result_to_var="module_path"/> <inp2:m_RenderElement name="menu_element" menu_href="$link" menu_title="$title" menu_icon_src="{$module_path}img/menu_home.gif"/> <inp2:st_CachedMenu level="0" category_id="0" render_as="static_top_menu_element"/> </tr> </table> </noscript> <inp2:m_Set m_cat_id="$current_category"/> <inp2:c_Field requery="1" name="Name" result_to_var="category_name"/> </td> </tr> </table> </td> <td align="right"> <table style="width: auto;"> <tr> <!-- menu: My Account --> <inp2:m_RenderElement design="menu_element"> <inp2:m_Capture to_var="menu_href"> <inp2:m_Link template="platform/my_account/my_account" m_cat_id="0" m_cat_page="1"/> </inp2:m_Capture> <inp2:m_Capture to_var="menu_icon"> <img src="<inp2:m_TemplatesBase module="In-Portal"/>img/menu_my_account.gif" alt="" /><br /> </inp2:m_Capture> <inp2:m_Capture to_var="menu_title"> <inp2:m_Phrase name="lu_title_MyAccount"/> </inp2:m_Capture> <inp2:m_IsActive template=".*/my_account" result_to_var="current"/> </inp2:m_RenderElement> <!-- // menu: My Account --> <inp2:m_if check="m_ModuleEnabled" module="In-Commerce"> <!-- menu: ShoppingCart --> <inp2:m_Include t="in-commerce/elements/menu_element.elm"/> <!-- // menu: ShoppingCart --> </inp2:m_if> </tr> </table> </td> </tr> </table> \ No newline at end of file Index: branches/5.0.x/themes/default2009/index.tpl =================================================================== --- branches/5.0.x/themes/default2009/index.tpl (revision 12297) +++ branches/5.0.x/themes/default2009/index.tpl (revision 12298) @@ -1,58 +1,58 @@ -<!--## -<NAME>Home</NAME> -<DESC>Welcome page</DESC> -<SECTION></SECTION> -##--> - -<!--## PAGE TITLE ELEMENT ##--> -<inp2:m_DefineElement name="page_title"> - <inp2:m_phrase name="lu_title_WelcomeTitle"/> -</inp2:m_DefineElement> -<!--## //PAGE TITLE ELEMENT ##--> - -<!--## SIDE-BAR ELEMENT ##--> -<inp2:m_DefineElement name="sidebar"> - <div class="movable-area"> - <div class="movable-element"> - <inp2:m_RenderElement name="platform/elements/side_boxes/login.elm" design="blue_box"/> - </div> - <div class="movable-element"> - <inp2:m_RenderElement name="platform/elements/side_boxes/search.elm" design="blue_box"/> - </div> - <div class="movable-element"> - <inp2:m_RenderElement name="platform/elements/side_boxes/recommend_site.elm" design="blue_box"/> - </div> - <div class="movable-element"> - <inp2:m_RenderElement name="platform/elements/side_boxes/mailing_list.elm" design="blue_box"/> - </div> - </div> -</inp2:m_DefineElement> -<!--## /SIDE-BAR ELEMENT ##--> - -<!--## MAIN CONTENT ##--> -<inp2:m_DefineElement name="content"> - <div class="movable-area"> - <div class="movable-element"> - <inp2:m_include template="platform/elements/navigation_bar.elm"/> - </div> - <div class="movable-element"> - <inp2:m_RenderElement design="content_box"> - <inp2:m_Capture to_var="header"> - <inp2:m_phrase name="lu_title_WelcomeTitle"/> - </inp2:m_Capture> - - <inp2:st_ContentBlock num="1"/> - </inp2:m_RenderElement> - </div> - <div class="movable-element"> - <!--## INCLUDE HOME PAGE ELEMENTS FOR EACH MODULE ##--> - <inp2:m_ModuleInclude template="elements/content_boxes/home_page_items.elm" data_exists="1"/> - <!--## /HOME PAGE ELEMENTS ##--> - </div> - </div> -</inp2:m_DefineElement> -<!--## /MAIN CONTENT ##--> - -<!--## DESIGN TEMPLATE ##--> -<inp2:m_include template="platform/designs/default_design.des" pass_params="1"/> +<!--## +<NAME>Home</NAME> +<DESC>Welcome page</DESC> +<SECTION></SECTION> +##--> + +<!--## PAGE TITLE ELEMENT ##--> +<inp2:m_DefineElement name="page_title"> + <inp2:m_phrase name="lu_title_WelcomeTitle" no_editing="1"/> +</inp2:m_DefineElement> +<!--## //PAGE TITLE ELEMENT ##--> + +<!--## SIDE-BAR ELEMENT ##--> +<inp2:m_DefineElement name="sidebar"> + <div class="movable-area"> + <div class="movable-element"> + <inp2:m_RenderElement name="platform/elements/side_boxes/login.elm" design="blue_box"/> + </div> + <div class="movable-element"> + <inp2:m_RenderElement name="platform/elements/side_boxes/search.elm" design="blue_box"/> + </div> + <div class="movable-element"> + <inp2:m_RenderElement name="platform/elements/side_boxes/recommend_site.elm" design="blue_box"/> + </div> + <div class="movable-element"> + <inp2:m_RenderElement name="platform/elements/side_boxes/mailing_list.elm" design="blue_box"/> + </div> + </div> +</inp2:m_DefineElement> +<!--## /SIDE-BAR ELEMENT ##--> + +<!--## MAIN CONTENT ##--> +<inp2:m_DefineElement name="content"> + <div class="movable-area"> + <div class="movable-element"> + <inp2:m_include template="platform/elements/navigation_bar.elm"/> + </div> + <div class="movable-element"> + <inp2:m_RenderElement design="content_box"> + <inp2:m_Capture to_var="header"> + <inp2:m_phrase name="lu_title_WelcomeTitle"/> + </inp2:m_Capture> + + <inp2:st_ContentBlock num="1"/> + </inp2:m_RenderElement> + </div> + <div class="movable-element"> + <!--## INCLUDE HOME PAGE ELEMENTS FOR EACH MODULE ##--> + <inp2:m_ModuleInclude template="elements/content_boxes/home_page_items.elm" data_exists="1"/> + <!--## /HOME PAGE ELEMENTS ##--> + </div> + </div> +</inp2:m_DefineElement> +<!--## /MAIN CONTENT ##--> + +<!--## DESIGN TEMPLATE ##--> +<inp2:m_include template="platform/designs/default_design.des" pass_params="1"/> <!--## /DESIGN TEMPLATE ##--> \ No newline at end of file Index: branches/5.0.x/admin/system_presets/simple/settings.php =================================================================== --- branches/5.0.x/admin/system_presets/simple/settings.php (revision 12297) +++ branches/5.0.x/admin/system_presets/simple/settings.php (revision 12298) @@ -1,8 +1,7 @@ <?php $visible_editing_modes = Array ( - 1, // Browse Mode - 4, // Content Mode - 2, // Layout Mode - 3, // Design Mode + EDITING_MODE_BROWSE, + EDITING_MODE_CONTENT, + EDITING_MODE_DESIGN, ); \ No newline at end of file Index: branches/5.0.x/core/kernel/db/db_tag_processor.php =================================================================== --- branches/5.0.x/core/kernel/db/db_tag_processor.php (revision 12297) +++ branches/5.0.x/core/kernel/db/db_tag_processor.php (revision 12298) @@ -1,2512 +1,2512 @@ <?php /** * @version $Id$ * @package In-Portal * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. * @license GNU/GPL * In-Portal is Open Source software. * This means that this software may have been modified pursuant * the GNU General Public License, and as distributed it includes * or is derivative of works licensed under the GNU General Public License * or other free or open source software licenses. * See http://www.in-portal.net/license/ for copyright notices and details. */ class kDBTagProcessor extends TagProcessor { /** * Description * * @var kDBConnection * @access public */ var $Conn; function kDBTagProcessor() { parent::kBase(); $this->Conn =& $this->Application->GetADODBConnection(); } /** * Returns true if "new" button was pressed in toolbar * * @param Array $params * @return bool */ function IsNewMode($params) { $object =& $this->getObject($params); return $object->GetID() <= 0; } /** * Returns view menu name for current prefix * * @param Array $params * @return string */ function GetItemName($params) { $item_name = $this->Application->getUnitOption($this->Prefix, 'ViewMenuPhrase'); return $this->Application->Phrase($item_name); } function ViewMenu($params) { $block_params = $params; unset($block_params['block']); $block_params['name'] = $params['block']; $list =& $this->GetList($params); $block_params['PrefixSpecial'] = $list->getPrefixSpecial(); return $this->Application->ParseBlock($block_params); } function SearchKeyword($params) { $list =& $this->GetList($params); return $this->Application->RecallVar($list->getPrefixSpecial().'_search_keyword'); } /** * Draw filter menu content (for ViewMenu) based on filters defined in config * * @param Array $params * @return string */ function DrawFilterMenu($params) { $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['spearator_block']; $separator = $this->Application->ParseBlock($block_params); $filter_menu = $this->Application->getUnitOption($this->Prefix,'FilterMenu'); if (!$filter_menu) { trigger_error('<span class="debug_error">no filters defined</span> for prefix <b>'.$this->Prefix.'</b>, but <b>DrawFilterMenu</b> tag used', E_USER_WARNING); return ''; } // Params: label, filter_action, filter_status $block_params['name'] = $params['item_block']; $view_filter = $this->Application->RecallVar($this->getPrefixSpecial().'_view_filter'); if ($view_filter === false) { $event_params = Array ('prefix' => $this->Prefix, 'special' => $this->Special, 'name' => 'OnRemoveFilters'); $this->Application->HandleEvent( new kEvent($event_params) ); $view_filter = $this->Application->RecallVar($this->getPrefixSpecial().'_view_filter'); } $view_filter = unserialize($view_filter); $filters = Array(); $prefix_special = $this->getPrefixSpecial(); foreach ($filter_menu['Filters'] as $filter_key => $filter_params) { $group_params = isset($filter_params['group_id']) ? $filter_menu['Groups'][ $filter_params['group_id'] ] : Array(); if (!isset($group_params['element_type'])) { $group_params['element_type'] = 'checkbox'; } if (!$filter_params) { $filters[] = $separator; continue; } $block_params['label'] = addslashes( $this->Application->Phrase($filter_params['label']) ); if (getArrayValue($view_filter,$filter_key)) { $submit = 0; if (isset($params['old_style'])) { $status = $group_params['element_type'] == 'checkbox' ? 1 : 2; } else { $status = $group_params['element_type'] == 'checkbox' ? '[\'img/check_on.gif\']' : '[\'img/menu_dot.gif\']'; } } else { $submit = 1; $status = 'null'; } $block_params['filter_action'] = 'set_filter("'.$prefix_special.'","'.$filter_key.'","'.$submit.'",'.$params['ajax'].');'; $block_params['filter_status'] = $status; // 1 - checkbox, 2 - radio, 0 - no image $filters[] = $this->Application->ParseBlock($block_params); } return implode('', $filters); } /** * Draws auto-refresh submenu in View Menu. * * @param Array $params * @return string */ function DrawAutoRefreshMenu($params) { $refresh_intervals = $this->Application->ConfigValue('AutoRefreshIntervals'); if (!$refresh_intervals) { trigger_error('<span class="debug_error">no filters defined</span> for prefix <strong>'.$this->Prefix.'</strong>, but <strong>DrawAutoRefreshMenu</strong> tag used', E_USER_WARNING); return ''; } $refresh_intervals = explode(',', $refresh_intervals); $view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view'); $current_refresh_interval = $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_refresh_interval.'.$view_name); if ($current_refresh_interval === false) { // if no interval was selected before, then choose 1st interval $current_refresh_interval = $refresh_intervals[0]; } $ret = ''; $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['render_as']; foreach ($refresh_intervals as $refresh_interval) { $block_params['label'] = $this->_formatInterval($refresh_interval); $block_params['refresh_interval'] = $refresh_interval; $block_params['selected'] = $current_refresh_interval == $refresh_interval; $ret .= $this->Application->ParseBlock($block_params); } return $ret; } /** * Tells, that current grid is using auto refresh * * @param Array $params * @return bool */ function UseAutoRefresh($params) { $view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view'); return $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_auto_refresh.'.$view_name); } /** * Returns current grid refresh interval * * @param Array $params * @return bool */ function AutoRefreshInterval($params) { $view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view'); return $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_refresh_interval.'.$view_name); } /** * Formats time interval using given text for hours and minutes * * @param int $intervalmMinutes * @param string $hour_text Text for hours * @param string $min_text Text for minutes * @return unknown */ function _formatInterval($interval, $hour_text = 'h', $min_text = 'min') { // 65 $minutes = $interval % 60; $hours = ($interval - $minutes) / 60; $ret = ''; if ($hours) { $ret .= $hours.$hour_text.' '; } if ($minutes) { $ret .= $minutes.$min_text; } return $ret; } function IterateGridFields($params) { $mode = $params['mode']; $def_block = isset($params['block']) ? $params['block'] : ''; $force_block = isset($params['force_block']) ? $params['force_block'] : false; $grids = $this->Application->getUnitOption($this->Prefix,'Grids'); $grid_config = $grids[$params['grid']]['Fields']; $picker_helper =& $this->Application->RecallObject('ColumnPickerHelper'); /* @var $picker_helper kColumnPickerHelper */ $picker_helper->ApplyPicker($this->getPrefixSpecial(), $grid_config, $params['grid']); if ($mode == 'fields') { return "'".join("','", array_keys($grid_config))."'"; } $std_params['pass_params'] = 'true'; $std_params['PrefixSpecial'] = $this->getPrefixSpecial(); $object =& $this->GetList($params); $o = ''; $i = 0; foreach ($grid_config as $field => $options) { $i++; $block_params = Array(); $block_params['name'] = $force_block ? $force_block : (isset($options[$mode.'_block']) ? $options[$mode.'_block'] : $def_block); $block_params['field'] = $field; $block_params['sort_field'] = isset($options['sort_field']) ? $options['sort_field'] : $field; $block_params['filter_field'] = isset($options['filter_field']) ? $options['filter_field'] : $field; $w = $picker_helper->GetWidth($field); if ($w) $options['width'] = $w; /*if (isset($options['filter_width'])) { $block_params['filter_width'] = $options['filter_width']; } elseif (isset($options['width'])) { if (isset($options['filter_block']) && preg_match('/range/', $options['filter_block'])) { if ($options['width'] < 60) { $options['width'] = 60; $block_params['filter_width'] = 20; } else { $block_params['filter_width'] = $options['width'] - 40; } } else { $block_params['filter_width'] = max($options['width']-10, 20); } }*/ /*if (isset($block_params['filter_width'])) $block_params['filter_width'] .= 'px'; if (isset($options['filter_block']) && preg_match('/range/', $options['filter_block'])) { $block_params['filter_width'] = '20px'; } else { $block_params['filter_width'] = '97%'; // $block_params['filter_width'] = max($options['width']-10, 20); }*/ $field_options = $object->GetFieldOptions($field); if (array_key_exists('use_phrases', $field_options)) { $block_params['use_phrases'] = $field_options['use_phrases']; } $block_params['is_last'] = ($i == count($grid_config)); $block_params = array_merge($std_params, $options, $block_params); $o.= $this->Application->ParseBlock($block_params, 1); } return $o; } function PickerCRC($params) { /* @var $picker_helper kColumnPickerHelper */ $picker_helper =& $this->Application->RecallObject('ColumnPickerHelper'); $picker_helper->SetGridName($params['grid']); $data = $picker_helper->LoadColumns($this->getPrefixSpecial()); return $data['crc']; } function FreezerPosition($params) { /* @var $picker_helper kColumnPickerHelper */ $picker_helper =& $this->Application->RecallObject('ColumnPickerHelper'); $picker_helper->SetGridName($params['grid']); $data = $picker_helper->LoadColumns($this->getPrefixSpecial()); $freezer_pos = array_search('__FREEZER__', $data['order']); return $freezer_pos === false || in_array('__FREEZER__', $data['hidden_fields']) ? 1 : ++$freezer_pos; } function GridFieldsCount($params) { $grids = $this->Application->getUnitOption($this->Prefix, 'Grids'); $grid_config = $grids[$params['grid']]['Fields']; return count($grid_config); } /** * Prints list content using block specified * * @param Array $params * @return string * @access public */ function PrintList($params) { $params['no_table'] = 1; return $this->PrintList2($params); } function InitList($params) { $list_name = isset($params['list_name']) ? $params['list_name'] : ''; $names_mapping = $this->Application->GetVar('NamesToSpecialMapping'); if( !getArrayValue($names_mapping, $this->Prefix, $list_name) ) { $list =& $this->GetList($params); } } function BuildListSpecial($params) { return $this->Special; } /** * Returns key, that identifies each list on template (used internally, not tag) * * @param Array $params * @return string */ function getUniqueListKey($params) { $types = $this->SelectParam($params, 'types'); $except = $this->SelectParam($params, 'except'); $list_name = $this->SelectParam($params, 'list_name'); if (!$list_name) { $list_name = $this->Application->Parser->GetParam('list_name'); } return $types.$except.$list_name; } /** * Enter description here... * * @param Array $params * @return kDBList */ function &GetList($params) { $list_name = $this->SelectParam($params, 'list_name,name'); if (!$list_name) { $list_name = $this->Application->Parser->GetParam('list_name'); } $requery = isset($params['requery']) && $params['requery']; if ($list_name && !$requery) { $names_mapping = $this->Application->GetVar('NamesToSpecialMapping'); $special = is_array($names_mapping) && isset($names_mapping[$this->Prefix]) && isset($names_mapping[$this->Prefix][$list_name]) ? $names_mapping[$this->Prefix][$list_name] : false; // $special = getArrayValue($names_mapping, $this->Prefix, $list_name); if (!$special) { $special = $this->BuildListSpecial($params); } } else { $special = $this->BuildListSpecial($params); } $prefix_special = rtrim($this->Prefix.'.'.$special, '.'); $params['skip_counting'] = true; $list =& $this->Application->recallObject( $prefix_special, $this->Prefix.'_List', $params); /* @var $list kDBList */ if (!array_key_exists('skip_quering', $params) || !$params['skip_quering']) { if ($requery) { $this->Application->HandleEvent($an_event, $prefix_special.':OnListBuild', $params); } if (array_key_exists('offset', $params)) { $list->Offset += $params['offset']; // apply custom offset } $list->Query($requery); if (array_key_exists('offset', $params)) { $list->Offset -= $params['offset']; // remove custom offset } } $this->Special = $special; if ($list_name) { $names_mapping[$this->Prefix][$list_name] = $special; $this->Application->SetVar('NamesToSpecialMapping', $names_mapping); } return $list; } function ListMarker($params) { $list =& $this->GetList($params); $ret = $list->getPrefixSpecial(); if( getArrayValue($params, 'as_preg') ) $ret = preg_quote($ret, '/'); return $ret; } /** * Prepares name for field with event in it (used only on front-end) * * @param Array $params * @return string */ function SubmitName($params) { $list =& $this->GetList($params); $prefix_special = $list->getPrefixSpecial(); return 'events['.$prefix_special.']['.$params['event'].']'; } /** * Prints list content using block specified * * @param Array $params * @return string * @access public */ function PrintList2($params) { $per_page = $this->SelectParam($params, 'per_page,max_items'); if ($per_page !== false) $params['per_page'] = $per_page; $list =& $this->GetList($params); $o = ''; $direction = (isset($params['direction']) && $params['direction']=="H")?"H":"V"; $columns = (isset($params['columns'])) ? $params['columns'] : 1; $id_field = (isset($params['id_field'])) ? $params['id_field'] : $this->Application->getUnitOption($this->Prefix, 'IDField'); if ($columns > 1 && $direction == 'V') { $records_left = array_splice($list->Records, $list->SelectedCount); // because we have 1 more record for "More..." link detection (don't need to sort it) $list->Records = $this->LinearToVertical($list->Records, $columns, $list->GetPerPage()); $list->Records = array_merge($list->Records, $records_left); } $list->GoFirst(); $block_params=$this->prepareTagParams($params); $block_params['name'] = $this->SelectParam($params, 'render_as,block'); $block_params['pass_params'] = 'true'; $block_params['column_width'] = $params['column_width'] = 100 / $columns; $block_start_row_params = $this->prepareTagParams($params); $block_start_row_params['name'] = $this->SelectParam($params, 'row_start_render_as,block_row_start,row_start_block'); $block_end_row_params=$this->prepareTagParams($params); $block_end_row_params['name'] = $this->SelectParam($params, 'row_end_render_as,block_row_end,row_end_block'); $block_empty_cell_params = $this->prepareTagParams($params); $block_empty_cell_params['name'] = $this->SelectParam($params, 'empty_cell_render_as,block_empty_cell,empty_cell_block'); $i=0; $backup_id=$this->Application->GetVar($this->Prefix."_id"); $displayed = array(); $column_number = 1; $cache_mod_rw = $this->Application->getUnitOption($this->Prefix, 'CacheModRewrite') && $this->Application->RewriteURLs(); $limit = isset($params['limit']) ? $params['limit'] : false; while (!$list->EOL() && (!$limit || $i<$limit)) { $this->Application->SetVar( $this->getPrefixSpecial().'_id', $list->GetDBField($id_field) ); // for edit/delete links using GET $this->Application->SetVar( $this->Prefix.'_id', $list->GetDBField($id_field) ); $block_params['is_last'] = ($i == $list->SelectedCount - 1); $block_params['last_row'] = ($i + (($i+1) % $columns) >= $list->SelectedCount - 1); $block_params['not_last'] = !$block_params['is_last']; // for front-end if ($cache_mod_rw) { if ($this->Prefix == 'c') { // for listing subcategories in category $this->Application->setCache('filenames', $this->Prefix.'_'.$list->GetDBField($id_field), $list->GetDBField('NamedParentPath')); $this->Application->setCache('category_tree', $list->GetDBField($id_field), $list->GetDBField('TreeLeft') . ';' . $list->GetDBField('TreeRight')); } else { // for listing items in category $this->Application->setCache('filenames', 'c_'.$list->GetDBField('CategoryId'), $list->GetDBField('CategoryFilename')); $this->Application->setCache('filenames', $this->Prefix.'_'.$list->GetDBField($id_field), $list->GetDBField('Filename')); } } if ($i % $columns == 0) { // record in this iteration is first in row, then open row $column_number = 1; $o.= $block_start_row_params['name'] ? $this->Application->ParseBlock($block_start_row_params, 1) : (!isset($params['no_table']) ? '<tr>' : ''); } else { $column_number++; } $block_params['first_col'] = $column_number == 1 ? 1 : 0; $block_params['last_col'] = $column_number == $columns ? 1 : 0; $block_params['column_number'] = $column_number; $block_params['num'] = ($i+1); $this->PrepareListElementParams($list, $block_params); // new, no need to rewrite PrintList $o.= $this->Application->ParseBlock($block_params, 1); array_push($displayed, $list->GetDBField($id_field)); if($direction == 'V' && $list->SelectedCount % $columns > 0 && $column_number == ($columns - 1) && ceil(($i + 1) / $columns) > $list->SelectedCount % ceil($list->SelectedCount / $columns)) { // if vertical output, then draw empty cells vertically, not horizontally $o .= $block_empty_cell_params['name'] ? $this->Application->ParseBlock($block_empty_cell_params, 1) : '<td> </td>'; $i++; } if (($i + 1) % $columns == 0) { // record in next iteration is first in row too, then close this row $o.= $block_end_row_params['name'] ? $this->Application->ParseBlock($block_end_row_params, 1) : (!isset($params['no_table']) ? '</tr>' : ''); } $list->GoNext(); $i++; } // append empty cells in place of missing cells in last row while ($i % $columns != 0) { // until next cell will be in new row append empty cells $o .= $block_empty_cell_params['name'] ? $this->Application->ParseBlock($block_empty_cell_params, 1) : '<td> </td>'; if (($i+1) % $columns == 0) { // record in next iteration is first in row too, then close this row $o .= $block_end_row_params['name'] ? $this->Application->ParseBlock($block_end_row_params, 1) : '</tr>'; } $i++; } $cur_displayed = $this->Application->GetVar($this->Prefix.'_displayed_ids'); if (!$cur_displayed) { $cur_displayed = Array(); } else { $cur_displayed = explode(',', $cur_displayed); } $displayed = array_unique(array_merge($displayed, $cur_displayed)); $this->Application->SetVar($this->Prefix.'_displayed_ids', implode(',',$displayed)); $this->Application->SetVar( $this->Prefix.'_id', $backup_id); $this->Application->SetVar( $this->getPrefixSpecial().'_id', ''); if (isset($params['more_link_render_as'])) { $block_params = $params; $params['render_as'] = $params['more_link_render_as']; $o .= $this->MoreLink($params); } return $o; } /** * Allows to modify block params & current list record before PrintList parses record * * @param kDBList $object * @param Array $block_params */ function PrepareListElementParams(&$object, &$block_params) { // $fields_hash =& $object->getCurrentRecord(); } function MoreLink($params) { $per_page = $this->SelectParam($params, 'per_page,max_items'); if ($per_page !== false) $params['per_page'] = $per_page; $list =& $this->GetList($params); if ($list->PerPage < $list->RecordsCount) { $block_params = $this->prepareTagParams($params); $block_params['name'] = $this->SelectParam($params, 'render_as,block'); return $this->Application->ParseBlock($block_params); } } function NotLastItem($params) { $object =& $this->getList($params); // maybe we should use $this->GetList($params) instead return ($object->CurrentIndex < min($object->PerPage == -1 ? $object->RecordsCount : $object->PerPage, $object->RecordsCount) - 1); } function PageLink($params) { $t = isset($params['template']) ? $params['template'] : ''; unset($params['template']); if (!$t) $t = $this->Application->GetVar('t'); if (isset($params['page'])) { $this->Application->SetVar($this->getPrefixSpecial().'_Page', $params['page']); unset($params['page']); } if (!isset($params['pass'])) { $params['pass'] = 'm,'.$this->getPrefixSpecial(); } return $this->Application->HREF($t, '', $params); } function ColumnWidth($params) { $columns = $this->Application->Parser->GetParam('columns'); return round(100/$columns).'%'; } /** * Append prefix and special to tag * params (get them from tagname) like * they were really passed as params * * @param Array $tag_params * @return Array * @access protected */ function prepareTagParams($tag_params = Array()) { /*if (isset($tag_params['list_name'])) { $list =& $this->GetList($tag_params); $this->Init($list->Prefix, $list->Special); }*/ $ret = $tag_params; $ret['Prefix'] = $this->Prefix; $ret['Special'] = $this->Special; $ret['PrefixSpecial'] = $this->getPrefixSpecial(); return $ret; } function GetISO($currency) { if ($currency == 'selected') { $iso = $this->Application->RecallVar('curr_iso'); } elseif ($currency == 'primary' || $currency == '') { $iso = $this->Application->GetPrimaryCurrency(); } else { //explicit currency $iso = $currency; } return $iso; } function ConvertCurrency($value, $iso) { $converter =& $this->Application->recallObject('kCurrencyRates'); // convery primary currency to selected (if they are the same, converter will just return) $value = $converter->Convert($value, 'PRIMARY', $iso); return $value; } function AddCurrencySymbol($value, $iso) { $currency =& $this->Application->recallObject('curr.-'.$iso, null, Array('skip_autoload' => true)); if( !$currency->isLoaded() ) $currency->Load($iso, 'ISO'); $symbol = $currency->GetDBField('Symbol'); if (!$symbol) $symbol = $currency->GetDBField('ISO').' '; if ($currency->GetDBField('SymbolPosition') == 0) { $value = $symbol.$value; } if ($currency->GetDBField('SymbolPosition') == 1) { $value = $value.$symbol; } return $value; } /** * Get's requested field value * * @param Array $params * @return string * @access public */ function Field($params) { $field = $this->SelectParam($params, 'name,field'); if( !$this->Application->IsAdmin() ) $params['no_special'] = 'no_special'; $object =& $this->getObject($params); if ( $this->HasParam($params, 'db') ) { $value = $object->GetDBField($field); } else { if( $this->HasParam($params, 'currency') ) { $iso = $this->GetISO($params['currency']); $original = $object->GetDBField($field); $value = $this->ConvertCurrency($original, $iso); $object->SetDBField($field, $value); $object->Fields[$field]['converted'] = true; } $format = getArrayValue($params, 'format'); if (!$format || $format == '$format') { $format = null; } $value = $object->GetField($field, $format); if( $this->SelectParam($params, 'negative') ) { if(strpos($value, '-') === 0) { $value = substr($value, 1); } else { $value = '-'.$value; } } if( $this->HasParam($params, 'currency') ) { $value = $this->AddCurrencySymbol($value, $iso); $params['no_special'] = 1; } } if( !$this->HasParam($params, 'no_special') ) $value = htmlspecialchars($value); if( getArrayValue($params,'checked' ) ) $value = ($value == ( isset($params['value']) ? $params['value'] : 1)) ? 'checked' : ''; if( isset($params['plus_or_as_label']) ) { $value = substr($value, 0,1) == '+' ? substr($value, 1) : $this->Application->Phrase($value); } elseif( isset($params['as_label']) && $params['as_label'] ) $value = $this->Application->Phrase($value); $first_chars = $this->SelectParam($params,'first_chars,cut_first'); if($first_chars) { $needs_cut = mb_strlen($value) > $first_chars; $value = mb_substr($value, 0, $first_chars); if ($needs_cut) $value .= ' ...'; } if( getArrayValue($params,'nl2br' ) ) $value = nl2br($value); if ($value != '') $this->Application->Parser->DataExists = true; if( $this->HasParam($params, 'currency') ) { //restoring value in original currency, for other Field tags to work properly $object->SetDBField($field, $original); } return $value; } function SetField($params) { // <inp2:SetField field="Value" src=p:cust_{$custom_name}"/> $object =& $this->getObject($params); $dst_field = $this->SelectParam($params, 'name,field'); list($prefix_special, $src_field) = explode(':', $params['src']); $src_object =& $this->Application->recallObject($prefix_special); $object->SetDBField($dst_field, $src_object->GetDBField($src_field)); } /** * Checks if parameter is passed * Note: works like Tag and line simple method too * * @param Array $params * @param string $param_name * @return bool */ function HasParam($params, $param_name = null) { if( !isset($param_name) ) { $param_name = $this->SelectParam($params, 'name'); $params = $this->Application->Parser->Params; } $value = isset($params[$param_name]) ? $params[$param_name] : false; return $value && ($value != '$'.$param_name); } function PhraseField($params) { $field_label = $this->Field($params); $translation = $this->Application->Phrase( $field_label ); return $translation; } function Error($params) { $field = $this->SelectParam($params, 'name,field'); $object =& $this->getObject($params); $msg = $object->GetErrorMsg($field, false); return $msg; } function HasError($params) { if ($params['field'] == 'any') { $object =& $this->getObject($params); $skip_fields = getArrayValue($params, 'except'); $skip_fields = $skip_fields ? explode(',', $skip_fields) : Array(); return $object->HasErrors($skip_fields); } else { $fields = $this->SelectParam($params, 'field,fields'); $fields = explode(',', $fields); $res = false; foreach($fields as $field) { $params['field'] = $field; $res = $res || ($this->Error($params) != ''); } return $res; } } function ErrorWarning($params) { if (!isset($params['field'])) { $params['field'] = 'any'; } if ($this->HasError($params)) { $params['prefix'] = $this->getPrefixSpecial(); return $this->Application->ParseBlock($params); } } function IsRequired($params) { $field = $params['field']; $object =& $this->getObject($params);; $formatter_class = getArrayValue($object->Fields, $field, 'formatter'); if ($formatter_class == 'kMultiLanguage') { $formatter =& $this->Application->recallObject($formatter_class); $field = $formatter->LangFieldName($field); } $options = $object->GetFieldOptions($field); return getArrayValue($options,'required'); } function FieldOption($params) { $object =& $this->getObject($params);; $options = $object->GetFieldOptions($params['field']); $ret = isset($options[$params['option']]) ? $options[$params['option']] : ''; if (isset($params['as_label']) && $params['as_label']) $ret = $this->Application->ReplaceLanguageTags($ret); return $ret; } function PredefinedOptions($params) { $object =& $this->getObject($params); $field = $params['field']; $value = array_key_exists('value', $params) ? $params['value'] : $object->GetDBField($field); $field_options = $object->GetFieldOptions($field); if (!array_key_exists('options', $field_options) || !is_array($field_options['options'])) { trigger_error('Options not defined for <strong>'.$object->Prefix.'</strong> field <strong>'.$field.'</strong>', E_USER_WARNING); return ''; } $options = $field_options['options']; if ($this->HasParam($params, 'has_empty')) { $empty_value = array_key_exists('empty_value', $params) ? $params['empty_value'] : ''; $options = array_merge_recursive2(Array ($empty_value => ''), $options); // don't use other array merge function, because they will reset keys !!! } $block_params = $this->prepareTagParams($params); $block_params['name'] = $this->SelectParam($params, 'render_as,block'); $block_params['pass_params'] = 'true'; if (method_exists($object, 'EOL') && count($object->Records) == 0) { // for drawing grid column filter $block_params['field_name'] = ''; } else { $block_params['field_name'] = $this->InputName($params); // depricated (produces warning when used as grid filter), but used in Front-End (submission create), admin (submission view) } $selected_param_name = getArrayValue($params, 'selected_param'); if (!$selected_param_name) { $selected_param_name = $params['selected']; } $selected = $params['selected']; $o = ''; if ($this->HasParam($params, 'no_empty') && !getArrayValue($options, '')) { // removes empty option, when present (needed?) array_shift($options); } if (strpos($value, '|') !== false) { // multiple checkboxes OR multiselect $value = explode('|', substr($value, 1, -1) ); foreach ($options as $key => $val) { $block_params['key'] = $key; $block_params['option'] = $val; $block_params[$selected_param_name] = ( in_array($key, $value) ? ' '.$selected : ''); $o .= $this->Application->ParseBlock($block_params, 1); } } else { // single selection radio OR checkboxes OR dropdown foreach ($options as $key => $val) { $block_params['key'] = $key; $block_params['option'] = $val; $block_params[$selected_param_name] = (strlen($key) == strlen($value) && ($key == $value) ? ' '.$selected : ''); $o .= $this->Application->ParseBlock($block_params, 1); } } return $o; } function PredefinedSearchOptions($params) { $object =& $this->GetList($params); /* @var $object kDBList */ $params['value'] = $this->SearchField($params); return $this->PredefinedOptions($params); } function Format($params) { $field = $this->SelectParam($params, 'name,field'); $object =& $this->getObject($params); $options = $object->GetFieldOptions($field); $format = $options[ $this->SelectParam($params, 'input_format') ? 'input_format' : 'format' ]; $formatter_class = getArrayValue($options,'formatter'); if ($formatter_class) { $formatter =& $this->Application->recallObject($formatter_class); $human_format = getArrayValue($params,'human'); $edit_size = getArrayValue($params,'edit_size'); $sample = getArrayValue($params,'sample'); if($sample) { return $formatter->GetSample($field, $options, $object); } elseif($human_format || $edit_size) { $format = $formatter->HumanFormat($format); return $edit_size ? strlen($format) : $format; } } return $format; } /** * Returns grid padination information * Can return links to pages * * @param Array $params * @return mixed */ function PageInfo($params) { $object =& $this->GetList($params); /* @var $object kDBList */ $type = $params['type']; unset($params['type']); // remove parameters used only by current tag $ret = ''; switch ($type) { case 'current': $ret = $object->Page; break; case 'total': $ret = $object->GetTotalPages(); break; case 'prev': $ret = $object->Page > 1 ? $object->Page - 1 : false; break; case 'next': $ret = $object->Page < $object->GetTotalPages() ? $object->Page + 1 : false; break; } if ($ret && isset($params['as_link']) && $params['as_link']) { unset($params['as_link']); // remove parameters used only by current tag $params['page'] = $ret; $current_page = $object->Page; // backup current page $ret = $this->PageLink($params); $this->Application->SetVar($object->getPrefixSpecial().'_Page', $current_page); // restore page } return $ret; } /** * Print grid pagination using * block names specified * * @param Array $params * @return string * @access public */ function PrintPages($params) { $list =& $this->GetList($params); $prefix_special = $list->getPrefixSpecial(); $total_pages = $list->GetTotalPages(); if ($total_pages > 1) $this->Application->Parser->DataExists = true; if($total_pages == 0) $total_pages = 1; // display 1st page as selected in case if we have no pages at all $o = ''; // what are these 2 lines for? $this->Application->SetVar($prefix_special.'_event',''); $this->Application->SetVar($prefix_special.'_id',''); $current_page = $list->Page; // $this->Application->RecallVar($prefix_special.'_Page'); $block_params = $this->prepareTagParams($params); $split = ( isset($params['split'] ) ? $params['split'] : 10 ); $split_start = $current_page - ceil($split/2); if ($split_start < 1){ $split_start = 1; } $split_end = $split_start + $split-1; if ($split_end > $total_pages) { $split_end = $total_pages; $split_start = max($split_end - $split + 1, 1); } if ($current_page > 1){ $prev_block_params = $this->prepareTagParams(); if ($total_pages > $split){ $prev_block_params['page'] = max($current_page-$split, 1); $prev_block_params['name'] = $this->SelectParam($params, 'prev_page_split_render_as,prev_page_split_block'); if ($prev_block_params['name']){ $o .= $this->Application->ParseBlock($prev_block_params, 1); } } $prev_block_params['name'] = 'page'; $prev_block_params['page'] = $current_page-1; $prev_block_params['name'] = $this->SelectParam($params, 'prev_page_render_as,block_prev_page,prev_page_block'); if ($prev_block_params['name']) { $this->Application->SetVar($this->getPrefixSpecial().'_Page', $current_page-1); $o .= $this->Application->ParseBlock($prev_block_params, 1); } } else { if ( $no_prev_page_block = $this->SelectParam($params, 'no_prev_page_render_as,block_no_prev_page') ) { $block_params['name'] = $no_prev_page_block; $o .= $this->Application->ParseBlock($block_params, 1); } } $separator_params['name'] = $this->SelectParam($params, 'separator_render_as,block_separator'); for ($i = $split_start; $i <= $split_end; $i++) { if ($i == $current_page) { $block = $this->SelectParam($params, 'current_render_as,active_render_as,block_current,active_block'); } else { $block = $this->SelectParam($params, 'link_render_as,inactive_render_as,block_link,inactive_block'); } $block_params['name'] = $block; $block_params['page'] = $i; $this->Application->SetVar($this->getPrefixSpecial().'_Page', $i); $o .= $this->Application->ParseBlock($block_params, 1); if ($this->SelectParam($params, 'separator_render_as,block_separator') && $i < $split_end) { $o .= $this->Application->ParseBlock($separator_params, 1); } } if ($current_page < $total_pages){ $next_block_params = $this->prepareTagParams(); $next_block_params['page']=$current_page+1; $next_block_params['name'] = $this->SelectParam($params, 'next_page_render_as,block_next_page,next_page_block'); if ($next_block_params['name']){ $this->Application->SetVar($this->getPrefixSpecial().'_Page', $current_page+1); $o .= $this->Application->ParseBlock($next_block_params, 1); } if ($total_pages > $split){ $next_block_params['page']=min($current_page+$split, $total_pages); $next_block_params['name'] = $this->SelectParam($params, 'next_page_split_render_as,next_page_split_block'); if ($next_block_params['name']){ $o .= $this->Application->ParseBlock($next_block_params, 1); } } } else { if ( $no_next_page_block = $this->SelectParam($params, 'no_next_page_render_as,block_no_next_page') ) { $block_params['name'] = $no_next_page_block; $o .= $this->Application->ParseBlock($block_params, 1); } } $this->Application->SetVar($this->getPrefixSpecial().'_Page', $current_page); return $o; } /** * Print grid pagination using * block names specified * * @param Array $params * @return string * @access public */ function PaginationBar($params) { return $this->PrintPages($params); } /** * Returns field name (processed by kMultiLanguage formatter * if required) and item's id from it's IDField or field required * * @param Array $params * @return Array (id,field) * @access private */ function prepareInputName($params) { $field = $this->SelectParam($params, 'name,field'); $object =& $this->getObject($params); $formatter_class = getArrayValue($object->Fields, $field, 'formatter'); if ($formatter_class == 'kMultiLanguage') { $formatter =& $this->Application->recallObject($formatter_class); /* @var $formatter kMultiLanguage */ $force_primary = isset($object->Fields[$field]['force_primary']) && $object->Fields[$field]['force_primary']; $field = $formatter->LangFieldName($field, $force_primary); } if (array_key_exists('force_id', $params)) { $id = $params['force_id']; } else { $id_field = getArrayValue($params, 'IdField'); $id = $id_field ? $object->GetDBField($id_field) : $object->GetID(); } return Array($id, $field); } /** * Returns input field name to * be placed on form (for correct * event processing) * * @param Array $params * @return string * @access public */ function InputName($params) { list($id, $field) = $this->prepareInputName($params); $ret = $this->getPrefixSpecial().'['.$id.']['.$field.']'; if( getArrayValue($params, 'as_preg') ) $ret = preg_quote($ret, '/'); return $ret; } /** * Allows to override various field options through hidden fields with specific names in submit. * This tag generates this special names * * @param Array $params * @return string * @author Alex */ function FieldModifier($params) { list($id, $field) = $this->prepareInputName($params); $ret = 'field_modifiers['.$this->getPrefixSpecial().']['.$field.']['.$params['type'].']'; if( getArrayValue($params, 'as_preg') ) $ret = preg_quote($ret, '/'); if (isset($params['value'])) { $object =& $this->getObject($params); $field_modifiers[$field][$params['type']] = $params['value']; $object->ApplyFieldModifiers($field_modifiers); } return $ret; } /** * Returns index where 1st changable sorting field begins * * @return int * @access private */ function getUserSortIndex() { $list_sortings = $this->Application->getUnitOption($this->Prefix, 'ListSortings'); $sorting_prefix = getArrayValue($list_sortings, $this->Special) ? $this->Special : ''; $user_sorting_start = 0; if ( $forced_sorting = getArrayValue($list_sortings, $sorting_prefix, 'ForcedSorting') ) { $user_sorting_start = count($forced_sorting); } return $user_sorting_start; } /** * Returns order direction for given field * * * * @param Array $params * @return string * @access public */ function Order($params) { $field = $params['field']; $user_sorting_start = $this->getUserSortIndex(); $list =& $this->GetList($params); if ($list->GetOrderField($user_sorting_start) == $field) { return strtolower($list->GetOrderDirection($user_sorting_start)); } elseif($this->Application->ConfigValue('UseDoubleSorting') && $list->GetOrderField($user_sorting_start+1) == $field) { return '2_'.strtolower($list->GetOrderDirection($user_sorting_start+1)); } else { return 'no'; } } /** * Detects, that current sorting is not default * * @param Array $params * @return bool */ function OrderChanged($params) { $list =& $this->GetList($params); $user_sorting_start = $this->getUserSortIndex(); $sorting_configs = $this->Application->getUnitOption($this->Prefix, 'ConfigMapping', Array ()); $list_sortings = $this->Application->getUnitOption($this->Prefix, 'ListSortings', Array ()); $sorting_prefix = getArrayValue($list_sortings, $this->Special) ? $this->Special : ''; if (array_key_exists('DefaultSorting1Field', $sorting_configs)) { $list_sortings[$sorting_prefix]['Sorting'] = Array ( $this->Application->ConfigValue($sorting_configs['DefaultSorting1Field']) => $this->Application->ConfigValue($sorting_configs['DefaultSorting1Dir']), $this->Application->ConfigValue($sorting_configs['DefaultSorting2Field']) => $this->Application->ConfigValue($sorting_configs['DefaultSorting2Dir']), ); } $sorting = getArrayValue($list_sortings, $sorting_prefix, 'Sorting'); $sort_fields = is_array($sorting) ? array_keys($sorting) : Array (); for ($order_number = 0; $order_number < 2; $order_number++) { // currect sorting in list $sorting_pos = $user_sorting_start + $order_number; $current_order_field = $list->GetOrderField($sorting_pos, true); $current_order_direction = $list->GetOrderDirection($sorting_pos, true); if (!$current_order_field || !$current_order_direction) { // no sorting defined for this sorting position continue; } // user sorting found if (array_key_exists($order_number, $sort_fields)) { // default sorting found $default_order_field = $sort_fields[$order_number]; $default_order_direction = $sorting[$default_order_field]; if ($current_order_field != $default_order_field || $current_order_direction != $default_order_direction) { // #1. user sorting differs from default sorting -> changed return true; } } else { // #2. user sorting + no default sorting -> changed return true; } } // #3. user sorting match default or not defined -> not changed return false; } /** * Get's information of sorting field at "pos" position, * like sorting field name (type="field") or sorting direction (type="direction") * * @param Array $params * @return mixed */ function OrderInfo($params) { $user_sorting_start = $this->getUserSortIndex() + --$params['pos']; $list =& $this->GetList($params); // $object =& $this->Application->recallObject( $this->getPrefixSpecial() ); if($params['type'] == 'field') return $list->GetOrderField($user_sorting_start); if($params['type'] == 'direction') return $list->GetOrderDirection($user_sorting_start); } /** * Checks if sorting field/direction matches passed field/direction parameter * * @param Array $params * @return bool */ function IsOrder($params) { $params['type'] = isset($params['field']) ? 'field' : 'direction'; $value = $this->OrderInfo($params); if( isset($params['field']) ) return $params['field'] == $value; if( isset($params['direction']) ) return $params['direction'] == $value; } /** * Returns list perpage * * @param Array $params * @return int */ function PerPage($params) { $object =& $this->getObject($params); return $object->PerPage; } /** * Checks if list perpage matches value specified * * @param Array $params * @return bool */ function PerPageEquals($params) { $object =& $this->getObject($params); return $object->PerPage == $params['value']; } function SaveEvent($params) { // SaveEvent is set during OnItemBuild, but we may need it before any other tag calls OnItemBuild $object =& $this->getObject($params); return $this->Application->GetVar($this->getPrefixSpecial().'_SaveEvent'); } function NextId($params) { $object =& $this->getObject($params); $wid = $this->Application->GetTopmostWid($this->Prefix); $session_name = rtrim($this->getPrefixSpecial().'_selected_ids_'.$wid, '_'); $ids = explode(',', $this->Application->RecallVar($session_name)); $cur_id = $object->GetID(); $i = array_search($cur_id, $ids); if ($i !== false) { return $i < count($ids) - 1 ? $ids[$i + 1] : ''; } return ''; } function PrevId($params) { $object =& $this->getObject($params); $wid = $this->Application->GetTopmostWid($this->Prefix); $session_name = rtrim($this->getPrefixSpecial().'_selected_ids_'.$wid, '_'); $ids = explode(',', $this->Application->RecallVar($session_name)); $cur_id = $object->GetID(); $i = array_search($cur_id, $ids); if ($i !== false) { return $i > 0 ? $ids[$i - 1] : ''; } return ''; } function IsSingle($params) { return ($this->NextId($params) === '' && $this->PrevId($params) === ''); } function IsLast($params) { return ($this->NextId($params) === ''); } function IsFirst($params) { return ($this->PrevId($params) === ''); } /** * Checks if field value is equal to proposed one * * @param Array $params * @return bool */ function FieldEquals($params) { $object =& $this->getObject($params); $ret = $object->GetDBField($this->SelectParam($params, 'name,field')) == $params['value']; // if( getArrayValue($params,'inverse') ) $ret = !$ret; return $ret; } /** * Checks, that grid has icons defined and they should be shown * * @param Array $params * @return bool */ function UseItemIcons($params) { $grids = $this->Application->getUnitOption($this->Prefix, 'Grids'); return array_key_exists('Icons', $grids[ $params['grid'] ]); } /** * Returns corresponding to grid layout selector column width * * @param Array $params * @return int */ function GridSelectorColumnWidth($params) { $width = 0; if ($params['selector']) { $width += $params['selector_width']; } if ($this->UseItemIcons($params)) { $width += $params['icon_width']; } return $width; } /** * Returns grids item selection mode (checkbox, radio, ) * * @param Array $params * @return string */ function GridSelector($params) { $grids = $this->Application->getUnitOption($this->Prefix, 'Grids'); return array_key_exists('Selector', $grids[ $params['grid'] ]) ? $grids[ $params['grid'] ]['Selector'] : $params['default']; } function ItemIcon($params) { $object =& $this->getObject($params); $grids = $this->Application->getUnitOption($this->Prefix,'Grids'); $icons =& $grids[ $params['grid'] ]['Icons']; $key = ''; $status_fields = $this->Application->getUnitOption($this->Prefix,'StatusField'); if(!$status_fields) return $icons['default']; foreach($status_fields as $status_field) { $key .= $object->GetDBField($status_field).'_'; } $key = rtrim($key,'_'); $value = ($key !== false) ? $key : 'default'; return isset($icons[$value]) ? $icons[$value] : $icons['default']; } /** * Generates bluebar title + initializes prefixes used on page * * @param Array $params * @return string */ function SectionTitle($params) { $preset_name = replaceModuleSection($params['title_preset']); $title_presets = $this->Application->getUnitOption($this->Prefix,'TitlePresets'); $title_info = getArrayValue($title_presets, $preset_name); if ($title_info === false) { $title = str_replace('#preset_name#', $preset_name, $params['title']); if ($this->Application->ConfigValue('UseSmallHeader') && isset($params['group_title']) && $params['group_title']) { $title .= ' - '.$params['group_title']; } return $title; } if (getArrayValue($title_presets,'default')) { // use default labels + custom labels specified in preset used $title_info = array_merge_recursive2($title_presets['default'], $title_info); } $title = $title_info['format']; // 1. get objects in use for title construction $objects = Array(); $object_status = Array(); $status_labels = Array(); $prefixes = getArrayValue($title_info,'prefixes'); $all_tag_params = getArrayValue($title_info,'tag_params'); if ($prefixes) { // extract tag_perams passed directly to SectionTitle tag for specific prefix foreach ($params as $tp_name => $tp_value) { if (preg_match('/(.*)\[(.*)\]/', $tp_name, $regs)) { $all_tag_params[ $regs[1] ][ $regs[2] ] = $tp_value; unset($params[$tp_name]); } } $tag_params = Array(); foreach ($prefixes as $prefix_special) { $prefix_data = $this->Application->processPrefix($prefix_special); $prefix_data['prefix_special'] = rtrim($prefix_data['prefix_special'],'.'); if ($all_tag_params) { $tag_params = getArrayValue($all_tag_params, $prefix_data['prefix_special']); if (!$tag_params) $tag_params = Array(); } $tag_params = array_merge_recursive2($params, $tag_params); $objects[ $prefix_data['prefix_special'] ] =& $this->Application->recallObject($prefix_data['prefix_special'], $prefix_data['prefix'], $tag_params); $object_status[ $prefix_data['prefix_special'] ] = $objects[ $prefix_data['prefix_special'] ]->IsNewItem() ? 'new' : 'edit'; // a. set object's status field (adding item/editing item) for each object in title if (getArrayValue($title_info[ $object_status[ $prefix_data['prefix_special'] ].'_status_labels' ],$prefix_data['prefix_special'])) { $status_labels[ $prefix_data['prefix_special'] ] = $title_info[ $object_status[ $prefix_data['prefix_special'] ].'_status_labels' ][ $prefix_data['prefix_special'] ]; $title = str_replace('#'.$prefix_data['prefix_special'].'_status#', $status_labels[ $prefix_data['prefix_special'] ], $title); } // b. setting object's titlefield value (in titlebar ONLY) to default in case if object beeing created with no titlefield filled in if ($object_status[ $prefix_data['prefix_special'] ] == 'new') { $new_value = $this->getInfo( $objects[ $prefix_data['prefix_special'] ], 'titlefield' ); if(!$new_value && getArrayValue($title_info['new_titlefield'],$prefix_data['prefix_special']) ) $new_value = $this->Application->Phrase($title_info['new_titlefield'][ $prefix_data['prefix_special'] ]); $title = str_replace('#'.$prefix_data['prefix_special'].'_titlefield#', $new_value, $title); } } } // replace to section title $section = array_key_exists('section', $params) ? $params['section'] : false; if ($section) { $sections_helper =& $this->Application->recallObject('SectionsHelper'); /* @var $sections_helper kSectionsHelper */ $section_data =& $sections_helper->getSectionData($section); $title = str_replace('#section_label#', '!' . $section_data['label'] . '!', $title); } // 2. replace phrases if any found in format string $title = $this->Application->ReplaceLanguageTags($title, false); // 3. find and replace any replacement vars preg_match_all('/#(.*_.*)#/Uis',$title,$rets); if ($rets[1]) { $replacement_vars = array_keys( array_flip($rets[1]) ); foreach ($replacement_vars as $replacement_var) { $var_info = explode('_',$replacement_var,2); $object =& $objects[ $var_info[0] ]; $new_value = $this->getInfo($object,$var_info[1]); $title = str_replace('#'.$replacement_var.'#', $new_value, $title); } } // replace trailing spaces inside title preset + '' occurences into single space $title = preg_replace('/[ ]*\'\'[ ]*/', ' ', $title); if ($this->Application->ConfigValue('UseSmallHeader') && isset($params['group_title']) && $params['group_title']) { $title .= ' - '.$params['group_title']; } $cut_first = getArrayValue($params, 'cut_first'); if ($cut_first && mb_strlen($title) > $cut_first) { if (!preg_match('/<a href="(.*)">(.*)<\/a>/',$title)) { $title = mb_substr($title, 0, $cut_first).' ...'; } } return $title; } function getInfo(&$object, $info_type) { switch ($info_type) { case 'titlefield': $field = $this->Application->getUnitOption($object->Prefix,'TitleField'); return $field !== false ? $object->GetField($field) : 'TitleField Missing'; break; case 'recordcount': $of_phrase = $this->Application->Phrase('la_of'); return $object->NoFilterCount != $object->RecordsCount ? $object->RecordsCount.' '.$of_phrase.' '.$object->NoFilterCount : $object->RecordsCount; break; default: return $object->GetField($info_type); break; } } function GridInfo($params) { $object =& $this->GetList($params); /* @var $object kDBList */ switch ($params['type']) { case 'filtered': return $object->GetRecordsCount(); case 'total': return $object->GetNoFilterCount(); case 'from': return $object->RecordsCount ? $object->Offset+1 : 0; //0-based case 'to': return $object->PerPage > 0 ? min($object->Offset + $object->PerPage, $object->RecordsCount) : $object->RecordsCount; case 'total_pages': return $object->GetTotalPages(); case 'needs_pagination': return ($object->PerPage != -1) && (($object->RecordsCount > $object->PerPage) || ($object->Page > 1)); } } /** * Parses block depending on its element type. * For radio and select elements values are taken from 'value_list_field' in key1=value1,key2=value2 * format. key=value can be substituted by <SQL>SELECT f1 AS OptionName, f2 AS OptionValue... FROM <PREFIX>TableName </SQL> * where prefix is TABLE_PREFIX * * @param Array $params * @return string */ function ConfigFormElement($params) { $object =& $this->getObject($params); $field = $params['field']; $helper =& $this->Application->recallObject('InpCustomFieldsHelper'); /* @var $helper InpCustomFieldsHelper */ $element_type = $object->GetDBField($params['element_type_field']); if($element_type == 'label') $element_type = 'text'; $params['name'] = $params['blocks_prefix'].$element_type; switch ($element_type) { case 'select': case 'multiselect': case 'radio': $field_options = $object->GetFieldOptions($field, 'options'); if ($object->GetDBField('DirectOptions')) { // used for custom fields $field_options['options'] = $object->GetDBField('DirectOptions'); } else { // used for configuration $field_options['options'] = $helper->GetValuesHash($object->GetDBField($params['value_list_field']), ','); } $object->SetFieldOptions($field, $field_options); break; case 'text': case 'textarea': $params['field_params'] = $helper->ParseConfigSQL($object->GetDBField($params['value_list_field'])); break; case 'password': case 'checkbox': default: break; } return $this->Application->ParseBlock($params, 1); } /** * Get's requested custom field value * * @param Array $params * @return string * @access public */ function CustomField($params) { $params['name'] = 'cust_'.$this->SelectParam($params, 'name,field'); return $this->Field($params); } function CustomFieldLabel($params) { $object =& $this->getObject($params); $field = $this->SelectParam($params, 'name,field'); $sql = 'SELECT FieldLabel FROM '.$this->Application->getUnitOption('cf', 'TableName').' WHERE FieldName = '.$this->Conn->qstr($field); return $this->Application->Phrase($this->Conn->GetOne($sql)); } /** * transposes 1-dimensional array elements for vertical alignment according to given columns and per_page parameters * * @param array $arr * @param int $columns * @param int $per_page * @return array */ function LinearToVertical(&$arr, $columns, $per_page) { $rows = $columns; // in case if after applying per_page limit record count less then // can fill requrested column count, then fill as much as we can $cols = min(ceil($per_page / $columns), ceil(count($arr) / $columns)); $imatrix = array(); for ($row = 0; $row < $rows; $row++) { for ($col = 0; $col < $cols; $col++) { $source_index = $row * $cols + $col; if (!isset($arr[$source_index])) { // in case if source array element count is less then element count in one row continue; } $imatrix[$col * $rows + $row] = $arr[$source_index]; } } ksort($imatrix); return array_values($imatrix); } /** * If data was modfied & is in TempTables mode, then parse block with name passed; * remove modification mark if not in TempTables mode * * @param Array $params * @return string * @access public * @author Alexey */ function SaveWarning($params) { $main_prefix = getArrayValue($params, 'main_prefix'); if ($main_prefix && $main_prefix != '$main_prefix') { $top_prefix = $main_prefix; } else { $top_prefix = $this->Application->GetTopmostPrefix($this->Prefix); } $temp_tables = substr($this->Application->GetVar($top_prefix.'_mode'), 0, 1) == 't'; $modified = $this->Application->RecallVar($top_prefix.'_modified'); if ($temp_tables && $modified) { $block_params = $this->prepareTagParams($params); $block_params['name'] = $this->SelectParam($params, 'render_as,name'); $block_params['edit_mode'] = $temp_tables ? 1 : 0; return $this->Application->ParseBlock($block_params); } $this->Application->RemoveVar($top_prefix.'_modified'); return ''; } /** * Returns list record count queries (on all pages) * * @param Array $params * @return int */ function TotalRecords($params) { $list =& $this->GetList($params); if (!$list->Counted) $list->CountRecs(); return $list->RecordsCount; } /** * Range filter field name * * @param Array $params * @return string */ function SearchInputName($params) { $field = $this->SelectParam($params, 'field,name'); $ret = 'custom_filters['.$this->getPrefixSpecial().']['.$params['grid'].']['.$field.']['.$params['filter_type'].']'; if (isset($params['type'])) { $ret .= '['.$params['type'].']'; } return $ret; } /** * Return range filter field value * * @param Array $params * @return string */ function SearchField($params) // RangeValue { $field = $this->SelectParam($params, 'field,name'); $view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view'); $custom_filter = $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_custom_filter.'.$view_name/*, ALLOW_DEFAULT_SETTINGS*/); $custom_filter = $custom_filter ? unserialize($custom_filter) : Array(); if (isset($custom_filter[ $params['grid'] ][$field])) { $ret = $custom_filter[ $params['grid'] ][$field][ $params['filter_type'] ]['submit_value']; if (isset($params['type'])) { $ret = $ret[ $params['type'] ]; } if( !$this->HasParam($params, 'no_special') ) $ret = htmlspecialchars($ret); return $ret; } return ''; } function SearchFormat($params) { $field = $params['field']; $object =& $this->GetList($params); $options = $object->GetFieldOptions($field); $format = $options[ $this->SelectParam($params, 'input_format') ? 'input_format' : 'format' ]; $formatter_class = getArrayValue($options,'formatter'); if($formatter_class) { $formatter =& $this->Application->recallObject($formatter_class); $human_format = getArrayValue($params,'human'); $edit_size = getArrayValue($params,'edit_size'); $sample = getArrayValue($params,'sample'); if($sample) { return $formatter->GetSample($field, $options, $object); } elseif($human_format || $edit_size) { $format = $formatter->HumanFormat($format); return $edit_size ? strlen($format) : $format; } } return $format; } /** * Returns error of range field * * @param unknown_type $params * @return unknown */ function SearchError($params) { $field = $this->SelectParam($params, 'field,name'); $error_var_name = $this->getPrefixSpecial().'_'.$field.'_error'; $pseudo = $this->Application->RecallVar($error_var_name); if ($pseudo) { $this->Application->RemoveVar($error_var_name); } $object =& $this->Application->recallObject($this->Prefix.'.'.$this->Special.'-item', null, Array('skip_autoload' => true)); /* @var $object kDBItem */ $object->SetError($field, $pseudo); return $object->GetErrorMsg($field, false); } /** * Returns object used in tag processor * * @access public * @return kDBBase */ function &getObject($params = Array()) { $object =& $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix, $params); if (isset($params['requery']) && $params['requery']) { $this->Application->HandleEvent($q_event, $this->getPrefixSpecial().':LoadItem', $params); } return $object; } /** * Checks if object propery value matches value passed * * @param Array $params * @return bool */ function PropertyEquals($params) { $object =& $this->getObject($params); $property_name = $this->SelectParam($params, 'name,var,property'); return $object->$property_name == $params['value']; } /** * Group list records by header, saves internal order in group * * @param Array $records * @param string $heading_field */ function groupRecords(&$records, $heading_field) { $sorted = Array(); $i = 0; $record_count = count($records); while ($i < $record_count) { $sorted[ $records[$i][$heading_field] ][] = $records[$i]; $i++; } $records = Array(); foreach ($sorted as $heading => $heading_records) { $records = array_merge_recursive($records, $heading_records); } } function DisplayOriginal($params) { return false; } - function MultipleEditing($params) + /*function MultipleEditing($params) { $wid = $this->Application->GetTopmostWid($this->Prefix); $session_name = rtrim($this->getPrefixSpecial().'_selected_ids_'.$wid, '_'); $selected_ids = explode(',', $this->Application->RecallVar($session_name)); $ret = ''; if ($selected_ids) { $selected_ids = explode(',', $selected_ids); $object =& $this->getObject( array_merge_recursive2($params, Array('skip_autoload' => true)) ); $params['name'] = $params['render_as']; foreach ($selected_ids as $id) { $object->Load($id); $ret .= $this->Application->ParseBlock($params); } } return $ret; - } + }*/ /** * Returns import/export process percent * * @param Array $params * @return int * @deprecated Please convert to event-model, not tag based */ function ExportStatus($params) { $export_object =& $this->Application->recallObject('CatItemExportHelper'); $event = new kEvent($this->getPrefixSpecial().':OnDummy'); $action_method = 'perform'.ucfirst($this->Special); $field_values = $export_object->$action_method($event); // finish code is done from JS now if ($field_values['start_from'] >= $field_values['total_records']) { if ($this->Special == 'import') { // this is used? $this->Application->StoreVar('PermCache_UpdateRequired', 1); $this->Application->Redirect('categories/cache_updater', Array('m_opener' => 'r', 'pass' => 'm', 'continue' => 1, 'no_amp' => 1)); } elseif ($this->Special == 'export') { // used for orders export in In-Commerce $finish_t = $this->Application->RecallVar('export_finish_t'); $this->Application->Redirect($finish_t, Array('pass' => 'all')); $this->Application->RemoveVar('export_finish_t'); } } $export_options = $export_object->loadOptions($event); return $export_options['start_from'] * 100 / $export_options['total_records']; } /** * Returns path where exported category items should be saved * * @param Array $params */ function ExportPath($params) { $ret = EXPORT_PATH.'/'; if( getArrayValue($params, 'as_url') ) { $ret = str_replace( FULL_PATH.'/', $this->Application->BaseURL(), $ret); } $export_options = unserialize($this->Application->RecallVar($this->getPrefixSpecial().'_options')); $ret .= $export_options['ExportFilename'].'.'.($export_options['ExportFormat'] == 1 ? 'csv' : 'xml'); return $ret; } function FieldTotal($params) { $list =& $this->GetList($params); return $list->GetFormattedTotal($this->SelectParam($params, 'field,name'), $params['function']); } /** * Returns FCKEditor locale, that matches default site language * * @return string */ function _getFCKLanguage() { static $language_code = null; if (!isset($language_code)) { $language_code = 'en'; // defaut value $sql = 'SELECT Locale FROM '. $this->Application->getUnitOption('lang', 'TableName') . ' WHERE LanguageId = ' . $this->Application->GetDefaultLanguageId(); // $this->Application->GetVar('m_lang'); $locale = strtolower( $this->Conn->GetOne($sql) ); if (file_exists(FULL_PATH . EDITOR_PATH . 'editor/lang/' . $locale . '.js')) { // found language file, that exactly matches locale name (e.g. "en") $language_code = $locale; } else { $locale = explode('-', $locale); if (file_exists(FULL_PATH . EDITOR_PATH . 'editor/lang/' . $locale[0] . '.js')) { // language file matches first part of locale (e.g. "ru-RU") $language_code = $locale[0]; } } } return $language_code; } function FCKEditor($params) { $params['no_special'] = 1; $params['format'] = array_key_exists('format', $params) ? $params['format'] . ';fck_ready' : 'fck_ready'; $value = $this->Field($params); $name = array_key_exists('name', $params) ? $params['name'] : $this->InputName($params); $theme_path = substr($this->Application->GetFrontThemePath(), 1) . '/inc/'; if (!file_exists(FULL_PATH . '/' . $theme_path . 'style.css')) { $theme_path = EDITOR_PATH; } $styles_xml = $this->Application->BaseURL() . $theme_path . 'styles.xml'; $styles_css = $this->Application->BaseURL() . $theme_path . 'style.css'; $bgcolor = array_key_exists('bgcolor', $params) ? $params['bgcolor'] : $this->Application->GetVar('bgcolor'); if (!$bgcolor) { $bgcolor = '#ffffff'; } $preview_url = ''; $page_id = $this->Application->GetVar('c_id'); $content_id = $this->Application->GetVar('content_id'); if ($page_id && $content_id) { // editing content block from Front-End, not category in admin $sql = 'SELECT NamedParentPath FROM ' . $this->Application->getUnitOption('c', 'TableName') . ' WHERE ' . $this->Application->getUnitOption('c', 'IDField') . ' = ' . $page_id; $template = strtolower( $this->Conn->GetOne($sql) ); - $url_params = Array ('m_cat_id' => $page_id, 'no_amp' => 1, 'editing_mode' => EDITING_MODE_CMS, 'pass' => 'm'); + $url_params = Array ('m_cat_id' => $page_id, 'no_amp' => 1, 'editing_mode' => EDITING_MODE_CONTENT, 'pass' => 'm'); $preview_url = $this->Application->HREF($template, '_FRONT_END_', $url_params, 'index.php'); $preview_url = preg_replace('/&(admin|editing_mode)=[\d]/', '', $preview_url); } include_once(FULL_PATH . EDITOR_PATH . 'fckeditor.php'); $oFCKeditor = new FCKeditor($name); $oFCKeditor->FullUrl = $this->Application->BaseURL(); $oFCKeditor->BaseUrl = BASE_PATH . '/'; $oFCKeditor->BasePath = BASE_PATH . EDITOR_PATH; $oFCKeditor->Width = $params['width'] ; $oFCKeditor->Height = $params['height'] ; $oFCKeditor->ToolbarSet = $page_id && $content_id ? 'Advanced' : 'Default'; $oFCKeditor->Value = $value; $oFCKeditor->PreviewUrl = $preview_url; $oFCKeditor->DefaultLanguage = $this->_getFCKLanguage(); $oFCKeditor->LateLoad = array_key_exists('late_load', $params) && $params['late_load']; $oFCKeditor->Config = Array ( //'UserFilesPath' => $pathtoroot.'kernel/user_files', 'ProjectPath' => BASE_PATH . '/', 'CustomConfigurationsPath' => $this->Application->BaseURL() . 'core/admin_templates/js/inp_fckconfig.js', 'StylesXmlPath' => $styles_xml, 'EditorAreaCSS' => $styles_css, 'DefaultStyleLabel' => $this->Application->Phrase('la_editor_default_style'), // 'Debug' => 1, 'Admin' => 1, 'K4' => 1, 'newBgColor' => $bgcolor, 'PreviewUrl' => $preview_url, 'BaseUrl' => BASE_PATH . '/', 'DefaultLanguage' => $this->_getFCKLanguage(), 'EditorAreaStyles' => 'body { background-color: '.$bgcolor.' }', ); return $oFCKeditor->CreateHtml(); } function IsNewItem($params) { $object =& $this->getObject($params); return $object->IsNewItem(); } /** * Creates link to an item including only it's id * * @param Array $params * @return string */ function ItemLink($params) { $object =& $this->getObject($params); if (!isset($params['pass'])) { $params['pass'] = 'm'; } $params[$object->getPrefixSpecial().'_id'] = $object->GetID(); $m =& $this->Application->recallObject('m_TagProcessor'); return $m->t($params); } /** * Calls OnNew event from template, when no other event submitted * * @param Array $params */ function PresetFormFields($params) { $prefix = $this->getPrefixSpecial(); if (!$this->Application->GetVar($prefix.'_event')) { $this->Application->HandleEvent(new kEvent($prefix.':OnNew')); } } function PrintSerializedFields($params) { $object =& $this->getObject(); $field = $this->SelectParam($params, 'field'); $data = unserialize($object->GetDBField($field)); $o = ''; $std_params['name'] = $params['render_as']; $std_params['field'] = $params['field']; $std_params['pass_params'] = true; foreach ($data as $key => $row) { $block_params = array_merge($std_params, $row, array('key'=>$key)); $o .= $this->Application->ParseBlock($block_params); } return $o; } /** * Checks if current prefix is main item * * @param Array $params * @return bool */ function IsTopmostPrefix($params) { return $this->Prefix == $this->Application->GetTopmostPrefix($this->Prefix); } function PermSection($params) { $section = $this->SelectParam($params, 'section,name'); $perm_sections = $this->Application->getUnitOption($this->Prefix, 'PermSection'); return isset($perm_sections[$section]) ? $perm_sections[$section] : ''; } function PerPageSelected($params) { $list =& $this->GetList($params); return $list->PerPage == $params['per_page'] ? $params['selected'] : ''; } /** * Returns prefix + generated sepcial + any word * * @param Array $params * @return string */ function VarName($params) { $list =& $this->GetList($params); return $list->getPrefixSpecial().'_'.$params['type']; } /** * Returns edit tabs by specified preset name or false in case of error * * @param string $preset_name * @return mixed */ function getEditTabs($preset_name) { $presets = $this->Application->getUnitOption($this->Prefix, 'EditTabPresets'); if (!$presets || !isset($presets[$preset_name]) || count($presets[$preset_name]) == 0) { return false; } return count($presets[$preset_name]) > 1 ? $presets[$preset_name] : false; } /** * Detects if specified preset has tabs in it * * @param Array $params * @return bool */ function HasEditTabs($params) { return $this->getEditTabs($params['preset_name']) ? true : false; } /** * Sorts edit tabs based on their priority * * @param Array $tab_a * @param Array $tab_b * @return int */ function sortEditTabs($tab_a, $tab_b) { if ($tab_a['priority'] == $tab_b['priority']) { return 0; } return $tab_a['priority'] < $tab_b['priority'] ? -1 : 1; } /** * Prints edit tabs based on preset name specified * * @param Array $params * @return string */ function PrintEditTabs($params) { $edit_tabs = $this->getEditTabs($params['preset_name']); if (!$edit_tabs) { return ; } usort($edit_tabs, Array (&$this, 'sortEditTabs')); $ret = ''; $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['render_as']; foreach ($edit_tabs as $tab_info) { $block_params['title'] = $tab_info['title']; $block_params['template'] = $tab_info['t']; $ret .= $this->Application->ParseBlock($block_params); } return $ret; } /** * Performs image resize to required dimensions and returns resulting url (cached resized image) * * @param Array $params * @return string */ function ImageSrc($params) { $max_width = isset($params['MaxWidth']) ? $params['MaxWidth'] : false; $max_height = isset($params['MaxHeight']) ? $params['MaxHeight'] : false; $logo_filename = isset($params['LogoFilename']) ? $params['LogoFilename'] : false; $logo_h_margin = isset($params['LogoHMargin']) ? $params['LogoHMargin'] : false; $logo_v_margin = isset($params['LogoVMargin']) ? $params['LogoVMargin'] : false; $object =& $this->getObject($params); $field = $this->SelectParam($params, 'name,field'); return $object->GetField($field, 'resize:'.$max_width.'x'.$max_height.';wm:'.$logo_filename.'|'.$logo_h_margin.'|'.$logo_v_margin); } /** * Allows to retrieve given setting from unit config * * @param Array $params * @return mixed */ function UnitOption($params) { return $this->Application->getUnitOption($this->Prefix, $params['name']); } /** * Returns list of allowed toolbar buttons or false, when all is allowed * * @param Array $params * @return string */ function VisibleToolbarButtons($params) { $preset_name = replaceModuleSection($params['title_preset']); $title_presets = $this->Application->getUnitOption($this->Prefix, 'TitlePresets'); if (!array_key_exists($preset_name, $title_presets)) { trigger_error('Title preset not specified or missing (in tag "<strong>' . $this->getPrefixSpecial() . ':' . __METHOD__ . '</strong>")', E_USER_WARNING); return false; } $preset_info = $title_presets[$preset_name]; if (!array_key_exists('toolbar_buttons', $preset_info) || !is_array($preset_info['toolbar_buttons'])) { return false; } // always add search buttons array_push($preset_info['toolbar_buttons'], 'search', 'search_reset_alt'); $toolbar_buttons = array_map('addslashes', $preset_info['toolbar_buttons']); return $toolbar_buttons ? "'" . implode("', '", $toolbar_buttons) . "'" : 'false'; } /** * Checks, that "To" part of at least one of range filters is used * * @param Array $params * @return bool */ function RangeFiltersUsed($params) { $search_helper =& $this->Application->recallObject('SearchHelper'); /* @var $search_helper kSearchHelper */ return $search_helper->rangeFiltersUsed($this->getPrefixSpecial(), $params['grid']); } /** * This is abstract tag, used to modify unit config data based on template, where it's used. * Tag is called from "combined_header" block in admin only. * * @param Array $params */ function ModifyUnitConfig($params) { } /** * Checks, that field is visible on edit form * * @param Array $params * @return bool */ function FieldVisible($params) { $check_field = $params['field']; $fields = $this->Application->getUnitOption($this->Prefix, 'Fields'); if (!array_key_exists($check_field, $fields)) { // field not found in real fields array -> it's 100% virtual then $fields = $this->Application->getUnitOption($this->Prefix, 'VirtualFields'); } if (!array_key_exists($check_field, $fields)) { $params['field'] = 'Password'; return $check_field == 'VerifyPassword' ? $this->FieldVisible($params) : true; } $show_mode = array_key_exists('show_mode', $fields[$check_field]) ? $fields[$check_field]['show_mode'] : true; if ($show_mode === smDEBUG) { return defined('DEBUG_MODE') && DEBUG_MODE; } return $show_mode; } /** * Checks, that there area visible fields in given section on edit form * * @param Array $params * @return bool */ function FieldsVisible($params) { if (!$params['fields']) { return true; } $check_fields = explode(',', $params['fields']); $fields = $this->Application->getUnitOption($this->Prefix, 'Fields'); $virtual_fields = $this->Application->getUnitOption($this->Prefix, 'VirtualFields'); foreach ($check_fields as $check_field) { // when at least one field in subsection is visible, then subsection is visible too if (array_key_exists($check_field, $fields)) { $show_mode = array_key_exists('show_mode', $fields[$check_field]) ? $fields[$check_field]['show_mode'] : true; } else { $show_mode = array_key_exists('show_mode', $virtual_fields[$check_field]) ? $virtual_fields[$check_field]['show_mode'] : true; } if (($show_mode === true) || (($show_mode === smDEBUG) && (defined('DEBUG_MODE') && DEBUG_MODE))) { // field is visible return true; } } return false; } } ?> \ No newline at end of file Index: branches/5.0.x/core/kernel/db/dbitem.php =================================================================== --- branches/5.0.x/core/kernel/db/dbitem.php (revision 12297) +++ branches/5.0.x/core/kernel/db/dbitem.php (revision 12298) @@ -1,1297 +1,1301 @@ <?php /** * @version $Id$ * @package In-Portal * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. * @license GNU/GPL * In-Portal is Open Source software. * This means that this software may have been modified pursuant * the GNU General Public License, and as distributed it includes * or is derivative of works licensed under the GNU General Public License * or other free or open source software licenses. * See http://www.in-portal.net/license/ for copyright notices and details. */ /** * DBItem * * Desciption * @package kernel4 */ class kDBItem extends kDBBase { /** * Description * * @var array Associative array of current item' field values * @access public */ var $FieldValues; /** * Unformatted field values, before parse * * @var Array * @access private */ var $DirtyFieldValues = Array(); /** * Holds item values after loading (not affected by submit) * * @var Array * @access private */ var $OriginalFieldValues = Array (); var $FieldErrors; var $ErrorMsgs = Array(); /** * If set to true, Update will skip Validation before running * * @var array Associative array of current item' field values * @access public */ var $IgnoreValidation = false; var $Loaded = false; /** * Holds item' primary key value * * @var int Value of primary key field for current item * @access public */ var $ID; function kDBItem() { parent::kDBBase(); $this->ErrorMsgs['required'] = '!la_err_required!'; //'Field is required'; $this->ErrorMsgs['unique'] = '!la_err_unique!'; //'Field value must be unique'; $this->ErrorMsgs['value_out_of_range'] = '!la_err_value_out_of_range!'; //'Field is out of range, possible values from %s to %s'; $this->ErrorMsgs['length_out_of_range'] = '!la_err_length_out_of_range!'; //'Field is out of range'; $this->ErrorMsgs['bad_type'] = '!la_err_bad_type!'; //'Incorrect data format, please use %s'; $this->ErrorMsgs['invalid_format'] = '!la_err_invalid_format!'; //'Incorrect data format, please use %s'; $this->ErrorMsgs['bad_date_format'] = '!la_err_bad_date_format!'; //'Incorrect date format, please use (%s) ex. (%s)'; $this->ErrorMsgs['primary_lang_required'] = '!la_err_primary_lang_required!'; } function SetDirtyField($field_name, $field_value) { $this->DirtyFieldValues[$field_name] = $field_value; } function GetDirtyField($field_name) { return $this->DirtyFieldValues[$field_name]; } function GetOriginalField($field_name, $formatted = false, $format=null) { if (array_key_exists($field_name, $this->OriginalFieldValues)) { // item was loaded before $value = $this->OriginalFieldValues[$field_name]; } else { // no original fields -> use default field value $value = $this->Fields[$field_name]['default']; } if (!$formatted) { return $value; } $options = $this->GetFieldOptions($field_name); $res = $value; if (array_key_exists('formatter', $options)) { $formatter =& $this->Application->recallObject($options['formatter']); /* @var $formatter kFormatter */ $res = $formatter->Format($value, $field_name, $this, $format); } return $res; } /** * Sets original field value (useful for custom virtual fields) * * @param string $field_name */ function SetOriginalField($field_name, $field_value) { $this->OriginalFieldValues[$field_name] = $field_value; } /** * Set's default values for all fields * * @param bool $populate_ml_fields create all ml fields from db in config or not * * @access public */ function SetDefaultValues($populate_ml_fields = false) { parent::SetDefaultValues($populate_ml_fields); if ($populate_ml_fields) { $this->PopulateMultiLangFields(); } foreach ($this->Fields as $field => $params) { if ( isset($params['default']) ) { $this->SetDBField($field, $params['default']); } else { $this->SetDBField($field, NULL); } } } /** * Sets current item field value * (applies formatting) * * @access public * @param string $name Name of the field * @param mixed $value Value to set the field to * @return void */ function SetField($name,$value) { $options = $this->GetFieldOptions($name); $parsed = $value; if ($value == '') { $parsed = NULL; } // kFormatter is always used, to make sure, that numeric value is converted to normal representation // according to regional format, even when formatter is not set (try seting format to 1.234,56 to understand why) $formatter =& $this->Application->recallObject(isset($options['formatter']) ? $options['formatter'] : 'kFormatter'); $parsed = $formatter->Parse($value, $name, $this); $this->SetDBField($name,$parsed); } /** * Sets current item field value * (doesn't apply formatting) * * @access public * @param string $name Name of the field * @param mixed $value Value to set the field to * @return void */ function SetDBField($name,$value) { $this->FieldValues[$name] = $value; /*if (isset($this->Fields[$name]['formatter'])) { $formatter =& $this->Application->recallObject($this->Fields[$name]['formatter']); $formatter->UpdateSubFields($name, $value, $this->Fields[$name], $this); }*/ } /** * Set's field error, if pseudo passed not found then create it with message text supplied. * Don't owerrite existing pseudo translation. * * @param string $field * @param string $pseudo * @param string $error_label * * @return bool */ function SetError($field, $pseudo, $error_label = null, $error_params = null) { $error_field = isset($this->Fields[$field]['error_field']) ? $this->Fields[$field]['error_field'] : $field; if (isset($this->FieldErrors[$error_field]['pseudo'])) { // don't set more then one error on field return false; } $this->FieldErrors[$error_field]['pseudo'] = $pseudo; if (isset($error_params)) { // additional params, that helps to determine error sources $this->FieldErrors[$error_field]['params'] = $error_params; } if (isset($error_label) && !isset($this->ErrorMsgs[$pseudo])) { // label for error (only when not already set) $this->ErrorMsgs[$pseudo] = (substr($error_label, 0, 1) == '+') ? substr($error_label, 1) : '!'.$error_label.'!'; } return true; } /** * Return current item' field value by field name * (doesn't apply formatter) * * @access public * @param string $name field name to return * @return mixed */ function GetDBField($name) { + /*if (!array_key_exists($name, $this->FieldValues) && defined('DEBUG_MODE') && DEBUG_MODE) { + $this->Application->Debugger->appendTrace(); + }*/ + return $this->FieldValues[$name]; } function HasField($name) { return isset($this->FieldValues[$name]); } function GetFieldValues() { return $this->FieldValues; } /** * Sets item' fields corresponding to elements in passed $hash values. * * The function sets current item fields to values passed in $hash, by matching $hash keys with field names * of current item. If current item' fields are unknown {@link kDBItem::PrepareFields()} is called before acutally setting the fields * * @access public * @param Array $hash * @param Array $set_fields Optional param, field names in target object to set, other fields will be skipped * @return void */ function SetFieldsFromHash($hash, $set_fields = null) { // used in formatter which work with multiple fields together foreach($hash as $field_name => $field_value) { if (is_numeric($field_name) || !array_key_exists($field_name, $this->Fields)) { continue; } if (is_array($set_fields) && !in_array($field_name, $set_fields)) { continue; } $this->SetDirtyField($field_name, $field_value); } // formats all fields using associated formatters foreach ($hash as $field_name => $field_value) { if (is_numeric($field_name) || !array_key_exists($field_name, $this->Fields)) { continue; } if (is_array($set_fields) && !in_array($field_name, $set_fields)) { continue; } $this->SetField($field_name,$field_value); } } function SetDBFieldsFromHash($hash, $set_fields = null) { foreach ($hash as $field_name => $field_value) { if (is_numeric($field_name) || !array_key_exists($field_name, $this->Fields)) { continue; } if (is_array($set_fields) && !in_array($field_name, $set_fields)) { continue; } $this->SetDBField($field_name, $field_value); } } /** * Returns part of SQL WHERE clause identifing the record, ex. id = 25 * * @access public * @param string $method Child class may want to know who called GetKeyClause, Load(), Update(), Delete() send its names as method * @param Array $keys_hash alternative, then item id, keys hash to load item by * @return void * @see kDBItem::Load() * @see kDBItem::Update() * @see kDBItem::Delete() */ function GetKeyClause($method=null, $keys_hash = null) { if( !isset($keys_hash) ) $keys_hash = Array($this->IDField => $this->ID); $ret = ''; foreach($keys_hash as $field => $value) { if (!preg_match('/\./', $field)) { $ret .= '(`'.$this->TableName.'`.'.$field.' = '.$this->Conn->qstr($value).') AND '; } else { $ret .= '('.$field.' = '.$this->Conn->qstr($value).') AND '; } } return preg_replace('/(.*) AND $/', '\\1', $ret); } /** * Loads item from the database by given id * * @access public * @param mixed $id item id of keys->values hash to load item by * @param string $id_field_name Optional parameter to load item by given Id field * @return bool True if item has been loaded, false otherwise */ function Load($id, $id_field_name = null) { if ( isset($id_field_name) ) { $this->SetIDField($id_field_name); // set new IDField } $keys_sql = ''; if (is_array($id)) { $keys_sql = $this->GetKeyClause('load', $id); } else { $this->setID($id); $keys_sql = $this->GetKeyClause('load'); } if ( isset($id_field_name) ) { // restore original IDField from unit config $this->setIDField( $this->Application->getUnitOption($this->Prefix, 'IDField') ); } if (($id === false) || !$keys_sql) { return $this->Clear(); } if (!$this->raiseEvent('OnBeforeItemLoad', $id)) { return false; } $q = $this->GetSelectSQL() . ' WHERE ' . $keys_sql; $field_values = $this->Conn->GetRow($q); if ($field_values) { $this->FieldValues = array_merge_recursive2($this->FieldValues, $field_values); $this->OriginalFieldValues = $this->FieldValues; } else { return $this->Clear(); } if (is_array($id) || isset($id_field_name)) { $this->setID($this->FieldValues[$this->IDField]); } $this->UpdateFormattersSubFields(); // used for updating separate virtual date/time fields from DB timestamp (for example) $this->raiseEvent('OnAfterItemLoad', $this->GetID()); $this->Loaded = true; return true; } /** * Builds select sql, SELECT ... FROM parts only * * @access public * @return string */ function GetSelectSQL() { $sql = $this->addCalculatedFields($this->SelectClause); return parent::GetSelectSQL($sql); } function UpdateFormattersMasterFields() { foreach ($this->Fields as $field => $options) { if (isset($options['formatter'])) { $formatter =& $this->Application->recallObject($options['formatter']); $formatter->UpdateMasterFields($field, $this->GetDBField($field), $options, $this); } } } /** * Allows to skip certain fields from getting into sql queries * * @param string $field_name * @param mixed $force_id * @return bool */ function skipField($field_name, $force_id = false) { $skip = false; // 1. skipping 'virtual' field $skip = $skip || array_key_exists($field_name, $this->VirtualFields); // 2. don't write empty field value to db, when "skip_empty" option is set $field_value = array_key_exists($field_name, $this->FieldValues) ? $this->FieldValues[$field_name] : false; $skip_empty = array_key_exists('skip_empty', $this->Fields[$field_name]) ? $this->Fields[$field_name]['skip_empty'] : false; $skip = $skip || (!$field_value && $skip_empty); // 3. skipping field not in Fields (nor virtual, nor real) $skip = $skip || !array_key_exists($field_name, $this->Fields); return $skip; } /** * Updates previously loaded record with current item' values * * @access public * @param int Primery Key Id to update * @return bool */ function Update($id = null, $system_update = false) { if (isset($id)) { $this->setID($id); } if (!$this->raiseEvent('OnBeforeItemUpdate')) { return false; } if (!isset($this->ID)) { // ID could be set inside OnBeforeItemUpdate event, so don't combine this check with previous one return false; } // validate before updating if (!$this->Validate()) { return false; } if (!$this->raiseEvent('OnAfterItemValidate')) { return false; } if (!$this->FieldValues) { // nothing to update return true; } $sql = ''; foreach ($this->FieldValues as $field_name => $field_value) { if ($this->skipField($field_name)) { continue; } if ( is_null($field_value) ) { if (array_key_exists('not_null', $this->Fields[$field_name]) && $this->Fields[$field_name]['not_null']) { // "kFormatter::Parse" methods converts empty values to NULL and for // not-null fields they are replaced with default value here $field_value = $this->Fields[$field_name]['default']; } } $sql .= '`' . $field_name . '` = ' . $this->Conn->qstr($field_value) . ', '; } $sql = 'UPDATE ' . $this->TableName . ' SET ' . substr($sql, 0, -2) . ' WHERE ' . $this->GetKeyClause('update'); if ($this->Conn->ChangeQuery($sql) === false) { // there was and sql error return false; } $affected = $this->Conn->getAffectedRows(); if (!$system_update && $affected == 1) { $this->setModifiedFlag(clUPDATE); } $this->saveCustomFields(); $this->raiseEvent('OnAfterItemUpdate'); $this->Loaded = true; if ($this->mode != 't') { $this->Application->resetCounters($this->TableName); } return true; } function ValidateField($field) { $options = $this->Fields[$field]; /*if (isset($options['formatter'])) { $formatter =& $this->Application->recallObject($options['formatter']); $formatter->UpdateMasterFields($field, $this->GetDBField($field), $options, $this); }*/ $error_field = isset($options['error_field']) ? $options['error_field'] : $field; $res = !isset($this->FieldErrors[$error_field]['pseudo']) || !$this->FieldErrors[$error_field]['pseudo']; $res = $res && $this->ValidateRequired($field, $options); $res = $res && $this->ValidateType($field, $options); $res = $res && $this->ValidateRange($field, $options); $res = $res && $this->ValidateUnique($field, $options); $res = $res && $this->CustomValidation($field, $options); return $res; } /** * Validate all item fields based on * constraints set in each field options * in config * * @return bool * @access private */ function Validate() { $this->UpdateFormattersMasterFields(); //order is critical - should be called BEFORE checking errors if ($this->IgnoreValidation) { return true; } $global_res = true; foreach ($this->Fields as $field => $params) { $res = $this->ValidateField($field); $global_res = $global_res && $res; } if (!$global_res && $this->Application->isDebugMode()) { $error_msg = ' Validation failed in prefix <strong>'.$this->Prefix.'</strong>, FieldErrors follow (look at items with <strong>"pseudo"</strong> key set)<br /> You may ignore this notice if submitted data really has a validation error'; trigger_error(trim($error_msg), E_USER_NOTICE); $this->Application->Debugger->dumpVars($this->FieldErrors); } return $global_res; } /** * Check field value by user-defined alghoritm * * @param string $field field name * @param Array $params field options from config * @return bool */ function CustomValidation($field, $params) { return true; } /** * Check if item has errors * * @param Array $skip_fields fields to skip during error checking * @return bool */ function HasErrors($skip_fields) { $global_res = false; foreach ($this->Fields as $field => $field_params) { // If Formatter has set some error messages during values parsing if ( !( in_array($field, $skip_fields) ) && isset($this->FieldErrors[$field]['pseudo']) && $this->FieldErrors[$field] != '') { $global_res = true; } } return $global_res; } /** * Check if value in field matches field type specified in config * * @param string $field field name * @param Array $params field options from config * @return bool */ function ValidateType($field, $params) { $res = true; $val = $this->FieldValues[$field]; if ( $val != '' && isset($params['type']) && preg_match("#int|integer|double|float|real|numeric|string#", $params['type']) ) { if ($params['type'] == 'numeric') { trigger_error('Invalid field type <strong>'.$params['type'].'</strong> (in ValidateType method), please use <strong>float</strong> instead', E_USER_NOTICE); $params['type'] = 'float'; } $res = is_numeric($val); if ($params['type']=='string' || $res) { $f = 'is_'.$params['type']; settype($val, $params['type']); $res = $f($val) && ($val == $this->FieldValues[$field]); } if (!$res) { $this->SetError($field, 'bad_type', null, $params['type']); } } return $res; } /** * Check if value is set for required field * * @param string $field field name * @param Array $params field options from config * @return bool * @access private */ function ValidateRequired($field, $params) { $res = true; if (isset($params['required']) && $params['required']) { $check_value = $this->FieldValues[$field]; if ($this->Application->ConfigValue('TrimRequiredFields')) { $check_value = trim($check_value); } $res = ((string)$check_value != ''); } if (!$res) { $this->SetError($field, 'required'); } return $res; } /** * Validates that current record has unique field combination among other table records * * @param string $field field name * @param Array $params field options from config * @return bool * @access private */ function ValidateUnique($field, $params) { $res = true; $unique_fields = getArrayValue($params,'unique'); if($unique_fields !== false) { $where = Array(); array_push($unique_fields,$field); foreach($unique_fields as $unique_field) { // if field is not empty or if it is required - we add where condition if ((string)$this->GetDBField($unique_field) != '' || (isset($this->Fields[$unique_field]['required']) && $this->Fields[$unique_field]['required'])) { $where[] = '`'.$unique_field.'` = '.$this->Conn->qstr( $this->GetDBField($unique_field) ); } else { // not good if we check by less fields than indicated return true; } } // This can ONLY happen if all unique fields are empty and not required. // In such case we return true, because if unique field is not required there may be numerous empty values // if (!$where) return true; $sql = 'SELECT COUNT(*) FROM %s WHERE ('.implode(') AND (',$where).') AND ('.$this->IDField.' <> '.(int)$this->ID.')'; $res_temp = $this->Conn->GetOne( str_replace('%s', $this->TableName, $sql) ); $current_table_only = getArrayValue($params, 'current_table_only'); // check unique record only in current table $res_live = $current_table_only ? 0 : $this->Conn->GetOne( str_replace('%s', $this->Application->GetLiveName($this->TableName), $sql) ); $res = ($res_temp == 0) && ($res_live == 0); if (!$res) { $this->SetError($field, 'unique'); } } return $res; } /** * Check if field value is in range specified in config * * @param string $field field name * @param Array $params field options from config * @return bool * @access private */ function ValidateRange($field, $params) { $res = true; $val = $this->FieldValues[$field]; if ( isset($params['type']) && preg_match("#int|integer|double|float|real#", $params['type']) && strlen($val) > 0 ) { if ( isset($params['max_value_inc'])) { $res = $res && $val <= $params['max_value_inc']; $max_val = $params['max_value_inc'].' (inclusive)'; } if ( isset($params['min_value_inc'])) { $res = $res && $val >= $params['min_value_inc']; $min_val = $params['min_value_inc'].' (inclusive)'; } if ( isset($params['max_value_exc'])) { $res = $res && $val < $params['max_value_exc']; $max_val = $params['max_value_exc'].' (exclusive)'; } if ( isset($params['min_value_exc'])) { $res = $res && $val > $params['min_value_exc']; $min_val = $params['min_value_exc'].' (exclusive)'; } } if (!$res) { if ( !isset($min_val) ) $min_val = '-∞'; if ( !isset($max_val) ) $max_val = '∞'; $this->SetError($field, 'value_out_of_range', null, Array ($min_val, $max_val)); return $res; } if ( isset($params['max_len'])) { $res = $res && mb_strlen($val) <= $params['max_len']; } if ( isset($params['min_len'])) { $res = $res && mb_strlen($val) >= $params['min_len']; } if (!$res) { $error_params = Array (getArrayValue($params, 'min_len'), getArrayValue($params, 'max_len')); $this->SetError($field, 'length_out_of_range', null, $error_params); return $res; } return $res; } /** * Return error message for field * * @param string $field * @return string * @access public */ function GetErrorMsg($field, $force_escape = null) { if( !isset($this->FieldErrors[$field]) ) return ''; $err = getArrayValue($this->FieldErrors[$field], 'pseudo'); if (!$err) return ''; // if special error msg defined in config if( isset($this->Fields[$field]['error_msgs'][$err]) ) { $msg = $this->Fields[$field]['error_msgs'][$err]; } else //fall back to defaults { if( !isset($this->ErrorMsgs[$err]) ) { trigger_error('No user message is defined for pseudo error <b>'.$err.'</b><br>', E_USER_WARNING); return $err; //return the pseudo itself } $msg = $this->ErrorMsgs[$err]; } $msg = $this->Application->ReplaceLanguageTags($msg, $force_escape); if ( isset($this->FieldErrors[$field]['params']) ) { return vsprintf($msg, $this->FieldErrors[$field]['params']); } return $msg; } /** * Creates a record in the database table with current item' values * * @param mixed $force_id Set to TRUE to force creating of item's own ID or to value to force creating of passed id. Do not pass 1 for true, pass exactly TRUE! * @access public * @return bool */ function Create($force_id = false, $system_create = false) { if (!$this->raiseEvent('OnBeforeItemCreate')) { return false; } // Validating fields before attempting to create record if (!$this->Validate()) { return false; } if (!$this->raiseEvent('OnAfterItemValidate')) { return false; } if (is_int($force_id)) { $this->FieldValues[$this->IDField] = $force_id; } elseif (!$force_id || !is_bool($force_id)) { $this->FieldValues[$this->IDField] = $this->generateID(); } $fields_sql = ''; $values_sql = ''; foreach ($this->FieldValues as $field_name => $field_value) { if ($this->skipField($field_name, $force_id)) { continue; } if (is_null($field_value)) { if (array_key_exists('not_null', $this->Fields[$field_name]) && $this->Fields[$field_name]['not_null']) { // "kFormatter::Parse" methods converts empty values to NULL and for // not-null fields they are replaced with default value here $values_sql .= $this->Conn->qstr($this->Fields[$field_name]['default']); } else { $values_sql .= $this->Conn->qstr($field_value); } } else { if (($field_name == $this->IDField) && ($field_value == 0)) { // don't skip IDField in INSERT statement, just use DEFAULT keyword as it's value $values_sql .= 'DEFAULT'; } else { $values_sql .= $this->Conn->qstr($field_value); } } $fields_sql .= '`' . $field_name . '`, '; //Adding field name to fields block of Insert statement $values_sql .= ', '; } $sql = 'INSERT INTO ' . $this->TableName . ' (' . substr($fields_sql, 0, -2) . ') VALUES (' . substr($values_sql, 0, -2) . ')'; //Executing the query and checking the result if ($this->Conn->ChangeQuery($sql) === false) { return false; } $insert_id = $this->Conn->getInsertID(); if ($insert_id == 0) { // insert into temp table (id is not auto-increment field) $insert_id = $this->FieldValues[$this->IDField]; } $this->setID($insert_id); if (!$system_create){ $this->setModifiedFlag(clCREATE); } $this->saveCustomFields(); if ($this->mode != 't') { $this->Application->resetCounters($this->TableName); } $this->raiseEvent('OnAfterItemCreate'); $this->Loaded = true; return true; } /** * Deletes the record from databse * * @access public * @return bool */ function Delete($id = null) { if (isset($id)) { $this->setID($id); } if (!$this->raiseEvent('OnBeforeItemDelete')) { return false; } $sql = 'DELETE FROM ' . $this->TableName . ' WHERE ' . $this->GetKeyClause('Delete'); $ret = $this->Conn->ChangeQuery($sql); $affected_rows = $this->Conn->getAffectedRows(); $this->setModifiedFlag(clDELETE); // will change affected rows, so get it before this line if ($affected_rows > 0) { // something was actually deleted $this->raiseEvent('OnAfterItemDelete'); } if ($this->mode != 't') { $this->Application->resetCounters($this->TableName); } return $ret; } function PopulateMultiLangFields() { $ml_helper =& $this->Application->recallObject('kMultiLanguageHelper'); /* @var $ml_helper kMultiLanguageHelper */ $lang_count = $ml_helper->getLanguageCount(); foreach ($this->Fields as $field => $options) { // master field is set only for CURRENT language if (isset($options['formatter']) && $options['formatter'] == 'kMultiLanguage' && isset($options['master_field'])) { if (preg_match('/^l([0-9]+)_(.*)/', $field, $regs)) { $l = $regs[1]; $name = $regs[2]; // MuliLanguage formatter sets error_field to master_field, but in PopulateMlFields mode, we display ML fields directly // so we set it back to itself, otherwise error will not be displayed $this->Fields['l' . $l . '_' . $name]['error_field'] = 'l' . $l . '_' . $name; for ($i = 1; $i <= $lang_count; $i++) { if ($i == $l || !$ml_helper->LanguageFound($i)) continue; $f_options = $options; $f_options['error_field'] = 'l' . $i . '_' . $name; // set error field back to itself - see comment above if ($i != $this->Application->GetDefaultLanguageId()) { unset($f_options['required']); // all non-primary language field set to non-required } $this->Fields['l' . $i . '_' . $name] = $f_options; } } } } } /** * Sets new name for item in case if it is beeing copied * in same table * * @param array $master Table data from TempHandler * @param int $foreign_key ForeignKey value to filter name check query by * @param string $title_field FieldName to alter, by default - TitleField of the prefix * @param string $format sprintf-style format of renaming pattern, by default Copy %1$s of %2$s which makes it Copy [Number] of Original Name * @access private */ function NameCopy($master=null, $foreign_key=null, $title_field=null, $format='Copy %1$s of %2$s') { if (!isset($title_field)) { $title_field = $this->Application->getUnitOption($this->Prefix, 'TitleField'); if (!$title_field || isset($this->CalculatedFields[$title_field]) ) return; } $new_name = $this->GetDBField($title_field); $original_checked = false; do { if ( preg_match('/'.sprintf($format, '([0-9]*) *', '(.*)').'/', $new_name, $regs) ) { $new_name = sprintf($format, ($regs[1]+1), $regs[2]); } elseif ($original_checked) { $new_name = sprintf($format, '', $new_name); } // if we are cloning in temp table this will look for names in temp table, // since object' TableName contains correct TableName (for temp also!) // if we are cloning live - look in live $query = 'SELECT '.$title_field.' FROM '.$this->TableName.' WHERE '.$title_field.' = '.$this->Conn->qstr($new_name); $foreign_key_field = getArrayValue($master, 'ForeignKey'); $foreign_key_field = is_array($foreign_key_field) ? $foreign_key_field[ $master['ParentPrefix'] ] : $foreign_key_field; if ($foreign_key_field && isset($foreign_key)) { $query .= ' AND '.$foreign_key_field.' = '.$foreign_key; } $res = $this->Conn->GetOne($query); /*// if not found in live table, check in temp table if applicable if ($res === false && $object->Special == 'temp') { $query = 'SELECT '.$name_field.' FROM '.$this->GetTempName($master['TableName']).' WHERE '.$name_field.' = '.$this->Conn->qstr($new_name); $res = $this->Conn->GetOne($query); }*/ $original_checked = true; } while ($res !== false); $this->SetDBField($title_field, $new_name); } function raiseEvent($name, $id = null, $additional_params = Array()) { if( !isset($id) ) $id = $this->GetID(); $event = new kEvent( Array('name'=>$name,'prefix'=>$this->Prefix,'special'=>$this->Special) ); $event->setEventParam('id', $id); if ($additional_params) { foreach ($additional_params as $ap_name => $ap_value) { $event->setEventParam($ap_name, $ap_value); } } $this->Application->HandleEvent($event); return $event->status == erSUCCESS ? true : false; } /** * Set's new ID for item * * @param int $new_id * @access public */ function setID($new_id) { $this->ID = $new_id; $this->SetDBField($this->IDField, $new_id); } /** * Generate and set new temporary id * * @access private */ function setTempID() { $new_id = (int)$this->Conn->GetOne('SELECT MIN('.$this->IDField.') FROM '.$this->TableName); if($new_id > 0) $new_id = 0; --$new_id; $this->Conn->Query('UPDATE '.$this->TableName.' SET `'.$this->IDField.'` = '.$new_id.' WHERE `'.$this->IDField.'` = '.$this->GetID()); if ($this->ShouldLogChanges()) { // Updating TempId in ChangesLog, if changes are disabled $ses_var_name = $this->Application->GetTopmostPrefix($this->Prefix).'_changes_'.$this->Application->GetTopmostWid($this->Prefix); $changes = $this->Application->RecallVar($ses_var_name); $changes = $changes ? unserialize($changes) : Array (); if ($changes) { foreach ($changes as $key => $rec) { if ($rec['Prefix'] == $this->Prefix && $rec['ItemId'] == $this->GetID()) { $changes[$key]['ItemId'] = $new_id; } } } $this->Application->StoreVar($ses_var_name, serialize($changes)); } $this->SetID($new_id); } /** * Set's modification flag for main prefix of current prefix to true * * @access private * @author Alexey */ function setModifiedFlag($mode = null) { $main_prefix = $this->Application->GetTopmostPrefix($this->Prefix); $this->Application->StoreVar($main_prefix.'_modified', '1'); if ($this->ShouldLogChanges()) { $this->LogChanges($main_prefix, $mode); if (!$this->IsTempTable()) { $handler =& $this->Application->recallObject($this->Prefix.'_EventHandler'); $ses_var_name = $main_prefix.'_changes_'.$this->Application->GetTopmostWid($this->Prefix); $handler->SaveLoggedChanges($ses_var_name); } } } /** * Determines, that changes made to this item should be written to change log * * @return bool */ function ShouldLogChanges() { $log_changes = $this->Application->getUnitOption($this->Prefix, 'LogChanges') || $this->Application->ConfigValue('UseChangeLog'); return $log_changes && !$this->Application->getUnitOption($this->Prefix, 'ForceDontLogChanges'); } function LogChanges($main_prefix, $mode) { if (!$mode) { return ; } $ses_var_name = $main_prefix.'_changes_'.$this->Application->GetTopmostWid($this->Prefix); $changes = $this->Application->RecallVar($ses_var_name); $changes = $changes ? unserialize($changes) : array(); $general = array( 'Prefix' => $this->Prefix, 'ItemId' => $this->GetID(), 'OccuredOn' => adodb_mktime(), 'MasterPrefix' => $main_prefix, 'MasterId' => $this->Prefix == $main_prefix ? $this->GetID() : $this->Application->GetVar($main_prefix.'_id'), // is that correct (Kostja)?? 'Action' => $mode, ); switch ($mode) { case clUPDATE: $changes[] = array_merge($general, Array( 'Changes' => serialize(array_merge($this->GetTitleField(), $this->GetChangedFields())), )); break; case clCREATE: $changes[] = array_merge($general, Array( 'Changes' => serialize($this->GetTitleField()), )); break; case clDELETE: $changes[] = array_merge($general, Array( 'Changes' => serialize(array_merge($this->GetTitleField(), $this->GetRealFields())), )); } $this->Application->StoreVar($ses_var_name, serialize($changes)); } function GetTitleField() { $title_field = $this->Application->getUnitOption($this->Prefix, 'TitleField'); if ($title_field && $this->GetField($title_field)) { return Array($title_field => $this->GetField($title_field)); } } function GetRealFields() { if (function_exists('array_diff_key')) { $db_fields = array_diff_key($this->FieldValues, $this->VirtualFields, $this->CalculatedFields); } else { $db_fields = array(); foreach ($this->FieldValues as $key => $value) { if (array_key_exists($key, $this->VirtualFields) || array_key_exists($key, $this->CalculatedFields)) continue; $db_fields[$key] = $value; } } return $db_fields; } function GetChangedFields() { $changes = array(); $diff = array_diff_assoc($this->GetRealFields(), $this->OriginalFieldValues); foreach ($diff as $field => $new_value) { $changes[$field] = array('old' => $this->GetOriginalField($field, true), 'new' => $this->GetField($field)); } return $changes; } /** * Returns ID of currently processed record * * @return int * @access public */ function GetID() { return $this->ID; } /** * Generates ID for new items before inserting into database * * @return int * @access private */ function generateID() { return 0; } /** * Returns true if item was loaded successfully by Load method * * @return bool */ function isLoaded() { return $this->Loaded; } /** * Checks if field is required * * @param string $field * @return bool */ function isRequired($field) { return getArrayValue( $this->Fields[$field], 'required' ); } /** * Sets new required flag to field * * @param string $field * @param bool $is_required */ function setRequired($field, $is_required = true) { $this->Fields[$field]['required'] = $is_required; } function Clear($new_id = null) { $this->Loaded = false; $this->FieldValues = Array(); $this->OriginalFieldValues = Array (); $this->SetDefaultValues(); // will wear off kDBItem::setID effect, so set it later $this->FieldErrors = Array(); $this->setID($new_id); return $this->Loaded; } function Query($force = false) { if( $this->Application->isDebugMode() ) { $this->Application->Debugger->appendTrace(); } trigger_error('<b>Query</b> method is called in class <b>'.get_class($this).'</b> for prefix <b>'.$this->getPrefixSpecial().'</b>', E_USER_ERROR); } function saveCustomFields() { if (!$this->customFields) { return true; } $cdata_key = rtrim($this->Prefix.'-cdata.'.$this->Special, '.'); $cdata =& $this->Application->recallObject($cdata_key, null, Array('skip_autoload' => true, 'populate_ml_fields' => true)); $resource_id = $this->GetDBField('ResourceId'); $cdata->Load($resource_id, 'ResourceId'); $cdata->SetDBField('ResourceId', $resource_id); $ml_formatter =& $this->Application->recallObject('kMultiLanguage'); /* @var $ml_formatter kMultiLanguage */ foreach ($this->customFields as $custom_id => $custom_name) { $force_primary = isset($cdata->Fields['cust_'.$custom_id]['force_primary']) && $cdata->Fields['cust_'.$custom_id]['force_primary']; $cdata->SetDBField($ml_formatter->LangFieldName('cust_'.$custom_id, $force_primary), $this->GetDBField('cust_'.$custom_name)); } if ($cdata->isLoaded()) { $ret = $cdata->Update(); } else { $ret = $cdata->Create(); if ($cdata->mode == 't') $cdata->setTempID(); } return $ret; } /** * Returns specified field value from all selected rows. * Don't affect current record index * * @param string $field * @return Array */ function GetCol($field) { return Array (0 => $this->GetDBField($field)); } } ?> \ No newline at end of file Index: branches/5.0.x/core/kernel/application.php =================================================================== --- branches/5.0.x/core/kernel/application.php (revision 12297) +++ branches/5.0.x/core/kernel/application.php (revision 12298) @@ -1,2955 +1,2956 @@ <?php /** * @version $Id$ * @package In-Portal * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. * @license GNU/GPL * In-Portal is Open Source software. * This means that this software may have been modified pursuant * the GNU General Public License, and as distributed it includes * or is derivative of works licensed under the GNU General Public License * or other free or open source software licenses. * See http://www.in-portal.net/license/ for copyright notices and details. */ /** * Basic class for Kernel4-based Application * * This class is a Facade for any other class which needs to deal with Kernel4 framework.<br> * The class incapsulates the main run-cycle of the script, provide access to all other objects in the framework.<br> * <br> * The class is a singleton, which means that there could be only one instance of kApplication in the script.<br> * This could be guranteed by NOT calling the class constuctor directly, but rather calling kApplication::Instance() method, * which returns an instance of the application. The method gurantees that it will return exactly the same instance for any call.<br> * See singleton pattern by GOF. * @package kernel4 */ class kApplication { /** * Is true, when Init method was called already, prevents double initialization * * @var bool */ var $InitDone = false; /** * Holds internal NParser object * @access private * @var NParser */ var $Parser; /** * New Parser (Experimental) * * @var NParser */ var $NParser; /** * Holds parser output buffer * @access private * @var string */ var $HTML; /** * Prevents request from beeing proceeded twice in case if application init is called mere then one time * * @var bool * @todo This is not good anyway (by Alex) */ var $RequestProcessed = false; /** * The main Factory used to create * almost any class of kernel and * modules * * @access private * @var kFactory */ var $Factory; /** * All ConfigurationValues table content (hash) here * * @var Array * @access private */ var $ConfigHash = Array(); /** * Ids of config variables used in current run (for caching) * * @var Array * @access private */ var $ConfigCacheIds = array(); /** * Template names, that will be used instead of regular templates * * @var Array */ var $ReplacementTemplates = Array (); /** * Mod-Rewrite listeners used during url building and parsing * * @var Array */ var $RewriteListeners = Array (); /** * Reference to debugger * * @var Debugger */ var $Debugger = null; /** * Holds all phrases used * in code and template * * @var PhrasesCache */ var $Phrases; /** * Modules table content, key - module name * * @var Array */ var $ModuleInfo = Array(); /** * Holds DBConnection * * @var kDBConnection */ var $Conn = null; /** * Maintains list of user-defined error handlers * * @var Array */ var $errorHandlers = Array(); // performance needs: /** * Holds a refererence to httpquery * * @var kHttpQuery */ var $HttpQuery = null; /** * Holds a reference to UnitConfigReader * * @var kUnitConfigReader */ var $UnitConfigReader = null; /** * Holds a reference to Session * * @var Session */ var $Session = null; /** * Holds a ref to kEventManager * * @var kEventManager */ var $EventManager = null; /** * Ref to itself, needed because everybody used to write $this->Application, even inside kApplication * * @var kApplication */ var $Application = null; /** * Ref for TemplatesChache * * @var TemplatesCache */ var $TemplatesCache = null; var $CompilationCache = array(); //used when compiling templates var $CachedProcessors = array(); //used when running compiled templates var $LambdaElements = 1; // for autonumbering unnamed RenderElements [any better place for this prop? KT] /** * Holds current NParser tag while parsing, can be used in error messages to display template file and line * * @var unknown_type */ var $CurrentNTag = null; /** * Memcache object pointer * * @var Memcache */ var $Memcached = null; /** * Returns kApplication instance anywhere in the script. * * This method should be used to get single kApplication object instance anywhere in the * Kernel-based application. The method is guranteed to return the SAME instance of kApplication. * Anywhere in the script you could write: * <code> * $application =& kApplication::Instance(); * </code> * or in an object: * <code> * $this->Application =& kApplication::Instance(); * </code> * to get the instance of kApplication. Note that we call the Instance method as STATIC - directly from the class. * To use descendand of standard kApplication class in your project you would need to define APPLICATION_CLASS constant * BEFORE calling kApplication::Instance() for the first time. If APPLICATION_CLASS is not defined the method would * create and return default KernelApplication instance. * @static * @access public * @return kApplication */ function &Instance() { static $instance = false; if(!$instance) { safeDefine('APPLICATION_CLASS', 'kApplication'); $class = APPLICATION_CLASS; $instance = new $class(); $instance->Application =& $instance; } return $instance; } function InitMemcached() { return ; $memcached_servers = 'localhost:11211'; // $this->Application->ConfigValue('MemcachedServers'); if ($memcached_servers && class_exists('Memcache')) { $this->Memcached = new Memcache(); $servers = explode(';', $memcached_servers); foreach ($servers as $server) { list ($server, $port) = strpos($server, ':') !== false ? explode(':', $server, 2) : Array ($server, 11211); $this->Memcached->addServer($server, $port); } } //try to set something to cache, if not working - set $this->Memcached to null } function CacheSet($name, $value, $expiration) { if (isset($this->Memcached)) { return $this->Memcached->set($name, $value, 0, $expiration); } return false; } function CacheGet($name) { if (isset($this->Memcached)) { return $this->Memcached->get($name); } return false; } /** * Initializes the Application * * @access public * @see kHTTPQuery * @see Session * @see TemplatesCache * @return bool Was Init actually made now or before */ function Init() { if($this->InitDone) return false; $this->InitMemcached(); if (!constOn('SKIP_OUT_COMPRESSION')) { ob_start(); // collect any output from method (other then tags) into buffer } if(defined('DEBUG_MODE') && $this->isDebugMode() && constOn('DBG_PROFILE_MEMORY')) { $this->Debugger->appendMemoryUsage('Application before Init:'); } if (!$this->isDebugMode() && !constOn('DBG_ZEND_PRESENT')) { error_reporting(0); ini_set('display_errors', 0); } if (!constOn('DBG_ZEND_PRESENT')) { $error_handler = set_error_handler( Array (&$this, 'handleError') ); if ($error_handler) { // wrap around previous error handler, if any was set $this->errorHandlers[] = $error_handler; } } $this->Conn = new kDBConnection(SQL_TYPE, Array(&$this, 'handleSQLError') ); $this->Conn->debugMode = $this->isDebugMode(); $this->Conn->Connect(SQL_SERVER, SQL_USER, SQL_PASS, SQL_DB); $this->Factory = new kFactory(); $this->registerDefaultClasses(); $this->Phrases = new PhrasesCache(); $this->EventManager =& $this->Factory->makeClass('EventManager'); $this->Factory->Storage['EventManager'] =& $this->EventManager; $this->RegisterDefaultBuildEvents(); $this->SetDefaultConstants(); if( defined('DEBUG_MODE') && $this->isDebugMode() ) { $this->Debugger->appendTimestamp('Before UnitConfigReader'); } $this->UnitConfigReader =& $this->recallObject('kUnitConfigReader'); $this->UnitConfigReader->scanModules(MODULES_PATH); $this->registerModuleConstants(); if( defined('DEBUG_MODE') && $this->isDebugMode() ) { $this->Debugger->appendTimestamp('After UnitConfigReader'); } $rewrite_on = $this->ConfigValue('UseModRewrite'); // admin=1 - when front is browsed using admin session $admin_on = getArrayValue($_REQUEST, 'admin') || $this->IsAdmin(); define('MOD_REWRITE', $rewrite_on && !$admin_on ? 1 : 0); $this->HttpQuery =& $this->recallObject('HTTPQuery'); if( defined('DEBUG_MODE') && $this->isDebugMode() ) { $this->Debugger->appendTimestamp('Processed HTTPQuery initial'); } $this->Session =& $this->recallObject('Session'); if( defined('DEBUG_MODE') && $this->isDebugMode() ) { $this->Debugger->appendTimestamp('Processed Session'); } if (!$this->RecallVar('UserGroups')) { $user_groups = trim($this->Session->GetField('GroupList'), ','); if (!$user_groups) { $user_groups = $this->ConfigValue('User_GuestGroup'); } $this->Session->SetField('GroupList', $user_groups); $this->StoreVar('UserGroups', $user_groups); } $this->HttpQuery->AfterInit(); $this->Session->ValidateExpired(); if( defined('DEBUG_MODE') && $this->isDebugMode() ) { $this->Debugger->appendTimestamp('Processed HTTPQuery AfterInit'); } $this->LoadCache(); $this->InitConfig(); $this->Phrases->Init('phrases'); if( defined('DEBUG_MODE') && $this->isDebugMode() ) { $this->Debugger->appendTimestamp('Loaded cache and phrases'); } $this->UnitConfigReader->AfterConfigRead(); if( defined('DEBUG_MODE') && $this->isDebugMode() ) { $this->Debugger->appendTimestamp('Processed AfterConfigRead'); } /*// Module items are recalled during url parsing & PhrasesCache is needed already there, // because it's used in their build events. That's why phrases cache initialization is // called from kHTTPQuery in case when mod_rewrite is used if (!$this->RewriteURLs()) { $this->Phrases = new PhrasesCache(); }*/ if ($this->GetVar('m_cat_id') === false) $this->SetVar('m_cat_id', 0); if( !$this->RecallVar('curr_iso') ) $this->StoreVar('curr_iso', $this->GetPrimaryCurrency() ); $this->SetVar('visits_id', $this->RecallVar('visit_id') ); $language =& $this->recallObject( 'lang.current', null, Array('live_table' => true) ); if (preg_match('/utf-8/', $language->GetDBField('Charset'))) { setlocale(LC_ALL, 'en_US.UTF-8'); mb_internal_encoding('UTF-8'); } $this->ValidateLogin(); if( defined('DEBUG_MODE') && $this->isDebugMode() ) { $this->Debugger->profileFinish('kernel4_startup'); } $this->InitDone = true; $this->HandleEvent( new kEvent('adm:OnStartup') ); return true; } /** * Returns module information. Searches module by requested field * * @param string $field * @param mixed $value * @param string field value to returns, if not specified, then return all fields * @param string field to return * @return Array */ function findModule($field, $value, $return_field = null) { $found = false; foreach ($this->ModuleInfo as $module_name => $module_info) { if (strtolower($module_info[$field]) == strtolower($value)) { $found = true; break; } } if ($found) { return isset($return_field) ? $module_info[$return_field] : $module_info; } return false; } function refreshModuleInfo() { if (defined('IS_INSTALL') && IS_INSTALL && !$this->TableFound('Modules')) { $this->registerModuleConstants(); return false; } $modules_helper =& $this->recallObject('ModulesHelper'); /* @var $modules_helper kModulesHelper */ $sql = 'SELECT * FROM ' . TABLE_PREFIX . 'Modules WHERE Loaded = 1 ORDER BY LoadOrder'; $this->ModuleInfo = $this->Conn->Query($sql, 'Name'); $sql = 'SELECT * FROM '.TABLE_PREFIX.'Modules WHERE '.$modules_helper->getWhereClause().' ORDER BY LoadOrder'; $this->ModuleInfo = $this->Conn->Query($sql, 'Name'); $this->registerModuleConstants(); } /** * Checks if passed language id if valid and sets it to primary otherwise * */ function VerifyLanguageId() { $language_id = $this->GetVar('m_lang'); if (!$language_id) { $language_id = 'default'; } $this->SetVar('lang.current_id', $language_id ); $this->SetVar('m_lang', $language_id ); $lang_mode = $this->GetVar('lang_mode'); $this->SetVar('lang_mode', ''); $lang =& $this->recallObject('lang.current'); if ( !$lang->IsLoaded() || (!$this->Application->IsAdmin() && !$lang->GetDBField('Enabled')) ) { if (!defined('IS_INSTALL')) $this->ApplicationDie('Unknown or disabled language'); } $this->SetVar('lang_mode',$lang_mode); } /** * Checks if passed theme id if valid and sets it to primary otherwise * */ function VerifyThemeId() { if ($this->Application->IsAdmin()) { safeDefine('THEMES_PATH', '/core/admin_templates'); return; } $path = $this->GetFrontThemePath(); if ($path === false) { $this->ApplicationDie('No Primary Theme Selected or Current Theme is Unknown or Disabled'); } safeDefine('THEMES_PATH', $path); /*$theme_id = $this->GetVar('m_theme'); if (!$theme_id) { $theme_id = $this->GetDefaultThemeId(); if (!$theme_id) { if (!defined('IS_INSTALL')) $this->ApplicationDie('No Primary Theme Selected'); } } $this->SetVar('m_theme', $theme_id); $this->SetVar('theme.current_id', $theme_id ); // KOSTJA: this is to fool theme' getPassedId $theme =& $this->recallObject('theme.current'); if (!$theme->IsLoaded() || !$theme->GetDBField('Enabled')) { if (!defined('IS_INSTALL')) $this->ApplicationDie('Unknown or disabled theme'); } safeDefine('THEMES_PATH', '/themes/'.$theme->GetDBField('Name'));*/ } function GetFrontThemePath($force=0) { static $path=null; if (!$force && isset($path)) return $path; $theme_id = $this->GetVar('m_theme'); if (!$theme_id) { // $theme_id = $this->GetDefaultThemeId(1); //1 to force front-end mode! $theme_id = 'default'; } $this->SetVar('m_theme', $theme_id); $this->SetVar('theme.current_id', $theme_id ); // KOSTJA: this is to fool theme' getPassedId $theme =& $this->recallObject('theme.current'); if (!$theme->IsLoaded() || !$theme->GetDBField('Enabled')) { return false; } $path = '/themes/'.$theme->GetDBField('Name'); return $path; } function GetDefaultLanguageId() { static $language_id = 0; if ($language_id > 0) { return $language_id; } $table = $this->getUnitOption('lang', 'TableName'); $id_field = $this->getUnitOption('lang', 'IDField'); $sql = 'SELECT '.$id_field.' FROM '.$table.' WHERE (PrimaryLang = 1) AND (Enabled = 1)'; $language_id = $this->Conn->GetOne($sql); if (!$language_id && defined('IS_INSTALL') && IS_INSTALL) { $language_id = 1; } return $language_id; } function GetDefaultThemeId($force_front=0) { static $theme_id = 0; if ($theme_id > 0) { return $theme_id; } if (constOn('DBG_FORCE_THEME')) { $theme_id = DBG_FORCE_THEME; } elseif (!$force_front && $this->IsAdmin()) { $theme_id = 999; } else { $table = $this->getUnitOption('theme','TableName'); $id_field = $this->getUnitOption('theme','IDField'); $sql = 'SELECT '.$id_field.' FROM '.$table.' WHERE (PrimaryTheme = 1) AND (Enabled = 1)'; $theme_id = $this->Conn->GetOne($sql); } return $theme_id; } function GetPrimaryCurrency() { if ($this->isModuleEnabled('In-Commerce')) { $table = $this->getUnitOption('curr', 'TableName'); return $this->Conn->GetOne('SELECT ISO FROM '.$table.' WHERE IsPrimary = 1'); } else { return 'USD'; } } /** * Registers default classes such as ItemController, GridController and LoginController * * Called automatically while initializing Application * @access private * @return void */ function RegisterDefaultClasses() { $this->registerClass('kTempTablesHandler', KERNEL_PATH.'/utility/temp_handler.php'); $this->registerClass('kEventManager', KERNEL_PATH.'/event_manager.php', 'EventManager'); $this->registerClass('kUnitConfigReader', KERNEL_PATH.'/utility/unit_config_reader.php'); $this->registerClass('kArray', KERNEL_PATH.'/utility/params.php'); $this->registerClass('Params', KERNEL_PATH.'/utility/params.php'); $this->registerClass('kHelper', KERNEL_PATH.'/kbase.php'); $this->registerClass('kCache', KERNEL_PATH.'/utility/cache.php', 'Cache', Array('Params')); $this->registerClass('kHTTPQuery', KERNEL_PATH.'/utility/http_query.php', 'HTTPQuery', Array('Params') ); $this->registerClass('Session', KERNEL_PATH.'/session/session.php'); $this->registerClass('SessionStorage', KERNEL_PATH.'/session/session.php'); $this->registerClass('Params', KERNEL_PATH.'/utility/params.php', 'kActions'); $this->registerClass('kMultipleFilter', KERNEL_PATH.'/utility/filters.php'); $this->registerClass('kDBList', KERNEL_PATH.'/db/dblist.php'); $this->registerClass('kDBItem', KERNEL_PATH.'/db/dbitem.php'); $this->registerClass('kDBEventHandler', KERNEL_PATH.'/db/db_event_handler.php'); $this->registerClass('kTagProcessor', KERNEL_PATH.'/processors/tag_processor.php'); $this->registerClass('kMainTagProcessor', KERNEL_PATH.'/processors/main_processor.php','m_TagProcessor', 'kTagProcessor'); $this->registerClass('kDBTagProcessor', KERNEL_PATH.'/db/db_tag_processor.php', null, 'kTagProcessor'); $this->registerClass('TemplatesCache', KERNEL_PATH.'/parser/template.php',null, 'kDBTagProcessor'); $this->registerClass('Template', KERNEL_PATH.'/parser/template.php'); $this->registerClass('TemplateParser', KERNEL_PATH.'/parser/template_parser.php',null, 'kDBTagProcessor'); $this->registerClass('NParser', KERNEL_PATH.'/nparser/nparser.php'); $this->registerClass('kEmailSendingHelper', KERNEL_PATH.'/utility/email_send.php', 'EmailSender', Array('kHelper')); $this->registerClass('kSocket', KERNEL_PATH.'/utility/socket.php', 'Socket'); if (file_exists(MODULES_PATH.'/in-commerce/units/currencies/currency_rates.php')) { $this->registerClass('kCurrencyRates', MODULES_PATH.'/in-commerce/units/currencies/currency_rates.php'); } $this->registerClass('FCKeditor', FULL_PATH.'/admin/editor/cmseditor/fckeditor.php'); // need this? /* Moved from MyApplication */ $this->registerClass('Inp1Parser',KERNEL_PATH.'/../units/general/inp1_parser.php','Inp1Parser'); $this->registerClass('InpSession',KERNEL_PATH.'/../units/general/inp_ses_storage.php','Session'); $this->registerClass('InpSessionStorage',KERNEL_PATH.'/../units/general/inp_ses_storage.php','SessionStorage'); $this->registerClass('kCatDBItem',KERNEL_PATH.'/../units/general/cat_dbitem.php'); $this->registerClass('kCatDBItemExportHelper',KERNEL_PATH.'/../units/general/cat_dbitem_export.php', 'CatItemExportHelper'); $this->registerClass('kCatDBList',KERNEL_PATH.'/../units/general/cat_dblist.php'); $this->registerClass('kCatDBEventHandler',KERNEL_PATH.'/../units/general/cat_event_handler.php'); $this->registerClass('kCatDBTagProcessor',KERNEL_PATH.'/../units/general/cat_tag_processor.php'); // Do not move to config - this helper is used before configs are read $this->registerClass('kModulesHelper', KERNEL_PATH.'/../units/general/helpers/modules.php', 'ModulesHelper'); /* End moved */ } function RegisterDefaultBuildEvents() { $event_manager =& $this->recallObject('EventManager'); $event_manager->registerBuildEvent('kTempTablesHandler', 'OnTempHandlerBuild'); } /** * Returns item's filename that corresponds id passed. If possible, then get it from cache * * @param string $prefix * @param int $id * @return string */ function getFilename($prefix, $id, $category_id=null) { $filename = $this->getCache('filenames', $prefix.'_'.$id); if ($filename === false) { $table = $this->getUnitOption($prefix, 'TableName'); $id_field = $this->getUnitOption($prefix, 'IDField'); if ($prefix == 'c') { if(!$id) { $this->setCache('filenames', $prefix.'_'.$id, ''); return ''; } // this allows to save 2 sql queries for each category $sql = 'SELECT NamedParentPath, CachedTemplate, TreeLeft, TreeRight FROM '.$table.' WHERE '.$id_field.' = '.$this->Conn->qstr($id); $category_data = $this->Conn->GetRow($sql); // only direct links to category pages work (symlinks, container pages and so on won't work) $filename = $category_data['NamedParentPath']; $this->setCache('category_templates', $id, $filename); $this->setCache('category_designs', $id, ltrim($category_data['CachedTemplate'], '/')); $this->setCache('category_tree', $id, $category_data['TreeLeft'] . ';' . $category_data['TreeRight']); } else { $resource_id = $this->Conn->GetOne('SELECT ResourceId FROM '.$table.' WHERE '.$id_field.' = '.$this->Conn->qstr($id)); if (is_null($category_id)) $category_id = $this->GetVar('m_cat_id'); $sql = 'SELECT Filename FROM '.TABLE_PREFIX.'CategoryItems WHERE ItemResourceId = '.$resource_id.' AND CategoryId = '.$category_id; $filename = $this->Conn->GetOne($sql); /*if (!$filename) { $sql = 'SELECT Filename FROM '.TABLE_PREFIX.'CategoryItems WHERE ItemResourceId = '.$resource_id.' AND PrimaryCat = 1'; $filename = $this->Conn->GetOne($sql); }*/ /*$sql = 'SELECT Filename FROM '.$table.' WHERE '.$id_field.' = '.$this->Conn->qstr($id); $filename = $this->Conn->GetOne($sql);*/ } $this->setCache('filenames', $prefix.'_'.$id, $filename); } return $filename; } /** * Adds new value to cache $cache_name and identified by key $key * * @param string $cache_name cache name * @param int $key key name to add to cache * @param mixed $value value of chached record */ function setCache($cache_name, $key, $value, $expiration=3600) { $cache =& $this->recallObject('Cache'); /* @var $cache kCache */ return $cache->setCache($cache_name, $key, $value, $expiration); } /** * Returns cached $key value from cache named $cache_name * * @param string $cache_name cache name * @param int $key key name from cache * @return mixed */ function getCache($cache_name, $key) { $cache =& $this->recallObject('Cache'); return $cache->getCache($cache_name, $key); } /** * Defines default constants if it's not defined before - in config.php * * @access private */ function SetDefaultConstants() // it's defined in startup.php - can be removed?? { safeDefine('SERVER_NAME', $_SERVER['HTTP_HOST']); } /** * Registers each module specific constants if any found * */ function registerModuleConstants() { if (file_exists(KERNEL_PATH.'/constants.php')) { k4_include_once(KERNEL_PATH.'/constants.php'); } if (!$this->ModuleInfo) return false; foreach($this->ModuleInfo as $module_name => $module_info) { $module_path = '/'.$module_info['Path']; $contants_file = FULL_PATH.$module_path.'constants.php'; if( file_exists($contants_file) ) k4_include_once($contants_file); } return true; } function ProcessRequest() { $event_manager =& $this->recallObject('EventManager'); /* @var $event_manager kEventManager */ if($this->isDebugMode() && constOn('DBG_SHOW_HTTPQUERY')) { $this->Debugger->appendHTML('HTTPQuery:'); $this->Debugger->dumpVars($this->HttpQuery->_Params); } $event_manager->ProcessRequest(); $event_manager->RunRegularEvents(reBEFORE); $this->RequestProcessed = true; } /** * Actually runs the parser against current template and stores parsing result * * This method gets t variable passed to the script, loads the template given in t variable and * parses it. The result is store in {@link $this->HTML} property. * @access public * @return void */ function Run() { if($this->isDebugMode() && constOn('DBG_PROFILE_MEMORY')) { $this->Debugger->appendMemoryUsage('Application before Run:'); } if ($this->IsAdmin()) { // for permission checking in events & templates $this->LinkVar('module'); // for common configuration templates $this->LinkVar('module_key'); // for common search templates $this->LinkVar('section'); // for common configuration templates if ($this->GetVar('m_opener') == 'p') { $this->LinkVar('main_prefix'); // window prefix, that opened selector $this->LinkVar('dst_field'); // field to set value choosed in selector // $this->LinkVar('return_template'); // template to go, when something was coosen from popup (from finalizePopup) // $this->LinkVar('return_m'); // main env part to restore after popup will be closed (from finalizePopup) } if ($this->GetVar('ajax') == 'yes' && !$this->GetVar('debug_ajax')) { // hide debug output from ajax requests automatically define('DBG_SKIP_REPORTING', 1); } } elseif ($this->GetVar('admin')) { // viewing front-end through admin's frame $admin_session =& $this->Application->recallObject('Session.admin'); $user = (int)$admin_session->RecallVar('user_id'); // in case, when no valid admin session found $perm_helper =& $this->recallObject('PermissionsHelper'); /* @var $perm_helper kPermissionsHelper */ if ($perm_helper->CheckUserPermission($user, 'CATEGORY.MODIFY', 0, 0)) { // user can edit cms blocks $editing_mode = $this->GetVar('editing_mode'); - define('EDITING_MODE', $editing_mode ? $editing_mode : EDITING_MODE_CMS); + define('EDITING_MODE', $editing_mode ? $editing_mode : EDITING_MODE_BROWSE); + $this->Phrases->setPhraseEditing(); } } safeDefine('EDITING_MODE', ''); // user can't edit anything if (!$this->RequestProcessed) $this->ProcessRequest(); $this->InitParser(); $t = $this->GetVar('t'); if (!$this->TemplatesCache->TemplateExists($t) && !$this->IsAdmin()) { $cms_handler =& $this->recallObject('st_EventHandler'); /* @var $cms_handler CategoriesEventHandler */ $t = ltrim($cms_handler->GetDesignTemplate(), '/'); if ($this->isDebugMode()) { $this->Debugger->appendHTML('<strong>Design Template</strong>: ' . $t . '; <strong>CategoryID</strong>: ' . $this->GetVar('m_cat_id')); } } /*else { $cms_handler->SetCatByTemplate(); }*/ if($this->isDebugMode() && constOn('DBG_PROFILE_MEMORY')) { $this->Debugger->appendMemoryUsage('Application before Parsing:'); } if (defined('NPARSER') && 'NPARSER') { $this->HTML = $this->NParser->Run( $t ); } else { $this->HTML = $this->Parser->ParseTemplate( $t ); } if ($this->isDebugMode() && constOn('DBG_PROFILE_MEMORY')) { $this->Debugger->appendMemoryUsage('Application after Parsing:'); } } function InitParser($theme_name = false) { if (defined('NPARSER') && 'NPARSER') { if( !is_object($this->NParser) ) { $this->NParser =& $this->recallObject('NParser'); $this->TemplatesCache =& $this->recallObject('TemplatesCache'); // can be removed in future // $this->Parser =& $this->recallObject('TemplateParser'); $this->Parser =& $this->NParser; } } else { if( !is_object($this->Parser) ) { $this->Parser =& $this->recallObject('TemplateParser'); $this->TemplatesCache =& $this->recallObject('TemplatesCache'); } } $this->TemplatesCache->forceThemeName = $theme_name; } /** * Send the parser results to browser * * Actually send everything stored in {@link $this->HTML}, to the browser by echoing it. * @access public * @return void */ function Done() { $this->HandleEvent( new kEvent('adm:OnBeforeShutdown') ); if ($this->isDebugMode() && constOn('DBG_PROFILE_MEMORY')) { $this->Debugger->appendMemoryUsage('Application before Done:'); } if ($this->isDebugMode()) { $this->EventManager->RunRegularEvents(reAFTER); $this->Session->SaveData(); if (constOn('DBG_CACHE')) { $cache =& $this->recallObject('Cache'); $cache->printStatistics(); } $this->HTML = ob_get_clean() . $this->HTML . $this->Debugger->printReport(true); } else { $this->HTML = ob_get_clean().$this->HTML; } if ($this->UseOutputCompression()) { header('Content-Encoding: gzip'); $compression_level = $this->ConfigValue('OutputCompressionLevel'); if ($compression_level < 0 || $compression_level > 9) $compression_level = 7; echo gzencode($this->HTML, $compression_level); } else { echo $this->HTML; } $this->UpdateCache(); flush(); if (!$this->isDebugMode()) { $this->EventManager->RunRegularEvents(reAFTER); $this->Session->SaveData(); } if (defined('DBG_CAPTURE_STATISTICS') && DBG_CAPTURE_STATISTICS && !$this->IsAdmin()) { $this->_storeStatistics(); } } /** * Stores script execution statistics to database * */ function _storeStatistics() { global $start; $script_time = getmicrotime() - $start; $query_statistics = $this->Conn->getQueryStatistics(); // time & count $sql = 'SELECT * FROM ' . TABLE_PREFIX . 'StatisticsCapture WHERE TemplateName = "' . $this->GetVar('t') . '"'; $data = $this->Conn->GetRow($sql); if ($data) { $this->_updateAverageStatistics($data, 'ScriptTime', $script_time); $this->_updateAverageStatistics($data, 'SqlTime', $query_statistics['time']); $this->_updateAverageStatistics($data, 'SqlCount', $query_statistics['count']); $data['Hits']++; $data['LastHit'] = adodb_mktime(); $this->Conn->doUpdate($data, TABLE_PREFIX . 'StatisticsCapture', 'StatisticsId = ' . $data['StatisticsId']); } else { $data['ScriptTimeMin'] = $data['ScriptTimeAvg'] = $data['ScriptTimeMax'] = $script_time; $data['SqlTimeMin'] = $data['SqlTimeAvg'] = $data['SqlTimeMax'] = $query_statistics['time']; $data['SqlCountMin'] = $data['SqlCountAvg'] = $data['SqlCountMax'] = $query_statistics['count']; $data['TemplateName'] = $this->GetVar('t'); $data['Hits'] = 1; $data['LastHit'] = adodb_mktime(); $this->Conn->doInsert($data, TABLE_PREFIX . 'StatisticsCapture'); } } /** * Calculates average time for statistics * * @param Array $data * @param string $field_prefix * @param float $current_value */ function _updateAverageStatistics(&$data, $field_prefix, $current_value) { $data[$field_prefix . 'Avg'] = (($data['Hits'] * $data[$field_prefix . 'Avg']) + $current_value) / ($data['Hits'] + 1); if ($current_value < $data[$field_prefix . 'Min']) { $data[$field_prefix . 'Min'] = $current_value; } if ($current_value > $data[$field_prefix . 'Max']) { $data[$field_prefix . 'Max'] = $current_value; } } function logSlowQuery($slow_sql, $time) { $query_crc = crc32($slow_sql); $sql = 'SELECT * FROM ' . TABLE_PREFIX . 'SlowSqlCapture WHERE QueryCrc = ' . $query_crc; $data = $this->Conn->Query($sql, null, true); if ($data) { $this->_updateAverageStatistics($data, 'Time', $time); $template_names = explode(',', $data['TemplateNames']); array_push($template_names, $this->GetVar('t')); $data['TemplateNames'] = implode(',', array_unique($template_names)); $data['Hits']++; $data['LastHit'] = adodb_mktime(); $this->Conn->doUpdate($data, TABLE_PREFIX . 'SlowSqlCapture', 'CaptureId = ' . $data['CaptureId']); } else { $data['TimeMin'] = $data['TimeAvg'] = $data['TimeMax'] = $time; $data['SqlQuery'] = $slow_sql; $data['QueryCrc'] = $query_crc; $data['TemplateNames'] = $this->GetVar('t'); $data['Hits'] = 1; $data['LastHit'] = adodb_mktime(); $this->Conn->doInsert($data, TABLE_PREFIX . 'SlowSqlCapture'); } } /** * Checks if output compression options is available * * @return string */ function UseOutputCompression() { if (constOn('IS_INSTALL') || constOn('DBG_ZEND_PRESENT') || constOn('SKIP_OUT_COMPRESSION')) return false; return $this->ConfigValue('UseOutputCompression') && function_exists('gzencode') && strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip'); } // Facade /** * Returns current session id (SID) * @access public * @return longint */ function GetSID() { $session =& $this->recallObject('Session'); return $session->GetID(); } function DestroySession() { $session =& $this->recallObject('Session'); $session->Destroy(); } /** * Returns variable passed to the script as GET/POST/COOKIE * * @access public * @param string $name Name of variable to retrieve * @param int $default default value returned in case if varible not present * @return mixed */ function GetVar($name, $default = false) { return isset($this->HttpQuery->_Params[$name]) ? $this->HttpQuery->_Params[$name] : $default; } /** * Returns ALL variables passed to the script as GET/POST/COOKIE * * @access public * @return array */ function GetVars() { return $this->HttpQuery->GetParams(); } /** * Set the variable 'as it was passed to the script through GET/POST/COOKIE' * * This could be useful to set the variable when you know that * other objects would relay on variable passed from GET/POST/COOKIE * or you could use SetVar() / GetVar() pairs to pass the values between different objects.<br> * * This method is formerly known as $this->Session->SetProperty. * @param string $var Variable name to set * @param mixed $val Variable value * @access public * @return void */ function SetVar($var,$val) { return $this->HttpQuery->Set($var, $val); } /** * Deletes kHTTPQuery variable * * @param string $var * @todo think about method name */ function DeleteVar($var) { return $this->HttpQuery->Remove($var); } /** * Deletes Session variable * * @param string $var */ function RemoveVar($var) { return $this->Session->RemoveVar($var); } function RemovePersistentVar($var) { return $this->Session->RemovePersistentVar($var); } /** * Restores Session variable to it's db version * * @param string $var */ function RestoreVar($var) { return $this->Session->RestoreVar($var); } /** * Returns session variable value * * Return value of $var variable stored in Session. An optional default value could be passed as second parameter. * * @see SimpleSession * @access public * @param string $var Variable name * @param mixed $default Default value to return if no $var variable found in session * @return mixed */ function RecallVar($var,$default=false) { return $this->Session->RecallVar($var,$default); } function RecallPersistentVar($var, $default = false) { return $this->Session->RecallPersistentVar($var, $default); } /** * Stores variable $val in session under name $var * * Use this method to store variable in session. Later this variable could be recalled. * @see RecallVar * @access public * @param string $var Variable name * @param mixed $val Variable value */ function StoreVar($var, $val, $optional = false) { $session =& $this->recallObject('Session'); $this->Session->StoreVar($var, $val, $optional); } function StorePersistentVar($var, $val) { $this->Session->StorePersistentVar($var, $val); } function StoreVarDefault($var, $val, $optional=false) { $session =& $this->recallObject('Session'); $this->Session->StoreVarDefault($var, $val, $optional); } /** * Links HTTP Query variable with session variable * * If variable $var is passed in HTTP Query it is stored in session for later use. If it's not passed it's recalled from session. * This method could be used for making sure that GetVar will return query or session value for given * variable, when query variable should overwrite session (and be stored there for later use).<br> * This could be used for passing item's ID into popup with multiple tab - * in popup script you just need to call LinkVar('id', 'current_id') before first use of GetVar('id'). * After that you can be sure that GetVar('id') will return passed id or id passed earlier and stored in session * @access public * @param string $var HTTP Query (GPC) variable name * @param mixed $ses_var Session variable name * @param mixed $default Default variable value */ function LinkVar($var, $ses_var = null, $default = '', $optional = false) { if (!isset($ses_var)) $ses_var = $var; if ($this->GetVar($var) !== false) { $this->StoreVar($ses_var, $this->GetVar($var), $optional); } else { $this->SetVar($var, $this->RecallVar($ses_var, $default)); } } /** * Returns variable from HTTP Query, or from session if not passed in HTTP Query * * The same as LinkVar, but also returns the variable value taken from HTTP Query if passed, or from session if not passed. * Returns the default value if variable does not exist in session and was not passed in HTTP Query * * @see LinkVar * @access public * @param string $var HTTP Query (GPC) variable name * @param mixed $ses_var Session variable name * @param mixed $default Default variable value * @return mixed */ function GetLinkedVar($var, $ses_var = null, $default = '') { $this->LinkVar($var, $ses_var, $default); return $this->GetVar($var); } function AddBlock($name, $tpl) { $this->cache[$name] = $tpl; } /* Seems to be not used anywhere... /Kostja function SetTemplateBody($title,$body) { $templates_cache =& $this->recallObject('TemplatesCache'); $templates_cache->SetTemplateBody($title,$body); }*/ function ProcessTag($tag_data) { $a_tag = new Tag($tag_data,$this->Parser); return $a_tag->DoProcessTag(); } function ProcessParsedTag($prefix, $tag, $params) { if (defined('NPARSER') && NPARSER) { $p = $this->Parser->GetProcessor($prefix); return $p->ProcessParsedTag($tag, $params, $prefix); } $a_tag = new Tag('',$this->Parser); $a_tag->Tag = $tag; $tmp=$this->Application->processPrefix($prefix); $a_tag->Processor = $tmp['prefix']; $a_tag->Special = $tmp['special']; $a_tag->NamedParams = $params; return $a_tag->DoProcessTag(); } /** * Return ADODB Connection object * * Returns ADODB Connection object already connected to the project database, configurable in config.php * @access public * @return kDBConnection */ function &GetADODBConnection() { return $this->Conn; } /** * Allows to parse given block name or include template * * @param Array $params Parameters to pass to block/template. Reserved parameter "name" used to specify block/template name. * @param Array $pass_params Forces to pass current parser params to this block/template. Use with cauntion, because you can accidently pass "block_no_data" parameter. * @param bool $as_template * @return string */ function ParseBlock($params, $pass_params = 0, $as_template = false) { if (substr($params['name'], 0, 5) == 'html:') return substr($params['name'], 6); return $this->Parser->ParseBlock($params, $pass_params, $as_template); } /** * Returns index file, that could be passed as parameter to method, as parameter to tag and as constant or not passed at all * * @param string $prefix * @param string $index_file * @param Array $params * @return string */ function getIndexFile($prefix, $index_file, &$params) { if (isset($params['index_file'])) { $index_file = $params['index_file']; unset($params['index_file']); return $index_file; } if (isset($index_file)) { return $index_file; } if (defined('INDEX_FILE')) { return INDEX_FILE; } $cut_prefix = trim(BASE_PATH, '/').'/'.trim($prefix, '/'); return trim(preg_replace('/'.preg_quote($cut_prefix, '/').'(.*)/', '\\1', $_SERVER['PHP_SELF']), '/'); } /** * Return href for template * * @access public * @param string $t Template path * @var string $prefix index.php prefix - could be blank, 'admin' */ function HREF($t, $prefix='', $params=null, $index_file=null) { if(!$t) $t = $this->GetVar('t'); // moved from kMainTagProcessor->T() $t = preg_replace('/^Content\//i', '', $t); /*if ($this->GetVar('skip_last_template')) { $params['opener'] = 'p'; $this->SetVar('m_opener', 'p'); } if ($t == 'incs/close_popup') { // because this template closes the popup and we don't need popup mark here anymore $params['m_opener'] = 's'; }*/ if( substr($t, -4) == '.tpl' ) $t = substr($t, 0, strlen($t) - 4 ); if ( $this->IsAdmin() && $prefix == '') $prefix = ADMIN_DIRECTORY; if ( $this->IsAdmin() && $prefix == '_FRONT_END_') $prefix = ''; $index_file = $this->getIndexFile($prefix, $index_file, $params); if (isset($params['_auto_prefix_'])) { unset($params['_auto_prefix_']); // this is parser-related param, do not need to pass it here } $ssl = isset($params['__SSL__']) ? $params['__SSL__'] : null; if ($ssl !== null) { $session =& $this->recallObject('Session'); $cookie_url = trim($session->CookieDomain.$session->CookiePath, '/.'); if ($ssl) { $target_url = defined('ADMIN') && ADMIN ? $this->ConfigValue('AdminSSL_URL') : false; if (!$target_url) { $target_url = $this->ConfigValue('SSL_URL'); } } else { $target_url = 'http://'.DOMAIN.$this->ConfigValue('Site_Path'); } if (!preg_match('#'.preg_quote($cookie_url).'#', $target_url)) { $session->SetMode(smGET_ONLY); } } if (isset($params['opener']) && $params['opener'] == 'u') { $wid = $this->Application->GetVar('m_wid'); $stack_name = rtrim('opener_stack_'.$wid, '_'); $opener_stack = $this->RecallVar($stack_name); if ($opener_stack && $opener_stack != serialize(Array())) { $opener_stack = unserialize($opener_stack); list($index_file, $env) = explode('|', $opener_stack[count($opener_stack) - 1]); $ret = $this->BaseURL($prefix, $ssl).$index_file.'?'.ENV_VAR_NAME.'='.$env; if ( getArrayValue($params,'escape') ) $ret = addslashes($ret); if (isset($params['m_opener']) && $params['m_opener'] == 'u') { array_pop($opener_stack); if (!$opener_stack) { $this->RemoveVar($stack_name); // remove popups last templates, because popup is closing now $this->RemoveVar('last_template_'.$wid); $this->RemoveVar('last_template_popup_'.$wid); // don't save popups last templates again :) $this->SetVar('skip_last_template', 1); } else { $this->StoreVar($stack_name, serialize($opener_stack)); } /*// store window relations $window_relations = $this->Application->RecallVar('window_relations'); $window_relations = $window_relations ? unserialize($window_relations) : Array (); if (array_key_exists($wid, $window_relations)) { unset($window_relations[$wid]); $this->Application->StoreVar('window_relations', serialize($window_relations)); }*/ } return $ret; } else { //define('DBG_REDIRECT', 1); $t = $this->GetVar('t'); } } $pass = isset($params['pass']) ? $params['pass'] : ''; $pass_events = isset($params['pass_events']) ? $params['pass_events'] : false; // pass events with url $map_link = ''; if( isset($params['anchor']) ) { $map_link = '#'.$params['anchor']; unset($params['anchor']); } if ( isset($params['no_amp']) ) { $params['__URLENCODE__'] = $params['no_amp']; unset($params['no_amp']); } $no_rewrite = false; if( isset($params['__NO_REWRITE__']) ) { $no_rewrite = true; unset($params['__NO_REWRITE__']); } $force_rewrite = false; if( isset($params['__MOD_REWRITE__']) ) { $force_rewrite = true; unset($params['__MOD_REWRITE__']); } $force_no_sid = false; if( isset($params['__NO_SID__']) ) { $force_no_sid = true; unset($params['__NO_SID__']); } // append pass through variables to each link to be build // $params = array_merge_recursive2($this->getPassThroughVariables($params), $params); $params = array_merge($this->getPassThroughVariables($params), $params); if ($force_rewrite || ($this->RewriteURLs($ssl) && !$no_rewrite)) { static $rewrite_listeners_done = false; if (!$rewrite_listeners_done) { $mod_rewrite_helper =& $this->recallObject('ModRewriteHelper'); /* @var $mod_rewrite_helper kModRewriteHelper */ $mod_rewrite_helper->initRewriteListeners(); $rewrite_listeners_done = true; } $session =& $this->recallObject('Session'); if ($session->NeedQueryString() && !$force_no_sid) { $params['sid'] = $this->GetSID(); } $url = $this->BuildEnv_NEW($t, $params, $pass, $pass_events); $ret = $this->BaseURL($prefix, $ssl).$url.$map_link; } else { unset($params['pass_category']); // we don't need to pass it when mod_rewrite is off $env = $this->BuildEnv($t, $params, $pass, $pass_events); $ret = $this->BaseURL($prefix, $ssl).$index_file.'?'.$env.$map_link; } return $ret; } /** * Returns variables with values that should be passed throught with this link + variable list * * @param Array $params * @return Array */ function getPassThroughVariables(&$params) { static $cached_pass_through = null; if (isset($params['no_pass_through']) && $params['no_pass_through']) { unset($params['no_pass_through']); return Array(); } // because pass through is not changed during script run, then we can cache it if (is_null($cached_pass_through)) { $cached_pass_through = Array(); $pass_through = $this->Application->GetVar('pass_through'); if ($pass_through) { // names of variables to pass to each link $cached_pass_through['pass_through'] = $pass_through; $pass_through = explode(',', $pass_through); foreach ($pass_through as $pass_through_var) { $cached_pass_through[$pass_through_var] = $this->Application->GetVar($pass_through_var); } } } return $cached_pass_through; } /** * Returns sorted array of passed prefixes (to build url from) * * @param string $pass * @return Array */ function getPassInfo($pass = 'all') { if (!$pass) $pass = 'all'; $pass = trim( preg_replace( '/(?<=,|\\A)all(?=,|\\z)/', trim($this->GetVar('passed'), ','), trim($pass, ',') ), ','); if (!$pass) { return Array(); } $pass_info = array_unique( explode(',', $pass) ); // array( prefix[.special], prefix[.special] ... // we need to keep that sorting despite the sorting below, because this sorts prefixes with same priority by name sort($pass_info, SORT_STRING); // to be prefix1,prefix1.special1,prefix1.special2,prefix3.specialX foreach ($pass_info as $prefix) { list($prefix_only) = explode('.', $prefix, 1); $sorted[$prefix] = $this->getUnitOption($prefix_only, 'RewritePriority', 0); } arsort($sorted); $pass_info = array_keys($sorted); // ensure that "m" prefix is at the beginning $main_index = array_search('m', $pass_info); if ($main_index !== false) { unset($pass_info[$main_index]); array_unshift($pass_info, 'm'); } return $pass_info; } function BuildEnv_NEW($t, $params, $pass='all', $pass_events = false) { // $session =& $this->recallObject('Session'); $force_admin = getArrayValue($params,'admin') || $this->GetVar('admin'); // if($force_admin) $sid = $this->GetSID(); $ret = ''; $env = ''; $encode = false; if (isset($params['__URLENCODE__'])) { $encode = $params['__URLENCODE__']; unset($params['__URLENCODE__']); } if (isset($params['__SSL__'])) { unset($params['__SSL__']); } $catalog_item_found = false; $pass_info = $this->getPassInfo($pass); if ($pass_info) { if ($pass_info[0] == 'm') { array_shift($pass_info); } $inject_parts = Array (); // url parts for beginning of url $params['t'] = $t; // make template available for rewrite listeners $params['pass_template'] = true; // by default we keep given template in resulting url if (!array_key_exists('pass_category', $params)) { $params['pass_category'] = false; // by default we don't keep categories in url } foreach ($pass_info as $pass_index => $pass_element) { list ($prefix) = explode('.', $pass_element); $catalog_item = $this->findModule('Var', $prefix) && $this->getUnitOption($prefix, 'CatalogItem'); if (array_key_exists($prefix, $this->RewriteListeners)) { // if next prefix is same as current, but with special => exclude current prefix from url $next_prefix = array_key_exists($pass_index + 1, $pass_info) ? $pass_info[$pass_index + 1] : false; if ($next_prefix) { $next_prefix = substr($next_prefix, 0, strlen($prefix) + 1); if ($prefix . '.' == $next_prefix) { continue; } } // rewrited url part $url_part = $this->BuildModuleEnv_NEW($pass_element, $params, $pass_events); if (is_string($url_part) && $url_part) { $ret .= $url_part . '/'; if ($catalog_item) { // pass category later only for catalog items $catalog_item_found = true; } } elseif (is_array($url_part)) { // rewrite listener want to insert something at the beginning of url too if ($url_part[0]) { $inject_parts[] = $url_part[0]; } if ($url_part[1]) { $ret .= $url_part[1] . '/'; } if ($catalog_item) { // pass category later only for catalog items $catalog_item_found = true; } } elseif ($url_part === false) { // rewrite listener decided not to rewrite given $pass_element $env .= ':' . $this->BuildModuleEnv($pass_element, $params, $pass_events); } } else { $env .= ':' . $this->BuildModuleEnv($pass_element, $params, $pass_events); } } if ($catalog_item_found || preg_match('/c\.[-\d]*/', implode(',', $pass_info))) { // "c" prefix is present -> keep category $params['pass_category'] = true; } $params['inject_parts'] = $inject_parts; $ret = $this->BuildModuleEnv_NEW('m', $params, $pass_events) . '/' . $ret; $cat_processed = array_key_exists('category_processed', $params) && $params['category_processed']; // remove tempporary parameters used by listeners unset($params['t'], $params['inject_parts'], $params['pass_template'], $params['pass_category'], $params['category_processed']); if ($catalog_item_found || !$cat_processed || !defined('EXP_DIR_URLS')) { // this catalog item detail page OR there is no category given $ret = trim($ret, '/') . '.html'; } else { // url ends with "/" and not with ".html" $ret = trim($ret, '/') . '/'; } if ($env) { $params[ENV_VAR_NAME] = ltrim($env, ':'); } } unset($params['pass'], $params['opener'], $params['m_event']); if ($force_admin) { $params['admin'] = 1; } if (array_key_exists('escape', $params) && $params['escape']) { $ret = addslashes($ret); unset($params['escape']); } $ret = str_replace('%2F', '/', urlencode($ret)); $params_str = ''; $join_string = $encode ? '&' : '&'; foreach ($params as $param => $value) { $params_str .= $join_string . $param . '=' . $value; } if ($params_str) { $ret .= '?' . substr($params_str, strlen($join_string)); } if ($encode) { $ret = str_replace('\\', '%5C', $ret); } return $ret; } function BuildModuleEnv_NEW($prefix_special, &$params, $keep_events = false) { list ($prefix) = explode('.', $prefix_special); $url_parts = Array (); $listener = $this->RewriteListeners[$prefix]; $ret = $listener[0]->$listener[1](REWRITE_MODE_BUILD, $prefix_special, $params, $url_parts, $keep_events); return $ret; } /** * Builds env part that corresponds prefix passed * * @param string $prefix_special item's prefix & [special] * @param Array $params url params * @param bool $pass_events */ function BuildModuleEnv($prefix_special, &$params, $pass_events = false) { list($prefix) = explode('.', $prefix_special); $query_vars = $this->getUnitOption($prefix, 'QueryString'); //if pass events is off and event is not implicity passed if( !$pass_events && !isset($params[$prefix_special.'_event']) ) { $params[$prefix_special.'_event'] = ''; // remove event from url if requested //otherwise it will use value from get_var } if(!$query_vars) return ''; $tmp_string = Array(0 => $prefix_special); foreach($query_vars as $index => $var_name) { //if value passed in params use it, otherwise use current from application $var_name = $prefix_special.'_'.$var_name; $tmp_string[$index] = isset( $params[$var_name] ) ? $params[$var_name] : $this->GetVar($var_name); if ( isset($params[$var_name]) ) unset( $params[$var_name] ); } $escaped = array(); foreach ($tmp_string as $tmp_val) { $escaped[] = str_replace(Array('-',':'), Array('\-','\:'), $tmp_val); } $ret = implode('-', $escaped); if ($this->getUnitOption($prefix, 'PortalStyleEnv') == true) { $ret = preg_replace('/^([a-zA-Z]+)-([0-9]+)-(.*)/','\\1\\2-\\3', $ret); } return $ret; } function BuildEnv($t, $params, $pass='all', $pass_events = false, $env_var = true) { $session =& $this->recallObject('Session'); $ssl = isset($params['__SSL__']) ? $params['__SSL__'] : 0; $sid = $session->NeedQueryString() && !$this->RewriteURLs($ssl) ? $this->GetSID() : ''; // if (getArrayValue($params,'admin') == 1) $sid = $this->GetSID(); $ret = ''; if ($env_var) { $ret = ENV_VAR_NAME.'='; } $ret .= $sid.(constOn('INPORTAL_ENV') ? '-' : ':'); $encode = false; if (isset($params['__URLENCODE__'])) { $encode = $params['__URLENCODE__']; unset($params['__URLENCODE__']); } if (isset($params['__SSL__'])) { unset($params['__SSL__']); } $env_string = ''; $category_id = isset($params['m_cat_id']) ? $params['m_cat_id'] : $this->GetVar('m_cat_id'); $item_id = false; $pass_info = $this->getPassInfo($pass); if ($pass_info) { if ($pass_info[0] == 'm') array_shift($pass_info); foreach ($pass_info as $pass_element) { list($prefix) = explode('.', $pass_element); $require_rewrite = $this->findModule('Var', $prefix); if ($require_rewrite) { $item_id = isset($params[$pass_element.'_id']) ? $params[$pass_element.'_id'] : $this->GetVar($pass_element.'_id'); } $env_string .= ':'.$this->BuildModuleEnv($pass_element, $params, $pass_events); } } if (strtolower($t) == '__default__') { // to put category & item templates into cache $filename = $this->getFilename('c', $category_id); if (is_numeric($item_id)) { $mod_rw_helper =& $this->Application->recallObject('ModRewriteHelper'); /* @var $mod_rw_helper kModRewriteHelper */ $t = $mod_rw_helper->GetItemTemplate($category_id, $pass_element); // $pass_element should be the last processed element // $t = $this->getCache('item_templates', $category_id); } elseif ($category_id) { $t = strtolower( preg_replace('/^Content\//i', '', $this->getCache('category_templates', $category_id)) ); } else { $t = 'index'; } } $ret .= $t.':'.$this->BuildModuleEnv('m', $params, $pass_events).$env_string; unset($params['pass'], $params['opener'], $params['m_event']); if ($this->GetVar('admin') && !isset($params['admin'])) { $params['admin'] = 1; if (!array_key_exists('editing_mode', $params)) { $params['editing_mode'] = EDITING_MODE; } } if (array_key_exists('escape', $params) && $params['escape']) { $ret = addslashes($ret); unset($params['escape']); } $join_string = $encode ? '&' : '&'; $params_str = ''; foreach ($params as $param => $value) { $params_str .= $join_string.$param.'='.$value; } $ret .= $params_str; if ($encode) { $ret = str_replace('\\', '%5C', $ret); } return $ret; } function BaseURL($prefix='', $ssl=null) { if ($ssl === null) { return PROTOCOL.SERVER_NAME.(defined('PORT')?':'.PORT : '').rtrim(BASE_PATH, '/').$prefix.'/'; } else { if ($ssl) { $base_url = defined('ADMIN') && ADMIN ? $this->ConfigValue('AdminSSL_URL') : false; if (!$base_url) { $base_url = $this->ConfigValue('SSL_URL'); } return rtrim($base_url, '/').$prefix.'/'; } else { return 'http://'.DOMAIN.(defined('PORT')?':'.PORT : '').rtrim( $this->ConfigValue('Site_Path'), '/').$prefix.'/'; } } } function Redirect($t='', $params=null, $prefix='', $index_file=null) { $js_redirect = getArrayValue($params, 'js_redirect'); if (preg_match("/external:(.*)/", $t, $rets)) { $location = $rets[1]; } else { if ($t == '' || $t === true) $t = $this->GetVar('t'); // pass prefixes and special from previous url if( isset($params['js_redirect']) ) unset($params['js_redirect']); if (!isset($params['pass'])) $params['pass'] = 'all'; if ($this->GetVar('ajax') == 'yes' && $t == $this->GetVar('t')) { // redirects to the same template as current $params['ajax'] = 'yes'; } $params['__URLENCODE__'] = 1; $location = $this->HREF($t, $prefix, $params, $index_file); //echo " location : $location <br>"; } $a_location = $location; $location = "Location: $location"; if ($this->isDebugMode() && constOn('DBG_REDIRECT')) { $this->Debugger->appendTrace(); echo "<b>Debug output above!!!</b> Proceed to redirect: <a href=\"$a_location\">$a_location</a><br>"; } else { if ($js_redirect) { $this->SetVar('t', 'redirect'); $this->SetVar('redirect_to_js', addslashes($a_location) ); $this->SetVar('redirect_to', $a_location); return true; } else { if ($this->GetVar('ajax') == 'yes' && $t != $this->GetVar('t')) { // redirection to other then current template during ajax request echo '#redirect#'.$a_location; } elseif (headers_sent() != '') { // some output occured -> redirect using javascript echo '<script type="text/javascript">window.location.href = \''.$a_location.'\';</script>'; } else { // no output before -> redirect using HTTP header // header('HTTP/1.1 302 Found'); header("$location"); } } } ob_end_flush(); // session expiration is called from session initialization, // that's why $this->Session may be not defined here $session =& $this->Application->recallObject('Session'); /* @var $session Session */ $this->HandleEvent( new kEvent('adm:OnBeforeShutdown') ); $session->SaveData(); exit; } - function Phrase($label) + function Phrase($label, $allow_editing = true) { - return $this->Phrases->GetPhrase($label); + return $this->Phrases->GetPhrase($label, $allow_editing); } /** * Replace language tags in exclamation marks found in text * * @param string $text * @param bool $force_escape force escaping, not escaping of resulting string * @return string * @access public */ function ReplaceLanguageTags($text, $force_escape=null) { // !!!!!!!! // if( !is_object($this->Phrases) ) $this->Debugger->appendTrace(); return $this->Phrases->ReplaceLanguageTags($text,$force_escape); } /** * Checks if user is logged in, and creates * user object if so. User object can be recalled * later using "u.current" prefix_special. Also you may * get user id by getting "u.current_id" variable. * * @access private */ function ValidateLogin() { $session =& $this->recallObject('Session'); $user_id = $session->GetField('PortalUserId'); if (!$user_id && $user_id != -1) $user_id = -2; $this->SetVar('u.current_id', $user_id); if (!$this->IsAdmin()) { // needed for "profile edit", "registration" forms ON FRONT ONLY $this->SetVar('u_id', $user_id); } $this->StoreVar('user_id', $user_id); if ($this->GetVar('expired') == 1) { // this parameter is set only from admin $user =& $this->recallObject('u.current'); $user->SetError('ValidateLogin', 'session_expired', 'la_text_sess_expired'); } if (($user_id != -2) && constOn('DBG_REQUREST_LOG') ) { $http_query =& $this->recallObject('HTTPQuery'); $http_query->writeRequestLog(DBG_REQUREST_LOG); } if ($user_id != -2) { // normal users + root $this->LoadPersistentVars(); } } /** * Loads current user persistent session data * */ function LoadPersistentVars() { $this->Session->LoadPersistentVars(); } function LoadCache() { $cache_key = $this->GetVar('t').$this->GetVar('m_theme').$this->GetVar('m_lang').$this->IsAdmin(); $query = sprintf("SELECT PhraseList, ConfigVariables FROM %s WHERE Template = %s", TABLE_PREFIX.'PhraseCache', $this->Conn->qstr(md5($cache_key))); $res = $this->Conn->GetRow($query); if ($res) { $this->Caches['PhraseList'] = $res['PhraseList'] ? explode(',', $res['PhraseList']) : array(); $config_ids = $res['ConfigVariables'] ? explode(',', $res['ConfigVariables']) : array(); if (isset($this->Caches['ConfigVariables'])) { $config_ids = array_diff($config_ids, $this->Caches['ConfigVariables']); } } else { $config_ids = array(); } $this->Caches['ConfigVariables'] = $config_ids; $this->ConfigCacheIds = $config_ids; } function UpdateCache() { $update = false; //something changed $update = $update || $this->Phrases->NeedsCacheUpdate(); $update = $update || (count($this->ConfigCacheIds) && $this->ConfigCacheIds != $this->Caches['ConfigVariables']); if ($update) { $cache_key = $this->GetVar('t').$this->GetVar('m_theme').$this->GetVar('m_lang').$this->IsAdmin(); $query = sprintf("REPLACE %s (PhraseList, CacheDate, Template, ConfigVariables) VALUES (%s, %s, %s, %s)", TABLE_PREFIX.'PhraseCache', $this->Conn->Qstr(join(',', $this->Phrases->Ids)), adodb_mktime(), $this->Conn->Qstr(md5($cache_key)), $this->Conn->qstr(implode(',', array_unique($this->ConfigCacheIds)))); $this->Conn->Query($query); } } function InitConfig() { if (isset($this->Caches['ConfigVariables']) && count($this->Caches['ConfigVariables']) > 0) { $this->ConfigHash = array_merge($this->ConfigHash, $this->Conn->GetCol( 'SELECT VariableValue, VariableName FROM '.TABLE_PREFIX.'ConfigurationValues WHERE VariableId IN ('.implode(',', $this->Caches['ConfigVariables']).')', 'VariableName')); } } /** * Returns configuration option value by name * * @param string $name * @return string */ function ConfigValue($name) { $res = array_key_exists($name, $this->ConfigHash) ? $this->ConfigHash[$name] : false; if ($res !== false) { return $res; } if (defined('IS_INSTALL') && IS_INSTALL && !$this->TableFound('ConfigurationValues')) { return false; } $sql = 'SELECT VariableId, VariableValue FROM '.TABLE_PREFIX.'ConfigurationValues WHERE VariableName = '.$this->Conn->qstr($name); $res = $this->Conn->GetRow($sql); if ($res !== false) { $this->ConfigHash[$name] = $res['VariableValue']; $this->ConfigCacheIds[] = $res['VariableId']; return $res['VariableValue']; } return false; } function UpdateConfigCache() { if ($this->ConfigCacheIds) { } } /** * Allows to process any type of event * * @param kEvent $event * @access public * @author Alex */ function HandleEvent(&$event, $params=null, $specificParams=null) { if ( isset($params) ) { $event = new kEvent( $params, $specificParams ); } if (!isset($this->EventManager)) { $this->EventManager =& $this->recallObject('EventManager'); } $this->EventManager->HandleEvent($event); } /** * Registers new class in the factory * * @param string $real_class Real name of class as in class declaration * @param string $file Filename in what $real_class is declared * @param string $pseudo_class Name under this class object will be accessed using getObject method * @param Array $dependecies List of classes required for this class functioning * @access public * @author Alex */ function registerClass($real_class, $file, $pseudo_class = null, $dependecies = Array() ) { $this->Factory->registerClass($real_class, $file, $pseudo_class, $dependecies); } /** * Add $class_name to required classes list for $depended_class class. * All required class files are included before $depended_class file is included * * @param string $depended_class * @param string $class_name * @author Alex */ function registerDependency($depended_class, $class_name) { $this->Factory->registerDependency($depended_class, $class_name); } /** * Registers Hook from subprefix event to master prefix event * * @param string $hookto_prefix * @param string $hookto_special * @param string $hookto_event * @param string $mode * @param string $do_prefix * @param string $do_special * @param string $do_event * @param string $conditional * @access public * @todo take care of a lot parameters passed * @author Kostja */ function registerHook($hookto_prefix, $hookto_special, $hookto_event, $mode, $do_prefix, $do_special, $do_event, $conditional) { $event_manager =& $this->recallObject('EventManager'); $event_manager->registerHook($hookto_prefix, $hookto_special, $hookto_event, $mode, $do_prefix, $do_special, $do_event, $conditional); } /** * Allows one TagProcessor tag act as other TagProcessor tag * * @param Array $tag_info * @author Kostja */ function registerAggregateTag($tag_info) { $aggregator =& $this->recallObject('TagsAggregator', 'kArray'); $aggregator->SetArrayValue($tag_info['AggregateTo'], $tag_info['AggregatedTagName'], Array($tag_info['LocalPrefix'], $tag_info['LocalTagName'], getArrayValue($tag_info, 'LocalSpecial'))); } /** * Returns object using params specified, * creates it if is required * * @param string $name * @param string $pseudo_class * @param Array $event_params * @return Object * @author Alex */ function &recallObject($name,$pseudo_class=null,$event_params=Array()) { $result =& $this->Factory->getObject($name, $pseudo_class, $event_params); return $result; } /** * Returns object using Variable number of params, * all params starting with 4th are passed to object consturctor * * @param string $name * @param string $pseudo_class * @param Array $event_params * @return Object * @author Alex */ function &recallObjectP($name,$pseudo_class=null,$event_params=Array()) { $func_args = func_get_args(); $result =& ref_call_user_func_array( Array(&$this->Factory, 'getObjectP'), $func_args ); return $result; } /** * Returns tag processor for prefix specified * * @param string $prefix * @return kDBTagProcessor */ function &recallTagProcessor($prefix) { $this->InitParser(); // because kDBTagProcesor is in TemplateParser dependencies $result =& $this->recallObject($prefix.'_TagProcessor'); return $result; } /** * Checks if object with prefix passes was already created in factory * * @param string $name object presudo_class, prefix * @return bool * @author Kostja */ function hasObject($name) { return isset($this->Factory->Storage[$name]); } /** * Removes object from storage by given name * * @param string $name Object's name in the Storage * @author Kostja */ function removeObject($name) { $this->Factory->DestroyObject($name); } /** * Get's real class name for pseudo class, * includes class file and creates class * instance * * @param string $pseudo_class * @return Object * @access public * @author Alex */ function &makeClass($pseudo_class) { $func_args = func_get_args(); $result =& ref_call_user_func_array( Array(&$this->Factory, 'makeClass'), $func_args); return $result; } /** * Checks if application is in debug mode * * @param bool $check_debugger check if kApplication debugger is initialized too, not only for defined DEBUG_MODE constant * @return bool * @author Alex * @access public */ function isDebugMode($check_debugger = true) { $debug_mode = defined('DEBUG_MODE') && DEBUG_MODE; if ($check_debugger) { $debug_mode = $debug_mode && is_object($this->Debugger); } return $debug_mode; } /** * Checks if it is admin * * @return bool * @author Alex */ function IsAdmin() { return constOn('ADMIN'); } /** * Apply url rewriting used by mod_rewrite or not * * @param bool $ssl Force ssl link to be build * @return bool */ function RewriteURLs($ssl = false) { // case #1,#4: // we want to create https link from http mode // we want to create https link from https mode // conditions: ($ssl || PROTOCOL == 'https://') && $this->ConfigValue('UseModRewriteWithSSL') // case #2,#3: // we want to create http link from https mode // we want to create http link from http mode // conditions: !$ssl && (PROTOCOL == 'https://' || PROTOCOL == 'http://') $allow_rewriting = (!$ssl && (PROTOCOL == 'https://' || PROTOCOL == 'http://')) // always allow mod_rewrite for http || // or allow rewriting for redirect TO httpS or when already in httpS (($ssl || PROTOCOL == 'https://') && $this->ConfigValue('UseModRewriteWithSSL')); // but only if it's allowed in config! return constOn('MOD_REWRITE') && $allow_rewriting; } /** * Reads unit (specified by $prefix) * option specified by $option * * @param string $prefix * @param string $option * @param mixed $default * @return string * @access public * @author Alex */ function getUnitOption($prefix, $option, $default = false) { /*if (!isset($this->UnitConfigReader)) { $this->UnitConfigReader =& $this->recallObject('kUnitConfigReader'); }*/ return $this->UnitConfigReader->getUnitOption($prefix, $option, $default); } /** * Set's new unit option value * * @param string $prefix * @param string $name * @param string $value * @author Alex * @access public */ function setUnitOption($prefix, $option, $value) { // $unit_config_reader =& $this->recallObject('kUnitConfigReader'); return $this->UnitConfigReader->setUnitOption($prefix,$option,$value); } /** * Read all unit with $prefix options * * @param string $prefix * @return Array * @access public * @author Alex */ function getUnitOptions($prefix) { // $unit_config_reader =& $this->recallObject('kUnitConfigReader'); return $this->UnitConfigReader->getUnitOptions($prefix); } /** * Returns true if config exists and is allowed for reading * * @param string $prefix * @return bool */ function prefixRegistred($prefix) { /*if (!isset($this->UnitConfigReader)) { $this->UnitConfigReader =& $this->recallObject('kUnitConfigReader'); }*/ return $this->UnitConfigReader->prefixRegistred($prefix); } /** * Splits any mixing of prefix and * special into correct ones * * @param string $prefix_special * @return Array * @access public * @author Alex */ function processPrefix($prefix_special) { return $this->Factory->processPrefix($prefix_special); } /** * Set's new event for $prefix_special * passed * * @param string $prefix_special * @param string $event_name * @access public */ function setEvent($prefix_special,$event_name) { $event_manager =& $this->recallObject('EventManager'); $event_manager->setEvent($prefix_special,$event_name); } /** * SQL Error Handler * * @param int $code * @param string $msg * @param string $sql * @return bool * @access private * @author Alex */ function handleSQLError($code, $msg, $sql) { if ( isset($this->Debugger) ) { $errorLevel = constOn('DBG_SQL_FAILURE') && !defined('IS_INSTALL') ? E_USER_ERROR : E_USER_WARNING; $this->Debugger->appendTrace(); $error_msg = '<span class="debug_error">'.$msg.' ('.$code.')</span><br><a href="javascript:$Debugger.SetClipboard(\''.htmlspecialchars($sql).'\');"><b>SQL</b></a>: '.$this->Debugger->formatSQL($sql); $long_id = $this->Debugger->mapLongError($error_msg); trigger_error( mb_substr($msg.' ('.$code.') ['.$sql.']',0,1000).' #'.$long_id, $errorLevel); return true; } else { //$errorLevel = constOn('IS_INSTALL') ? E_USER_WARNING : E_USER_ERROR; $errorLevel = E_USER_WARNING; trigger_error('<b>SQL Error</b> in sql: '.$sql.', code <b>'.$code.'</b> ('.$msg.')', $errorLevel); /*echo '<b>xProcessing SQL</b>: '.$sql.'<br>'; echo '<b>Error ('.$code.'):</b> '.$msg.'<br>';*/ return $errorLevel == E_USER_ERROR ? false : true; } } /** * Default error handler * * @param int $errno * @param string $errstr * @param string $errfile * @param int $errline * @param Array $errcontext */ function handleError($errno, $errstr, $errfile = '', $errline = '', $errcontext = '') { if (defined('SILENT_LOG') && SILENT_LOG) { if ( !(defined('DBG_IGNORE_STRICT_ERRORS') && DBG_IGNORE_STRICT_ERRORS && defined('E_STRICT') && ($errno == E_STRICT)) ) { $fp = fopen(FULL_PATH.'/silent_log.txt','a'); $time = adodb_date('d/m/Y H:i:s'); fwrite($fp, '['.$time.'] #'.$errno.': '.strip_tags($errstr).' in ['.$errfile.'] on line '.$errline."\n"); fclose($fp); } } $debug_mode = defined('DEBUG_MODE') && DEBUG_MODE; $skip_reporting = defined('DBG_SKIP_REPORTING') && DBG_SKIP_REPORTING; if (!$this->errorHandlers || ($debug_mode && $skip_reporting)) { // when debugger absent OR it's present, but we actually can't see it's error report (e.g. during ajax request) $ignore_fatal_errors = defined('DBG_IGNORE_FATAL_ERRORS') && DBG_IGNORE_FATAL_ERRORS; if (($errno == E_USER_ERROR) && !$ignore_fatal_errors) { echo (' <div style="background-color: #FEFFBF; margin: auto; padding: 10px; border: 2px solid red; text-align: center"> <strong>Fatal Error: </strong>'."$errstr in $errfile on line $errline".' </div>'); exit; } if (!$this->errorHandlers) { return true; } } $res = false; $i = 0; // while (not foreach) because it is array of references in some cases $eh_count = count($this->errorHandlers); while ($i < $eh_count) { if ( is_array($this->errorHandlers[$i]) ) { $object =& $this->errorHandlers[$i][0]; $method = $this->errorHandlers[$i][1]; $res = $object->$method($errno, $errstr, $errfile, $errline, $errcontext); } else { $function = $this->errorHandlers[$i]; $res = $function($errno, $errstr, $errfile, $errline, $errcontext); } $i++; } return $res; } /** * Returns & blocks next ResourceId available in system * * @return int * @access public * @author Alex */ function NextResourceId() { $table_name = TABLE_PREFIX.'IdGenerator'; $this->Conn->Query('LOCK TABLES '.$table_name.' WRITE'); $this->Conn->Query('UPDATE '.$table_name.' SET lastid = lastid + 1'); $id = $this->Conn->GetOne('SELECT lastid FROM '.$table_name); if($id === false) { $this->Conn->Query('INSERT INTO '.$table_name.' (lastid) VALUES (2)'); $id = 2; } $this->Conn->Query('UNLOCK TABLES'); return $id - 1; } /** * Returns genealogical main prefix for subtable prefix passes * OR prefix, that has been found in REQUEST and some how is parent of passed subtable prefix * * @param string $current_prefix * @param string $real_top if set to true will return real topmost prefix, regardless of its id is passed or not * @return string * @access public * @author Kostja / Alex */ function GetTopmostPrefix($current_prefix, $real_top = false) { // 1. get genealogical tree of $current_prefix $prefixes = Array ($current_prefix); while ( $parent_prefix = $this->getUnitOption($current_prefix, 'ParentPrefix') ) { if (!$this->prefixRegistred($parent_prefix)) { // stop searching, when parent prefix is not registered break; } $current_prefix = $parent_prefix; array_unshift($prefixes, $current_prefix); } if ($real_top) { return $current_prefix; } // 2. find what if parent is passed $passed = explode(',', $this->GetVar('all_passed')); foreach ($prefixes as $a_prefix) { if (in_array($a_prefix, $passed)) { return $a_prefix; } } return $current_prefix; } /** * Triggers email event of type Admin * * @param string $email_event_name * @param int $to_user_id * @param array $send_params associative array of direct send params, possible keys: to_email, to_name, from_email, from_name, message, message_text * @return unknown */ function &EmailEventAdmin($email_event_name, $to_user_id = -1, $send_params = false) { $event =& $this->EmailEvent($email_event_name, 1, $to_user_id, $send_params); return $event; } /** * Triggers email event of type User * * @param string $email_event_name * @param int $to_user_id * @param array $send_params associative array of direct send params, possible keys: to_email, to_name, from_email, from_name, message, message_text * @return unknown */ function &EmailEventUser($email_event_name, $to_user_id = -1, $send_params = false) { $event =& $this->EmailEvent($email_event_name, 0, $to_user_id, $send_params); return $event; } /** * Triggers general email event * * @param string $email_event_name * @param int $email_event_type ( 0 for User, 1 for Admin) * @param int $to_user_id * @param array $send_params associative array of direct send params, * possible keys: to_email, to_name, from_email, from_name, message, message_text * @return unknown */ function &EmailEvent($email_event_name, $email_event_type, $to_user_id = -1, $send_params = false) { $params = array( 'EmailEventName' => $email_event_name, 'EmailEventToUserId' => $to_user_id, 'EmailEventType' => $email_event_type, ); if ($send_params) { $params['DirectSendParams'] = $send_params; } $event_str = isset($send_params['use_special']) ? 'emailevents.'.$send_params['use_special'].':OnEmailEvent' : 'emailevents:OnEmailEvent'; $this->HandleEvent($event, $event_str, $params); return $event; } /** * Allows to check if user in this session is logged in or not * * @return bool */ function LoggedIn() { // no session during expiration process return is_null($this->Session) ? false : $this->Session->LoggedIn(); } /** * Check current user permissions based on it's group permissions in specified category * * @param string $name permission name * @param int $cat_id category id, current used if not specified * @param int $type permission type {1 - system, 0 - per category} * @return int */ function CheckPermission($name, $type = 1, $cat_id = null) { $perm_helper =& $this->recallObject('PermissionsHelper'); return $perm_helper->CheckPermission($name, $type, $cat_id); } /** * Set's any field of current visit * * @param string $field * @param mixed $value */ function setVisitField($field, $value) { $visit =& $this->recallObject('visits'); $visit->SetDBField($field, $value); $visit->Update(); } /** * Allows to check if in-portal is installed * * @return bool */ function isInstalled() { return $this->InitDone && (count($this->ModuleInfo) > 0); } /** * Allows to determine if module is installed & enabled * * @param string $module_name * @return bool */ function isModuleEnabled($module_name) { return $this->findModule('Name', $module_name) !== false; } function reportError($class, $method) { $this->Debugger->appendTrace(); trigger_error('depricated method <b>'.$class.'->'.$method.'(...)</b>', E_USER_ERROR); } /** * Returns Window ID of passed prefix main prefix (in edit mode) * * @param string $prefix * @return mixed */ function GetTopmostWid($prefix) { $top_prefix = $this->GetTopmostPrefix($prefix); $mode = $this->GetVar($top_prefix.'_mode'); return $mode != '' ? substr($mode, 1) : ''; } /** * Get temp table name * * @param string $table * @param mixed $wid * @return string */ function GetTempName($table, $wid = '') { if (preg_match('/prefix:(.*)/', $wid, $regs)) { $wid = $this->GetTopmostWid($regs[1]); } return TABLE_PREFIX.'ses_'.$this->GetSID().($wid ? '_'.$wid : '').'_edit_'.$table; } function GetTempTablePrefix($wid = '') { if (preg_match('/prefix:(.*)/', $wid, $regs)) { $wid = $this->GetTopmostWid($regs[1]); } return TABLE_PREFIX.'ses_'.$this->GetSID().($wid ? '_'.$wid : '').'_edit_'; } function IsTempTable($table) { return preg_match('/'.TABLE_PREFIX.'ses_'.$this->GetSID().'(_[\d]+){0,1}_edit_(.*)/',$table); } /** * Checks, that given prefix is in temp mode * * @param string $prefix * @return bool */ function IsTempMode($prefix, $special = '') { $top_prefix = $this->Application->GetTopmostPrefix($prefix); $var_names = Array ( $top_prefix, rtrim($top_prefix . '_' . $special, '_'), // from post rtrim($top_prefix . '.' . $special, '.'), // assembled locally ); $var_names = array_unique($var_names); $temp_mode = false; foreach ($var_names as $var_name) { $value = $this->Application->GetVar($var_name . '_mode'); if ($value && (substr($value, 0, 1) == 't')) { $temp_mode = true; break; } } return $temp_mode; } /** * Return live table name based on temp table name * * @param string $temp_table * @return string */ function GetLiveName($temp_table) { if( preg_match('/'.TABLE_PREFIX.'ses_'.$this->GetSID().'(_[\d]+){0,1}_edit_(.*)/',$temp_table, $rets) ) { // cut wid from table end if any return $rets[2]; } else { return $temp_table; } } function CheckProcessors($processors) { foreach ($processors as $a_processor) { if (!isset($this->CachedProcessors[$a_processor])) { $this->CachedProcessors[$a_processor] =& $this->recallObject($a_processor.'_TagProcessor'); } } } function TimeZoneAdjustment($time_zone = null) { if ($time_zone == 'GMT') { return (-1) * adodb_date('Z'); } $target_zone = isset($time_zone) ? $time_zone : $this->ConfigValue('Config_Site_Time'); return 3600 * ($target_zone - $this->ConfigValue('Config_Server_Time')); } function ApplicationDie($message = '') { $message = ob_get_clean().$message; if ($this->isDebugMode()) { $message .= $this->Debugger->printReport(true); } echo $this->UseOutputCompression() ? gzencode($message, DBG_COMPRESSION_LEVEL) : $message; exit; } /* moved from MyApplication */ function getUserGroups($user_id) { switch($user_id) { case -1: $user_groups = $this->ConfigValue('User_LoggedInGroup'); break; case -2: $user_groups = $this->ConfigValue('User_LoggedInGroup'); $user_groups .= ','.$this->ConfigValue('User_GuestGroup'); break; default: $sql = 'SELECT GroupId FROM '.TABLE_PREFIX.'UserGroup WHERE PortalUserId = '.$user_id; $res = $this->Conn->GetCol($sql); $user_groups = Array( $this->ConfigValue('User_LoggedInGroup') ); if(is_array($res)) { $user_groups = array_merge($user_groups, $res); } $user_groups = implode(',', $user_groups); } return $user_groups; } /** * Allows to detect if page is browsed by spider (293 agents supported) * * @return bool */ function IsSpider() { static $is_spider = null; if (!isset($is_spider)) { $user_agent = trim($_SERVER['HTTP_USER_AGENT']); $robots = file(FULL_PATH.'/core/robots_list.txt'); foreach ($robots as $robot_info) { $robot_info = explode("\t", $robot_info, 3); if ($user_agent == trim($robot_info[2])) { $is_spider = true; break; } } } return $is_spider; } /** * Allows to detect table's presense in database * * @param string $table_name * @return bool */ function TableFound($table_name) { return $this->Conn->TableFound($table_name); } /** * Returns counter value * * @param string $name counter name * @param Array $params counter parameters * @param string $query_name specify query name directly (don't generate from parmeters) * @param bool $multiple_results * @return mixed */ function getCounter($name, $params = Array (), $query_name = null, $multiple_results = false) { $count_helper =& $this->Application->recallObject('CountHelper'); /* @var $count_helper kCountHelper */ return $count_helper->getCounter($name, $params, $query_name, $multiple_results); } /** * Resets counter, whitch are affected by one of specified tables * * @param string $tables comma separated tables list used in counting sqls */ function resetCounters($tables) { if (constOn('IS_INSTALL')) { return ; } $count_helper =& $this->Application->recallObject('CountHelper'); /* @var $count_helper kCountHelper */ return $count_helper->resetCounters($tables); } /** * Sends XML header + optionally displays xml heading * * @param string $xml_version * @return string * @author Alex */ function XMLHeader($xml_version = false) { $lang =& $this->recallObject('lang.current'); header('Content-type: text/xml; charset='.$lang->GetDBField('Charset')); return $xml_version ? '<?xml version="'.$xml_version.'" encoding="'.$lang->GetDBField('Charset').'"?>' : ''; } /** * Returns category tree * * @param int $category_id * @return Array */ function getTreeIndex($category_id) { $category_template = $this->getFilename('c', $category_id); // to rebuild "category_tree" cache $tree_index = $this->getCache('category_tree', $category_id); if ($tree_index) { $ret = Array (); list ($ret['TreeLeft'], $ret['TreeRight']) = explode(';', $tree_index); return $ret; } return false; } } ?> \ No newline at end of file Index: branches/5.0.x/core/kernel/constants.php =================================================================== --- branches/5.0.x/core/kernel/constants.php (revision 12297) +++ branches/5.0.x/core/kernel/constants.php (revision 12298) @@ -1,126 +1,125 @@ <?php /** * @version $Id$ * @package In-Portal * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. * @license GNU/GPL * In-Portal is Open Source software. * This means that this software may have been modified pursuant * the GNU General Public License, and as distributed it includes * or is derivative of works licensed under the GNU General Public License * or other free or open source software licenses. * See http://www.in-portal.net/license/ for copyright notices and details. */ // kDBList filter types (then, types are divided into classes) define('HAVING_FILTER', 1); define('WHERE_FILTER', 2); define('AGGREGATE_FILTER', 3); // kDBList filter classes define('FLT_SYSTEM', 1); // System Having/Where filter [AND] define('FLT_NORMAL', 2); // User Having/Where filter [OR] define('FLT_SEARCH', 3); // User "Search" Having/Where filter [OR] define('FLT_VIEW', 4); // User "View Menu" Having/Where filter [AND] define('FLT_CUSTOM', 5); // Custom fields (above) grid columns [AND] // kMultipleFilter types define('FLT_TYPE_AND', 'AND'); define('FLT_TYPE_OR', 'OR'); // item statuses define('STATUS_DISABLED', 0); define('STATUS_ACTIVE', 1); define('STATUS_PENDING', 2); define('STATUS_PENDING_EDITING', -2); // sections define('stTREE', 1); define('stTAB', 2); // event statuses define('erSUCCESS', 0); // event finished working succsessfully define('erFAIL', -1); // event finished working, but result is unsuccsessfull define('erFATAL', -2); // event experienced FATAL error - no hooks should continue! define('erPERM_FAIL', -3); // event failed on internal permission checking (user has not permission) define('erSTOP', -4); // event requested to stop processing (don't parse templates) // permission types define('ptCATEGORY', 0); define('ptSYSTEM', 1); // email event types define('EVENT_TYPE_FRONTEND', 0); define('EVENT_TYPE_ADMIN', 1); define('EDIT_MARK', '&|edit|&'); // replace this sequence inside filters to SID[_main_wid] $application =& kApplication::Instance(); $spacer_url = $application->BaseURL().'core/admin_templates/img/spacer.gif'; define('SPACER_URL', $spacer_url); if (!$application->IsAdmin()) { // don't show debugger buttons on front (if not overrided in "debug.php") safeDefine('DBG_TOOLBAR_BUTTONS', 0); } define('smHIDE', 0); // always hide section from tree define('smNORMAL', 1); // show section even, if they were marked as smDEBUG or smSUPER_ADMIN before define('smDEBUG', 2); // show section in debug mode only define('smSUPER_ADMIN', 4); // show section in super admin & debug mode // common usage regular expressions define('REGEX_EMAIL_USER', '[-a-zA-Z0-9!\#$%&*+\/=?^_`{|}~.]+'); define('REGEX_EMAIL_DOMAIN', '[a-zA-Z0-9]{1}[-.a-zA-Z0-9_]*\.[a-zA-Z]{2,6}'); define('ALLOW_DEFAULT_SETTINGS', '_USE_DEFAULT_USER_DATA_'); //Allow persistent vars to take data from default user's persistent data define('XML_NO_TEXT_NODES', 1); // Normal mode for XMLHelper define('XML_WITH_TEXT_NODES', 2); // Will create text nodes for every char-data (used in kPDFHelper) // ChangeLog actions define('clCREATE', 1); define('clUPDATE', 2); define('clDELETE', 3); /** * Separator for ValueList fields * */ define('VALUE_LIST_SEPARATOR', '||'); // template editing modes - define('EDITING_MODE_CMS', 1); // content block only - define('EDITING_MODE_LAYOUT', 2); // content blocks, marked with "layout_view" parameter - define('EDITING_MODE_DESIGN', 3); // blocks, used as designs - define('EDITING_MODE_INSIDES', 4); // all other stuff, that could be editable + define('EDITING_MODE_BROWSE', 1); // no changes, front-end as users see it + define('EDITING_MODE_CONTENT', 2); // content blocks + phrase editing + define('EDITING_MODE_DESIGN', 3); // all other blocks // agent types define('AGENT_TYPE_USER', 1); define('AGENT_TYPE_SYSTEM', 2); // agent last run statuses define('AGENT_LAST_RUN_SUCCEDED', 1); define('AGENT_LAST_RUN_FAILED', 0); define('AGENT_LAST_RUN_RUNNING', 2); // place for product file uploads (sort of "/system/images" but for all other files) define('ITEM_FILES_PATH', WRITEBALE_BASE . '/downloads/'); // mailing list statuses define('MAILING_LIST_NOT_PROCESSED', 1); define('MAILING_LIST_PARTIALLY_PROCESSED', 2); define('MAILING_LIST_PROCESSED', 3); define('MAILING_LIST_CANCELLED', 4); // theme file statuses (related to structure creation process) define('SMS_MODE_AUTO', 1); define('SMS_MODE_FORCE', 2); /** * Means, that actual category Template field value should inherited from parent category * */ define('CATEGORY_TEMPLATE_INHERIT', '#inherit#'); define('REWRITE_MODE_BUILD', 1); define('REWRITE_MODE_PARSE', 2); Index: branches/5.0.x/core/kernel/processors/main_processor.php =================================================================== --- branches/5.0.x/core/kernel/processors/main_processor.php (revision 12297) +++ branches/5.0.x/core/kernel/processors/main_processor.php (revision 12298) @@ -1,1158 +1,1159 @@ <?php /** * @version $Id$ * @package In-Portal * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. * @license GNU/GPL * In-Portal is Open Source software. * This means that this software may have been modified pursuant * the GNU General Public License, and as distributed it includes * or is derivative of works licensed under the GNU General Public License * or other free or open source software licenses. * See http://www.in-portal.net/license/ for copyright notices and details. */ class kMainTagProcessor extends TagProcessor { function Init($prefix, $special, $event_params = null) { parent::Init($prefix, $special, $event_params); $actions =& $this->Application->recallObject('kActions'); $actions->Set('t', $this->Application->GetVar('t')); $actions->Set('sid', $this->Application->GetSID()); $actions->Set('m_opener', $this->Application->GetVar('m_opener') ); } /** * Used to handle calls where tag name * match with existing php function name * * @param Tag $tag * @return string */ function ProcessTag(&$tag) { if ($tag->Tag=='include') $tag->Tag='MyInclude'; return parent::ProcessTag($tag); } /** * Base folder for all template includes * * @param Array $params * @return string */ function TemplatesBase($params) { $force_admin = array_key_exists('force_admin', $params) && $params['force_admin']; $module = array_key_exists('module', $params) ? $params['module'] : 'core'; if ($this->Application->IsAdmin() || $force_admin) { if ($module == 'in-portal') { $module = 'kernel'; } $path = $force_admin ? '/core/admin_templates' : THEMES_PATH; $path = preg_replace('/\/(.*?)\/(.*)/', $module.'/\\2', $path); // remove leading slash + substitute module } else { $path = mb_substr(THEMES_PATH, 1); if (mb_strtolower($module) == 'in-portal') { $module_folder = 'platform'; } else { $module_folder = $this->Application->findModule('Name', $module, 'TemplatePath'); } $path .= rtrim('/' . trim($module_folder, '/'), '/') . '/'; } return $this->Application->BaseURL() . $path; } /** * Creates <base href ..> HTML tag for all templates * affects future css, js files and href params of links * * @return string * @access public */ function Base_Ref($params) { return '<base href="'.$this->TemplatesBase($params).'/" />'; } /** * Returns base url for web-site * * @return string * @access public */ function BaseURL() { return $this->Application->BaseURL(); } //for compatability with K3 tags function Base($params) { return $this->TemplatesBase($params).'/'; } function ProjectBase($params) { return $this->Application->BaseURL(); } /*function Base($params) { return $this->Application->BaseURL().$params['add']; }*/ /** * Used to create link to any template. * use "pass" paramter if "t" tag to specify * prefix & special of object to be represented * in resulting url * * @param Array $params * @return string * @access public */ function T($params) { //by default link to current template $t = $this->SelectParam($params, 't,template'); unset($params['t']); unset($params['template']); $prefix=isset($params['prefix']) ? $params['prefix'] : ''; unset($params['prefix']); $index_file = isset($params['index_file']) ? $params['index_file'] : null; unset($params['index_file']); return $this->Application->HREF($t, $prefix, $params, $index_file); } function Link($params) { if (isset($params['template'])) { $params['t'] = $params['template']; unset($params['template']); } if (!isset($params['pass']) && !isset($params['no_pass'])) $params['pass'] = 'm'; if (isset($params['no_pass'])) unset($params['no_pass']); if ( $this->Application->GetVar('admin') ) { $params['admin'] = 1; if (!array_key_exists('editing_mode', $params)) { $params['editing_mode'] = EDITING_MODE; } } return $this->T($params); } function Env($params) { $t = $params['template']; unset($params['template']); return $this->Application->BuildEnv($t, $params, 'm', null, false); } function FormAction($params) { $params['pass'] = 'all,m'; $params['pass_category'] = 1; return $this->Application->HREF('', '', $params); } /*// NEEDS TEST function Config($params) { return $this->Application->ConfigOption($params['var']); } function Object($params) { $name = $params['name']; $method = $params['method']; $tmp =& $this->Application->recallObject($name); if ($tmp != null) { if (method_exists($tmp, $method)) return $tmp->$method($params); else echo "Method $method does not exist in object ".get_class($tmp)." named $name<br>"; } else echo "Object $name does not exist in the appliaction<br>"; }*/ /** * Tag, that always returns true. * For parser testing purposes * * @param Array $params * @return bool * @access public */ function True($params) { return true; } /** * Tag, that always returns false. * For parser testing purposes * * @param Array $params * @return bool * @access public */ function False($params) { return false; } /** * Returns block parameter by name * * @param Array $params * @return stirng * @access public */ function Param($params) { //$parser =& $this->Application->recallObject('TemplateParser'); $name = $params['name']; if (isset($this->Application->LateParsed[$name])) { $f = $this->Application->PreParsedBlocks['capture_'.$name.$this->Application->LateParsed[$name]]; $this->Application->Parser->SetParam($name, $f(array())); } $res = $this->Application->Parser->GetParam($params['name']); if ($res === false) $res = ''; if (isset($params['plus'])) $res += $params['plus']; return $res; } function DefaultParam($params) { foreach ($params as $key => $val) { if ($this->Application->Parser->GetParam($key) === false) { $this->Application->Parser->SetParam($key, $val); } } } /** * Gets value of specified field from specified prefix_special and set it as parser param * * @param Array $params */ /*function SetParam($params) { // <inp2:m_SetParam param="custom_name" src="cf:FieldName"/> list($prefix_special, $field_name) = explode(':', $params['src']); $object =& $this->Application->recallObject($prefix_special); $name = $this->SelectParam($params, 'param,name,var'); $this->Application->Parser->SetParam($name, $object->GetField($field_name) ); }*/ /** * Compares block parameter with value specified * * @param Array $params * @return bool * @access public */ function ParamEquals($params) { //$parser =& $this->Application->recallObject('TemplateParser'); $name = $this->SelectParam($params, 'name,var,param'); $value = $params['value']; return ($this->Application->Parser->GetParam($name) == $value); } /*function PHP_Self($params) { return $HTTP_SERVER_VARS['PHP_SELF']; } */ /** * Returns session variable value by name * * @param Array $params * @return string * @access public */ function Recall($params) { $var_name = $this->SelectParam($params,'name,var,param'); if (isset($params['persistent']) && $params['persistent']) { $ret = $this->Application->RecallPersistentVar($var_name); } else { $ret = $this->Application->RecallVar($var_name); } $ret = ($ret === false && isset($params['no_null'])) ? '' : $ret; if (getArrayValue($params, 'special') || getArrayValue($params, 'htmlchars')) { $ret = htmlspecialchars($ret); } if (getArrayValue($params, 'urlencode')) { $ret = urlencode($ret); } return $ret; } function RemoveVar($params) { $this->Application->RemoveVar( $this->SelectParam($params,'name,var,param') ); } // bad style to store something from template to session !!! (by Alex) // Used here only to test how session works, nothing more function Store($params) { //echo"Store $params[name]<br>"; $name = $params['name']; $value = $params['value']; $this->Application->StoreVar($name,$value); } /** * Sets application variable value(-s) * * @param Array $params * @access public */ function Set($params) { foreach ($params as $param => $value) { $this->Application->SetVar($param, $value); } } /** * Increment application variable * specified by number specified * * @param Array $params * @access public */ function Inc($params) { $this->Application->SetVar($params['param'], $this->Application->GetVar($params['param']) + $params['by']); } /** * Retrieves application variable * value by name * * @param Array $params * @return string * @access public */ function Get($params) { $ret = $this->Application->GetVar($this->SelectParam($params, 'name,var,param'), ''); return getArrayValue($params, 'htmlchars') ? htmlspecialchars($ret) : $ret; } /** * Retrieves application constant * value by name * * @param Array $params * @return string * @access public */ function GetConst($params) { return defined($this->SelectParam($params, 'name,const')) ? constant($this->SelectParam($params, 'name,const,param')) : ''; } /** * Retrieves configuration variable value by name * * @param Array $params * @return string * @access public */ function GetConfig($params) { $config_name = $this->SelectParam($params, 'name,var'); $ret = $this->Application->ConfigValue($config_name); if( getArrayValue($params, 'escape') ) $ret = addslashes($ret); return $ret; } function ConfigEquals($params) { $option = $this->SelectParam($params, 'name,option,var'); return $this->Application->ConfigValue($option) == getArrayValue($params, 'value'); } /** * Creates all hidden fields * needed for kernel_form * * @param Array $params * @return string * @access public */ function DumpSystemInfo($params) { $actions =& $this->Application->recallObject('kActions'); $actions->Set('t', $this->Application->GetVar('t') ); $params = $actions->GetParams(); $o=''; foreach ($params AS $name => $val) { $o .= "<input type='hidden' name='$name' id='$name' value='$val'>\n"; } return $o; } /** * Used for search sidebox on front-end only * * @param Array $params * @return string * @author Alex */ function GetFormHiddens($params) { $t = $this->SelectParam($params, 'template,t'); unset($params['template']); $form_fields = Array (); if ($this->Application->RewriteURLs()) { $session =& $this->Application->recallObject('Session'); if ($session->NeedQueryString()) { $form_fields['sid'] = $this->Application->GetSID(); } } else { $form_fields['env'] = $this->Application->BuildEnv($t, $params, 'm', null, false); } if ($this->Application->GetVar('admin') == 1) { $form_fields['admin'] = 1; } $ret = ''; $field_tpl = '<input type="hidden" name="%1$s" id="%1$s" value="%2$s"/>'."\n"; foreach ($form_fields as $form_field => $field_value) { $ret .= sprintf($field_tpl, $form_field, $field_value); } return $ret; } function Odd_Even($params) { $odd = $params['odd']; $even = $params['even']; if (!isset($params['var'])) { $var = 'odd_even'; } else { $var = $params['var']; } if ($this->Application->GetVar($var) == 'even') { if (!isset($params['readonly']) || !$params['readonly']) { $this->Application->SetVar($var, 'odd'); } return $even; } else { if (!isset($params['readonly']) || !$params['readonly']) { $this->Application->SetVar($var, 'even'); } return $odd; } } /** * Returns phrase translation by name * * @param Array $params * @return string * @access public */ function Phrase($params) { // m:phrase name="phrase_name" default="Tr-alala" updated="2004-01-29 12:49" $phrase_name = $this->SelectParam($params, 'label,name,title'); if (isset($params['source']) && $params['source']) { $phrase_name = $this->Application->GetVar($phrase_name); if (array_key_exists('default', $params) && !$phrase_name) { $phrase_name = $params['default']; } } - $translation = $this->Application->Phrase($phrase_name); + $no_editing = array_key_exists('no_editing', $params) && $params['no_editing']; + $translation = $this->Application->Phrase($phrase_name, !$no_editing); if (isset($params['escape']) && $params['escape']) { $translation = htmlspecialchars($translation, ENT_QUOTES); $translation = addslashes($translation); } return $translation; } // for tabs function is_active($params) { $test_templ = $this->SelectParam($params, 'templ,template,t'); if ( !getArrayValue($params,'allow_empty') ) { $if_true=getArrayValue($params,'true') ? $params['true'] : 1; $if_false=getArrayValue($params,'false') ? $params['false'] : 0; } else { $if_true=$params['true']; $if_false=$params['false']; } if ( preg_match("/^".str_replace('/', '\/', $test_templ)."/i", $this->Application->GetVar('t'))) { return $if_true; } else { return $if_false; } } function IsNotActive($params) { return !$this->is_active($params); } function IsActive($params) { return $this->is_active($params); } function is_t_active($params) { return $this->is_active($params); } function CurrentTemplate($params) { return $this->is_active($params); } /** * Checks if session variable * specified by name value match * value passed as parameter * * @param Array $params * @return string * @access public */ function RecallEquals($params) { $name = $this->SelectParam($params, 'name,var'); $value = $params['value']; if (isset($params['persistent']) && $params['persistent']) { return $this->Application->RecallPersistentVar($name) == $value; } return ($this->Application->RecallVar($name) == $value); } /** * Checks if application variable * specified by name value match * value passed as parameter * * @param Array $params * @return bool * @access public */ function GetEquals($params) { $name = $this->SelectParam($params, 'var,name,param'); $value = $params['value']; if ($this->Application->GetVar($name) == $value) { return 1; } } /** * Includes template * and returns it's * parsed version * * @param Array $params * @return string * @access public */ function MyInclude($params) { if (defined('NPARSER') && NPARSER) { return $this->Application->Parser->IncludeTemplate($params, isset($params['is_silent']) ? 1 : 0); } $BlockParser =& $this->Application->makeClass('TemplateParser'); /* @var $BlockParser TemplateParser */ // $BlockParser->SetParams($params); $parser =& $this->Application->Parser; $this->Application->Parser =& $BlockParser; // this is for the parser to know the master template in case an error occurs, // ParseTemplate will reset it anyway, but this will allow error handler to display the tempalte // which tries to include missing template for example $this->Application->Parser->TemplateName = $parser->TemplateName; $t = $this->SelectParam($params, 't,template,block,name'); $t = eregi_replace("\.tpl$", '', $t); if (!$t) { trigger_error('Template name not specified in <b><inp2:m_include .../></b> tag', E_USER_ERROR); } if (isset($this->Application->PreParsedBlocks[$t]) ) { $params['name'] = $t; $res = $this->Application->ParseBlock($params); } else { $res = $BlockParser->ParseTemplate($t, 1, $params, isset($params['is_silent']) ? 1 : 0 ); } if (!$BlockParser->DataExists && ((isset($params['data_exists']) && $params['data_exists']) || isset($params['block_no_data']))) { if ($block_no_data = getArrayValue($params, 'block_no_data')) { if (isset($this->Application->PreParsedBlocks[$block_no_data]) ) { // block_no_data is another block name $res = $this->Application->ParseBlock(Array('name' => $block_no_data)); } else { // block_no_data is template name (only looks through real templates) $res = $BlockParser->ParseTemplate($block_no_data, 1, Array(), getArrayValue($params, 'is_silent')); } } else { $res = ''; } } $this->Application->Parser =& $parser; $this->Application->Parser->DataExists = $this->Application->Parser->DataExists || $BlockParser->DataExists; if (isset($params['return_params']) && $params['return_params']) { $new_params = array_merge($this->Application->Parser->Params, $BlockParser->ParamsStack[0]); $this->Application->Parser->SetParams($new_params, false); } return $res; } function ModuleInclude($params) { $ret = ''; $block_params = array_merge($params, Array('is_silent' => 2)); // don't make fatal errors in case if template is missing $current_template = $this->Application->GetVar('t'); $replace_main = isset($params['replace_m']) && $params['replace_m']; $skip_prefixes = isset($params['skip_prefixes']) ? explode(',', $params['skip_prefixes']) : Array(); $cms_mode = $this->Application->GetVar('admin'); foreach ($this->Application->ModuleInfo as $module_name => $module_data) { $module_key = mb_strtolower($module_name); if ($module_name == 'In-Portal') { if (!$cms_mode && $this->Application->IsAdmin()) { // don't process In-Portal templates in admin continue; } // Front-End still relies on In-Portal module $module_prefix = $module_data['TemplatePath']; } else { $module_prefix = $this->Application->IsAdmin() ? $module_key.'/' : rtrim($module_data['TemplatePath'], '/').'/'; } $block_params['t'] = $module_prefix.$this->SelectParam($params, $module_key.'_template,'.$module_key.'_t,template,t'); $check_prefix = $module_data['Var']; if ($check_prefix == 'adm' && $replace_main) { $check_prefix = 'c'; } if ($block_params['t'] == $current_template || in_array($check_prefix, $skip_prefixes)) { continue; } $no_data = $this->SelectParam($params, $module_key.'_block_no_data,block_no_data'); if ($no_data) { $block_params['block_no_data'] = $module_prefix.'/'.$no_data; } $ret .= $this->MyInclude($block_params); } return $ret; } function ModuleEnabled($params) { return $this->Application->isModuleEnabled( $params['module'] ); } /*function Kernel_Scripts($params) { return '<script type="text/javascript" src="'.PROTOCOL.SERVER_NAME.BASE_PATH.'/kernel3/js/grid.js"></script>'; }*/ /*function GetUserPermission($params) { // echo"GetUserPermission $params[name]"; if ($this->Application->RecallVar('user_type') == 1) return 1; else { $perm_name = $params[name]; $aPermissions = unserialize($this->Application->RecallVar('user_permissions')); if ($aPermissions) return $aPermissions[$perm_name]; } }*/ /** * Set's parser block param value * * @param Array $params * @access public */ function AddParam($params) { $parser =& $this->Application->Parser; // recallObject('TemplateParser'); foreach ($params as $param => $value) { $this->Application->SetVar($param, $value); $parser->SetParam($param, $value); $parser->AddParam('/\$'.$param.'/', $value); } } /*function ParseToVar($params) { $var = $params['var']; $tagdata = $params['tag']; $parser =& $this->Application->Parser; //recallObject('TemplateParser'); $res = $this->Application->ProcessTag($tagdata); $parser->SetParam($var, $res); $parser->AddParam('/\$'.$var.'/', $res); return ''; }*/ /*function TagNotEmpty($params) { $tagdata = $params['tag']; $res = $this->Application->ProcessTag($tagdata); return $res != ''; }*/ /*function TagEmpty($params) { return !$this->TagNotEmpty($params); }*/ /** * Checks if debug mode is on * * @param Array $params * @return bool * @access public */ function IsDebugMode($params) { return $this->Application->isDebugMode(); } function MassParse($params) { $qty = $params['qty']; $block = $params['block']; $mode = $params['mode']; $o = ''; if ($mode == 'func') { $func = create_function('$params', ' $o = \'<tr>\'; $o.= \'<td>a\'.$params[\'param1\'].\'</td>\'; $o.= \'<td>a\'.$params[\'param2\'].\'</td>\'; $o.= \'<td>a\'.$params[\'param3\'].\'</td>\'; $o.= \'<td>a\'.$params[\'param4\'].\'</td>\'; $o.= \'</tr>\'; return $o; '); for ($i=1; $i<$qty; $i++) { $block_params['param1'] = rand(1, 10000); $block_params['param2'] = rand(1, 10000); $block_params['param3'] = rand(1, 10000); $block_params['param4'] = rand(1, 10000); $o .= $func($block_params); } return $o; } $block_params['name'] = $block; for ($i=0; $i<$qty; $i++) { $block_params['param1'] = rand(1, 10000); $block_params['param2'] = rand(1, 10000); $block_params['param3'] = rand(1, 10000); $block_params['param4'] = rand(1, 10000); $block_params['passed'] = $params['passed']; $block_params['prefix'] = 'm'; $o.= $this->Application->ParseBlock($block_params, 1); } return $o; } function LoggedIn($params) { return $this->Application->LoggedIn(); } /** * Allows to check if permission exists directly in template and perform additional actions if required * * @param Array $params * @return bool */ function CheckPermission($params) { $perm_helper =& $this->Application->recallObject('PermissionsHelper'); return $perm_helper->TagPermissionCheck($params); } /** * Checks if user is logged in and if not redirects it to template passed * * @param Array $params */ function RequireLogin($params) { $t = $this->Application->GetVar('t'); if ($next_t = getArrayValue($params, 'next_template')) { $t = $next_t; } // check by permissions: begin if ((isset($params['perm_event']) && $params['perm_event']) || (isset($params['perm_prefix']) && $params['perm_prefix']) || (isset($params['permissions']) && $params['permissions'])) { $perm_helper =& $this->Application->recallObject('PermissionsHelper'); /* @var $perm_helper kPermissionsHelper */ $perm_status = $perm_helper->TagPermissionCheck($params); if (!$perm_status) { list($redirect_template, $redirect_params) = $perm_helper->getPermissionTemplate($params); $this->Application->Redirect($redirect_template, $redirect_params); } else { return ; } } // check by permissions: end // check by configuration value: begin $condition = getArrayValue($params, 'condition'); if (!$condition) { $condition = true; } else { if (substr($condition, 0, 1) == '!') { $condition = !$this->Application->ConfigValue(substr($condition, 1)); } else { $condition = $this->Application->ConfigValue($condition); } } // check by configuration value: end // check by belonging to group: begin $group = $this->SelectParam($params, 'group'); $group_access = true; if ($group) { $conn =& $this->Application->GetADODBConnection(); $group_id = $conn->GetOne('SELECT GroupId FROM '.TABLE_PREFIX.'PortalGroup WHERE Name = '.$conn->qstr($group)); if ($group_id) { $groups = explode(',', $this->Application->RecallVar('UserGroups')); $group_access = in_array($group_id, $groups); } } // check by belonging to group: end if ((!$this->Application->LoggedIn() || !$group_access) && $condition) { $redirect_params = $this->Application->HttpQuery->getRedirectParams(true); $redirect_params['next_template'] = $t; if (array_key_exists('pass_category', $params)) { $redirect_params['pass_category'] = $params['pass_category']; } if ( $this->Application->LoggedIn() && !$group_access) { $this->Application->Redirect( $params['no_group_perm_template'], $redirect_params); } $this->Application->Redirect($params['login_template'], $redirect_params); } } function IsMember($params) { $group = getArrayValue($params, 'group'); $conn =& $this->Application->DB; $group_id = $conn->GetOne('SELECT GroupId FROM '.TABLE_PREFIX.'PortalGroup WHERE Name = '.$conn->qstr($group)); if ($group_id) { $groups = explode(',', $this->Application->RecallVar('UserGroups')); $group_access = in_array($group_id, $groups); } return $group_access; } /** * Checks if SSL is on and redirects to SSL URL if needed * If SSL_URL is not defined in config - the tag does not do anything * If for_logged_in_only="1" exits if user is not logged in. * If called without params forces https right away. If called with by_config="1" checks the * Require SSL setting from General Config and if it is ON forces https * * @param unknown_type $params */ function CheckSSL($params) { $ssl = $this->Application->IsAdmin() ? $this->Application->ConfigValue('AdminSSL_URL') : false; if (!$ssl) { // not in admin or admin ssl url is empty $ssl = $this->Application->ConfigValue('SSL_URL'); } if (!$ssl) return; //SSL URL is not set - no way to require SSL $require = false; if (isset($params['mode']) && $params['mode'] == 'required') { $require = true; if (isset($params['for_logged_in_only']) && $params['for_logged_in_only'] && !$this->Application->LoggedIn()) { $require = false; } if (isset($params['condition'])) { if (!$this->Application->ConfigValue($params['condition'])) { $require = false; } } } $http_query =& $this->Application->recallObject('HTTPQuery'); $pass = $http_query->getRedirectParams(); if ($require) { if (PROTOCOL == 'https://') { $this->Application->SetVar('__KEEP_SSL__', 1); return; } $this->Application->Redirect('', array_merge_recursive2($pass, Array('__SSL__' => 1))); } else { if (PROTOCOL == 'https://' && $this->Application->ConfigValue('Force_HTTP_When_SSL_Not_Required')) { if ($this->Application->GetVar('__KEEP_SSL__')) return; // $pass_more = Array ('pass' => 'm', 'm_cat_id' => 0, '__SSL__' => 0); $this->Application->Redirect('', array_merge_recursive2($pass, Array('__SSL__' => 0))); // $pass_more } } } function ConstOn($params) { $name = $this->SelectParam($params,'name,const'); return constOn($name); } function SetDefaultCategory($params) { $category_id = $this->Application->findModule('Name', $params['module'], 'RootCat'); $this->Application->SetVar('m_cat_id', $category_id); } function XMLTemplate($params) { safeDefine('DBG_SKIP_REPORTING', 1); if (isset($params['cache']) && $params['cache']) { $nextyear = intval(date('Y') + 1); $format = "D, d M Y H:i:s"; $expiration = gmdate($format, mktime() + $params['cache']).' GMT'; $last_modified = mktime(); header ('Cache-Control: public, cache, max-age='.$params['cache']); header ("Expires: $expiration"); header ('Pragma: public'); // Getting headers sent by the client. $headers = request_headers(); // Checking if the client is validating his cache and if it is current. if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) > $last_modified-$params['cache'])) { // Client's cache IS current, so we just respond '304 Not Modified'. header('Last-Modified: '.date($format, strtotime($headers['If-Modified-Since'])).' GMT', true, 304); exit(); } else { // Image not cached or cache outdated, we respond '200 OK' and output the image. header('Last-Modified: '.gmdate($format, $last_modified).' GMT', true, 200); } } // xml documents are usually long set_time_limit(0); ini_set('memory_limit', -1); return $this->Application->XMLHeader(getArrayValue($params, 'xml_version')); } function Header($params) { header($params['data']); } function NoDebug($params) { if (!$this->Application->GetVar('debug')) { define('DBG_SKIP_REPORTING', 1); } } function RootCategoryName($params) { $root_phrase = $this->Application->ConfigValue('Root_Name'); return $this->Application->Phrase($root_phrase); } /** * Allows to attach file directly from email event template * * @param Array $params */ function AttachFile($params) { $esender =& $application->recallObject('EmailSender'.(isset($params['special']) ? '.'.$params['special'] : '')); /* @var $esender kEmailSendingHelper */ $path = FULL_PATH.'/'.$params['path']; if (file_exists($path)) { $esender->AddAttachment($path); } } function CaptchaImage($params){ $captcha_helper =& $this->Application->recallObject('CaptchaHelper'); /* @var $captcha_helper kCaptchaHelper */ $captcha_helper->GenerateCaptchaImage( $this->Application->RecallVar($this->Application->GetVar('var')), $this->Application->GetVar('w'), $this->Application->GetVar('h'), true ); } function SID($params) { return $this->Application->GetSID(); } function ModuleInfo($params) { return $this->Application->findModule($params['key'], $params['value'], $params['return']); } function Random($params) { return rand(1, 100000000); } /** * Prints parser params, available at current deep level * * @param Array $params * @return string */ function PrintCurrentParams($params) { $current_params = $this->Application->Parser->Params; foreach ($current_params as $param_name => $param_value) { $current_params[$param_name] = $param_name . ' = "' . $param_value . '"'; } return '<pre>' . implode("\n", $current_params) . '</pre>'; } /** * Gets previously defined counter result * * @param Array $params * @return int */ function GetCounter($params) { return $this->Application->getCounter($params['name'], $params); } /** * Increments PageHit counter * * @param Array $params * @return int */ function RegisterPageHit($params) { if ($this->Application->ConfigValue('UsePageHitCounter')) { $db =& $this->Application->GetADODBConnection(); // get current counte $sql = 'SELECT VariableValue FROM '.TABLE_PREFIX.'ConfigurationValues WHERE VariableName = "PageHitCounter"'; $page_counter = (int)$db->GetOne($sql); $sql = 'UPDATE LOW_PRIORITY '.TABLE_PREFIX.'ConfigurationValues SET VariableValue = '.($page_counter + 1).' WHERE VariableName = "PageHitCounter"'; $db->Query($sql); } } function Timestamp($params) { $format = isset($params['format']) ? $params['format'] : 'd.m.Y H:i:s'; return adodb_date($format); } } Index: branches/5.0.x/core/kernel/languages/phrases_cache.php =================================================================== --- branches/5.0.x/core/kernel/languages/phrases_cache.php (revision 12297) +++ branches/5.0.x/core/kernel/languages/phrases_cache.php (revision 12298) @@ -1,282 +1,361 @@ <?php /** * @version $Id$ * @package In-Portal * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. * @license GNU/GPL * In-Portal is Open Source software. * This means that this software may have been modified pursuant * the GNU General Public License, and as distributed it includes * or is derivative of works licensed under the GNU General Public License * or other free or open source software licenses. * See http://www.in-portal.net/license/ for copyright notices and details. */ class PhrasesCache extends kBase { /** * Connection to database * * @var kDBConnection * @access public */ var $Conn; var $Phrases = Array(); var $Ids = Array(); var $OriginalIds = Array(); //for comparing cache var $LanguageId = null; var $fromTag = false; + /** + * Allows to edit existing phrases + * + * @var bool + */ + var $_editExisting = false; + + /** + * Allows to edit missing phrases + * + * @var bool + */ + var $_editMissing = false; + + /** + * Template, used for phrase adding/editing + * + * @var string + */ + var $_phraseEditTemplate = ''; + + /** + * Use popup for phrase editing + * + * @var bool + */ + var $_usePopups = false; + + /** + * Use simplified form for phrase editing + * + * @var bool + */ + var $_simpleEditingMode = false; + + /** + * HTML tag used to translate phrases + * + * @var string + */ + var $_translateHtmlTag = 'a'; + function PhrasesCache() { parent::kBase(); $this->Conn =& $this->Application->GetADODBConnection(); + + if (defined('DEBUG_MODE') && DEBUG_MODE && $this->Application->IsAdmin()) { + // only has effect in admin, because on front-end phrases are translated in "Content Mode" + $this->_editMissing = defined('DBG_PHRASES') && DBG_PHRASES; + } + + // now we use admin phrase editing template even on front-end + $this->_phraseEditTemplate = 'regional/phrases_edit'; + $this->_usePopups = $this->Application->ConfigValue('UsePopups'); + } + + /** + * Sets phrase editing mode, that corresponds current editing mode + * + */ + function setPhraseEditing() + { + if (!$this->Application->IsAdmin() && (EDITING_MODE == EDITING_MODE_CONTENT)) { + $this->_editExisting = true; + $this->_editMissing = true; + $this->_simpleEditingMode = true; + $this->_translateHtmlTag = 'span'; + } } function Init($prefix, $special = '') { if (constOn('IS_INSTALL')) { $this->LanguageId = 1; } else { if ($this->Application->IsAdmin()) { $id_field = $this->Application->getUnitOption('lang', 'IDField'); $table_name = $this->Application->getUnitOption('lang', 'TableName'); $sql = 'SELECT '.$id_field.' FROM '.$table_name.' WHERE AdminInterfaceLang = 1'; $this->LanguageId = $this->Conn->GetOne($sql); } else { $this->LanguageId = $this->Application->GetVar('m_lang'); } } if (isset($this->Application->Caches['PhraseList'])) { $this->LoadPhrases( $this->Application->Caches['PhraseList'] ); } } function GetCachedIds() { - $query = sprintf("SELECT PhraseList, ConfigVariables FROM %s WHERE Template = %s", - TABLE_PREFIX.'PhraseCache', - $this->Conn->Qstr(md5($this->Application->GetVar('t').$this->Application->GetVar('m_theme').$this->Application->GetVar('m_lang')))); - $res = $this->Conn->GetRow($query); + $cache_key = md5($this->Application->GetVar('t') . $this->Application->GetVar('m_theme') . $this->Application->GetVar('m_lang')); + + $sql = 'SELECT PhraseList, ConfigVariables + FROM ' . TABLE_PREFIX . 'PhraseCache + WHERE Template = ' . $this->Conn->qstr($cache_key); + $res = $this->Conn->GetRow($sql); if ($res && $res['ConfigVariables']) { $this->Application->OriginalConfigCacheIds = explode(',', $res['ConfigVariables']); $this->Application->ConfigCacheIds = $this->Application->OriginalConfigCacheIds; } return ($res === false) ? Array() : explode(',', $res['PhraseList']); } function LoadPhrases($ids) { - if ( !is_array($ids) || !implode('', $ids) ) return; - $query = sprintf("SELECT Translation,UPPER(Phrase) AS Phrase FROM %s WHERE LanguageId = %s AND PhraseId IN (%s)", - TABLE_PREFIX.'Phrase', - $this->LanguageId, - join(',', $ids)); - $this->Phrases = $this->Conn->GetCol($query,'Phrase'); + if ( !is_array($ids) || !implode('', $ids) ) { + return; + } + + $sql = 'SELECT Translation, UPPER(Phrase) AS Phrase + FROM ' . TABLE_PREFIX . 'Phrase + WHERE (LanguageId = ' . $this->LanguageId . ') AND PhraseId IN (' . implode(',', $ids) . ')'; + $this->Phrases = $this->Conn->GetCol($sql, 'Phrase'); + /*foreach($phrases as $phrase => $tanslation) { $this->AddCachedPhrase(mb_strtoupper($phrase), $tanslation); }*/ + $this->Ids = $ids; $this->OriginalIds = $ids; } function AddCachedPhrase($label, $value) { $label = mb_strtoupper($label); $this->Phrases[$label] = $value; } function NeedsCacheUpdate() { return is_array($this->Ids) && count($this->Ids) > 0 && $this->Ids != $this->OriginalIds; } /** * Copy from Application->UpdateCache method * * @deprecated */ function UpdateCache() { $update = false; //something changed $update = $update || (is_array($this->Ids) && count($this->Ids) > 0 && $this->Ids != $this->OriginalIds); $update = $update || (count($this->Application->ConfigCacheIds) && $this->Application->ConfigCacheIds != $this->Application->OriginalConfigCacheIds); if ($update) { $query = sprintf("REPLACE %s (PhraseList, CacheDate, Template, ConfigVariables) VALUES (%s, %s, %s, %s)", TABLE_PREFIX.'PhraseCache', $this->Conn->Qstr(join(',', $this->Ids)), adodb_mktime(), $this->Conn->Qstr(md5($this->Application->GetVar('t').$this->Application->GetVar('m_theme').$this->Application->GetVar('m_lang'))), $this->Conn->qstr(implode(',', array_unique($this->Application->ConfigCacheIds)))); $this->Conn->Query($query); } } - function GetPhrase($label) + function GetPhrase($label, $allow_editing = true) { - if (!isset($this->LanguageId)) return 'impossible case'; - //actually possible when custom field contains references to language labels and its being rebuilt in OnAfterConfigRead - //which is triggered by Sections rebuild, which in turn read all the configs and all of that happens BEFORE seeting the language... + if (!isset($this->LanguageId)) { + //actually possible when custom field contains references to language labels and its being rebuilt in OnAfterConfigRead + //which is triggered by Sections rebuild, which in turn read all the configs and all of that happens BEFORE seeting the language... + return 'impossible case'; + } - if (ereg("^!.+!$", $label) > 0) - { + if (ereg("^!.+!$", $label) > 0) { $label = substr($label, 1, -1); //cut exclamation marks } - if( strlen($label) == 0 ) return ''; + if (strlen($label) == 0) { + return ''; + } $original_label = $label; $label = mb_strtoupper($label); - if(isset($this->Phrases[$label])) { - $translated_label = $this->Phrases[$label]; - // debug mode is checked directly to improve performance - if (defined('DEBUG_MODE') && DEBUG_MODE && constOn('DBG_PHRASES_HIGHLIGHT')) { - if (!$this->Application->isDebugMode()) return $translated_label; - - if ($this->Application->IsAdmin()) { - $sql = 'SELECT Module - FROM '.TABLE_PREFIX.'Phrase - WHERE (LanguageId = '.$this->LanguageId.') AND (Phrase = '.$this->Conn->qstr($label).')'; - $this->Application->Debugger->appendHTML('Phrase: <b>'.$label.'</b>; Module: <b>'.$this->Conn->GetOne($sql).'</b>'); -// $translated_label = $translated_label.' [m: '.$this->Conn->GetOne($sql).'; l: '.$label.']'; - } - else { - // highlight text created via translated phrase (used to detect if text on screen is phrase or not) - $translated_label = '<span style="border: 1px solid #999999; background-color: #cccccc; color: #999999; ">'.$translated_label.'</span></a> <span style="color: red; background-color:#ffffcc">'.$original_label.'</span>'; - } - } + if (array_key_exists($label, $this->Phrases)) { + $translated_label = $this->Phrases[$label]; - if (defined('DEBUG_MODE') && DEBUG_MODE && - (($this->Application->IsAdmin() && constOn('DBG_PHRASES_EDIT_ADMIN')) || (!$this->Application->IsAdmin() && constOn('DBG_PHRASES_EDIT_FRONT')) ) ) { + if ($this->_editExisting && $allow_editing) { // option to change translation for Labels - list($edit_tpl, $index_file) = $this->Application->IsAdmin() ? Array('regional/phrases_edit', 'index.php') : Array('phrases_edit', 'index.php'); - - if ($this->Application->IsAdmin() && $this->Application->ConfigValue('UsePopups')) { + if ($this->_usePopups) { // link to popup when using popups (only in admin) - $edit_url = 'javascript:translate_phrase(\''.addslashes($translated_label).'\', \''.$edit_tpl.'\');'; + $edit_url = 'javascript:translate_phrase(\'' . addslashes($original_label) . '\', \'' . $this->_phraseEditTemplate . '\', {event: \'OnPrepareUpdate\', simple_mode: ' . ($this->_simpleEditingMode ? 'true' : 'false') . '});'; } else { // direct link, when not using popups OR on frontend - $edit_url = $this->Application->HREF($edit_tpl,'',Array('m_opener'=>'d','phrases_label'=>$original_label,'phrases_event'=>'OnPrepareUpdate', 'pass'=>'all,phrases'), $index_file ); + $url_params = Array( + 'm_opener' => 'd', + 'phrases_label' => $original_label, + 'phrases_event' => 'OnPrepareUpdate', + 'simple_mode' => $this->_simpleEditingMode ? 1 : 0, + 'pass' => 'all,phrases' + ); + + $edit_url = $this->Application->HREF($this->_phraseEditTemplate, '', $url_params, 'index.php'); + } + + $translated_label = '<' . $this->_translateHtmlTag . ' href="' . $edit_url . '" name="cms-translate-phrase" title="Edit translation">' . $translated_label . '</' . $this->_translateHtmlTag . '>'; + + if ($this->fromTag) { + $translated_label = $this->escapeTagReserved($translated_label); } - $translated_label = '<a href="'.$edit_url.'">!'.$translated_label.'!</a>'; } return $translated_label; } - $this->LoadPhraseByLabel($label, $original_label); + $this->LoadPhraseByLabel($label, $original_label, $allow_editing); + return $this->GetPhrase($label); } - function LoadPhraseByLabel($label, $original_label) + function LoadPhraseByLabel($label, $original_label, $allow_editing = true) { - $query = sprintf("SELECT PhraseId, Translation FROM %s WHERE LanguageId = %s AND UPPER(Phrase) = UPPER(%s)", - TABLE_PREFIX.'Phrase', - $this->LanguageId, - $this->Conn->qstr($label)); - $res = $this->Conn->GetRow($query); - if ($res === false || count($res) == 0) - { - $translation = '!'.$label.'!'; - if($this->Application->isDebugMode() && constOn('DBG_PHRASES')) { - list($edit_tpl, $index_file) = $this->Application->IsAdmin() ? Array('regional/phrases_edit', 'index.php') : Array('phrases_edit', 'index.php'); + $sql = 'SELECT PhraseId, Translation + FROM ' . TABLE_PREFIX . 'Phrase + WHERE (LanguageId = ' . $this->LanguageId . ') AND (UPPER(Phrase) = UPPER(' . $this->Conn->qstr($label) . '))'; + $res = $this->Conn->GetRow($sql); + + if ($res === false || count($res) == 0) { + $translation = '!' . $label . '!'; - if ($this->Application->IsAdmin() && $this->Application->ConfigValue('UsePopups')) { + if ($this->_editMissing && $allow_editing) { + if ($this->_usePopups) { // link to popup when using popups (only in admin) - $edit_url = 'javascript:translate_phrase(\''.addslashes($original_label).'\', \''.$edit_tpl.'\');'; + $edit_url = 'javascript:translate_phrase(\'' . addslashes($original_label) . '\', \'' . $this->_phraseEditTemplate . '\', {event: \'OnNew\', simple_mode: ' . ($this->_simpleEditingMode ? 'true' : 'false') . '});'; } else { // direct link, when not using popups OR on frontend - $edit_url = $this->Application->HREF($edit_tpl,'',Array('m_opener'=>'d','phrases_label'=>$original_label,'phrases_event'=>'OnNew', 'pass'=>'all,phrases'), $index_file ); + $url_params = Array ( + 'm_opener' => 'd', + 'phrases_label' => $original_label, + 'phrases_event' => 'OnNew', + 'simple_mode' => $this->_simpleEditingMode ? 1 : 0, + 'pass' => 'all,phrases' + ); + + $edit_url = $this->Application->HREF($this->_phraseEditTemplate, '', $url_params, 'index.php'); } - $translation = '<a href="'.$edit_url.'">!'.$label.'!</a>'; - if($this->fromTag) $translation = $this->escapeTagReserved($translation); + $translation = '<' . $this->_translateHtmlTag . ' href="' . $edit_url . '" class="cms-translate-phrase" title="Translate">!' . $label . '!</' . $this->_translateHtmlTag . '>'; + + if ($this->fromTag) { + $translation = $this->escapeTagReserved($translation); + } } - $this->AddCachedPhrase($label, $translation); //add it as already cached, as long as we dont need to cache not found phrase + + // add it as already cached, as long as we dont need to cache not found phrase + $this->AddCachedPhrase($label, $translation); + return false; } $this->Phrases[$label] = $res['Translation']; array_push($this->Ids, $res['PhraseId']); $this->Ids = array_unique($this->Ids); //just to make sure return true; } /** * Sort params by name and then by length * * @param string $a * @param string $b * @return int * @access private */ function CmpParams($a, $b) { $a_len = mb_strlen($a); $b_len = mb_strlen($b); if ($a_len == $b_len) return 0; return $a_len > $b_len ? -1 : 1; } /** * Replace language tags in exclamation marks found in text * * @param string $text * @param bool $force_escape force escaping, not escaping of resulting string * @return string * @access public */ function ReplaceLanguageTags($text,$forse_escaping=null) { $this->fromTag = true; if( isset($forse_escaping) ) $this->fromTag = $forse_escaping; preg_match_all("(!(la|lu)[^!]+!)", $text, $res, PREG_PATTERN_ORDER); $language_tags = $res[0]; uasort($language_tags, Array(&$this, 'CmpParams') ); $values = Array(); $i = 0; foreach ($language_tags as $label) { array_push($values, $this->GetPhrase($label) ); //array_push($values, $this->Application->Phrase($label) ); $language_tags[$i] = '/' . $language_tags[$i] . '/'; $i++; } $this->fromTag = false; + return preg_replace($language_tags, $values, $text); } /** * Escape chars in phrase translation, that could harm parser to process tag * * @param string $text * @return string * @access private */ function escapeTagReserved($text) { $reserved = Array('"',"'"); // = $replacement = Array('\"',"\'"); // \= return str_replace($reserved,$replacement,$text); } -} - - -?> \ No newline at end of file +} \ No newline at end of file Index: branches/5.0.x/core/kernel/nparser/nparser.php =================================================================== --- branches/5.0.x/core/kernel/nparser/nparser.php (revision 12297) +++ branches/5.0.x/core/kernel/nparser/nparser.php (revision 12298) @@ -1,879 +1,876 @@ <?php /** * @version $Id$ * @package In-Portal * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. * @license GNU/GPL * In-Portal is Open Source software. * This means that this software may have been modified pursuant * the GNU General Public License, and as distributed it includes * or is derivative of works licensed under the GNU General Public License * or other free or open source software licenses. * See http://www.in-portal.net/license/ for copyright notices and details. */ include_once(KERNEL_PATH.'/nparser/ntags.php'); define('TAG_NAMESPACE', 'inp2:'); define('TAG_NAMESPACE_LENGTH', 5); class NParser extends kBase { var $Stack = array(); var $Level = 0; var $Buffers = array(); var $InsideComment = false; var $Params = array(); var $ParamsStack = array(); var $ParamsLevel = 0; var $Definitions = ''; var $Elements = array(); // holds dynamic elements to function names mapping during execution /** * Holds location of element definitions inside templates. * key - element function name, value - array of 2 keys: {from_pos, to_pos} * * @var Array */ var $ElementLocations = Array (); var $DataExists = false; var $TemplateName = null; var $TempalteFullPath = null; var $CachePointers = array(); var $Cachable = array(); /** * Compress compiled templates * * @var bool */ var $_compressOutput = false; function NParser() { parent::kBase(); $this->_compressOutput = $this->Application->ConfigValue('UseTemplateCompression'); } function Compile($pre_parsed, $template_name = 'unknown') { $data = file_get_contents($pre_parsed['tname']); if (!$this->CompileRaw($data, $pre_parsed['tname'], $template_name)) { // compilation failed during errors in template // trigger_error('Template "<strong>' . $template_name . '</strong>" not compiled because of errors', E_USER_WARNING); return false; } // saving compiled version (only when compilation was successful) if (defined('SAFE_MODE') && SAFE_MODE) { // store cache files in database since can't save on filesystem if (!isset($conn)) $conn =& $this->Application->GetADODBConnection(); $conn->Query('REPLACE INTO '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ('.$conn->qstr($pre_parsed['fname']).','.$conn->qstr($this->Buffers[0]).','.adodb_mktime().')'); } else { $compiled = fopen($pre_parsed['fname'], 'w'); if ($this->_compressOutput) { $this->Buffers[0] = $this->_compress($this->Buffers[0]); } if (!fwrite($compiled, $this->Buffers[0])) { trigger_error('Saving compiled template failed', E_USER_ERROR); } fclose($compiled); } return true; } function Parse($raw_template, $name = null) { $this->CompileRaw($raw_template, $name); ob_start(); $_parser =& $this; eval('?'.'>'.$this->Buffers[0]); return ob_get_clean(); } function CompileRaw($data, $t_name, $template_name = 'unknown') { $code = "extract (\$_parser->Params);\n"; $code .= "\$_parser->ElementLocations['{$template_name}'] = Array('template' => '{$template_name}', 'start_pos' => 0, 'end_pos' => " . strlen($data) . ");\n"; // $code .= "__@@__DefinitionsMarker__@@__\n"; // $code .= "if (!\$this->CacheStart('".abs(crc32($t_name))."_0')) {\n"; $this->Buffers[0] = '<?'."php $code ?>\n"; $this->Cacheable[0] = true; $this->Definitions = ''; // finding all the tags $reg = '(.*?)(<[\\/]?)' . TAG_NAMESPACE . '([^>]*?)([\\/]?>)(\r\n){0,1}'; preg_match_all('/'.$reg.'/s', $data, $results, PREG_SET_ORDER + PREG_OFFSET_CAPTURE); $this->InsideComment = false; foreach ($results as $tag_data) { $tag = array( 'opening' => $tag_data[2][0], 'tag' => $tag_data[3][0], 'closing' => $tag_data[4][0], 'line' => substr_count(substr($data, 0, $tag_data[2][1]), "\n")+1, 'pos' => $tag_data[2][1], 'file' => $t_name, 'template' => $template_name, ); // the idea is to count number of comment openings and closings before current tag // if the numbers do not match we inverse the status of InsideComment if (substr_count($tag_data[1][0], '<!--') != substr_count($tag_data[1][0], '-->')) { $this->InsideComment = !$this->InsideComment; } // appending any text/html data found before tag $this->Buffers[$this->Level] .= $tag_data[1][0]; if (!$this->InsideComment) { $tmp_tag = $this->Application->CurrentNTag; $this->Application->CurrentNTag = $tag; if ($this->ProcessTag($tag) === false) { $this->Application->CurrentNTag = $tmp_tag; return false; } $this->Application->CurrentNTag = $tmp_tag; } else { $this->Buffers[$this->Level] .= $tag_data[2][0].$tag_data[3][0].$tag_data[4][0]; } } if ($this->Level > 0) { $this->Application->handleError(E_USER_ERROR, 'Unclosed tag opened by '.$this->TagInfo($this->Stack[$this->Level]->Tag), $this->Stack[$this->Level]->Tag['file'], $this->Stack[$this->Level]->Tag['line']); return false; } // appending text data after last tag (after its closing pos), // if no tag was found at all ($tag_data is not set) - append the whole $data $this->Buffers[$this->Level] .= isset($tag_data) ? substr($data, $tag_data[4][1]+strlen($tag_data[4][0])) : $data; $this->Buffers[$this->Level] = preg_replace('/<!--##(.*?)##-->/s', '', $this->Buffers[$this->Level]); // remove hidden comments IB#23065 // $this->Buffers[$this->Level] .= '<?'.'php '."\n\$_parser->CacheEnd();\n}\n"." ?".">\n"; // $this->Buffers[$this->Level] = str_replace('__@@__DefinitionsMarker__@@__', $this->Definitions, $this->Buffers[$this->Level]); return true; } function SplitParamsStr($params_str) { preg_match_all('/([\${}a-zA-Z0-9_.\\-\\\\#\\[\\]]+)=(["\']{1,1})(.*?)(?<!\\\)\\2/s', $params_str, $rets, PREG_SET_ORDER); $values = Array(); // we need to replace all occurences of any current param $key with {$key} for correct variable substitution foreach ($rets AS $key => $val){ $values[$val[1]] = str_replace('\\' . $val[2], $val[2], $val[3]); } return $values; } function SplitTag($tag) { if (!preg_match('/([^_ \t\r\n]*)[_]?([^ \t\r\n]*)[ \t\r\n]*(.*)$$/s', $tag['tag'], $parts)) { // this is virtually impossible, but just in case $this->Application->handleError(E_USER_ERROR, 'Incorrect tag format: '.$tag['tag'], $tag['file'], $tag['line']); return false; } $splited['prefix'] = $parts[2] ? $parts[1] : '__auto__'; $splited['name'] = $parts[2] ? $parts[2] : $parts[1]; $splited['attrs'] = $parts[3]; return $splited; } function ProcessTag($tag) { $splited = $this->SplitTag($tag); if ($splited === false) { return false; } $tag = array_merge($tag, $splited); $tag['processed'] = false; $tag['NP'] = $this->SplitParamsStr($tag['attrs']); $o = ''; $tag['is_closing'] = $tag['opening'] == '</' || $tag['closing'] == '/>'; if (class_exists('_Tag_'.$tag['name'])) { // block tags should have special handling class if ($tag['opening'] == '<') { $class = '_Tag_'.$tag['name']; $instance = new $class($tag); $instance->Parser =& $this; /* @var $instance _BlockTag */ $this->Stack[++$this->Level] =& $instance; $this->Buffers[$this->Level] = ''; $this->Cachable[$this->Level] = true; $open_code = $instance->Open($tag); if ($open_code === false) { return false; } $o .= $open_code; } if ($tag['is_closing']) { // not ELSE here, because tag may be <empty/> and still has a handler-class if ($this->Level == 0) { $dump = array(); foreach ($this->Stack as $instance) { $dump[] = $instance->Tag; } print_pre($dump); $this->Application->handleError(E_USER_ERROR, 'Closing tag without an opening: '.$this->TagInfo($tag).' <b> - probably opening tag was removed or nested tags error</b>', $tag['file'], $tag['line']); return false; } if ($this->Stack[$this->Level]->Tag['name'] != $tag['name']) { $opening_tag = $this->Stack[$this->Level]->Tag; $this->Application->handleError(E_USER_ERROR, 'Closing tag '.$this->TagInfo($tag).' does not match opening tag at current nesting level ('.$this->TagInfo($opening_tag).' opened at line '.$opening_tag['line'].')', $tag['file'], $tag['line']); return false; } $o .= $this->Stack[$this->Level]->Close($tag); // DO NOT use $this->Level-- here because it's used inside Close $this->Level--; } } else { // regular tags - just compile if (!$tag['is_closing']) { $this->Application->handleError(E_USER_ERROR, 'Tag without a handler: '.$this->TagInfo($tag).' <b> - probably missing <empty <span style="color: red">/</span>> tag closing</b>', $tag['file'], $tag['line']); return false; } if ($this->Level > 0) $o .= $this->Stack[$this->Level]->PassThrough($tag); if (!$tag['processed']) { $compiled = $this->CompileTag($tag); if ($compiled === false) return false; if (isset($tag['NP']['cachable']) && (!$tag['NP']['cachable'] || $tag['NP']['cachable'] == 'false')) { $this->Cachable[$this->Level] = false; } $o .= '<?'.'php ' . $compiled . " ?>\n"; // $o .= '<?'.'php '; // $o .= (isset($tag['NP']['cachable']) && (!$tag['NP']['cachable'] || $tag['NP']['cachable'] == 'false')) ? $this->BreakCache($compiled, $this->GetPointer($tag)) : $compiled; // $o .= " ?".">\n"; } } $this->Buffers[$this->Level] .= $o; return true; } function GetPointer($tag) { return abs(crc32($tag['file'])).'_'.$tag['line']; } function BreakCache($code, $pointer, $condition='') { return "\$_parser->CacheEnd();\n}\n" . $code."\nif ( !\$_parser->CacheStart('{$pointer}'" . ($condition ? ", {$condition}" : '') . ") ) {\n"; } function TagInfo($tag, $with_params=false) { return "<b>{$tag['prefix']}_{$tag['name']}".($with_params ? ' '.$tag['attrs'] : '')."</b>"; } function CompileParamsArray($arr) { $to_pass = 'Array('; foreach ($arr as $name => $val) { $to_pass .= '"'.$name.'" => "'.str_replace('"', '\"', $val).'",'; } $to_pass .= ')'; return $to_pass; } function CompileTag($tag) { $to_pass = $this->CompileParamsArray($tag['NP']); $code = ''; if ($tag['prefix'] == '__auto__') { $prefix = $this->GetParam('PrefixSpecial'); $code .= '$_p_ =& $_parser->GetProcessor($PrefixSpecial);'."\n"; $code .= 'echo $_p_->ProcessParsedTag(\''.$tag['name'].'\', '.$to_pass.', "$PrefixSpecial", \''.$tag['file'].'\', '.$tag['line'].');'."\n"; } else { $prefix = $tag['prefix']; $code .= '$_p_ =& $_parser->GetProcessor("'.$tag['prefix'].'");'."\n"; $code .= 'echo $_p_->ProcessParsedTag(\''.$tag['name'].'\', '.$to_pass.', "'.$tag['prefix'].'", \''.$tag['file'].'\', '.$tag['line'].');'."\n"; } if (isset($tag['NP']['result_to_var'])) { $code .= "\$params['{$tag['NP']['result_to_var']}'] = \$_parser->GetParam('{$tag['NP']['result_to_var']}');\n"; $code .= "\${$tag['NP']['result_to_var']} = \$params['{$tag['NP']['result_to_var']}'];\n"; } if ($prefix && strpos($prefix, '$') === false) { $p =& $this->GetProcessor($prefix); if (!is_object($p) || !$p->CheckTag($tag['name'], $tag['prefix'])) { $this->Application->handleError(E_USER_ERROR, 'Unknown tag: '.$this->TagInfo($tag).' <b> - incorrect tag name or prefix </b>', $tag['file'], $tag['line']); return false; } } return $code; } function CheckTemplate($t, $silent=null) { $pre_parsed = $this->Application->TemplatesCache->GetPreParsed($t); if (!$pre_parsed) { if (!$silent) { if ($this->Application->isDebugMode()) $this->Application->Debugger->appendTrace(); trigger_error('Cannot include "<strong>' . $t . '</strong>" - file does not exist', E_USER_ERROR); } return false; } $force_compile = defined('DBG_NPARSER_FORCE_COMPILE') && DBG_NPARSER_FORCE_COMPILE; if (!$pre_parsed || !$pre_parsed['active'] || $force_compile) { $inc_parser = new NParser(); if ($force_compile) { // remove Front-End theme markings during total compilation $t = preg_replace('/^theme:.*?\//', '', $t); } if (!$inc_parser->Compile($pre_parsed, $t)) return false; } return $pre_parsed; } function Run($t, $silent=null) { if ((strpos($t, '../') !== false) || (trim($t) !== $t)) { // when relative paths or special chars are found template names from url, then it's hacking attempt return false; } $pre_parsed = $this->CheckTemplate($t, $silent); if (!$pre_parsed) return false; $backup_template = $this->TemplateName; $backup_fullpath = $this->TempalteFullPath; $this->TemplateName = $t; $this->TempalteFullPath = $pre_parsed['tname']; ob_start(); $_parser =& $this; if (defined('SAFE_MODE') && SAFE_MODE) { // read cache files from database since can't save on filesystem $conn =& $this->Application->GetADODBConnection(); $cached = $conn->GetRow('SELECT * FROM '.TABLE_PREFIX.'Cache WHERE VarName = "'.$pre_parsed['fname'].'"'); if ($cached !== false && $cached['Cached'] > filemtime($pre_parsed['tname'])) { eval('?'.'>'.$cached['Data']); } } else { if ($pre_parsed['mode'] == 'file') { include($pre_parsed['fname']); } else { eval('?'.'>'.$pre_parsed['content']); } } $output = ob_get_contents(); ob_end_clean(); $this->TemplateName = $backup_template; $this->TempalteFullPath = $backup_fullpath; return $output; } function &GetProcessor($prefix) { static $Processors = array(); if (!isset($Processors[$prefix])) { $Processors[$prefix] = $this->Application->recallObject($prefix.'_TagProcessor'); } return $Processors[$prefix]; } function SelectParam($params, $possible_names) { if (!is_array($params)) return; if (!is_array($possible_names)) $possible_names = explode(',', $possible_names); foreach ($possible_names as $name) { if( isset($params[$name]) ) return $params[$name]; } return false; } function SetParams($params) { $this->Params = $params; $keys = array_keys($this->Params); } function GetParam($name) { return isset($this->Params[$name]) ? $this->Params[$name] : false; } function SetParam($name, $value) { $this->Params[$name] = $value; } function PushParams($params) { $this->ParamsStack[$this->ParamsLevel++] = $this->Params; $this->Params = $params; } function PopParams() { $this->Params = $this->ParamsStack[--$this->ParamsLevel]; } function ParseBlock($params, $pass_params=false) { if (isset($params['cache_timeout']) && ($ret = $this->CacheGet($this->FormCacheKey('element_'.$params['name'])))) { return $ret; } if (substr($params['name'], 0, 5) == 'html:') { return substr($params['name'], 6); } if (!array_key_exists($params['name'], $this->Elements) && array_key_exists('default_element', $params)) { // when given element not found, but default element name given, then render it instead $params['name'] = $params['default_element']; unset($params['default_element']); return $this->ParseBlock($params, $pass_params); } $original_params = $params; if ($pass_params || isset($params['pass_params'])) $params = array_merge($this->Params, $params); $this->PushParams($params); $data_exists_bak = $this->DataExists; // if we are parsing design block and we have block_no_data - we need to wrap block_no_data into design, // so we should set DataExists to true manually, otherwise the design block will be skipped because of data_exists in params (by Kostja) // // keep_data_exists is used by block RenderElement (always added in ntags.php), to keep the DataExists value // from inside-content block, otherwise when parsing the design block DataExists will be reset to false resulting missing design block (by Kostja) // // Inside-content block parsing result is given to design block in "content" parameter (ntags.php) and "keep_data_exists" // is only passed, when parsing design block. In case, when $this->DataExists is set to true, but // zero-length content (in 2 cases: method NParser::CheckNoData set it OR really empty block content) // is returned from inside-content block, then design block also should not be shown (by Alex) $this->DataExists = (isset($params['keep_data_exists']) && isset($params['content']) && $params['content'] != '' && $this->DataExists) || (isset($params['design']) && isset($params['block_no_data']) && $params['name'] == $params['design']); if (!array_key_exists($params['name'], $this->Elements)) { $pre_parsed = $this->Application->TemplatesCache->GetPreParsed($params['name']); if ($pre_parsed) { $ret = $this->IncludeTemplate($params); if (array_key_exists('no_editing', $params) && $params['no_editing']) { // when individual render element don't want to be edited return $ret; } return defined('EDITING_MODE') ? $this->DecorateBlock($ret, $params, true) : $ret; } if ($this->Application->isDebugMode()) { $this->Application->Debugger->appendTrace(); } $trace_results = debug_backtrace(); $this->Application->handleError(E_USER_ERROR, '<b>Rendering of undefined element '.$params['name'].'</b>', $trace_results[0]['file'], $trace_results[0]['line']); return false; } $m_processor =& $this->GetProcessor('m'); $flag_values = $m_processor->PreparePostProcess($params); $f_name = $this->Elements[$params['name']]; $ret = $f_name($this, $params); $ret = $m_processor->PostProcess($ret, $flag_values); $block_params = $this->Params; // input parameters, but modified inside rendered block $this->PopParams(); $this->CheckNoData($ret, $params); $this->DataExists = $data_exists_bak || $this->DataExists; if (isset($original_params['cache_timeout'])) { $this->CacheSet($this->FormCacheKey('element_'.$original_params['name']), $ret, $original_params['cache_timeout']); } if (array_key_exists('no_editing', $block_params) && $block_params['no_editing']) { // when individual render element don't want to be edited return $ret; } return defined('EDITING_MODE') ? $this->DecorateBlock($ret, $params) : $ret; } function DecorateBlock($block_content, $block_params, $is_template = false) { static $used_ids = Array (), $base_url = null; if (!isset($base_url)) { $base_url = $this->Application->BaseURL(); } // $prepend = '[name: ' . $block_params['name'] . '] [params: ' . implode(', ', array_keys($block_params)) . ']'; $decorate = false; + $design = false; - if ($is_template) { - // content inside pair RenderElement tag -// $prepend = '<strong>CONTENT_OF_DESIGN:</strong> ' . $prepend; + if (EDITING_MODE == EDITING_MODE_DESIGN) { + $decorate = true; - if (EDITING_MODE == EDITING_MODE_INSIDES) { - $decorate = true; - } - } - else { - if (strpos($block_params['name'], '__capture_') === 0) { - // capture tag (usually inside pair RenderElement) -// $prepend = '<strong>CAPTURE:</strong> ' . $prepend; - - if (EDITING_MODE == EDITING_MODE_INSIDES) { - $decorate = true; - } - } - elseif (array_key_exists('content', $block_params)) { - // pair RenderElement (on template, were it's used) -// $prepend = '<strong>PAIR_RENDER_ELEMENT:</strong> ' . $prepend; - - if (EDITING_MODE == EDITING_MODE_DESIGN) { - $decorate = true; - } + if ($is_template) { + // content inside pair RenderElement tag } else { - // non-pair RenderElement -// $prepend = '<strong>SINGLE_RENDER_ELEMENT:</strong> ' . $prepend; - - if (EDITING_MODE == EDITING_MODE_INSIDES) { - $decorate = true; + if (strpos($block_params['name'], '__capture_') === 0) { + // capture tag (usually inside pair RenderElement) } - - if (array_key_exists('layout_view', $block_params) && $block_params['layout_view'] && (EDITING_MODE == EDITING_MODE_LAYOUT)) { - $decorate = true; + elseif (array_key_exists('content', $block_params)) { + // pair RenderElement (on template, were it's used) + $design = true; } } } if (!$decorate) { return $block_content; } else { $block_content = /*$prepend .*/ $block_content; } $block_name = $block_params['name']; $function_name = $is_template ? $block_name : $this->Elements[$block_name]; + $block_title = ''; + if (array_key_exists($function_name, $this->Application->Parser->ElementLocations)) { + $element_location = $this->Application->Parser->ElementLocations[$function_name]; + + $block_title .= $element_location['template'] . '.tpl'; + $block_title .= ' (' . $element_location['start_pos'] . ' - ' . $element_location['end_pos'] . ')'; + } + // ensure unique id for every div (used from print lists) $container_num = 1; $container_id = 'parser_block[' . $function_name . ']'; while (in_array($container_id . '_' . $container_num, $used_ids)) { $container_num++; } $container_id .= '_' . $container_num; $used_ids[] = $container_id; // prepare parameter string $param_string = $block_name . ':' . $function_name; + if ($design) { + $btn_text = 'Edit design'; + $btn_class = 'cms-edit-design-btn'; + $btn_container_class = 'block-edit-design-btn-container'; + } + else { + $btn_text = 'Edit block'; + $btn_class = 'cms-edit-block-btn'; + $btn_container_class = 'block-edit-block-btn-container'; + } $block_editor = ' - <div id="' . $container_id . '" params="' . $param_string . '" class="block-edit-btn-container"> - <div class="cms-edit-btn"> + <div id="' . $container_id . '" params="' . $param_string . '" class="' . $btn_container_class . '" title="' . htmlspecialchars($block_title) . '"> + <div class="' . $btn_class . '"> <div class="cms-btn-image"> <img src="' . $base_url . 'core/admin_templates/img/top_frame/icons/content_mode.gif" width="15" height="16" alt=""/> </div> - <div class="cms-btn-text" id="' . $container_id . '_btn">Edit</div> + <div class="cms-btn-text" id="' . $container_id . '_btn">' . $btn_text . '</div> </div> <div class="cms-btn-content"> %s </div> </div>'; // 1 - text before, 2 - open tag, 3 - open tag attributes, 4 - content inside tag, 5 - closing tag, 6 - text after closing tag if (preg_match('/^(\s*)<(td|span)(.*?)>(.*)<\/(td|span)>(.*)$/is', $block_content, $regs)) { // div inside span -> put div outside span return $regs[1] . '<' . $regs[2] . ' ' . $regs[3] . '>' . str_replace('%s', $regs[4], $block_editor) . '</' . $regs[5] . '>' . $regs[6]; } return str_replace('%s', $block_content, $block_editor); } function IncludeTemplate($params, $silent=null) { $t = is_array($params) ? $this->SelectParam($params, 't,template,block,name') : $params; if (isset($params['cache_timeout']) && ($ret = $this->CacheGet('template:'.$t))) { return $ret; } $t = eregi_replace("\.tpl$", '', $t); $data_exists_bak = $this->DataExists; $this->DataExists = false; if (!isset($silent) && array_key_exists('is_silent', $params)) { $silent = $params['is_silent']; } if (isset($params['pass_params'])) { // ability to pass params from block to template $params = array_merge($this->Params, $params); } $this->PushParams($params); $ret = $this->Run($t, $silent); $this->PopParams(); $this->CheckNoData($ret, $params); $this->DataExists = $data_exists_bak || $this->DataExists; if (isset($params['cache_timeout'])) { $this->CacheSet('template:'.$t, $ret, $params['cache_timeout']); } return $ret; } function CheckNoData(&$ret, $params) { if (array_key_exists('data_exists', $params) && $params['data_exists'] && !$this->DataExists) { $block_no_data = isset($params['BlockNoData']) ? $params['BlockNoData'] : (isset($params['block_no_data']) ? $params['block_no_data'] : false); if ($block_no_data) { $ret = $this->ParseBlock(array('name'=>$block_no_data)); } else { $ret = ''; } } } function CacheGet($name) { if (!$this->Application->ConfigValue('SystemTagCache')) return false; return $this->Application->CacheGet($name); } function CacheSet($name, $value, $expiration=0) { if (!$this->Application->ConfigValue('SystemTagCache')) return false; return $this->Application->CacheSet($name, $value, $expiration); } function FormCacheKey($element, $file=null, $add_prefixes=null) { if (!isset($file)) { $file = str_replace(FULL_PATH, '', $this->TempalteFullPath).':'.$this->Application->GetVar('t'); } $parts = array( 'file_'.$file.'('.filemtime($this->TempalteFullPath).')' => 'serials:file_ts', // theme + template timestamp 'm_lang_'.$this->Application->GetVar('m_lang') => 'serials:lang_ts', 'm_cat_id_'.$this->Application->GetVar('m_cat_id') => 'serials:cat_'.$this->Application->GetVar('m_cat_id').'_ts', 'm_cat_page'.$this->Application->GetVar('m_cat_page') => false, ); if (isset($add_prefixes)) { foreach ($add_prefixes as $prefix) { $parts[$prefix.'_id_'.$this->Application->GetVar("{$prefix}_id")] = "serials:$prefix_".$this->Application->GetVar("{$prefix}_id").'_ts'; $parts[$prefix.'_page_'.$this->Application->GetVar("{$prefix}_Page")] = false; } } $key = ''; foreach ($parts as $part => $ts_name) { if ($ts_name) { $ts = $this->Application->CacheGet($ts_name); $key .= "$part($ts):"; } else { $key .= "$part:"; } } $key .= $element; return crc32($key); } function PushPointer($pointer) { $this->CachePointers[++$this->CacheLevel] = $this->FormCacheKey('pointer:'.$pointer); return $this->CachePointers[$this->CacheLevel]; } function PopPointer() { return $this->CachePointers[$this->CacheLevel--]; } function CacheStart($pointer=null) { if ($ret = $this->CacheGet($this->PushPointer($pointer)) ) { echo $ret; $this->PopPointer(); return true; } ob_start(); return false; } function CacheEnd($elem=null) { $ret = ob_get_clean(); $this->CacheSet($this->PopPointer(), $ret); // . ($this->CurrentKeyPart ? ':'.$this->CurrentKeyPart : '') echo $ret; } function _compress($src) { // Whitespaces left and right from this signs can be ignored static $IW = array( T_CONCAT_EQUAL, // .= T_DOUBLE_ARROW, // => T_BOOLEAN_AND, // && T_BOOLEAN_OR, // || T_IS_EQUAL, // == T_IS_NOT_EQUAL, // != or <> T_IS_SMALLER_OR_EQUAL, // <= T_IS_GREATER_OR_EQUAL, // >= T_INC, // ++ T_DEC, // -- T_PLUS_EQUAL, // += T_MINUS_EQUAL, // -= T_MUL_EQUAL, // *= T_DIV_EQUAL, // /= T_IS_IDENTICAL, // === T_IS_NOT_IDENTICAL, // !== T_DOUBLE_COLON, // :: T_PAAMAYIM_NEKUDOTAYIM, // :: T_OBJECT_OPERATOR, // -> T_DOLLAR_OPEN_CURLY_BRACES, // ${ T_AND_EQUAL, // &= T_MOD_EQUAL, // %= T_XOR_EQUAL, // ^= T_OR_EQUAL, // |= T_SL, // << T_SR, // >> T_SL_EQUAL, // <<= T_SR_EQUAL, // >>= ); $tokens = token_get_all($src); $new = ""; $c = sizeof($tokens); $iw = false; // ignore whitespace $ih = false; // in HEREDOC $ls = ""; // last sign $ot = null; // open tag for ($i = 0; $i < $c; $i++) { $token = $tokens[$i]; if (is_array($token)) { list ($tn, $ts) = $token; // tokens: number, string, line $tname = token_name($tn); if ($tn == T_INLINE_HTML) { $new .= $ts; $iw = false; } else { if ($tn == T_OPEN_TAG) { if (strpos($ts, " ") || strpos($ts, "\n") || strpos($ts, "\t") || strpos($ts, "\r")) { $ts = rtrim($ts); } $ts .= " "; $new .= $ts; $ot = T_OPEN_TAG; $iw = true; } elseif ($tn == T_OPEN_TAG_WITH_ECHO) { $new .= $ts; $ot = T_OPEN_TAG_WITH_ECHO; $iw = true; } elseif ($tn == T_CLOSE_TAG) { if ($ot == T_OPEN_TAG_WITH_ECHO) { $new = rtrim($new, "; "); } else { $ts = " ".$ts; } $new .= $ts; $ot = null; $iw = false; } elseif (in_array($tn, $IW)) { $new .= $ts; $iw = true; } elseif ($tn == T_CONSTANT_ENCAPSED_STRING || $tn == T_ENCAPSED_AND_WHITESPACE) { if ($ts[0] == '"') { $ts = addcslashes($ts, "\n\t\r"); } $new .= $ts; $iw = true; } elseif ($tn == T_WHITESPACE) { $nt = @$tokens[$i+1]; if (!$iw && (!is_string($nt) || $nt == '$') && !in_array($nt[0], $IW)) { $new .= " "; } $iw = false; } elseif ($tn == T_START_HEREDOC) { $new .= "<<<S\n"; $iw = false; $ih = true; // in HEREDOC } elseif ($tn == T_END_HEREDOC) { $new .= "S;"; $iw = true; $ih = false; // in HEREDOC for ($j = $i + 1; $j < $c; $j++) { if (is_string($tokens[$j]) && $tokens[$j] == ";") { $i = $j; break; } else if ($tokens[$j][0] == T_CLOSE_TAG) { break; } } } elseif ($tn == T_COMMENT || $tn == T_DOC_COMMENT) { $iw = true; } else { /*if (!$ih) { // this also lowecases attribute names :( $ts = strtolower($ts); }*/ $new .= $ts; $iw = false; } } $ls = ""; } else { if (($token != ";" && $token != ":") || $ls != $token) { $new .= $token; $ls = $token; } $iw = true; } } return $new; } } \ No newline at end of file Index: branches/5.0.x/core/units/theme_files/theme_file_eh.php =================================================================== --- branches/5.0.x/core/units/theme_files/theme_file_eh.php (revision 12297) +++ branches/5.0.x/core/units/theme_files/theme_file_eh.php (revision 12298) @@ -1,220 +1,220 @@ <?php /** * @version $Id$ * @package In-Portal * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. * @license GNU/GPL * In-Portal is Open Source software. * This means that this software may have been modified pursuant * the GNU General Public License, and as distributed it includes * or is derivative of works licensed under the GNU General Public License * or other free or open source software licenses. * See http://www.in-portal.net/license/ for copyright notices and details. */ class ThemeFileEventHandler extends kDBEventHandler { /** * Allows to override standart permission mapping * */ function mapPermissions() { parent::mapPermissions(); $permissions = Array ( 'OnLoadBlock' => Array ('subitem' => true), 'OnSaveBlock' => Array ('subitem' => true), 'OnSaveLayout' => Array ('subitem' => true), ); $this->permMapping = array_merge($this->permMapping, $permissions); } /** * Changes permission section to one from REQUEST, not from config * * @param kEvent $event */ function CheckPermission(&$event) { if ($event->Name == 'OnLoadBlock' || $event->Name == 'OnSaveBlock') { return $this->Application->LoggedIn() && $this->Application->IsAdmin(); } return parent::CheckPermission($event); } /** * Loads template contents into virtual field * * @param kEvent $event */ function OnAfterItemLoad(&$event) { parent::OnAfterItemLoad($event); $object =& $event->getObject(); /* @var $object kDBItem */ $filename = $this->_getTemplatePath($object); if (file_exists($filename)) { $object->SetDBField('FileContents', file_get_contents($filename)); } else { $object->SetError('FileContents', 'template_file_missing', 'la_error_TemplateFileMissing'); } } /** * Trim contents of edited template * * @param kEvent $event */ function OnBeforeItemUpdate(&$event) { parent::OnBeforeItemUpdate($event); $object =& $event->getObject(); /* @var $object kDBItem */ $file_data = $object->GetDBField('FileContents'); $file_data = str_replace("\r\n", "\n", $file_data); $file_data = str_replace("\r", "\n", $file_data); $object->SetDBField('FileContents', trim($file_data)); } /** * Saves updated content to template * * @param kEvent $event */ function OnAfterItemUpdate(&$event) { parent::OnAfterItemUpdate($event); $object =& $event->getObject(); /* @var $object kDBItem */ $filename = $this->_getTemplatePath($object); if (file_exists($filename) && is_writable($filename)) { $fp = fopen($filename, 'w'); fwrite($fp, $object->GetDBField('FileContents')); fclose($fp); $themes_helper =& $this->Application->recallObject('ThemesHelper'); /* @var $themes_helper kThemesHelper */ $meta_info = $themes_helper->parseTemplateMetaInfo($filename); $file_description = array_key_exists('desc', $meta_info) ? $meta_info['desc'] : ''; $object->SetDBField('Description', $file_description); $object->SetDBField('FileMetaInfo', serialize($meta_info)); $object->Update(); } } /** * Returns full path to template file * * @param kDBItem $object * @return string */ function _getTemplatePath(&$object) { $theme =& $this->Application->recallObject('theme'); /* @var $theme kDBItem */ $path = FULL_PATH . '/themes/' . $theme->GetDBField('Name'); $path .= $object->GetDBField('FilePath') . '/' . $object->GetDBField('FileName'); return $path; } /** * Loads block data based on it's name in request * * @param kEvent $event */ function OnLoadBlock(&$event) { parent::OnNew($event); $object =& $event->getObject(); /* @var $object kDBItem */ $template_helper =& $this->Application->recallObject('TemplateHelper'); /* @var $template_helper TemplateHelper */ $template_helper->InitHelper($object); $object->SetDBField('FileName', $template_helper->blockInfo('template_file')); $object->SetDBField('BlockPosition', $template_helper->blockInfo('start_pos') . ' - ' . $template_helper->blockInfo('end_pos')); $object->SetDBField('FileContents', $template_helper->blockInfo('content')); } /** * Saves changed template block * * @param kEvent $event */ function OnSaveBlock(&$event) { $object =& $event->getObject( Array('skip_autoload' => true) ); /* @var $object kDBItem */ $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); if ($items_info) { list ($id, $field_values) = each($items_info); $object->SetFieldsFromHash($field_values); $object->setID($id); } $status = $object->Validate(); $template_helper =& $this->Application->recallObject('TemplateHelper'); /* @var $template_helper TemplateHelper */ $template_helper->InitHelper($object); $status = $status && $template_helper->saveBlock($object); if ($status) { $event->SetRedirectParam('opener', 'u'); } else { $event->status = erFAIL; } } /** * Saves layout on given template * * @param kEvent $event */ function OnSaveLayout(&$event) { $event->status = erSTOP; - if (($this->Application->GetVar('ajax') != 'yes') || (EDITING_MODE != EDITING_MODE_LAYOUT)) { + if (($this->Application->GetVar('ajax') != 'yes') || (EDITING_MODE != EDITING_MODE_DESIGN)) { return ; } $target_order = $this->Application->GetVar('target_order'); $template_helper =& $this->Application->recallObject('TemplateHelper'); /* @var $template_helper TemplateHelper */ if ($template_helper->moveTemplateElements($target_order)) { echo 'OK'; return ; } echo 'FAILED'; } } \ No newline at end of file Index: branches/5.0.x/core/units/categories/categories_tag_processor.php =================================================================== --- branches/5.0.x/core/units/categories/categories_tag_processor.php (revision 12297) +++ branches/5.0.x/core/units/categories/categories_tag_processor.php (revision 12298) @@ -1,2080 +1,2135 @@ <?php /** * @version $Id$ * @package In-Portal * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. * @license GNU/GPL * In-Portal is Open Source software. * This means that this software may have been modified pursuant * the GNU General Public License, and as distributed it includes * or is derivative of works licensed under the GNU General Public License * or other free or open source software licenses. * See http://www.in-portal.net/license/ for copyright notices and details. */ class CategoriesTagProcessor extends kDBTagProcessor { /** * Cached version of site menu * * @var Array */ var $Menu = null; /** * Parent path mapping used in CachedMenu tag * * @var Array */ var $ParentPaths = Array (); function SubCatCount($params) { $object =& $this->getObject($params); if (isset($params['today']) && $params['today']) { $sql = 'SELECT COUNT(*) FROM '.$object->TableName.' WHERE (ParentPath LIKE "'.$object->GetDBField('ParentPath').'%") AND (CreatedOn > '.(adodb_mktime() - 86400).')'; return $this->Conn->GetOne($sql) - 1; } return $object->GetDBField('CachedDescendantCatsQty'); } /** * Returns category count in system * * @param Array $params * @return int */ function CategoryCount($params) { $count_helper =& $this->Application->recallObject('CountHelper'); /* @var $count_helper kCountHelper */ $today_only = isset($params['today']) && $params['today']; return $count_helper->CategoryCount($today_only); } function IsNew($params) { $object =& $this->getObject($params); return $object->GetDBField('IsNew') ? 1 : 0; } function IsPick($params) { return $this->IsEditorsPick($params); } /** * Returns item's editors pick status (using not formatted value) * * @param Array $params * @return bool */ function IsEditorsPick($params) { $object =& $this->getObject($params); return $object->GetDBField('EditorsPick') == 1; } function ItemIcon($params) { // only for categories, not structure if ($this->Prefix != 'c') { return parent::ItemIcon($params); } $object =& $this->getObject($params); if ($object->GetDBField('IsMenu')) { $status = $object->GetDBField('Status'); if ($status == 1) { $ret = $object->GetDBField('IsNew') ? 'icon16_cat_new.gif' : 'icon16_folder.gif'; } else { $ret = $status ? 'icon16_cat_pending.gif' : 'icon16_cat_disabled.gif'; } } else { $ret = 'icon16_folder-red.gif'; } return $ret; } function ItemCount($params) { $object =& $this->getObject($params); $ci_table = $this->Application->getUnitOption('l-ci', 'TableName'); $sql = 'SELECT COUNT(*) FROM ' . $object->TableName . ' c LEFT JOIN ' . $ci_table . ' ci ON c.CategoryId = ci.CategoryId WHERE (c.TreeLeft BETWEEN ' . $object->GetDBField('TreeLeft') . ' AND ' . $object->GetDBField('TreeRight') . ') AND NOT (ci.CategoryId IS NULL)'; return $this->Conn->GetOne($sql); } function ListCategories($params) { return $this->PrintList2($params); } function RootCategoryName($params) { return $this->Application->ProcessParsedTag('m', 'RootCategoryName', $params); } function CheckModuleRoot($params) { $module_name = getArrayValue($params, 'module') ? $params['module'] : 'In-Commerce'; $module_root_cat = $this->Application->findModule('Name', $module_name, 'RootCat'); $additional_cats = $this->SelectParam($params, 'add_cats'); if ($additional_cats) { $additional_cats = explode(',', $additional_cats); } else { $additional_cats = array(); } if ($this->Application->GetVar('m_cat_id') == $module_root_cat || in_array($this->Application->GetVar('m_cat_id'), $additional_cats)) { $home_template = getArrayValue($params, 'home_template'); if (!$home_template) return; $this->Application->Redirect($home_template, Array('pass'=>'all')); }; } function CategoryPath($params) { $category_helper =& $this->Application->recallObject('CategoryHelper'); /* @var $category_helper CategoryHelper */ return $category_helper->NavigationBar($params); } /** * Shows category path to specified category * * @param Array $params * @return string */ function FieldCategoryPath($params) { $object =& $this->getObject(); /* @var $object kDBItem */ $field = $this->SelectParam($params, 'name,field'); $category_id = $object->GetDBField($field); if ($category_id) { $params['cat_id'] = $category_id; return $this->CategoryPath($params); } return ''; } function CurrentCategoryName($params) { $cat_object =& $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix.'_List'); $sql = 'SELECT '.$this->getTitleField().' FROM '.$cat_object->TableName.' WHERE CategoryId = '.$this->Application->GetVar('m_cat_id'); return $this->Conn->GetOne($sql); } /** * Returns current category name * * @param Array $params * @return string * @todo Find where it's used */ function CurrentCategory($params) { return $this->CurrentCategoryName($params); } function getTitleField() { $ml_formatter =& $this->Application->recallObject('kMultiLanguage'); return $ml_formatter->LangFieldName('Name'); } function getCategorySymLink($category_id) { static $cache = null; if (!isset($cache)) { $id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName'); $sql = 'SELECT SymLinkCategoryId, '.$id_field.' FROM '.$table_name.' WHERE SymLinkCategoryId IS NOT NULL'; $cache = $this->Conn->GetCol($sql, $id_field); } if (isset($cache[$category_id])) { //check if sym. link category is valid $id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName'); $sql = 'SELECT '.$id_field.' FROM '.$table_name.' WHERE '.$id_field.' = '.$cache[$category_id]; $category_id = $this->Conn->GetOne($sql)? $cache[$category_id] : $category_id; } return $category_id; } function CategoryLink($params) { $category_id = getArrayValue($params, 'cat_id'); if ($category_id === false) { $category_id = $this->Application->GetVar($this->getPrefixSpecial().'_id'); } if ("$category_id" == 'Root') { $category_id = $this->Application->findModule('Name', $params['module'], 'RootCat'); } elseif ("$category_id" == 'current') { $category_id = $this->Application->GetVar('m_cat_id'); } $category_id = $this->getCategorySymLink($category_id); unset($params['cat_id'], $params['module']); $new_params = Array ('pass' => 'm', 'm_cat_id' => $category_id, 'pass_category' => 1); $params = array_merge_recursive2($params, $new_params); return $this->Application->ProcessParsedTag('m', 't', $params); } function CategoryList($params) { //$object =& $this->Application->recallObject( $this->getPrefixSpecial() , $this->Prefix.'_List', $params ); $object =& $this->GetList($params); if ($object->RecordsCount == 0) { if (isset($params['block_no_cats'])) { $params['name'] = $params['block_no_cats']; return $this->Application->ParseBlock($params); } else { return ''; } } if (isset($params['block'])) { return $this->PrintList($params); } else { $params['block'] = $params['block_main']; if (isset($params['block_row_start'])) { $params['row_start_block'] = $params['block_row_start']; } if (isset($params['block_row_end'])) { $params['row_end_block'] = $params['block_row_end']; } return $this->PrintList2($params); } } function Meta($params) { $object =& $this->Application->recallObject($this->Prefix); // .'.-item' /* @var $object CategoriesItem */ $meta_type = $params['name']; if ($object->isLoaded()) { // 1. get module prefix by current category $category_helper =& $this->Application->recallObject('CategoryHelper'); /* @var $category_helper CategoryHelper */ $category_path = explode('|', substr($object->GetDBField('ParentPath'), 1, -1)); $module_info = $category_helper->getCategoryModule($params, $category_path); // In-Edit & Proj-CMS module prefixes doesn't have custom field with item template if ($module_info && $module_info['Var'] != 'adm' && $module_info['Var'] != 'st') { // 2. get item template by current category & module prefix $mod_rewrite_helper = $this->Application->recallObject('ModRewriteHelper'); /* @var $mod_rewrite_helper kModRewriteHelper */ $category_params = Array ( 'CategoryId' => $object->GetID(), 'ParentPath' => $object->GetDBField('ParentPath'), ); $item_template = $mod_rewrite_helper->GetItemTemplate($category_params, $module_info['Var']); if ($this->Application->GetVar('t') == $item_template) { // we are located on item's details page $item =& $this->Application->recallObject($module_info['Var']); /* @var $item kCatDBItem */ // 3. get item's meta data $value = $item->GetField('Meta'.$meta_type); if ($value) { return $value; } } // 4. get category meta data $value = $object->GetField('Meta'.$meta_type); if ($value) { return $value; } } } // 5. get default meta data switch ($meta_type) { case 'Description': $config_name = 'Category_MetaDesc'; break; case 'Keywords': $config_name = 'Category_MetaKey'; break; } return $this->Application->ConfigValue($config_name); } function BuildListSpecial($params) { if ( isset($params['parent_cat_id']) ) { $parent_cat_id = $params['parent_cat_id']; } else { $parent_cat_id = $this->Application->GetVar($this->Prefix.'_id'); if (!$parent_cat_id) { $parent_cat_id = $this->Application->GetVar('m_cat_id'); } if (!$parent_cat_id) { $parent_cat_id = 0; } } $no_special = isset($params['no_special']) && $params['no_special']; if ($no_special) return $this->Special; $list_unique_key = $this->getUniqueListKey($params); // check for "admin" variable, because we are parsing front-end template from admin when using template editor feature if ($this->Application->GetVar('admin') || !$this->Application->IsAdmin()) { // add parent category to special, when on Front-End, // because there can be many category lists on same page $list_unique_key .= $parent_cat_id; } if ($list_unique_key == '') { return parent::BuildListSpecial($params); } return crc32($list_unique_key); } function IsCurrent($params) { $object =& $this->getObject($params); if ($object->GetID() == $this->Application->GetVar('m_cat_id')) { return true; } else { return false; } } /** * Substitutes category in last template base on current category * This is required becasue when you navigate catalog using AJAX, last_template is not updated * but when you open item edit from catalog last_template is used to build opener_stack * So, if we don't substitute m_cat_id in last_template, after saving item we'll get redirected * to the first category we've opened, not the one we navigated to using AJAX * * @param Array $params */ function UpdateLastTemplate($params) { $category_id = $this->Application->GetVar('m_cat_id'); $wid = $this->Application->GetVar('m_wid'); list($index_file, $env) = explode('|', $this->Application->RecallVar(rtrim('last_template_'.$wid, '_')), 2); $vars_backup = Array (); $vars = $this->Application->HttpQuery->processQueryString( str_replace('%5C', '\\', $env) ); foreach ($vars as $var_name => $var_value) { $vars_backup[$var_name] = $this->Application->GetVar($var_name); $this->Application->SetVar($var_name, $var_value); } // update required fields $this->Application->SetVar('m_cat_id', $category_id); $this->Application->Session->SaveLastTemplate($params['template']); foreach ($vars_backup as $var_name => $var_value) { $this->Application->SetVar($var_name, $var_value); } } function GetParentCategory($params) { $parent_id = 0; $id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); $table = $this->Application->getUnitOption($this->Prefix,'TableName'); $cat_id = $this->Application->GetVar('m_cat_id'); if ($cat_id > 0) { $sql = 'SELECT ParentId FROM '.$table.' WHERE '.$id_field.' = '.$cat_id; $parent_id = $this->Conn->GetOne($sql); } return $parent_id; } function InitCacheUpdater($params) { safeDefine('CACHE_PERM_CHUNK_SIZE', 30); $continue = $this->Application->GetVar('continue'); $total_cats = (int) $this->Conn->GetOne('SELECT COUNT(*) FROM '.TABLE_PREFIX.'Category'); if ($continue === false && $total_cats > CACHE_PERM_CHUNK_SIZE) { // first step, if category count > CACHE_PERM_CHUNK_SIZE, then ask for cache update return true; } if ($continue === false) { // if we don't have to ask, then assume user selected "Yes" in permcache update dialog $continue = 1; } $updater =& $this->Application->recallObject('kPermCacheUpdater', null, Array('continue' => $continue)); /* @var $updater kPermCacheUpdater */ if ($continue === '0') { // No in dialog $updater->clearData(); $this->Application->Redirect($params['destination_template']); } $ret = false; // don't ask for update if ($continue == 1) { // Initial run $updater->setData(); } if ($continue == 2) { // Continuing // called from AJAX request => returns percent $needs_more = true; while ($needs_more && $updater->iteration <= CACHE_PERM_CHUNK_SIZE) { // until proceeeded in this step category count exceeds category per step limit $needs_more = $updater->DoTheJob(); } if ($needs_more) { // still some categories are left for next step $updater->setData(); } else { // all done -> redirect $updater->SaveData(); $this->Application->RemoveVar('PermCache_UpdateRequired'); $this->Application->Redirect($params['destination_template']); } $ret = $updater->getDonePercent(); } return $ret; } /** * Parses warning block, but with style="display: none;". Used during permissions saving from AJAX * * @param Array $params * @return string */ function SaveWarning($params) { if ($this->Prefix == 'st') { // don't use this method for other prefixes then Category, that use this tag processor return parent::SaveWarning($params); } $main_prefix = getArrayValue($params, 'main_prefix'); if ($main_prefix && $main_prefix != '$main_prefix') { $top_prefix = $main_prefix; } else { $top_prefix = $this->Application->GetTopmostPrefix($this->Prefix); } $temp_tables = substr($this->Application->GetVar($top_prefix.'_mode'), 0, 1) == 't'; $modified = $this->Application->RecallVar($top_prefix.'_modified'); if (!$temp_tables) { $this->Application->RemoveVar($top_prefix.'_modified'); return ''; } $block_name = $this->SelectParam($params, 'render_as,name'); if ($block_name) { $block_params = $this->prepareTagParams($params); $block_params['name'] = $block_name; $block_params['edit_mode'] = $temp_tables ? 1 : 0; $block_params['display'] = $temp_tables && $modified ? 1 : 0; return $this->Application->ParseBlock($block_params); } else { return $temp_tables && $modified ? 1 : 0; } return ; } /** * Allows to detect if this prefix has something in clipboard * * @param Array $params * @return bool */ function HasClipboard($params) { $clipboard = $this->Application->RecallVar('clipboard'); if ($clipboard) { $clipboard = unserialize($clipboard); foreach ($clipboard as $prefix => $clipboard_data) { foreach ($clipboard_data as $mode => $ids) { if (count($ids)) return 1; } } } return 0; } /** * Allows to detect if root category being edited * * @param Array $params */ function IsRootCategory($params) { $object =& $this->getObject($params); return $object->IsRoot(); } /** * Returns home category id * * @param Array $params * @return int */ function HomeCategory($params) { static $root_category = null; if (!isset($root_category)) { $root_category = $this->Application->findModule('Name', 'Core', 'RootCat'); } return $root_category; } /** * Used for disabling "Home" and "Up" buttons in category list * * @param Array $params * @return bool */ function ModuleRootCategory($params) { return $this->Application->GetVar('m_cat_id') == $this->HomeCategory($params); } function CatalogItemCount($params) { $params['skip_quering'] = true; $object =& $this->GetList($params); if (!$object->Counted) { $object->CountRecs(); } return $object->NoFilterCount != $object->RecordsCount ? $object->RecordsCount.' / '.$object->NoFilterCount : $object->RecordsCount; } /** * Print grid pagination using * block names specified * * @param Array $params * @return string * @access public */ function PrintPages($params) { if ($this->Application->Parser->GetParam('no_special')) { $params['no_special'] = $this->Application->Parser->GetParam('no_special'); } return parent::PrintPages($params); } function InitCatalog($params) { $tab_prefixes = $this->Application->GetVar('tp'); // {all, <prefixes_list>, none} if ($tab_prefixes === false) $tab_prefixes = 'all'; $skip_prefixes = isset($params['skip_prefixes']) && $params['skip_prefixes'] ? explode(',', $params['skip_prefixes']) : Array(); $replace_main = isset($params['replace_m']) && $params['replace_m']; // get all prefixes available $prefixes = Array(); foreach ($this->Application->ModuleInfo as $module_name => $module_data) { $prefix = $module_data['Var']; if ($prefix == 'adm'/* || $prefix == 'm'*/) continue; if ($prefix == 'm' && $replace_main) { $prefix = 'c'; } $prefixes[] = $prefix; } if ($tab_prefixes == 'none') { $skip_prefixes = array_unique(array_merge($skip_prefixes, $prefixes)); unset($skip_prefixes[ array_search($replace_main ? 'c' : 'm', $skip_prefixes) ]); } elseif ($tab_prefixes != 'all') { // prefix list here $tab_prefixes = explode(',', $tab_prefixes); // list of prefixes that should stay $skip_prefixes = array_unique(array_merge($skip_prefixes, array_diff($prefixes, $tab_prefixes))); } $params['name'] = $params['render_as']; $params['skip_prefixes'] = implode(',', $skip_prefixes); return $this->Application->ParseBlock($params, 1); } /** * Determines, that printed category/menu item is currently active (will also match parent category) * * @param Array $params * @return bool */ function IsActive($params) { static $current_path = null; if (!isset($current_path)) { $sql = 'SELECT ParentPath FROM ' . TABLE_PREFIX . 'Category WHERE CategoryId = ' . $this->Application->GetVar('m_cat_id'); $current_path = $this->Conn->GetOne($sql); } if (array_key_exists('parent_path', $params)) { $test_path = $params['parent_path']; } else { $template = $params['template']; if ($template) { // when using from "c:CachedMenu" tag $sql = 'SELECT ParentPath FROM ' . TABLE_PREFIX . 'Category WHERE NamedParentPath = ' . $this->Conn->qstr('Content/' . $template); $test_path = $this->Conn->GetOne($sql); } else { // when using from "c:PrintList" tag $cat_id = array_key_exists('cat_id', $params) && $params['cat_id'] ? $params['cat_id'] : false; if ($cat_id === false) { // category not supplied -> get current from PrintList $category =& $this->getObject($params); } else { if ("$cat_id" == 'Root') { $cat_id = $this->Application->findModule('Name', $params['module'], 'RootCat'); } $category =& $this->Application->recallObject($this->Prefix . '.-c' . $cat_id, $this->Prefix, Array ('skip_autoload' => true)); $category->Load($cat_id); } $test_path = $category->GetDBField('ParentPath'); } } return strpos($current_path, $test_path) !== false; } /** * Checks if user have one of required permissions * * @param Array $params * @return bool */ function HasPermission($params) { $perm_helper =& $this->Application->recallObject('PermissionsHelper'); /* @var $perm_helper kPermissionsHelper */ $params['raise_warnings'] = 0; $object =& $this->getObject($params); /* @var $object kDBItem */ $params['cat_id'] = $object->isLoaded() ? $object->GetDBField('ParentPath') : $this->Application->GetVar('m_cat_id'); return $perm_helper->TagPermissionCheck($params); } /** * Prepares name for field with event in it (used only on front-end) * * @param Array $params * @return string */ function SubmitName($params) { return 'events['.$this->Prefix.']['.$params['event'].']'; } /** * Returns last modification date of items in category / system * * @param Array $params * @return string */ function LastUpdated($params) { $category_id = $this->Application->GetVar('m_cat_id'); $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName'); if (isset($params['local']) && $params['local'] && $category_id > 0) { // scan only current category & it's children $sql = 'SELECT TreeLeft, TreeRight FROM '.TABLE_PREFIX.'Category WHERE CategoryId = '.$category_id; $tree_info = $this->Conn->GetRow($sql); $sql = 'SELECT MAX(c.Modified) AS ModDate, MAX(c.CreatedOn) AS NewDate FROM '.TABLE_PREFIX.'Category c WHERE c.TreeLeft BETWEEN '.$tree_info['TreeLeft'].' AND '.$tree_info['TreeRight']; } else { // scan all categories in system $sql = 'SELECT MAX(Modified) AS ModDate, MAX(CreatedOn) AS NewDate FROM '.$table_name; } $row_data = $this->Conn->GetRow($sql); if (!$row_data) { return ''; } $date = $row_data[ $row_data['NewDate'] > $row_data['ModDate'] ? 'NewDate' : 'ModDate' ]; // format date $format = isset($params['format']) ? $params['format'] : '_regional_DateTimeFormat'; if (preg_match("/_regional_(.*)/", $format, $regs)) { $lang =& $this->Application->recallObject('lang.current'); if ($regs[1] == 'DateTimeFormat') { // combined format $format = $lang->GetDBField('DateFormat').' '.$lang->GetDBField('TimeFormat'); } else { // simple format $format = $lang->GetDBField($regs[1]); } } return adodb_date($format, $date); } function CategoryItemCount($params) { $object =& $this->getObject($params); /* @var $object kDBList */ $params['cat_id'] = $object->GetID(); $count_helper =& $this->Application->recallObject('CountHelper'); /* @var $count_helper kCountHelper */ return $count_helper->CategoryItemCount($params['prefix'], $params); } /** * Returns prefix + any word (used for shared between categories per page settings) * * @param Array $params * @return string */ function VarName($params) { return $this->Prefix.'_'.$params['type']; } /** * Checks if current category is valid symbolic link to another category * * @param Array $params * @return string */ function IsCategorySymLink($params) { $object =& $this->getObject($params); /* @var $object kDBList */ $sym_category_id = $object->GetDBField('SymLinkCategoryId'); if (is_null($sym_category_id)) { return false; } $id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName'); $sql = 'SELECT '.$id_field.' FROM '.$table_name.' WHERE '.$id_field.' = '.$sym_category_id; return $this->Conn->GetOne($sql)? true : false; } /** * Returns module prefix based on root category for given * * @param Array $params * @return string */ function GetModulePrefix($params) { $object =& $this->getObject($params); /* @var $object kDBItem */ $parent_path = explode('|', substr($object->GetDBField('ParentPath'), 1, -1)); $category_helper =& $this->Application->recallObject('CategoryHelper'); /* @var $category_helper CategoryHelper */ $module_info = $category_helper->getCategoryModule($params, $parent_path); return $module_info['Var']; } function ImageSrc($params) { list ($ret, $tag_processed) = $this->processAggregatedTag('ImageSrc', $params, $this->getPrefixSpecial()); return $tag_processed ? $ret : false; } function PageLink($params) { $t = isset($params['template']) ? $params['template'] : ''; unset($params['template']); if (!$t) $t = $this->Application->GetVar('t'); if (isset($params['page'])) { $this->Application->SetVar($this->getPrefixSpecial().'_Page', $params['page']); unset($params['page']); } $params['m_cat_page'] = $this->Application->GetVar($this->getPrefixSpecial().'_Page'); if (!isset($params['pass'])) { $params['pass'] = 'm,'.$this->getPrefixSpecial(); } return $this->Application->HREF($t, '', $params); } /** * Returns spelling suggestions against search keyword * * @param Array $params * @return string */ function SpellingSuggestions($params) { $keywords = unhtmlentities( trim($this->Application->GetVar('keywords')) ); if (!$keywords) { return ; } // 1. try to get already cached suggestion $suggestion = $this->Application->getCache('search.suggestion', $keywords); if ($suggestion !== false) { return $suggestion; } $table_name = $this->Application->getUnitOption('spelling-dictionary', 'TableName'); // 2. search suggestion in database $sql = 'SELECT SuggestedCorrection FROM ' . $table_name . ' WHERE MisspelledWord = ' . $this->Conn->qstr($keywords); $suggestion = $this->Conn->GetOne($sql); if ($suggestion !== false) { $this->Application->setCache('search.suggestion', $keywords, $suggestion); return $suggestion; } // 3. suggestion not found in database, ask webservice $app_id = $this->Application->ConfigValue('YahooApplicationId'); $url = 'http://search.yahooapis.com/WebSearchService/V1/spellingSuggestion?appid=' . $app_id . '&query='; $curl_helper =& $this->Application->recallObject('CurlHelper'); /* @var $curl_helper kCurlHelper */ $xml_data = $curl_helper->Send($url . urlencode($keywords)); $xml_helper =& $this->Application->recallObject('kXMLHelper'); /* @var $xml_helper kXMLHelper */ $root_node =& $xml_helper->Parse($xml_data); $result = $root_node->FindChild('RESULT'); /* @var $result kXMLNode */ if (is_object($result)) { // webservice responded -> save in local database $fields_hash = Array ( 'MisspelledWord' => $keywords, 'SuggestedCorrection' => $result->Data, ); $this->Conn->doInsert($fields_hash, $table_name); $this->Application->setCache('search.suggestion', $keywords, $result->Data); return $result->Data; } return ''; } /** * Shows link for searching by suggested word * * @param Array $params * @return string */ function SuggestionLink($params) { $params['keywords'] = $this->SpellingSuggestions($params); return $this->Application->ProcessParsedTag('m', 'Link', $params); } function InitCatalogTab($params) { $tab_params['mode'] = $this->Application->GetVar('tm'); // single/multi selection possible $tab_params['special'] = $this->Application->GetVar('ts'); // use special for this tab $tab_params['dependant'] = $this->Application->GetVar('td'); // is grid dependant on categories grid // set default params (same as in catalog) if ($tab_params['mode'] === false) $tab_params['mode'] = 'multi'; if ($tab_params['special'] === false) $tab_params['special'] = ''; if ($tab_params['dependant'] === false) $tab_params['dependant'] = 'yes'; // pass params to block with tab content $params['name'] = $params['render_as']; $special = $tab_params['special'] ? $tab_params['special'] : $this->Special; $params['prefix'] = trim($this->Prefix.'.'.$special, '.'); $prefix_append = $this->Application->GetVar('prefix_append'); if ($prefix_append) { $params['prefix'] .= $prefix_append; } $default_grid = array_key_exists('default_grid', $params) ? $params['default_grid'] : 'Default'; $radio_grid = array_key_exists('radio_grid', $params) ? $params['radio_grid'] : 'Radio'; $params['cat_prefix'] = trim('c.'.($tab_params['special'] ? $tab_params['special'] : $this->Special), '.'); $params['tab_mode'] = $tab_params['mode']; $params['grid_name'] = ($tab_params['mode'] == 'multi') ? $default_grid : $radio_grid; $params['tab_dependant'] = $tab_params['dependant']; $params['show_category'] = $tab_params['special'] == 'showall' ? 1 : 0; // this is advanced view -> show category name if ($special == 'showall' || $special == 'user') { $params['grid_name'] .= 'ShowAll'; } return $this->Application->ParseBlock($params, 1); } /** * Show CachedNavbar of current item primary category * * @param Array $params * @return string */ function CategoryName($params) { // show category cachednavbar of $object =& $this->getObject($params); $category_id = isset($params['cat_id']) ? $params['cat_id'] : $object->GetDBField('CategoryId'); $category_path = $this->Application->getCache('category_paths', $category_id); if ($category_path === false) { // not chached if ($category_id > 0) { $cached_navbar = $object->GetField('CachedNavbar'); if ($category_id == $object->GetDBField('ParentId')) { // parent category cached navbar is one element smaller, then current ones $cached_navbar = explode('&|&', $cached_navbar); array_pop($cached_navbar); $cached_navbar = implode('&|&', $cached_navbar); } else { // no relation with current category object -> query from db $sql = 'SELECT l' . $this->Application->GetVar('m_lang') . '_CachedNavbar FROM ' . $object->TableName . ' WHERE ' . $object->IDField . ' = ' . $category_id; $cached_navbar = $this->Conn->GetOne($sql); } $cached_navbar = preg_replace('/^(Content&\|&|Content)/i', '', $cached_navbar); $category_path = trim($this->CategoryName( Array('cat_id' => 0) ).' > '.str_replace('&|&', ' > ', $cached_navbar), ' > '); } else { $category_path = $this->Application->Phrase( $this->Application->ConfigValue('Root_Name') ); } $this->Application->setCache('category_paths', $category_id, $category_path); } return $category_path; } // structure related /** * Returns page object based on requested params * * @param Array $params * @return PagesItem */ function &_getPage($params) { $page =& $this->Application->recallObject($this->Prefix . '.-virtual', null, $params); /* @var $page kDBItem */ // 1. load by given id $page_id = array_key_exists('page_id', $params) ? $params['page_id'] : false; if ($page_id) { if ($page_id != $page->GetID()) { // load if different $page->Load($page_id); } return $page; } // 2. load by template $template = array_key_exists('page', $params) ? $params['page'] : ''; if (!$template) { $template = $this->Application->GetVar('t'); } // different path in structure AND design template differes from requested template $structure_path_match = strtolower( $page->GetDBField('NamedParentPath') ) == strtolower('Content/' . $template); $design_match = $page->GetDBField('CachedTemplate') == $template; if (!$structure_path_match && !$design_match) { // Same sql like in "c:getPassedID". Load, when current page object doesn't match requested page object $themes_helper =& $this->Application->recallObject('ThemesHelper'); /* @var $themes_helper kThemesHelper */ $page_id = $themes_helper->getPageByTemplate($template); $page->Load($page_id); } return $page; } /** * Returns requested content block content of current or specified page * * @param Array $params * @return string */ function ContentBlock($params) { $num = getArrayValue($params, 'num'); if (!$num) { return 'NO CONTENT NUM SPECIFIED'; } $page =& $this->_getPage($params); /* @var $page kDBItem */ if (!$page->isLoaded()) { // page is not created yet => all blocks are empty return ''; } $page_id = $page->GetID(); $content =& $this->Application->recallObject('content.-block', null, Array ('skip_autoload' => true)); /* @var $content kDBItem */ $data = Array ('PageId' => $page_id, 'ContentNum' => $num); $content->Load($data); if (!$content->isLoaded()) { // bug: missing content blocks are created even if user have no SMS-management rights $content->SetFieldsFromHash($data); $content->Create(); } $edit_code_before = $edit_code_after = ''; - if (EDITING_MODE == EDITING_MODE_CMS) { + if (EDITING_MODE == EDITING_MODE_CONTENT) { $bg_color = isset($params['bgcolor']) ? $params['bgcolor'] : '#ffffff'; $url_params = Array ( 'pass' => 'm,c,content', 'm_opener' => 'd', 'c_id' => $page->GetID(), 'content_id' => $content->GetID(), 'front' => 1, 'admin' => 1, '__URLENCODE__' => 1, '__NO_REWRITE__'=> 1, 'escape' => 1, 'index_file' => 'index.php', // 'bgcolor' => $bg_color, // '__FORCE_SID__' => 1 ); $additional_css = ''; if (isset($params['float'])) { $additional_css .= 'position: relative; width: 100%; float: ' . $params['float'] . ';'; } // link from Front-End to admin, don't remove "index.php" $edit_url = $this->Application->HREF('categories/edit_content', ADMIN_DIRECTORY, $url_params, 'index.php'); $edit_code_before = ' <div class="cms-edit-btn-container"> <div class="cms-edit-btn" style="' . $additional_css . '" onclick="$form_name=\'kf_cont_'.$content->GetID().'\'; open_popup(\'content\', \'OnEdit\', \'categories/edit_content\');"> <div class="cms-btn-image"> <img src="' . $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/content_mode.gif" width="15" height="16" alt=""/> </div> - <div class="cms-btn-text">Edit '.(defined('DEBUG_MODE') && DEBUG_MODE ? " - #{$num}" : '').'</div> + <div class="cms-btn-text">Edit content '.(defined('DEBUG_MODE') && DEBUG_MODE ? " - #{$num}" : '').'</div> </div> <div class="cms-btn-content">'; $edit_form = '<form method="POST" style="display: inline; margin: 0px" name="kf_cont_'.$content->GetID().'" id="kf_cont_'.$content->GetID().'" action="'.$edit_url.'">'; $edit_form .= '<input type="hidden" name="c_id" value="'.$page->GetID().'"/>'; $edit_form .= '<input type="hidden" name="content_id" value="'.$content->GetID().'"/>'; $edit_form .= '<input type="hidden" name="front" value="1"/>'; $edit_form .= '<input type="hidden" name="bgcolor" value="'.$bg_color.'"/>'; $edit_form .= '<input type="hidden" name="m_lang" value="'.$this->Application->GetVar('m_lang').'"/>'; $edit_form .= '</form>'; $edit_code_after = '</div></div>'; if (array_key_exists('forms_later', $params) && $params['forms_later']) { $all_forms = $this->Application->GetVar('all_forms'); $this->Application->SetVar('all_forms', $all_forms . $edit_form); } else { $edit_code_after .= $edit_form; } } if ($this->Application->GetVar('_editor_preview_') == 1) { $data = $this->Application->RecallVar('_editor_preview_content_'); } else { $data = $content->GetField('Content'); } $data = $edit_code_before . $this->_transformContentBlockData($data, $params) . $edit_code_after; if ($data != '') { $this->Application->Parser->DataExists = true; } return $data; } /** * Apply all kinds of content block data transformations without rewriting ContentBlock tag * * @param string $data * @return string */ function _transformContentBlockData(&$data, $params) { return $data; } /** * Returns current page name or page based on page/page_id parameters * * @param Array $params * @return string * @todo Used? */ function PageName($params) { $page =& $this->_getPage($params); return $page->GetDBField('Name'); } /** * Returns current/given page information * * @param Array $params * @return string */ function PageInfo($params) { $page =& $this->_getPage($params); if ($params['type'] == 'index_tools') { $page_info = $page->GetDBField('IndexTools'); if ($page_info) { return $page_info; } else { if (PROTOCOL == 'https://') { return $this->Application->ConfigValue('cms_DefaultIndextoolsCode_SSL'); } else { return $this->Application->ConfigValue('cms_DefaultIndextoolsCode'); } } } switch ($params['type']) { case 'title': $db_field = 'Title'; break; case 'htmlhead_title': $db_field = 'Name'; break; case 'meta_title': $db_field = 'MetaTitle'; break; case 'meta_keywords': $db_field = 'MetaKeywords'; $cat_field = 'Keywords'; break; case 'meta_description': $db_field = 'MetaDescription'; $cat_field = 'Description'; break; default: return ''; } $default = isset($params['default']) ? $params['default'] : ''; $val = $page->GetField($db_field); if (!$default) { if ($this->Application->isModuleEnabled('In-Portal')) { if (!$val && ($params['type'] == 'meta_keywords' || $params['type'] == 'meta_description')) { // take category meta if it's not set for the page return $this->Application->ProcessParsedTag('c', 'Meta', Array('name' => $cat_field)); } } } if (isset($params['force_default']) && $params['force_default']) { return $default; } if (preg_match('/^_Auto:/', $val)) { $val = $default; /*if ($db_field == 'Title') { $page->SetDBField($db_field, $default); $page->Update(); }*/ } elseif ($page->GetID() == false) { return $default; } return $val; } /** * Includes admin css and js, that are required for cms usage on Front-Edn * * * @param Array $params * @return string */ function EditingScripts($params) { if ($this->Application->GetVar('admin_scripts_included') || !EDITING_MODE) { return ; } $this->Application->SetVar('admin_scripts_included', 1); $js_url = $this->Application->BaseURL() . 'core/admin_templates/js'; $ret = '<link rel="stylesheet" href="' . $js_url . '/jquery/thickbox/thickbox.css" type="text/css" media="screen"/>' . "\n"; $ret .= '<link rel="stylesheet" href="' . $js_url . '/../incs/cms.css" type="text/css" media="screen"/>' . "\n"; - if (EDITING_MODE == EDITING_MODE_LAYOUT) { + if (EDITING_MODE == EDITING_MODE_DESIGN) { $ret .= ' <style type="text/css" media="all"> div.movable-element .movable-header { cursor: move; } </style>'; } $ret .= '<script type="text/javascript" src="' . $js_url . '/jquery/jquery.pack.js"></script>' . "\n"; $ret .= '<script type="text/javascript" src="' . $js_url . '/jquery/jquery-ui.custom.min.js"></script>' . "\n"; $ret .= '<script type="text/javascript" src="' . $js_url . '/is.js"></script>' . "\n"; $ret .= '<script type="text/javascript" src="' . $js_url . '/application.js"></script>' . "\n"; $ret .= '<script type="text/javascript" src="' . $js_url . '/script.js"></script>' . "\n"; $ret .= '<script type="text/javascript" src="' . $js_url . '/jquery/thickbox/thickbox.js"></script>' . "\n"; $ret .= '<script type="text/javascript" src="' . $js_url . '/template_manager.js"></script>' . "\n"; $ret .= '<script language="javascript">' . "\n"; $ret .= "TB.pathToImage = 'js/jquery/thickbox/loadingAnimation.gif';" . "\n"; $template = $this->Application->GetVar('t'); $theme_id = $this->Application->GetVar('m_theme'); $url_params = Array ('block' => '#BLOCK#', 'theme-file_event' => '#EVENT#', 'theme_id' => $theme_id, 'source' => $template, 'pass' => 'all,theme-file', 'front' => 1, 'no_amp' => 1); $edit_template_url = $this->Application->HREF('themes/template_edit', ADMIN_DIRECTORY, $url_params, 'index.php'); $url_params = Array ('theme-file_event' => 'OnSaveLayout', 'source' => $template, 'pass' => 'all,theme-file', 'no_amp' => 1); $save_layout_url = $this->Application->HREF('index', '', $url_params); $this_url = $this->Application->HREF('', '', Array ('editing_mode' => '#EDITING_MODE#', 'no_amp' => 1)); $ret .= "var aTemplateManager = new TemplateManager('" . $edit_template_url . "', '" . $this_url . "', '" . $save_layout_url . "', " . (int)EDITING_MODE . ");\n"; - $ret .= "var \$modal_windows = " . ($this->Application->ConfigValue('UseModalWindows') ? 'true' : 'false') . ";\n"; - $ret .= "var main_title = '" . addslashes( $this->Application->ConfigValue('Site_Name') ) . "';" . "\n"; - $ret .= "var base_url = '" . $this->Application->BaseURL() . "';" . "\n"; - $ret .= 'TB.closeHtml = \'<img src="' . $js_url . '/../img/close_window15.gif" width="15" height="15" style="border-width: 0px;" alt="close"/><br/>\';' . "\n"; - - $url_params = Array('m_theme' => '', 'pass' => 'm', 'm_opener' => 'r', 'no_amp' => 1); - $browse_url = $this->Application->HREF('catalog/catalog', ADMIN_DIRECTORY, $url_params, 'index.php'); - $browse_url = preg_replace('/&(admin|editing_mode)=[\d]/', '', $browse_url); - - $ret .= ' - var topmost = window.top; - - topmost.document.title = document.title + \' - '.$this->Application->Phrase('la_AdministrativeConsole').'\'; - t = \''.$this->Application->GetVar('t').'\'; - - if (window.parent.frames["menu"] != undefined) { - if ( $.isFunction(window.parent.frames["menu"].SyncActive) ) { - window.parent.frames["menu"].SyncActive("' . $browse_url . '"); + if (EDITING_MODE != EDITING_MODE_BROWSE) { + $ret .= "var \$modal_windows = " . ($this->Application->ConfigValue('UseModalWindows') ? 'true' : 'false') . ";\n"; + $ret .= "var main_title = '" . addslashes( $this->Application->ConfigValue('Site_Name') ) . "';" . "\n"; + $ret .= "var base_url = '" . $this->Application->BaseURL() . "';" . "\n"; + $ret .= 'TB.closeHtml = \'<img src="' . $js_url . '/../img/close_window15.gif" width="15" height="15" style="border-width: 0px;" alt="close"/><br/>\';' . "\n"; + + $url_params = Array('m_theme' => '', 'pass' => 'm', 'm_opener' => 'r', 'no_amp' => 1); + $browse_url = $this->Application->HREF('catalog/catalog', ADMIN_DIRECTORY, $url_params, 'index.php'); + $browse_url = preg_replace('/&(admin|editing_mode)=[\d]/', '', $browse_url); + + $ret .= ' + var topmost = window.top; + + topmost.document.title = document.title + \' - '.$this->Application->Phrase('la_AdministrativeConsole', false).'\'; + t = \''.$this->Application->GetVar('t').'\'; + + if (window.parent.frames["menu"] != undefined) { + if ( $.isFunction(window.parent.frames["menu"].SyncActive) ) { + window.parent.frames["menu"].SyncActive("' . $browse_url . '"); + } } - } - '; + '; + } $ret .= '</script>' . "\n"; - // add form, so admin scripts could work - $ret .= '<form id="kernel_form" name="kernel_form" enctype="multipart/form-data" method="post" action="' . $browse_url . '"> - <input type="hidden" name="MAX_FILE_SIZE" id="MAX_FILE_SIZE" value="' . MAX_UPLOAD_SIZE . '" /> - <input type="hidden" name="sid" id="sid" value="' . $this->Application->GetSID() . '" /> - </form>'; + if (EDITING_MODE != EDITING_MODE_BROWSE) { + // add form, so admin scripts could work + $ret .= '<form id="kernel_form" name="kernel_form" enctype="multipart/form-data" method="post" action="' . $browse_url . '"> + <input type="hidden" name="MAX_FILE_SIZE" id="MAX_FILE_SIZE" value="' . MAX_UPLOAD_SIZE . '" /> + <input type="hidden" name="sid" id="sid" value="' . $this->Application->GetSID() . '" /> + </form>'; + } return $ret; } /** * Prints "Edit Page" button on cms page * * @param Array $params * @return string */ function EditPage($params) { if (!EDITING_MODE) { return ''; } $display_mode = array_key_exists('mode', $params) ? $params['mode'] : false; $edit_code = ''; $page =& $this->_getPage($params); - if (!$page->isLoaded()) { + if (!$page->isLoaded() || (($display_mode != 'end') && (EDITING_MODE == EDITING_MODE_BROWSE))) { // when "EditingScripts" tag is not used, make sure, that scripts are also included return $this->EditingScripts($params); } // show "EditPage" button only for pages, that exists in structure if ($display_mode != 'end') { - $url_params = Array( - 'pass' => 'm,c', - 'm_opener' => 'd', - 'c_id' => $page->GetID(), - 'c_mode' => 't', - 'c_event' => 'OnEdit', - 'front' => 1, - '__URLENCODE__' => 1, - '__NO_REWRITE__'=> 1, - 'escape' => 1, - 'index_file' => 'index.php', - ); + $edit_btn = ''; - $edit_url = $this->Application->HREF('categories/categories_edit', '/admin', $url_params); + if (EDITING_MODE == EDITING_MODE_CONTENT) { + $url_params = Array( + 'pass' => 'm,c', + 'm_opener' => 'd', + 'c_id' => $page->GetID(), + 'c_mode' => 't', + 'c_event' => 'OnEdit', + 'front' => 1, + '__URLENCODE__' => 1, + '__NO_REWRITE__'=> 1, + 'escape' => 1, + 'index_file' => 'index.php', + ); - $edit_btn = ''; + $edit_url = $this->Application->HREF('categories/categories_edit', '/admin', $url_params); - if (EDITING_MODE == EDITING_MODE_LAYOUT) { $edit_btn .= ' - <div class="cms-save-layout-btn"' . ($display_mode === false ? ' style="margin: 0px;"' : '') . ' onclick="aTemplateManager.saveLayout(); return false;"> + <div class="cms-section-properties-btn"' . ($display_mode === false ? ' style="margin: 0px;"' : '') . ' onmouseover="window.status=\''.$edit_url.'\'; return true" onclick="$form_name=\'kf_'.$page->GetID().'\'; open_popup(\'c\', \'OnEdit\', \'categories/categories_edit\');"> <div class="cms-btn-image"> <img src="' . $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/content_mode.gif" width="15" height="16" alt=""/> </div> - <div class="cms-btn-text">Save Layout</div> + <div class="cms-btn-text">Section Properties</div> </div>' . "\n"; - } + } elseif (EDITING_MODE == EDITING_MODE_DESIGN) { + $url_params = Array( + 'pass' => 'm,theme', + 'm_opener' => 'd', + 'theme_id' => $this->Application->GetVar('m_theme'), + 'theme_mode' => 't', + 'theme_event' => 'OnEdit', + 'theme-file_id' => $this->_getThemeFileId(), + 'front' => 1, + '__URLENCODE__' => 1, + '__NO_REWRITE__'=> 1, + 'escape' => 1, + 'index_file' => 'index.php', + ); - $edit_btn .= ' - <div class="cms-section-properties-btn"' . ($display_mode === false ? ' style="margin: 0px;"' : '') . ' onmouseover="window.status=\''.$edit_url.'\'; return true" onclick="$form_name=\'kf_'.$page->GetID().'\'; open_popup(\'c\', \'OnEdit\', \'categories/categories_edit\');"> - <div class="cms-btn-image"> - <img src="' . $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/content_mode.gif" width="15" height="16" alt=""/> + $edit_url = $this->Application->HREF('themes/file_edit', '/admin', $url_params); + + $edit_btn .= ' + <div class="cms-layout-btn-container"' . ($display_mode === false ? ' style="margin: 0px;"' : '') . '> + <div class="cms-save-layout-btn" onclick="aTemplateManager.saveLayout(); return false;"> + <div class="cms-btn-image"> + <img src="' . $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/content_mode.gif" width="15" height="16" alt=""/> + </div> + <div class="cms-btn-text">Save changes</div> + </div> + <div class="cms-cancel-layout-btn" onclick="aTemplateManager.cancelLayout(); return false;"> + <div class="cms-btn-image"> + <img src="' . $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/content_mode.gif" width="15" height="16" alt=""/> + </div> + <div class="cms-btn-text">Cancel</div> + </div> </div> - <div class="cms-btn-text">Section Properties</div> - </div>' . "\n"; + + <div class="cms-section-properties-btn"' . ($display_mode === false ? ' style="margin: 0px;"' : '') . ' onmouseover="window.status=\''.$edit_url.'\'; return true" onclick="$form_name=\'kf_'.$page->GetID().'\'; open_popup(\'theme\', \'OnEdit\', \'themes/file_edit\');"> + <div class="cms-btn-image"> + <img src="' . $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/content_mode.gif" width="15" height="16" alt=""/> + </div> + <div class="cms-btn-text">Section Template</div> + </div>' . "\n"; + } if ($display_mode == 'start') { // button with border around the page $edit_code .= '<div class="cms-section-properties-btn-container">' . $edit_btn . '<div class="cms-btn-content">'; } else { // button without border around the page $edit_code .= $edit_btn; } } if ($display_mode == 'end') { // draw border around the page $edit_code .= '</div></div>'; } if ($display_mode != 'end') { $edit_code .= '<form method="POST" style="display: inline; margin: 0px" name="kf_'.$page->GetID().'" id="kf_'.$page->GetID().'" action="'.$edit_url.'"></form>'; // when "EditingScripts" tag is not used, make sure, that scripts are also included $edit_code .= $this->EditingScripts($params); } return $edit_code; } + function _getThemeFileId() + { + $template = $this->Application->GetVar('t'); + + if (!$this->Application->TemplatesCache->TemplateExists($template) && !$this->Application->IsAdmin()) { + $cms_handler =& $this->Application->recallObject($this->Prefix . '_EventHandler'); + /* @var $cms_handler CategoriesEventHandler */ + + $template = ltrim($cms_handler->GetDesignTemplate(), '/'); + } + + $file_path = dirname($template) == '.' ? '' : '/' . dirname($template); + $file_name = basename($template); + + $sql = 'SELECT FileId + FROM ' . TABLE_PREFIX . 'ThemeFiles + WHERE (FilePath = ' . $this->Conn->qstr($file_path) . ') AND (FileName = ' . $this->Conn->qstr($file_name . '.tpl') . ')'; + return $this->Conn->GetOne($sql); + } + /** * Builds cached menu version * * @return Array */ function _prepareMenu() { static $root_cat = null; static $root_path = null; if (!$root_cat) { $root_cat = $this->Application->ModuleInfo['Core']['RootCat']; $root_path = $this->Conn->GetOne('SELECT ParentPath FROM '.TABLE_PREFIX.'Category WHERE CategoryId = '.$root_cat); } if (!$this->Menu) { $menu = $this->Conn->GetRow('SELECT Data, Cached FROM '.TABLE_PREFIX.'Cache WHERE VarName = "cms_menu"'); if ($menu && $menu['Cached'] > 0) { $menu = unserialize($menu['Data']); $this->ParentPaths = $menu['ParentPaths']; } else { $menu = $this->_altBuildMenuStructure(array('CategoryId' => $root_cat, 'ParentPath' => $root_path)); $menu['ParentPaths'] = $this->ParentPaths; $this->Conn->Query('REPLACE '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("cms_menu", '.$this->Conn->qstr(serialize($menu)).', '.adodb_mktime().')'); } unset($menu['ParentPaths']); $this->Menu = $menu; } return Array ($this->Menu, $root_path); } /** * Returns category id based tag parameters * * @param Array $params * @return int */ function _getCategoryId($params) { $cat = isset($params['category_id']) && $params['category_id'] != '' ? $params['category_id'] : $this->Application->GetVar('m_cat_id'); if ("$cat" == 'parent') { $this_category =& $this->Application->recallObject('c'); /* @var $this_category kDBItem */ $cat = $this_category->GetDBField('ParentId'); } else if ($cat == 0) { $cat = $this->Application->ModuleInfo['Core']['RootCat']; } return $cat; } /** * Prepares cms menu item block parameters * * @param Array $page * @param int $real_cat_id * @param string $root_path * @return Array */ function _prepareMenuItem($page, $real_cat_id, $root_path) { static $language_id = null; static $primary_language_id = null; if (!isset($language_id)) { $language_id = $this->Application->GetVar('m_lang'); $primary_language_id = $this->Application->GetDefaultLanguageId(); } $title = $page['l'.$language_id.'_ItemName'] ? $page['l'.$language_id.'_ItemName'] : $page['l'.$primary_language_id.'_ItemName']; $active = false; $category_active = false; if ($page['ItemType'] == 'cat') { if ( isset($this->ParentPaths[$real_cat_id])) { $active = strpos($this->ParentPaths[$real_cat_id], $page['ParentPath']) !== false; } $category_active = $page['CategoryId'] == $real_cat_id; } if ($page['ItemType'] == 'cat_index') { $check_path = str_replace($root_path, '', $page['ParentPath']); $active = strpos($parent_path, $check_path) !== false; } if ($page['ItemType'] == 'page') { $active = $page['ItemPath'] == preg_replace('/^Content\//i', '', $this->Application->GetVar('t')); } $block_params = Array ( 'title'=> $title, 'template'=> preg_replace('/^Content\//i', '', $page['ItemPath']), 'active'=>$active, 'category_active' => $category_active, // new 'parent_path'=>$page['ParentPath'], 'parent_id'=>$page['ParentId'], 'cat_id'=>$page['CategoryId'], 'is_index'=>$page['IsIndex'], 'item_type'=>$page['ItemType'], 'page_id'=>$page['ItemId'], 'has_sub_menu' => isset($page['sub_items']) && count($page['sub_items']) > 0, 'external_url' => $page['UseExternalUrl'] ? $page['ExternalUrl'] : false, 'menu_icon' => $page['UseMenuIconUrl'] ? $page['MenuIconUrl'] : false, ); return $block_params; } /** * Builds site menu * * @param Array $params * @return string */ function CachedMenu($params) { list ($menu, $root_path) = $this->_prepareMenu(); $cat = $this->_getCategoryId($params); $parent_path = isset($this->ParentPaths[$cat]) ? $this->ParentPaths[$cat] : ''; $parent_path = str_replace($root_path, '', $parent_path); //menu starts from module path $levels = explode('|',trim($parent_path,'|')); if ($levels[0] === '') $levels = array(); if (isset($params['level']) && $params['level'] > count($levels)) return ; $level = max(isset($params['level']) ? $params['level']-1 : count($levels)-1, 0); $parent = isset($levels[$level]) ? $levels[$level] : 0; $cur_menu =& $menu; $menu_path = array_slice($levels, 0, $level+1); foreach ($menu_path as $elem) { $cur_menu =& $cur_menu['c'.$elem]['sub_items']; } $ret = ''; $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['render_as']; $this->Application->SetVar('cur_parent_path', $parent_path); $real_cat_id = $this->Application->GetVar('m_cat_id'); if (is_array($cur_menu) && $cur_menu) { $cur_item = 1; $cur_menu = $this->_removeNonMenuItems($cur_menu); $block_params['total_items'] = count($cur_menu); foreach ($cur_menu as $page) { $block_params = array_merge_recursive2( $block_params, $this->_prepareMenuItem($page, $real_cat_id, $root_path) ); $block_params['is_last'] = $cur_item == $block_params['total_items']; $block_params['is_first'] = $cur_item == 1; // bug #1: this breaks active section highlighting when 2 menu levels are printed on same page (both visible) // bug #2: people doesn't pass cat_id parameter to m_Link tags in their blocks, so this line helps them; when removed their links will lead to nowhere $this->Application->SetVar('m_cat_id', $page['CategoryId']); $ret .= $this->Application->ParseBlock($block_params, 1); $cur_item++; } $this->Application->SetVar('m_cat_id', $real_cat_id); } return $ret; } /** * Returns only items, that are visible in menu * * @param Array $menu * @return Array */ function _removeNonMenuItems($menu) { foreach ($menu as $menu_index => $menu_item) { // $menu_index is in "cN" format, where N is category id if (!$menu_item['IsMenu']) { unset($menu[$menu_index]); } } return $menu; } /** * Trick to allow some kind of output formatting when using CachedMenu tag * * @param Array $params * @return bool */ function SplitColumn($params) { return $this->Application->GetVar($params['i']) > ceil($params['total'] / $params['columns']); } /** * Returns direct children count of given category * * @param Array $params * @return int */ function HasSubCats($params) { $sql = 'SELECT COUNT(*) FROM ' . TABLE_PREFIX . 'Category WHERE ParentId = ' . $params['cat_id']; return $this->Conn->GetOne($sql); } /** * Prints sub-pages of given/current page. * * @param Array $params * @return string * @todo This could be reached by using "parent_cat_id" parameter. Only difference here is new block parameter "path". Need to rewrite. */ function PrintSubPages($params) { $list =& $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix.'_List', $params); /* @var $list kDBList */ $category_id = array_key_exists('category_id', $params) ? $params['category_id'] : $this->Application->GetVar('m_cat_id'); $list->addFilter('current_pages', TABLE_PREFIX . 'CategoryItems.CategoryId = ' . $category_id); $list->Query(); $list->GoFirst(); $o = ''; $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['render_as']; while (!$list->EOL()) { $block_params['path'] = $list->GetDBField('Path'); $o .= $this->Application->ParseBlock($block_params, 1); $list->GoNext(); } return $o; } /** * Builds link for browsing current page on Front-End * * @param Array $params * @return string */ function PageBrowseLink($params) { $object =& $this->getObject($params); $template = $object->GetDBField('NamedParentPath'); $url_params = Array ('admin' => 1, 'pass' => 'm', 'm_cat_id' => $object->GetID(), 'index_file' => 'index.php'); return $this->Application->HREF($template, '_FRONT_END_', $url_params); } /** * Builds link to cms page (used?) * * @param Array $params * @return string */ function ContentPageLink($params) { $object =& $this->getObject($params); $params['t'] = $object->GetDBField('NamedParentPath'); $params['m_cat_id'] = 0; return $this->Application->ProcessParsedTag('m', 'Link', $params); } /** * Builds cache for children of given category (no matter, what menu status is) * * @param Array $parent * @return Array */ function _altBuildMenuStructure($parent) { static $languages_count = null; if (!isset($languages_count)) { $sql = 'SELECT COUNT(*) FROM ' . TABLE_PREFIX . 'Language'; $languages_count = ceil($this->Conn->GetOne($sql) / 5) * 5; } $items = Array (); $lang_part = ''; for ($i = 1; $i <= $languages_count; $i++) { // $lang_part .= 'c.l' . $i . '_Name AS l' . $i . '_ItemName,' . "\n"; $lang_part .= 'c.l' . $i . '_MenuTitle AS l' . $i . '_ItemName,' . "\n"; } // Sub-categories from current category $query = 'SELECT c.CategoryId AS CategoryId, CONCAT(\'c\', c.CategoryId) AS ItemId, c.Priority AS ItemPriority, ' . $lang_part . ' LOWER( IF(IsIndex = 2, ( SELECT cc.NamedParentPath FROM ' . TABLE_PREFIX . 'Category AS cc WHERE cc.ParentId = c.CategoryId AND cc.Status IN (1,4) AND cc.IsIndex = 1 ), c.NamedParentPath) ) AS ItemPath, 0 AS IsIndex, c.ParentPath AS ParentPath, c.ParentId As ParentId, \'cat\' AS ItemType, c.IsMenu, c.UseExternalUrl, c.ExternalUrl, c.UseMenuIconUrl, c.MenuIconUrl FROM ' . TABLE_PREFIX . 'Category AS c WHERE c.Status IN (1,4) AND #c.IsMenu = 1 AND c.ParentId = ' . $parent['CategoryId']; $items = array_merge($items, $this->Conn->Query($query, 'ItemId')); uasort($items, Array (&$this, '_menuSort')); $the_items = array(); foreach ($items as $an_item) { $the_items[ $an_item['ItemId'] ] = $an_item; $this->ParentPaths[ $an_item['CategoryId'] ] = $an_item['ParentPath']; } $items = $the_items; foreach ($items as $key => $menu_item) { if ($menu_item['CategoryId'] == $parent['CategoryId']) { continue; } $sub_items = $this->_altBuildMenuStructure($menu_item); if ($sub_items) { $items[$key]['sub_items'] = $sub_items; } } return $items; } /** * Method for sorting pages by priority in decending order * * @param Array $a * @param Array $b * @return int */ function _menuSort($a, $b) { if ($a['ItemPriority'] == $b['ItemPriority']) { return 0; } return ($a['ItemPriority'] < $b['ItemPriority']) ? 1 : -1; //descending } /** * Prepares cms page description for search result page * * @param Array $params * @return string */ function SearchDescription($params) { $object =& $this->getObject($params); $desc = $object->GetField('MetaDescription'); if (!$desc) { $sql = 'SELECT * FROM ' . TABLE_PREFIX . 'PageContent WHERE PageId = ' . $object->GetID() . ' AND ContentNum = 1'; $content = $this->Conn->GetRow($sql); if ($content['l'.$this->Application->GetVar('m_lang').'_Content']) { $desc = $content['l'.$this->Application->GetVar('m_lang').'_Content']; } else { $desc = $content['l'.$this->Application->GetDefaultLanguageId().'_Content']; } } return mb_substr($desc, 0, 300).(mb_strlen($desc) > 300 ? '...' : ''); } /** * Simplified version of "c:CategoryLink" for "c:PrintList" * * @param Array $params * @return string * @todo Used? Needs refactoring. */ function EnterCatLink($params) { $object =& $this->getObject($params); $url_params = Array ('pass' => 'm', 'm_cat_id' => $object->GetID()); return $this->Application->HREF($params['template'], '', $url_params); } /** * Simplified version of "c:CategoryPath", that do not use blocks for rendering * * @param Array $params * @return string * @todo Used? Maybe needs to be removed. */ function PagePath($params) { $object =& $this->getObject($params); $path = $object->GetField('CachedNavbar'); if ($path) { $items = explode('&|&', $path); array_shift($items); return implode(' -> ', $items); } return ''; } /** * Returns configuration variable value * * @param Array $params * @return string * @todo Needs to be replaced with "m:GetConfig" tag; Not used now (were used on structure_edit.tpl). */ function AllowManualFilenames($params) { return $this->Application->ConfigValue('ProjCMSAllowManualFilenames'); } /** * Draws path to current page (each page can be link to it) * * @param Array $params * @return string */ function CurrentPath($params) { $block_params = $this->prepareTagParams($params); $block_params['name'] = $block_params['render_as']; $object =& $this->Application->recallObject($this->Prefix); /* @var $object kDBItem */ $category_ids = explode('|', substr($object->GetDBField('ParentPath'), 1, -1)); $id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName'); $language = $this->Application->GetVar('m_lang'); $sql = 'SELECT l'.$language.'_Name AS Name, NamedParentPath FROM '.$table_name.' WHERE '.$id_field.' IN ('.implode(',', $category_ids).')'; $categories_data = $this->Conn->Query($sql); $ret = ''; foreach ($categories_data as $index => $category_data) { if ($category_data['Name'] == 'Content') { continue; } $block_params['title'] = $category_data['Name']; $block_params['template'] = preg_replace('/^Content\//i', '', $category_data['NamedParentPath']); $block_params['is_first'] = $index == 1; // because Content is 1st element $block_params['is_last'] = $index == count($categories_data) - 1; $ret .= $this->Application->ParseBlock($block_params); } return $ret; } /** * Synonim to PrintList2 for "onlinestore" theme * * @param Array $params * @return string */ function ListPages($params) { return $this->PrintList2($params); } /** * Returns information about parser element locations in template * * @param Array $params * @return mixed */ function BlockInfo($params) { if (!EDITING_MODE) { return ''; } $template_helper =& $this->Application->recallObject('TemplateHelper'); /* @var $template_helper TemplateHelper */ return $template_helper->blockInfo( $params['name'] ); } /** * Hide all editing tabs except permission tab, when editing "Home" (ID = 0) category * * @param Array $params */ function ModifyUnitConfig($params) { $root_category = $this->Application->RecallVar('IsRootCategory_' . $this->Application->GetVar('m_wid')); if (!$root_category) { return ; } $edit_tab_presets = $this->Application->getUnitOption($this->Prefix, 'EditTabPresets'); $edit_tab_presets['Default'] = Array ( 'permissions' => $edit_tab_presets['Default']['permissions'], ); $this->Application->setUnitOption($this->Prefix, 'EditTabPresets', $edit_tab_presets); } /** * Prints catalog export templates * * @param Array $params * @return string */ function PrintCatalogExportTemplates($params) { $prefixes = explode(',', $params['prefixes']); $ret = Array (); foreach ($prefixes as $prefix) { if ($this->Application->prefixRegistred($prefix)) { $ret[$prefix] = $this->Application->getUnitOption($prefix, 'ModuleFolder') . '/export'; } } $json_helper =& $this->Application->recallObject('JSONHelper'); /* @var $json_helper JSONHelper */ return $json_helper->encode($ret); } /** * Checks, that "view in browse mode" functionality available * * @param Array $params * @return bool */ function BrowseModeAvailable($params) { $valid_special = $params['Special'] != 'user'; $not_selector = $this->Application->GetVar('type') != 'item_selector'; return $valid_special && $not_selector; } /** * Returns a link for editing product * * @param Array $params * @return string */ function ItemEditLink($params) { $object =& $this->getObject(); /* @var $object kDBList */ $edit_template = $this->Application->getUnitOption($this->Prefix, 'AdminTemplatePath') . '/' . $this->Application->getUnitOption($this->Prefix, 'AdminTemplatePrefix') . 'edit'; $url_params = Array ( 'm_opener' => 'd', $this->Prefix.'_mode' => 't', $this->Prefix.'_event' => 'OnEdit', $this->Prefix.'_id' => $object->GetID(), 'm_cat_id' => $object->GetDBField('ParentId'), 'pass' => 'all,'.$this->Prefix, 'no_pass_through' => 1, ); return $this->Application->HREF($edit_template,'', $url_params); } } \ No newline at end of file Index: branches/5.0.x/core/units/sections/site_config_tp.php =================================================================== --- branches/5.0.x/core/units/sections/site_config_tp.php (revision 12297) +++ branches/5.0.x/core/units/sections/site_config_tp.php (revision 12298) @@ -1,60 +1,59 @@ <?php /** * @version $Id$ * @package In-Portal * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. * @license GNU/GPL * In-Portal is Open Source software. * This means that this software may have been modified pursuant * the GNU General Public License, and as distributed it includes * or is derivative of works licensed under the GNU General Public License * or other free or open source software licenses. * See http://www.in-portal.net/license/ for copyright notices and details. */ class SiteConfigTagProcessor extends TagProcessor { function PrintEditingModes($params) { $editing_modes = Array ( - 1 => Array ('image' => 'show_structure', 'title' => 'Browse Mode'), - 4 => Array ('image' => 'content_mode', 'title' => 'Content Mode'), - 2 => Array ('image' => 'show_all', 'title' => 'Layout Mode'), - 3 => Array ('image' => 'show_all', 'title' => 'Design Mode'), + EDITING_MODE_BROWSE => Array ('image' => 'show_structure', 'title' => 'Browse Mode'), + EDITING_MODE_CONTENT => Array ('image' => 'content_mode', 'title' => 'Content Mode'), + EDITING_MODE_DESIGN => Array ('image' => 'show_all', 'title' => 'Design Mode'), ); $preset_name = $this->Application->ConfigValue('AdminConsoleInterface'); $base_path = FULL_PATH . ADMIN_DIRECTORY . '/system_presets/' . $preset_name; if (file_exists($base_path . DIRECTORY_SEPARATOR . 'settings.php')) { include_once $base_path . DIRECTORY_SEPARATOR . 'settings.php'; // will get $visible_editing_modes foreach ($editing_modes as $editing_mode => $data) { if (!in_array($editing_mode, $visible_editing_modes)) { unset($editing_modes[$editing_mode]); } } if (count($editing_modes) == 1) { // don't show buttons, when there only one left return ''; } } $ret = ''; $i = 1; $count = count($editing_modes); $block_params = Array ('name' => $params['render_as']); foreach ($editing_modes as $editing_mode => $data) { $block_params = array_merge($block_params, $data); $block_params['editing_mode'] = $editing_mode; $block_params['is_last'] = $i == $count; $ret .= $this->Application->ParseBlock($block_params); $i++; } return $ret; } } \ No newline at end of file Index: branches/5.0.x/core/units/phrases/phrases_config.php =================================================================== --- branches/5.0.x/core/units/phrases/phrases_config.php (revision 12297) +++ branches/5.0.x/core/units/phrases/phrases_config.php (revision 12298) @@ -1,218 +1,218 @@ <?php /** * @version $Id$ * @package In-Portal * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. * @license GNU/GPL * In-Portal is Open Source software. * This means that this software may have been modified pursuant * the GNU General Public License, and as distributed it includes * or is derivative of works licensed under the GNU General Public License * or other free or open source software licenses. * See http://www.in-portal.net/license/ for copyright notices and details. */ $config = Array ( 'Prefix' => 'phrases', 'Clones' => Array ( 'phrases-single' => Array ( 'ForeignKey' => false, 'ParentTableKey' => false, 'ParentPrefix' => false, ) ), 'ItemClass' => Array ('class' => 'kDBItem', 'file' => '', 'build_event' => 'OnItemBuild'), 'ListClass' => Array ('class' => 'kDBList', 'file' => '', 'build_event' => 'OnListBuild'), 'EventHandlerClass' => Array ('class' => 'PhrasesEventHandler', 'file' => 'phrases_event_handler.php', 'build_event' => 'OnBuild'), - 'TagProcessorClass' => Array ('class' => 'kDBTagProcessor', 'file' => '', 'build_event' => 'OnBuild'), + 'TagProcessorClass' => Array ('class' => 'PhraseTagProcessor', 'file' => 'phrase_tp.php', 'build_event' => 'OnBuild'), 'AutoLoad' => true, 'Hooks' => Array ( Array ( 'Mode' => hBEFORE, 'Conditional' => false, 'HookToPrefix' => 'phrases', 'HookToSpecial' => '', 'HookToEvent' => Array('OnCreate'), 'DoPrefix' => 'phrases', 'DoSpecial' => '', 'DoEvent' => 'OnBeforePhraseCreate', ), Array ( 'Mode' => hAFTER, 'Conditional' => false, 'HookToPrefix' => 'phrases', 'HookToSpecial' => '', 'HookToEvent' => Array('OnBeforeItemCreate', 'OnBeforeItemUpdate'), 'DoPrefix' => 'phrases', 'DoSpecial' => '', 'DoEvent' => 'OnSetLastUpdated', ), ), 'QueryString' => Array ( 1 => 'id', 2 => 'page', 3 => 'event', 4 => 'label', 5 => 'mode', // labels can be edited directly ), 'IDField' => 'PhraseId', 'TitleField' => 'Phrase', 'TitlePresets' => Array ( 'default' => Array ( 'new_status_labels' => Array ('phrases' => '!la_title_Adding_Phrase!'), 'edit_status_labels' => Array ('phrases' => '!la_title_Editing_Phrase!'), ), 'phrase_edit' => Array ( 'prefixes' => Array ('phrases'), 'format' => '#phrases_status# #phrases_titlefield#', 'toolbar_buttons' => Array ('select', 'cancel', 'reset_edit', 'prev', 'next'), ), // for separate phrases list 'phrases_list_st' => Array ( 'prefixes' => Array ('phrases.st_List'), 'format' => "!la_title_Phrases!", 'toolbar_buttons' => Array ('new_item', 'edit', 'delete', 'view', 'dbl-click'), ), 'phrase_edit_single' => Array ( 'prefixes' => Array ('phrases'), 'format' => '#phrases_status# #phrases_titlefield#', 'toolbar_buttons' => Array ('select', 'cancel', 'reset_edit', 'prev', 'next'), ), ), 'FilterMenu' => Array ( 'Groups' => Array ( Array ('mode' => 'AND', 'filters' => Array ('show_front', 'show_admin', 'show_both'), 'type' => WHERE_FILTER), Array ('mode' => 'AND', 'filters' => Array ('translated', 'not_translated'), 'type' => WHERE_FILTER), ), 'Filters' => Array ( 'show_front' => Array ('label' =>'la_PhraseType_Front', 'on_sql' => '', 'off_sql' => '%1$s.PhraseType != 0'), 'show_admin' => Array ('label' => 'la_PhraseType_Admin', 'on_sql' => '', 'off_sql' => '%1$s.PhraseType != 1'), 'show_both' => Array ('label' => 'la_PhraseType_Both', 'on_sql' => '', 'off_sql' => '%1$s.PhraseType != 2'), 's1' => Array (), 'translated' => Array ('label' => 'la_PhraseTranslated', 'on_sql' => '', 'off_sql' => '%1$s.Translation = pri.Translation'), 'not_translated' => Array ('label' => 'la_PhraseNotTranslated', 'on_sql' => '', 'off_sql' => '%1$s.Translation != pri.Translation'), ) ), 'Sections' => Array ( // "Phrases" 'in-portal:phrases' => Array ( 'parent' => 'in-portal:site', 'icon' => 'conf_regional', 'label' => 'la_title_Phrases', 'url' => Array ('t' => 'languages/phrase_list', 'pass' => 'm'), 'permissions' => Array ('view', 'add', 'edit', 'delete'), // 'perm_prefix' => 'lang', 'priority' => 5, // 'show_mode' => smSUPER_ADMIN, 'type' => stTREE, ), ), 'TableName' => TABLE_PREFIX . 'Phrase', 'CalculatedFields' => Array ( '' => Array ( 'PrimaryTranslation' => 'pri.Translation', ), 'st' => Array ( 'PackName' => 'lang.PackName', ), ), 'ListSQLs' => Array( '' => ' SELECT %1$s.* %2$s FROM %1$s LEFT JOIN ' . TABLE_PREFIX . 'Phrase pri ON (%1$s.Phrase = pri.Phrase) AND (pri.LanguageId = 1)', 'st' => 'SELECT %1$s.* %2$s FROM %1$s LEFT JOIN ' . TABLE_PREFIX . 'Language lang ON (%1$s.LanguageId = lang.LanguageId)', ), 'ListSortings' => Array ( '' => Array ( 'Sorting' => Array ('Phrase' => 'asc'), ) ), 'ForeignKey' => 'LanguageId', 'ParentTableKey' => 'LanguageId', 'ParentPrefix' => 'lang', 'AutoDelete' => true, 'AutoClone' => true, 'Fields' => Array ( 'Phrase' => Array ( 'type' => 'string', 'required' => 1, 'unique' => Array ('LanguageId'), 'not_null' => 1, 'default' => '' ), 'Translation' => Array ('type' => 'string', 'formatter' => 'kFormatter', 'required' => 1, 'not_null' => 1, 'using_fck' => 1, 'default' => ''), 'PhraseType' => Array ('type' => 'int', 'required'=>1,'formatter' => 'kOptionsFormatter', 'options'=>Array (0=>'la_PhraseType_Front',1=>'la_PhraseType_Admin',2=>'la_PhraseType_Both'), 'use_phrases' => 1, 'not_null' => 1, 'default' => 0), 'PhraseId' => Array ('type' => 'int', 'not_null' => 1, 'default' => 0), 'LanguageId' => Array ( 'type' => 'int', 'formatter' => 'kOptionsFormatter', 'options_sql' => 'SELECT %s FROM ' . TABLE_PREFIX . 'Language ORDER BY LocalName', 'option_key_field' => 'LanguageId', 'option_title_field' => 'LocalName', 'not_null' => 1, 'default' => 0 ), 'LastChanged' => Array ('type' => 'int', 'formatter' => 'kDateFormatter', 'not_null' => 1, 'default' => 0), 'LastChangeIP' => Array ('type' => 'string', 'not_null' => 1, 'default' => ''), 'Module' => Array ( 'type' => 'string', 'formatter' => 'kOptionsFormatter', 'options'=>Array ('' => ''), 'options_sql' => 'SELECT %s FROM '.TABLE_PREFIX.'Modules WHERE Loaded = 1 ORDER BY LoadOrder', 'option_key_field' => 'Name', 'option_title_field' => 'Name', 'not_null' => 1, 'default' => 'In-Portal' ), ), 'VirtualFields' => Array ( 'PrimaryTranslation' => Array (), 'LangFile' => Array (), 'ImportOverwrite' => Array (), 'DoNotEncode' => Array (), 'PackName' => Array ( 'type' => 'string', 'formatter' => 'kOptionsFormatter', 'options_sql' => 'SELECT %s FROM ' . TABLE_PREFIX . 'Language ORDER BY PackName', 'option_title_field' => 'PackName', 'option_key_field' => 'PackName', ), ), 'Grids' => Array ( 'Default' => Array ( 'Icons' => Array ('default' => 'icon16_language_var.gif'), 'Fields' => Array ( 'Phrase' => Array ('title' => 'la_col_Label', 'data_block' => 'grid_checkbox_td'), 'Translation' => Array ('title' => 'la_col_Translation'), 'PrimaryTranslation' => Array ('title' => 'la_col_PrimaryValue'), 'PhraseType' => Array ('title' => 'la_col_PhraseType', 'filter_block' => 'grid_options_filter'), 'LastChanged' => Array ('title' => 'la_col_LastChanged', 'filter_block' => 'grid_date_range_filter'), 'Module' => Array ('title' => 'la_col_Module', 'filter_block' => 'grid_options_filter'), ), ), 'Phrases' => Array ( 'Icons' => Array ('default' => 'icon16_language_var.gif'), 'Fields' => Array ( 'PhraseId' => Array ('title' => 'la_col_Id', 'data_block' => 'grid_checkbox_td', 'filter_block' => 'grid_range_filter', 'width' => 50), 'Phrase' => Array ('title' => 'la_col_Name', 'filter_block' => 'grid_like_filter', 'width' => 150), 'Translation' => Array ('title' => 'la_col_Translation', 'filter_block' => 'grid_like_filter', 'width' => 150), 'PackName' => Array ('title' => 'la_col_Language', 'filter_block' => 'grid_options_filter', 'width' => 100), 'PhraseType' => Array ('title' => 'la_col_Location', 'filter_block' => 'grid_options_filter', 'width' => 80), 'LastChanged' => Array ('title' => 'la_col_LastChanged', 'filter_block' => 'grid_date_range_filter'), 'Module' => Array ('title' => 'la_col_Module', 'filter_block' => 'grid_options_filter'), ), ), ), ); \ No newline at end of file Index: branches/5.0.x/core/units/phrases/phrases_event_handler.php =================================================================== --- branches/5.0.x/core/units/phrases/phrases_event_handler.php (revision 12297) +++ branches/5.0.x/core/units/phrases/phrases_event_handler.php (revision 12298) @@ -1,161 +1,173 @@ <?php /** * @version $Id$ * @package In-Portal * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. * @license GNU/GPL * In-Portal is Open Source software. * This means that this software may have been modified pursuant * the GNU General Public License, and as distributed it includes * or is derivative of works licensed under the GNU General Public License * or other free or open source software licenses. * See http://www.in-portal.net/license/ for copyright notices and details. */ class PhrasesEventHandler extends kDBEventHandler { /** * Apply some special processing to * object beeing recalled before using * it in other events that call prepareObject * * @param Object $object * @param kEvent $event * @access protected */ function prepareObject(&$object, &$event) { // don't call parent } /** * Allow to create phrases from front end in debug mode with DBG_PHRASES constant set * * @param kEvent $event */ function CheckPermission(&$event) { if (!$this->Application->IsAdmin() && $this->Application->isDebugMode() && constOn('DBG_PHRASES')) { - if ($event->Name == 'OnNew' || $event->Name == 'OnCreate' || $event->Name == 'OnPrepareUpdate' || $event->Name == 'OnUpdate') { + $allow_events = Array ('OnCreate', 'OnUpdate'); + + if (in_array($event->Name, $allow_events)) { return true; } } - - return parent::CheckPermission($event); } function mapPermissions() { parent::mapPermissions(); - $permissions = Array ( - 'OnItemBuild' => Array('self' => true, 'subitem' => true), - ); + + $permissions = Array ( + 'OnItemBuild' => Array('self' => true, 'subitem' => true), + 'OnNew' => Array('self' => true, 'subitem' => true), + 'OnPrepareUpdate' => Array('self' => true, 'subitem' => true), + ); $this->permMapping = array_merge($this->permMapping, $permissions); } /** * Forces new label in case if issued from get link * * @param kEvent $event */ function OnNew(&$event) { parent::OnNew($event); $label = $this->Application->GetVar('phrases_label'); - $object =& $event->getObject( $label ? Array('live_table'=>true, 'skip_autoload' => true) : Array('skip_autoload' => true) ); + $object =& $event->getObject( $label ? Array('live_table' => true, 'skip_autoload' => true) : Array('skip_autoload' => true) ); if ($label) { - $object->SetDBField('Phrase',$label); + $object->SetDBField('Phrase', $label); // phrase is created in language, used to display phrases - $object->SetDBField('LanguageId', $this->Application->Phrases->LanguageId); - $object->SetDBField('PhraseType',1); + $object->SetDBField('LanguageId', $this->Application->GetVar('m_lang')); + $object->SetDBField('PhraseType', 1); $primary_language = $this->Application->GetDefaultLanguageId(); $live_table = $this->Application->getUnitOption($event->Prefix, 'TableName'); $sql = 'SELECT Translation FROM %s WHERE Phrase = %s'; $primary_value = $this->Conn->GetOne( sprintf($sql, $live_table, $this->Conn->qstr($label) ) ); $object->SetDBField('PrimaryTranslation', $primary_value); } $last_module = $this->Application->GetVar('last_module'); - if($last_module) $object->SetDBField('Module', $last_module); + if ($last_module) { + $object->SetDBField('Module', $last_module); + } - if($event->Special == 'export' || $event->Special == 'import') - { + if ($event->Special == 'export' || $event->Special == 'import') { $object->SetDBField('PhraseType', '|0|1|2|'); $modules = $this->Conn->GetCol('SELECT Name FROM '.TABLE_PREFIX.'Modules'); $object->SetDBField('Module', '|'.implode('|', $modules).'|' ); } } + /** + * Prepares existing phrase editing + * + * @param kEvent $event + */ function OnPrepareUpdate(&$event) { $language_id = $this->Application->GetVar('m_lang'); $label = $this->Application->GetVar('phrases_label'); $table_name = $this->Application->getUnitOption($event->Prefix, 'TableName'); $label_idfield = $this->Application->getUnitOption($event->Prefix, 'IDField'); - $sql = 'SELECT '.$label_idfield.' FROM '.$table_name.' WHERE Phrase = '.$this->Conn->qstr($label).' AND LanguageId = '.$language_id; + $sql = 'SELECT ' . $label_idfield . ' + FROM ' . $table_name . ' + WHERE Phrase = '.$this->Conn->qstr($label).' AND LanguageId = '.$language_id; $this->Application->SetVar($event->getPrefixSpecial() . '_id', $this->Conn->GetOne($sql)); -// $event->redirect = false; + + $event->redirect = false; } /** * Forces create to use live table * * @param kEvent $event */ function OnBeforePhraseCreate(&$event) { $edit_direct = $this->Application->GetVar($event->Prefix.'_label'); if ($edit_direct) { $object =& $event->getObject( Array('skip_autoload' => true) ); if ($this->Application->GetVar('m_lang') != $this->Application->GetVar('lang_id')) { $object->SwitchToLive(); } } } /** * Save phrase change date & ip translation was made from * * @param kEvent $event */ function OnSetLastUpdated(&$event) { $object =& $event->getObject(); $prev_translation = $this->Conn->GetOne('SELECT Translation FROM '.$object->TableName.' WHERE '.$object->IDField.' = '.(int)$object->GetId() ); if( $prev_translation != $object->GetDBField('Translation') ) { $ip_address = getenv('HTTP_X_FORWARDED_FOR') ? getenv('HTTP_X_FORWARDED_FOR') : getenv('REMOTE_ADDR'); $object->SetDBField('LastChanged_date', adodb_mktime() ); $object->SetDBField('LastChanged_time', adodb_mktime() ); $object->SetDBField('LastChangeIP', $ip_address); } $this->Application->Session->SetCookie('last_module', $object->GetDBField('Module')); } /** * Changes default module to custom (when available) * * @param kEvent $event */ function OnAfterConfigRead(&$event) { parent::OnAfterConfigRead($event); if ($this->Application->findModule('Name', 'Custom')) { $fields = $this->Application->getUnitOption($event->Prefix, 'Fields'); $fields['Module']['default'] = 'Custom'; $this->Application->setUnitOption($event->Prefix, 'Fields', $fields); } } } ?> \ No newline at end of file Index: branches/5.0.x/core/units/phrases/phrase_tp.php =================================================================== --- branches/5.0.x/core/units/phrases/phrase_tp.php (nonexistent) +++ branches/5.0.x/core/units/phrases/phrase_tp.php (revision 12298) @@ -0,0 +1,30 @@ +<?php +/** +* @version $Id$ +* @package In-Portal +* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. +* @license GNU/GPL +* In-Portal is Open Source software. +* This means that this software may have been modified pursuant +* the GNU General Public License, and as distributed it includes +* or is derivative of works licensed under the GNU General Public License +* or other free or open source software licenses. +* See http://www.in-portal.net/license/ for copyright notices and details. +*/ + + class PhraseTagProcessor extends kDBTagProcessor { + + /** + * Determines, that hidden field with language id should be shown + * + * @param Array $params + * @return bool + */ + function ShowHiddenLanguage($params) + { + $simple_mode = $this->Application->GetVar('simple_mode'); + $phrases_label = $this->Application->GetVar('phrases_label'); + + return $simple_mode || !$phrases_label; + } + } \ No newline at end of file Property changes on: branches/5.0.x/core/units/phrases/phrase_tp.php ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: branches/5.0.x/core/admin_templates/themes/file_edit.tpl =================================================================== --- branches/5.0.x/core/admin_templates/themes/file_edit.tpl (revision 12297) +++ branches/5.0.x/core/admin_templates/themes/file_edit.tpl (revision 12298) @@ -1,52 +1,52 @@ <inp2:adm_SetPopupSize width="1100" height="700"/> <inp2:m_include t="incs/header"/> <inp2:m_RenderElement name="combined_header" section="in-portal:configure_themes" prefix="theme" title_preset="theme_file_edit"/> <!-- ToolBar --> <table class="toolbar" height="30" cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td> <script type="text/javascript"> a_toolbar = new ToolBar(); a_toolbar.AddButton( new ToolBarButton('select', '<inp2:m_phrase label="la_ToolTip_Save" escape="1"/>', function() { submit_event('theme-file','<inp2:theme-file_SaveEvent/>'); } ) ); a_toolbar.AddButton( new ToolBarButton('cancel', '<inp2:m_phrase label="la_ToolTip_Cancel" escape="1"/>', function() { cancel_edit('theme-file', 'OnCancelEdit','<inp2:theme-file_SaveEvent/>','<inp2:m_Phrase label="la_FormCancelConfirmation" escape="1"/>'); } ) ); a_toolbar.AddButton( new ToolBarButton('reset_edit', '<inp2:m_phrase label="la_ToolTip_Reset" escape="1"/>', function() { reset_form('theme-file', 'OnReset', '<inp2:m_Phrase label="la_FormResetConfirmation" escape="1"/>'); } ) ); a_toolbar.Render(); </script> </td> </tr> </tbody> </table> <inp2:theme-file_SaveWarning name="grid_save_warning"/> <inp2:theme-file_ErrorWarning name="form_error_warning"/> <inp2:m_RenderElement name="inp_edit_hidden" prefix="theme-file" field="ThemeId"/> <div id="scroll_container"> <table class="edit-form"> <inp2:m_RenderElement name="subsection" prefix="theme-file" fields="FileId,FileName,FilePath,Description,FileContents" title="!la_section_General!"/> <inp2:m_RenderElement name="inp_id_label" prefix="theme-file" field="FileId" title="!la_fld_Id!"/> <inp2:m_RenderElement name="inp_label" prefix="theme-file" field="FileName" title="la_fld_FileName"/> - <inp2:m_RenderElement name="inp_label" prefix="theme-file" field="FilePath" title="la_fld_FileName"/> + <inp2:m_RenderElement name="inp_label" prefix="theme-file" field="FilePath" title="la_fld_FilePath"/> <inp2:m_RenderElement name="inp_label" prefix="theme-file" field="Description" title="la_fld_Description"/> <inp2:m_RenderElement name="inp_edit_codepress" prefix="theme-file" field="FileContents" title="la_fld_FileContents"/> <inp2:m_RenderElement name="inp_edit_filler" control_options="{height: 8}"/> </table> </div> <inp2:m_include t="incs/footer"/> \ No newline at end of file Index: branches/5.0.x/core/admin_templates/themes/template_edit.tpl =================================================================== --- branches/5.0.x/core/admin_templates/themes/template_edit.tpl (revision 12297) +++ branches/5.0.x/core/admin_templates/themes/template_edit.tpl (revision 12298) @@ -1,56 +1,56 @@ <inp2:adm_SetPopupSize width="1100" height="700"/> <inp2:m_include t="incs/header"/> <inp2:m_RenderElement name="combined_header" section="in-portal:configure_themes" prefix="theme" title_preset="block_edit"/> <!-- ToolBar --> <table class="toolbar" height="30" cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td> <script type="text/javascript"> a_toolbar = new ToolBar(); a_toolbar.AddButton( new ToolBarButton('select', '<inp2:m_phrase label="la_ToolTip_Save" escape="1"/>', function() { submit_event('theme-file','OnSaveBlock'); } ) ); a_toolbar.AddButton( new ToolBarButton('cancel', '<inp2:m_phrase label="la_ToolTip_Cancel" escape="1"/>', function() { - submit_event('theme-file', 'OnGoBack'); + window_close(); // submit_event('theme-file', 'OnGoBack'); } ) ); a_toolbar.Render(); </script> </td> </tr> </tbody> </table> <inp2:theme-file_SaveWarning name="grid_save_warning"/> <inp2:theme-file_ErrorWarning name="form_error_warning"/> <inp2:m_RenderElement name="inp_edit_hidden" prefix="theme-file" field="ThemeId"/> <input type="hidden" id="block" name="block" value="<inp2:m_Get name='block'/>"/> <input type="hidden" id="theme_id" name="theme_id" value="<inp2:m_Get name='theme_id'/>"/> <input type="hidden" id="source" name="source" value="<inp2:m_Get name='source'/>"/> <div id="scroll_container"> <table class="edit-form"> <inp2:m_RenderElement name="inp_label" prefix="theme-file" field="FileName" title="la_fld_FileName"/> <inp2:m_RenderElement name="inp_label" prefix="theme-file" field="BlockPosition" title="la_fld_BlockPosition"/> <inp2:m_RenderElement name="inp_edit_codepress" prefix="theme-file" field="FileContents" title="la_fld_FileContents"/> <!--<inp2:m_RenderElement name="inp_edit_filler" control_options="{height: 8}"/>--> </table> </div> <script type="text/javascript"> Application.setHook( new Array ('theme-file:OnSaveBlock'), function($event) { FileContents.toggleEditor(); // enable textarea back to save data $event.status = true; } ); </script> <inp2:m_include t="incs/footer"/> \ No newline at end of file Index: branches/5.0.x/core/admin_templates/js/script.js =================================================================== --- branches/5.0.x/core/admin_templates/js/script.js (revision 12297) +++ branches/5.0.x/core/admin_templates/js/script.js (revision 12298) @@ -1,1759 +1,1764 @@ if ( !( isset($init_made) && $init_made ) ) { var Application = new kApplication(); var Grids = new Array(); var GridScrollers = new Array (); var Toolbars = new Array(); var $Menus = new Array(); var $ViewMenus = new Array(); var $nls_menus = new Array(); var $MenuNames = new Array(); var $form_name = 'kernel_form'; if(!$fw_menus) var $fw_menus = new Array(); var $env = ''; var submitted = false; var unload_legal = false; var $edit_mode = false; var $init_made = true; // in case of double inclusion of script.js :) // hook processing var hBEFORE = 1; // this is const, but including this twice causes errors var hAFTER = 2; // this is const, but including this twice causes errors replaceFireBug(); } function use_popups($prefix_special, $event) { return $use_popups; } function getArrayValue() { var $value = arguments[0]; var $current_key = 0; $i = 1; while ($i < arguments.length) { $current_key = arguments[$i]; if (isset($value[$current_key])) { $value = $value[$current_key]; } else { return false; } $i++; } return $value; } function setArrayValue() { // first argument - array, other arguments - keys (arrays too), last argument - value var $array = arguments[0]; var $current_key = 0; $i = 1; while ($i < arguments.length - 1) { $current_key = arguments[$i]; if (!isset($array[$current_key])) { $array[$current_key] = new Array(); } $array = $array[$current_key]; $i++; } $array[$array.length] = arguments[arguments.length - 1]; } function resort_grid($prefix_special, $field, $ajax) { set_form($prefix_special, $ajax); set_hidden_field($prefix_special + '_Sort1', $field); submit_event($prefix_special, 'OnSetSorting', null, null, $ajax); } function direct_sort_grid($prefix_special, $field, $direction, $field_pos, $ajax) { if(!isset($field_pos)) $field_pos = 1; set_form($prefix_special, $ajax); set_hidden_field($prefix_special+'_Sort'+$field_pos,$field); set_hidden_field($prefix_special+'_Sort'+$field_pos+'_Dir',$direction); set_hidden_field($prefix_special+'_SortPos',$field_pos); submit_event($prefix_special,'OnSetSortingDirect', null, null, $ajax); } function reset_sorting($prefix_special, $ajax) { submit_event($prefix_special,'OnResetSorting', null, null, $ajax); } function set_per_page($prefix_special, $per_page, $ajax) { set_form($prefix_special, $ajax); set_hidden_field($prefix_special + '_PerPage', $per_page); submit_event($prefix_special, 'OnSetPerPage', null, null, $ajax); } function set_refresh_interval($prefix_special, $refresh_interval, $ajax) { set_form($prefix_special, $ajax); set_hidden_field('refresh_interval', $refresh_interval); submit_event($prefix_special, 'OnSetAutoRefreshInterval', null, null, $ajax); } function submit_event(prefix_special, event, t, form_action, $ajax) { if (!Application.processHooks(prefix_special + ':' + event)) { return false; } if ($ajax) { return $Catalog.submit_event(prefix_special, event, t); } if (event) { set_hidden_field('events[' + prefix_special + ']', event); } if (t) set_hidden_field('t', t); if (form_action) { var old_env = ''; if (!form_action.match(/\?/)) { document.getElementById($form_name).action.match(/.*(\?.*)/); old_env = RegExp.$1; } document.getElementById($form_name).action = form_action + old_env; } submit_kernel_form(); // reset remove special mark (otherwise all future events will have special removed too) set_hidden_field('remove_specials[' + prefix_special + ']', null); } function submit_action($url, $action) { $form = document.getElementById($form_name); $form.action = $url; set_hidden_field('Action', $action); submit_kernel_form(); } function show_form_data() { var $kf = document.getElementById($form_name); $ret = ''; for(var i in $kf.elements) { $elem = $kf.elements[i]; $ret += $elem.id + ' = ' + $elem.value + "\n"; } alert($ret); } function submit_kernel_form() { if (submitted) { return; } submitted = true; unload_legal = true; // bug: when opening new popup from this window, then this window is not refreshed and this mark stays forever var $form = document.getElementById($form_name); if (typeof $form.onsubmit == 'function') { $form.onsubmit(); } $form.submit(); $form.target = ''; set_hidden_field('t', t); // window.setTimeout(function() {submitted = false}, 500); } function set_event(prefix_special, event) { var event_field=document.getElementById('events[' + prefix_special + ']'); if(isset(event_field)) { event_field.value = event; } } function isset(variable) { if(variable==null) return false; return (typeof(variable)=='undefined')?false:true; } function in_array(needle, haystack) { return array_search(needle, haystack) != -1; } function array_search(needle, haystack) { for (var i=0; i<haystack.length; i++) { if (haystack[i] == needle) return i; } return -1; } function print_pre(variable, msg) { if (!isset(msg)) msg = ''; var s = msg; for (prop in variable) { s += prop+" => "+variable[prop] + "\n"; } alert(s); } function go_to_page($prefix_special, $page, $ajax) { set_form($prefix_special, $ajax); set_hidden_field($prefix_special + '_Page', $page); submit_event($prefix_special, 'OnSetPage', null, null, $ajax); } function go_to_list(prefix_special, tab) { set_hidden_field(prefix_special+'_GoTab', tab); submit_event(prefix_special,'OnUpdateAndGoToTab',null); } function go_to_tab(prefix_special, tab) { set_hidden_field(prefix_special+'_GoTab', tab); submit_event(prefix_special,'OnPreSaveAndGoToTab',null); } function go_to_id(prefix_special, id) { set_hidden_field(prefix_special+'_GoId', id); submit_event(prefix_special,'OnPreSaveAndGo') } // in-portal compatibility functions: begin function getScriptURL($script_name, tpl) { tpl = tpl ? '-'+tpl : ''; var $asid = get_hidden_field('sid'); return base_url+$script_name+'?env='+( isset($env)&&$env?$env:$asid )+tpl+'&en=0'; } function OpenEditor(extra_env,TargetForm,TargetField) { var $url = getScriptURL('admin/index.php', 'popups/editor'); $url = $url+'&TargetForm='+TargetForm+'&TargetField='+TargetField+'&destform=popup'; if(extra_env.length>0) $url += extra_env; openwin($url,'html_edit',800,575); } // in-portal compatibility functions: end function InitTranslator(prefix, field, t, multi_line, $before_callback) { var $window_name = 'select_' + t.replace(/(\/|-)/g, '_'); var $options = { onAfterShow: function ($popup_window) { if ($modal_windows) { getFrame('main').initTranslatorOnAfterShow(prefix, field, t, multi_line, $before_callback); } else { initTranslatorOnAfterShow(prefix, field, t, multi_line, $before_callback, $popup_window); } } }; openwin('', $window_name, 750, 400, $options); } function initTranslatorOnAfterShow(prefix, field, t, multi_line, $before_callback, $popup_window) { var $window_name = 'select_' + t.replace(/(\/|-)/g, '_'); $popup_window = onAfterWindowOpen($window_name, undefined, $popup_window); if ($popup_window === false) { // iframe onload happens on frame content change too -> don't react on it return ; } var $opener = getWindowOpener($popup_window); var $prev_opener = get_hidden_field('m_opener'); $opener.set_hidden_field('m_opener', 'p'); $opener.set_hidden_field('translator_wnd_name', $window_name); $opener.set_hidden_field('translator_field', field); $opener.set_hidden_field('translator_t', t); $opener.set_hidden_field('translator_prefixes', prefix); $opener.set_hidden_field('translator_multi_line', isset(multi_line) ? multi_line : 0); if ($.isFunction($before_callback)) { $before_callback($opener); } $opener.document.getElementById($opener.$form_name).target = $window_name; var split_prefix = prefix.split(','); $opener.submit_event(split_prefix[0], 'OnPreSaveAndOpenTranslator'); $opener.set_hidden_field('m_opener', $prev_opener); $opener.submitted = false; } function PreSaveAndOpenTranslator(prefix, field, t, multi_line) { InitTranslator(prefix, field, t, multi_line); } function PreSaveAndOpenTranslatorCV(prefix, field, t, resource_id, multi_line) { InitTranslator( prefix, field, t, multi_line, function ($opener) { $opener.set_hidden_field('translator_resource_id', resource_id); } ); } function openTranslator(prefix,field,url,wnd) { var $kf = document.getElementById($form_name); set_hidden_field('trans_prefix', prefix); set_hidden_field('trans_field', field); set_hidden_field('events[trans]', 'OnLoad'); var $regex = new RegExp('(.*)\?env=(' + document.getElementById('sid').value + ')?-(.*?):(.*)'); var $t = $regex.exec(url)[3]; $kf.target = wnd; submit_event(prefix,'',$t,url); submitted = false; } function openwin($url, $name, $width, $height, $options) { var $settings = { url: base_url + 'core/admin_templates/blank.html?width=' + $width + '&height=' + $height + '&TB_iframe=true&modal=true', caption: 'Loading ...', onAfterShow: function ($popup_window) { if ($modal_windows) { getFrame('main').onAfterWindowOpen($name, $url); } else { onAfterWindowOpen($name, $url, $popup_window); } } }; if ($options !== undefined) { $.extend($settings, $options); } if ($modal_windows) { if (window.name != 'main') { // all popups are opened based on main frame return getFrame('main').TB.show($settings); } TB.show($settings); return ; } // prevent window from opening larger, then screen resolution on user's computer (to Kostja) var left = Math.round((screen.width - $width) / 2); var top = Math.round((screen.height - $height) / 2); var cur_x = document.all ? window.screenLeft : window.screenX; var cur_y = document.all ? window.screenTop : window.screenY; var $window_params = 'left='+left+',top='+top+',width='+$width+',height='+$height+',status=yes,resizable=yes,menubar=no,scrollbars=yes,toolbar=no'; var $popup_window = window.open($url, $name, $window_params); if ( $.isFunction($settings.onAfterShow) ) { $settings.onAfterShow($popup_window); } return $popup_window; } function onAfterWindowOpen($window_name, $url, $popup_window) { // this is always invoked from "main" frame if ($popup_window === undefined) { var $popup_window = $('#' + TB.getId('TB_iframeContent')).get(0).contentWindow; if (!$.isFunction($popup_window.onLoad)) { // iframe onload happens on frame content change too -> don't react on it return false; } $popup_window.onLoad(); } $popup_window.name = $window_name; if ($url !== undefined) { $popup_window.location.href = $url; } if ($modal_windows) { TB.setWindowMetaData('window_name', $window_name); // used to simulate window.opener functionality } return $popup_window; } function OnResizePopup(e) { if (!document.all) { var $winW = window.innerWidth; var $winH = window.innerHeight; } else { var $winW = window.document.body.offsetWidth; var $winH = window.document.body.offsetHeight; } window.status = '[width: ' + $winW + '; height: ' + $winH + ']'; } function opener_action(new_action) { var $prev_opener = get_hidden_field('m_opener'); set_hidden_field('m_opener', new_action); return $prev_opener; } function open_popup($prefix_special, $event, $t, $window_size, $onAfterOpenPopup) { if (!$window_size) { // if no size given, then query it from ajax var $default_size = '750x400'; var $pm = getFrame('head').$popup_manager; if ($pm) { // popup manager was found in head frame $pm.ResponceFunction = function ($responce) { if (!$responce.match(/([\d]+)x([\d]+)/)) { // invalid responce was received, may be php fatal error during AJAX request $responce = $default_size; } open_popup($prefix_special, $event, $t, $responce, $onAfterOpenPopup); } $pm.GetSize($t); return ; } $window_size = $default_size; } $window_size = $window_size.split('x'); var $window_name = $t.replace(/(\/|-)/g, '_'); // replace "/" and "-" with "_" var $options = { onAfterShow: function ($popup_window) { if ($modal_windows) { getFrame('main').onAfterOpenPopup($prefix_special, $event, $t); } else { onAfterOpenPopup($prefix_special, $event, $t, $popup_window); } if ($onAfterOpenPopup !== undefined && $.isFunction($onAfterOpenPopup)) { $onAfterOpenPopup($popup_window); } } }; openwin('', $window_name, $window_size[0], $window_size[1], $options); } function onAfterOpenPopup($prefix_special, $event, $t, $popup_window) { // this is always invoked from "main" frame var $window_name = $t.replace(/(\/|-)/g, '_'); // replace "/" and "-" with "_" $popup_window = onAfterWindowOpen($window_name, undefined, $popup_window); if ($popup_window === false) { // iframe onload happens on frame content change too -> don't react on it return ; } var $opener = getWindowOpener($popup_window); if ($opener === null) { // we are already in main window $opener = window; } $opener.document.getElementById($opener.$form_name).target = $window_name; var $prev_opener = $opener.opener_action('p'); event_bak = $opener.get_hidden_field('events[' + $prefix_special + ']') if (!event_bak) { event_bak = ''; } $opener.submit_event($prefix_special, $event, $t); $opener.opener_action($prev_opener); // restore opener in parent window $opener.set_hidden_field('events[' + $prefix_special + ']', event_bak); // restore event // AJAX popup size respoce is received after std_edit_item/std_precreate_item function exit $opener.set_hidden_field($prefix_special + '_mode', null); $opener.submitted = false; $opener.Application.processHooks($prefix_special + ':OnAfterOpenPopup'); } function openSelector($prefix, $url, $dst_field, $window_size, $event) { // get template name from url var $regex = new RegExp('(.*)\?env=(' + document.getElementById('sid').value + ')?-(.*?):(m[^:]+)'); $regex = $regex.exec($url); var $t = $regex[3]; // substitute form action with selector's url var $kf = document.getElementById($form_name); var $prev_action = $kf.action; $kf.action = $url; // check parameter values if (!isset($event)) { $event = ''; } Application.processHooks($prefix + ':OnBeforeOpenSelector'); // set variables need for selector to work set_hidden_field('main_prefix', $prefix); set_hidden_field('dst_field', $dst_field); // alert('openSelector(' + $prefix + ', ' + $event + ', ' + $t + ', ' + $window_size + ')'); open_popup( $prefix, $event, $t, $window_size, function() { // restore form action back $kf.action = $prev_action; } ); } -function translate_phrase($label, $template) { +function translate_phrase($label, $template, $options) { set_hidden_field('phrases_label', $label); - open_popup('phrases', 'OnNew', $template); + + if ($options.simple_mode !== undefined) { + set_hidden_field('simple_mode', $options.simple_mode ? 1 : 0); + } + + open_popup('phrases', $options.event === undefined ? 'OnNew' : $options.event, $template); } function direct_edit($prefix_special, $url) { if (use_popups($prefix_special, '')) { openSelector($prefix_special, $url); } else { redirect($url); } return false; } function std_precreate_item(prefix_special, edit_template, $onAfterOpenPopup) { set_hidden_field(prefix_special+'_mode', 't'); if (use_popups(prefix_special, 'OnPreCreate')) { open_popup(prefix_special, 'OnPreCreate', edit_template, null, $onAfterOpenPopup); } else { opener_action('d'); submit_event(prefix_special,'OnPreCreate', edit_template); } // set_hidden_field(prefix_special+'_mode', ''); } function std_new_item(prefix_special, edit_template, $onAfterOpenPopup) { if (use_popups(prefix_special, 'OnNew')) { open_popup(prefix_special, 'OnNew', edit_template, null, $onAfterOpenPopup); } else { opener_action('d'); submit_event(prefix_special,'OnNew', edit_template); } } function std_edit_item(prefix_special, edit_template, $onAfterOpenPopup) { set_hidden_field(prefix_special+'_mode', 't'); if (use_popups(prefix_special, 'OnEdit')) { open_popup(prefix_special, 'OnEdit', edit_template, null, $onAfterOpenPopup); } else { opener_action('d'); submit_event(prefix_special,'OnEdit',edit_template); } // set_hidden_field(prefix_special+'_mode', ''); } function std_edit_temp_item(prefix_special, edit_template, $onAfterOpenPopup) { if (use_popups(prefix_special, '')) { open_popup(prefix_special, '', edit_template, null, $onAfterOpenPopup); } else { opener_action('d'); submit_event(prefix_special,'',edit_template); } } function std_delete_items(prefix_special, t, $ajax) { var phrase = phrases['la_Delete_Confirm'] ? phrases['la_Delete_Confirm'] : 'Are you sure you want to delete selected items?'; if (inpConfirm(phrase)) { submit_event(prefix_special, 'OnMassDelete', t, null, $ajax); } } function std_csv_export(prefix_special, grid, template) { set_hidden_field('PrefixSpecial', prefix_special); set_hidden_field('grid', grid); open_popup(prefix_special, '', template); } function std_csv_import(prefix_special, grid, template) { set_hidden_field('PrefixSpecial', prefix_special); set_hidden_field('grid', grid); if (use_popups(prefix_special, '')) { open_popup(prefix_special, '', template); } else { submit_event(prefix_special, '', template); } } // set current form base on ajax function set_form($prefix_special, $ajax) { if ($ajax) { $form_name = $Catalog.queryTabRegistry('prefix', $prefix_special, 'tab_id') + '_form'; } } // sets hidden field value // if the field does not exist - creates it function set_hidden_field($field_id, $value, $has_id) { var $kf = document.getElementById($form_name); var $field = $kf.elements[$field_id]; if ($value === null) { if ($field) { // alert('tag name on remove: ' + $field.parentNode.tagName); $field.parentNode.removeChild($field); // bug: sometimes hidden fields are inside BODY tag in DOM model, why? } return true; } if ($field) { $field.value = $value; return true; } $field = document.createElement('INPUT'); $field.type = 'hidden'; $field.name = $field_id; if (!isset($has_id) || $has_id) { $field.id = $field_id; } $field.value = $value; $kf.appendChild($field); return false; } // sets hidden field value // if the field does not exist - creates it function setInnerHTML($field_id, $value) { $( jq('#' + $field_id) ).html($value); } function get_hidden_field($field) { var $kf = document.getElementById($form_name); return $kf.elements[$field] ? $kf.elements[$field].value : false; } function search($prefix_special, $grid_name, $ajax) { set_form($prefix_special, $ajax); set_hidden_field('grid_name', $grid_name); submit_event($prefix_special, 'OnSearch', null, null, $ajax); } function search_reset($prefix_special, $grid_name, $ajax) { set_form($prefix_special, $ajax); set_hidden_field('grid_name', $grid_name); submit_event($prefix_special, 'OnSearchReset', null, null, $ajax); } function search_keydown($event, $prefix_special, $grid, $ajax) { if ($prefix_special !== undefined) { // if $prefix_special is passed, then keydown event was not assigned by jQuery $event = $event ? $event : event; if (window.event) {// IE var $key_code = $event.keyCode; } else if($event.which) { // Netscape/Firefox/Opera var $key_code = $event.which; } } else { // event bind with jQuery, so always use which var $key_code = $event.which; $prefix_special = $(this).attr('PrefixSpecial'); $grid = $(this).attr('Grid'); $ajax = $(this).attr('ajax'); } switch ($key_code) { case 13: search($prefix_special, $grid, parseInt($ajax)); break; case 27: search_reset($prefix_special, $grid, parseInt($ajax)); break; } } function getRealLeft(el) { if (typeof(el) == 'string') { el = document.getElementById(el); } xPos = el.offsetLeft; tempEl = el.offsetParent; while (tempEl != null) { xPos += tempEl.offsetLeft; tempEl = tempEl.offsetParent; } // if (obj.x) return obj.x; return xPos; } function getRealTop(el) { if (typeof(el) == 'string') { el = document.getElementById(el); } yPos = el.offsetTop; tempEl = el.offsetParent; while (tempEl != null) { yPos += tempEl.offsetTop; tempEl = tempEl.offsetParent; } // if (obj.y) return obj.y; return yPos; } function show_viewmenu_old($toolbar, $button_id) { var $img = $toolbar.GetButtonImage($button_id); var $pos_x = getRealLeft($img) - ((document.all) ? 6 : -2); var $pos_y = getRealTop($img) + 32; var $prefix_special = ''; window.triedToWriteMenus = false; if($ViewMenus.length == 1) { $prefix_special = $ViewMenus[$ViewMenus.length-1]; $fw_menus[$prefix_special+'_view_menu'](); $Menus[$prefix_special+'_view_menu'].writeMenus('MenuContainers['+$prefix_special+']'); window.FW_showMenu($Menus[$prefix_special+'_view_menu'], $pos_x, $pos_y); } else { // prepare menus for(var $i in $ViewMenus) { $prefix_special = $ViewMenus[$i]; $fw_menus[$prefix_special+'_view_menu'](); } $Menus['mixed'] = new Menu('ViewMenu_mixed'); // merge menus into new one for(var $i in $ViewMenus) { $prefix_special = $ViewMenus[$i]; $Menus['mixed'].addMenuItem( $Menus[$prefix_special+'_view_menu'] ); } $Menus['mixed'].writeMenus('MenuContainers[mixed]'); window.FW_showMenu($Menus['mixed'], $pos_x, $pos_y); } } var nlsMenuRendered = false; function show_viewmenu($toolbar, $button_id) { if($ViewMenus.length == 1) { $prefix_special = $ViewMenus[$ViewMenus.length-1]; menu_to_show = $prefix_special+'_view_menu'; } else { mixed_menu = menuMgr.createMenu(rs('mixed_menu')); mixed_menu.applyBorder(false, false, false, false); mixed_menu.dropShadow("none"); mixed_menu.showIcon = true; // merge menus into new one for(var $i in $ViewMenus) { $prefix_special = $ViewMenus[$i]; mixed_menu.addItem( rs($prefix_special+'.view.menu.mixed'), $MenuNames[$prefix_special+'_view_menu'], 'javascript:void()', null, true, null, rs($prefix_special+'.view.menu'),$MenuNames[$prefix_special+'_view_menu'] ); } menu_to_show = 'mixed_menu'; } renderMenus(); nls_showMenu(rs(menu_to_show), $toolbar.GetButtonImage($button_id)) } function renderMenus() { menuMgr.renderMenus('nlsMenuPlace'); nlsMenuRendered = true; } function set_window_title($title) { var $window = window; if ($window.name != 'main') { // traverse through real popups $window = getFrame('main'); } $window.top.document.title = (main_title.length ? main_title + ' - ' : '') + $title; if ($modal_windows) { $window.TB.setWindowTitle(''); } } function set_filter($prefix_special, $filter_id, $filter_value, $ajax) { set_form($prefix_special, $ajax); set_hidden_field('filter_id', $filter_id); set_hidden_field('filter_value', $filter_value); submit_event($prefix_special, 'OnSetFilter', null, null, $ajax); } function filters_remove_all($prefix_special, $ajax) { set_form($prefix_special, $ajax); submit_event($prefix_special,'OnRemoveFilters', null, null, $ajax); } function filters_apply_all($prefix_special, $ajax) { set_form($prefix_special, $ajax); submit_event($prefix_special,'OnApplyFilters', null, null, $ajax); } function filter_toggle($row_id, $prefix) { // var $row = $('#' + jq($row_id)); var $row = $('tr.to-range-filter'); var $hidden = $row.hasClass('hidden-filter'); if ($hidden) { $('td', $row).show(); $row.removeClass('hidden-filter'); } else { $('td', $row).hide(); $row.addClass('hidden-filter'); } // recalculate filter row heights/widths var $grid = GridScrollers[$prefix]; $grid.UpdateColWidths(); if ($hidden && $grid.FiltersExpanded !== true) { $grid.AdjustInputWidths(); $grid.FiltersExpanded = true; } // $grid.SetLeftHeights(); // $grid.UpdateTotalDimensions(); // $grid.SyncScroll(); // $grid.Resize( $grid.GetAutoSize() ); } function RemoveTranslationLink($string, $escaped) { if (!isset($escaped)) $escaped = true; if ($escaped) { return $string.replace(/<a href="(.*?)">(.*?)<\/a>/g, '$2'); } return $string.replace(/<a href="(.*?)">(.*?)<\/a>/g, '$2'); } function redirect($url) { window.location.href = $url; } function update_checkbox_options($cb_mask, $hidden_id) { var $kf = document.getElementById($form_name); var $tmp = ''; for (var i = 0; i < $kf.elements.length; i++) { if ( $kf.elements[i].id.match($cb_mask) ) { if ($kf.elements[i].checked) $tmp += '|'+$kf.elements[i].value; } } if($tmp.length > 0) $tmp += '|'; document.getElementById($hidden_id).value = $tmp.replace(/,$/, ''); } function update_multiple_options($hidden_id) { var $select = document.getElementById($hidden_id + '_select'); var $result = ''; for (var $i = 0; $i < $select.options.length; $i++) { if ($select.options[$i].selected) { $result += $select.options[$i].value + '|'; } } document.getElementById($hidden_id).value = $result ? '|' + $result : ''; } // related to lists operations (moving) function move_selected($from_list, $to_list, $error_msg) { if (typeof($from_list) != 'object') $from_list = document.getElementById($from_list); if (typeof($to_list) != 'object') $to_list = document.getElementById($to_list); if (has_selected_options($from_list)) { var $from_array = select_to_array($from_list); var $to_array = select_to_array($to_list); var $new_from = Array(); var $cur = null; for (var $i = 0; $i < $from_array.length; $i++) { $cur = $from_array[$i]; if ($cur[2]) // If selected - add to To array { $to_array[$to_array.length] = $cur; } else //Else - keep in new From { $new_from[$new_from.length] = $cur; } } $from_list = array_to_select($new_from, $from_list); $to_list = array_to_select($to_array, $to_list); } else { alert(isset($error_msg) ? $error_msg : 'Please select items to perform moving!'); } } function select_to_array($aSelect) { var $an_array = new Array(); var $cur = null; for (var $i = 0; $i < $aSelect.length; $i++) { $cur = $aSelect.options[$i]; $an_array[$an_array.length] = new Array($cur.text, $cur.value, $cur.selected); } return $an_array; } function array_to_select($anArray, $aSelect) { var $initial_length = $aSelect.length; for (var $i = $initial_length - 1; $i >= 0; $i--) { $aSelect.options[$i] = null; } for (var $i = 0; $i < $anArray.length; $i++) { $cur = $anArray[$i]; $aSelect.options[$aSelect.length] = new Option($cur[0], $cur[1]); } } function select_compare($a, $b) { if ($a[0] < $b[0]) return -1; if ($a[0] > $b[0]) return 1; return 0; } function select_to_string($aSelect) { var $result = ''; var $cur = null; if (typeof($aSelect) != 'object') $aSelect = document.getElementById($aSelect); for (var $i = 0; $i < $aSelect.length; $i++) { $result += $aSelect.options[$i].value + '|'; } return $result.length ? '|' + $result : ''; } function selected_to_string($aSelect) { var $result = ''; var $cur = null; if (typeof($aSelect) != 'object') $aSelect = document.getElementById($aSelect); for (var $i = 0; $i < $aSelect.length; $i++) { $cur = $aSelect.options[$i]; if ($cur.selected && $cur.value != '') { $result += $cur.value + '|'; } } return $result.length ? '|' + $result : ''; } function string_to_selected($str, $aSelect) { var $cur = null; for (var $i = 0; $i < $aSelect.length; $i++) { $cur = $aSelect.options[$i]; $aSelect.options[$i].selected = $str.match('\\|' + $cur.value + '\\|') ? true : false; } } function set_selected($selected_options, $aSelect) { if (!$selected_options.length) return false; for (var $i = 0; $i < $aSelect.length; $i++) { for (var $k = 0; $k < $selected_options.length; $k++) { if ($aSelect.options[$i].value == $selected_options[$k]) { $aSelect.options[$i].selected = true; } } } } function get_selected_count($theList) { var $count = 0; var $cur = null; for (var $i = 0; $i < $theList.length; $i++) { $cur = $theList.options[$i]; if ($cur.selected) $count++; } return $count; } function get_selected_index($aSelect, $typeIndex) { var $index = 0; for (var $i = 0; $i < $aSelect.length; $i++) { if ($aSelect.options[$i].selected) { $index = $i; if ($typeIndex == 'firstSelected') break; } } return $index; } function has_selected_options($theList) { var $ret = false; var $cur = null; for (var $i = 0; $i < $theList.length; $i++) { $cur = $theList.options[$i]; if ($cur.selected) { $ret = true; break; } } return $ret; } function select_sort($aSelect) { if (typeof($aSelect) != 'object') $aSelect = document.getElementById($aSelect); var $to_array = select_to_array($aSelect); $to_array.sort(select_compare); array_to_select($to_array, $aSelect); } function move_options_up($aSelect, $interval) { if (typeof($aSelect) != 'object') $aSelect = document.getElementById($aSelect); if (has_selected_options($aSelect)) { var $selected_options = Array(); var $first_selected = get_selected_index($aSelect, 'firstSelected'); for (var $i = 0; $i < $aSelect.length; $i++) { if ($aSelect.options[$i].selected && ($first_selected > 0) ) { swap_options($aSelect, $i, $i - $interval); $selected_options[$selected_options.length] = $aSelect.options[$i - $interval].value; } else if ($first_selected == 0) { //alert('Begin of list'); break; } } set_selected($selected_options, $aSelect); } else { //alert('Check items from moving'); } } function move_options_down($aSelect, $interval) { if (typeof($aSelect) != 'object') $aSelect = document.getElementById($aSelect); if (has_selected_options($aSelect)) { var $last_selected = get_selected_index($aSelect, 'lastSelected'); var $selected_options = Array(); for (var $i = $aSelect.length - 1; $i >= 0; $i--) { if ($aSelect.options[$i].selected && ($aSelect.length - ($last_selected + 1) > 0)) { swap_options($aSelect, $i, $i + $interval); $selected_options[$selected_options.length] = $aSelect.options[$i + $interval].value; } else if ($last_selected + 1 == $aSelect.length) { //alert('End of list'); break; } } set_selected($selected_options, $aSelect); } else { //alert('Check items from moving'); } } function swap_options($aSelect, $src_num, $dst_num) { var $src_html = $aSelect.options[$src_num].innerHTML; var $dst_html = $aSelect.options[$dst_num].innerHTML; var $src_value = $aSelect.options[$src_num].value; var $dst_value = $aSelect.options[$dst_num].value; var $src_option = document.createElement('OPTION'); var $dst_option = document.createElement('OPTION'); $aSelect.remove($src_num); $aSelect.options.add($dst_option, $src_num); $dst_option.innerText = $dst_html; $dst_option.value = $dst_value; $dst_option.innerHTML = $dst_html; $aSelect.remove($dst_num); $aSelect.options.add($src_option, $dst_num); $src_option.innerText = $src_html; $src_option.value = $src_value; $src_option.innerHTML = $src_html; } function getXMLHTTPObject(content_type) { if (!isset(content_type)) content_type = 'text/plain'; var http_request = false; if (window.XMLHttpRequest) { // Mozilla, Safari,... http_request = new XMLHttpRequest(); if (http_request.overrideMimeType) { http_request.overrideMimeType(content_type); // See note below about this line } } else if (window.ActiveXObject) { // IE try { http_request = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { http_request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} } } return http_request; } function str_repeat($symbol, $count) { var $i = 0; var $ret = ''; while($i < $count) { $ret += $symbol; $i++; } return $ret; } function getDocumentFromXML(xml) { if (window.ActiveXObject) { var doc = new ActiveXObject("Microsoft.XMLDOM"); doc.async=false; doc.loadXML(xml); } else { var parser = new DOMParser(); var doc = parser.parseFromString(xml,"text/xml"); } return doc; } function set_persistant_var($var_name, $var_value, $t, $form_action) { set_hidden_field('field', $var_name); set_hidden_field('value', $var_value); submit_event('u', 'OnSetPersistantVariable', $t, $form_action); } function setCookie($Name, $Value) { // set cookie if (getCookie($Name) != $Value) { document.cookie = $Name+'='+escape($Value); } } function getCookie($Name) { // get cookie var $cookieString = document.cookie; var $index = $cookieString.indexOf($Name+'='); if ($index == -1) { return null; } $index = $cookieString.indexOf('=',$index)+1; var $endstr = $cookieString.indexOf(';',$index); if($endstr == -1) $endstr = $cookieString.length; return unescape($cookieString.substring($index, $endstr)); } function deleteCookie($Name) { // deletes cookie if (getCookie($Name)) { var d = new Date(); document.cookie = $Name + '=;expires=' + d.toGMTString() + ';' + ';'; } } function addElement($dst_element, $tag_name) { var $new_element = document.createElement($tag_name.toUpperCase()); $dst_element.appendChild($new_element); return $new_element; } Math.sum = function($array) { var $i = 0; var $total = 0; while ($i < $array.length) { $total += $array[$i]; $i++; } return $total; } Math.average = function($array) { return Math.sum($array) / $array.length; } // remove spaces and underscores from a string, used for nls_menu function rs(str, is_phrase) { if (isset(is_phrase) && is_phrase) { str = RemoveTranslationLink(str, false); } return str.replace(/[ _\']+/g, '.'); } function getFrame($name) { var $main_window = window; // 1. cycle through popups to get main window try { // will be error, when other site is opened in parent window var $i = 0; var $opener; do { if ($i == 10) { break; } // get popup opener $opener = $main_window.opener; if (!$opener) { // when no opener found, then try parent window $opener = $main_window.parent; } if ($opener) { $main_window = $opener; } $i++; } while ($opener); } catch (err) { // catch Access/Permission Denied error // alert('getFrame.Error: [' + err.description + ']'); return window; } var $frameset = $main_window.parent.frames; for ($i = 0; $i < $frameset.length; $i++) { if ($frameset[$i].name == $name) { return $frameset[$i]; } } return $main_window.parent; } function ClearBrowserSelection() { if (window.getSelection) { // removeAllRanges will be supported by Opera from v 9+, do nothing by now var selection = window.getSelection(); if (selection.removeAllRanges) { // Mozilla & Opera 9+ // alert('clearing FF') window.getSelection().removeAllRanges(); } } else if (document.selection && !is.opera) { // IE // alert('clearing IE') document.selection.empty(); } } function reset_form(prefix, event, msg) { if (confirm(RemoveTranslationLink(msg, true))) { submit_event(prefix, event) } } function cancel_edit(prefix, cancel_ev, save_ev, msg) { if ((!Form || (Form && Form.HasChanged)) && confirm(RemoveTranslationLink(msg, true))) { submit_event(prefix, save_ev) } else { submit_event(prefix, cancel_ev) } } function execJS(node) { var bSaf = (navigator.userAgent.indexOf('Safari') != -1); var bOpera = (navigator.userAgent.indexOf('Opera') != -1); var bMoz = (navigator.appName == 'Netscape'); if (!node) return; /* IE wants it uppercase */ var st = node.getElementsByTagName('SCRIPT'); var strExec; for(var i=0;i<st.length; i++) { if (bSaf) { strExec = st[i].innerHTML; st[i].innerHTML = ""; } else if (bOpera) { strExec = st[i].text; st[i].text = ""; } else if (bMoz) { strExec = st[i].textContent; st[i].textContent = ""; } else { strExec = st[i].text; st[i].text = ""; } try { var x = document.createElement("script"); x.type = "text/javascript"; /* In IE we must use .text! */ if ((bSaf) || (bOpera) || (bMoz)) x.innerHTML = strExec; else x.text = strExec; document.getElementsByTagName("head")[0].appendChild(x); } catch(e) { alert(e); } } }; function NumberFormatter() {} NumberFormatter.ThousandsSep = '\''; NumberFormatter.DecimalSep = '.'; NumberFormatter.Parse = function(num) { if (num == '') return 0; return parseFloat( num.toString().replace(this.ThousandsSep, '').replace(this.DecimalSep, '.') ); } NumberFormatter.Format = function(num) { num += ''; x = num.split('.'); x1 = x[0]; x2 = x.length > 1 ? this.DecimalSep + x[1] : ''; var rgx = /(\d+)(\d{3})/; while (rgx.test(x1)) { x1 = x1.replace(rgx, '$1' + this.ThousandsSep + '$2'); } return x1 + x2; } function getDimensions(obj) { var style if (obj.currentStyle) { style = obj.currentStyle; } else { style = getComputedStyle(obj,''); } padding = [parseInt(style.paddingTop), parseInt(style.paddingRight), parseInt(style.paddingBottom), parseInt(style.paddingLeft)] border = [parseInt(style.borderTopWidth), parseInt(style.borderRightWidth), parseInt(style.borderBottomWidth), parseInt(style.borderLeftWidth)] for (var i = 0; i < padding.length; i++) if ( isNaN( padding[i] ) ) padding[i] = 0 for (var i = 0; i < border.length; i++) if ( isNaN( border[i] ) ) border[i] = 0 var result = new Object(); result.innerHeight = obj.clientHeight - padding[0] - padding[2]; result.innerWidth = obj.clientWidth - padding[1] - padding[3]; result.padding = padding; result.borders = border; result.outerHeight = obj.clientHeight + border[0] + border[2]; result.outerWidth = obj.clientHeight + border[1] + border[3]; return result; } function findPos(obj, with_scroll) { /*var $offset = $(obj).offset(); return [$offset.left, $offset.top];*/ if (!with_scroll) var with_scroll = false; var curleft = curtop = 0; if (obj.offsetParent) { curleft = obj.offsetLeft - (with_scroll ? obj.scrollLeft : 0) curtop = obj.offsetTop - (with_scroll ? obj.scrollTop : 0) while (obj = obj.offsetParent) { curleft += obj.offsetLeft - (with_scroll ? obj.scrollLeft : 0) curtop += obj.offsetTop - (with_scroll ? obj.scrollTop : 0) } } return [curleft,curtop]; } function scrollbarWidth() { // Scrollbalken im Body ausschalten var $overflow_backup = document.body.style.overflow; document.body.style.overflow = 'hidden'; var width = document.body.clientWidth; // Scrollbalken document.body.style.overflow = 'scroll'; width -= document.body.clientWidth; // Der IE im Standardmode if (!width) { width = document.body.offsetWidth - document.body.clientWidth; } // urspr?ngliche Einstellungen document.body.style.overflow = $overflow_backup; return width; } function maximizeElement($selector, $max_height) { if ($max_height === undefined) { $max_height = false; } var $element = $($selector); if ($element.length == 0) { return ; } $element.width('100%'); var $container_id = $element.attr('id') + '_container'; var $container = $( jq('#' + $container_id) ); if ($container.length == 0) { // don't create same container twice // all <script> tags will be executed again after wrap method is called, so remove them to prevent that $('script', $element).remove(); $element.wrap('<div id="' + $container_id + '" style="position: relative; overflow: auto; width: 100%;"></div>'); $container = $( jq('#' + $container_id) ); $(window).resize( function() { maximizeElement($selector, $max_height); } ); } var $offset_top = $container.offset().top; var $window_height = $(window).height(); var $height_left = $window_height - $offset_top; if (($max_height !== false) && ($max_height < $height_left)) { $height_left = $max_height; } $height_left -= ($element.outerHeight() - $element.height()); $container.height($height_left); var $element_width = $(window).width() - ($element.outerWidth() - $element.width()); if ( $height_left < $element.height() ) { // needs vertical scrolling, so substract vertical scrollbar width $element_width -= scrollbarWidth(); } $element.width($element_width); } function addEvent(el, evname, func, traditional) { if (traditional) { eval('el.on'+evname+'='+func); return; } if (evname.match(/mousedown|mousemove|mouseup/)) { $(el) .unbind(evname) // don't allow more then one .bind(evname, func); return ; } if (is.ie) { el.attachEvent("on" + evname, func); } else { el.addEventListener(evname, func, true); } }; /*function removeEvent(el, evname, func) { if (is.ie) { el.detachEvent('on' + evname, func); } else { el.removeEventListener(evname, func, true); } }*/ function addLoadEvent(func, wnd) { Application.setHook('m:OnAfterWindowLoad', func); } function replaceFireBug() { if (window.console === undefined || !console.firebug) { var names = [ 'log', 'debug', 'info', 'warn', 'error', 'assert', 'dir', 'dirxml', 'group', 'groupEnd', 'time', 'timeEnd', 'count', 'trace', 'profile', 'profileEnd' ]; if (window.top.console !== undefined || window.top.firebug) { // console is not defined in iframes, so define it here window.console = window.top.console; window._getFirebugConsoleElement = window.top._getFirebugConsoleElement; } else { window.console = {}; for (var i = 0; i < names.length; ++i) { window.console[names[i]] = function($msg) { alert('FireBug console object methods are not available outside Firefox!' + "\n" + $msg); } } } } } function runOnChange(elId) { var evt; var el = typeof(elId) == 'string' ? document.getElementById(elId) : elId if (document.createEvent) { evt = document.createEvent("HTMLEvents"); evt.initEvent("change", true, false); (evt) ? el.dispatchEvent(evt) : (el.onchange && el.onchange()); return; } if (el.fireEvent) { el.fireEvent('onchange'); } } function WatchClosing(win, $url) { window.setTimeout(function() { if (win.closed) { var req = Request.getRequest(); var $ajax_mark = ($url.indexOf('?') ? '&' : '?') + 'ajax=yes'; req.open('GET', $url + $ajax_mark, false); //!!!SYNCRONIOUS!!! REQUEST (3rd param = false!!!) req.send(null); } }, 2000 ) } function IterateUploaders($method) { if (typeof UploadsManager != 'undefined') { UploadsManager.iterate($method); } } String.prototype.trim = function () { return this.replace(/\s*((\S+\s*)*)/, "$1").replace(/((\s*\S+)*)\s*/, "$1"); } String.prototype.toNumeric = function () { return parseInt( this.replace(/(auto|medium)/, '0px').replace(/[a-z]/gi,'') ); } function jq($selector) { return $selector.replace(/(\[|\]|\.)/g, '\\$1'); } function setHelpLink($user_docs_url, $title_preset) { if (!$user_docs_url) { return ; } $('#help_link', getFrame('head').document).attr('href', $user_docs_url + '/' + $title_preset); } // window management functions: function getWindowOpener($window) { // use this intead of "window.opener" if (!$modal_windows) { return $window.opener; } if ($window.name == 'main' || $window.name == 'main_frame') { return null; } return getFrame('main').TB.findWindow($window.name, -1); } function window_close($close_callback) { // use this instead of "window.close();" if (!$modal_windows) { if ($.isFunction($close_callback)) { // use close callback, because iframe will be removed later in this method $close_callback(); } window.close(); return ; } if (window.name == 'main') { return ; } if ($close_callback !== undefined) { return getFrame('main').TB.remove(null, $close_callback); } return getFrame('main').TB.remove(); } Array.prototype.each = function($callback) { var $result = null; for (var $i = 0; $i < this.length; $i++) { $result = $callback.call(this[$i], $i); if ($result === false) { break; } } } \ No newline at end of file Index: branches/5.0.x/core/admin_templates/js/template_manager.js =================================================================== --- branches/5.0.x/core/admin_templates/js/template_manager.js (revision 12297) +++ branches/5.0.x/core/admin_templates/js/template_manager.js (revision 12298) @@ -1,200 +1,313 @@ function TemplateManager ($edit_url, $browse_url, $save_layout_url, $edting_mode) { this._editUrl = $edit_url; this.browseUrl = $browse_url; this._saveLayoutUrl = $save_layout_url; - this.editingMode = $edting_mode; // from 1 to 4 + this.editingMode = $edting_mode; // from {1 - browse, 2 - content, 3 - design} this._blocks = {}; - this._blockOrder = Array (); + this.inDrag = false; // don't process mouse over/out events while in drag mode var $template_manager = this; $(document).ready( function() { $template_manager.searchBlocks(); if (!$template_manager.editingMode) { return ; } - // show special toolbar when in any of 4 browse modes + // show special toolbar when in any of 3 browse modes var $head_frame = getFrame('head'); var $extra_toolbar = $head_frame.$('div.front-extra-toolbar').clone(); // clone to keep original untouched $('a', $extra_toolbar).each( function() { // cut from end, because IE7 adds base_href to beginning of href var $editing_mode = $(this).attr('href'); $editing_mode = $editing_mode.substr($editing_mode.length - 1, 1); $(this).attr('href', $template_manager.browseUrl.replace('#EDITING_MODE#', $editing_mode)); if ($editing_mode == $template_manager.editingMode) { $(this).parents('td:first').addClass('button-active').prevAll('td:first').addClass('button-active'); } } ); $head_frame.$('#extra_toolbar').html( $extra_toolbar.html() ); if ($template_manager.editingMode == 2) { - // Layout Mode + // Content Mode + + $('div.cms-edit-btn') + .mouseover( + function(e) { + $(this).css('opacity', 1); + } + ) + .mouseout( + function(e) { + $(this).css('opacity', 0.5); + } + ); + + // make all spans with phrases clickable + $template_manager.setupEditTranslationButtons(document); + } + + if ($template_manager.editingMode == 3) { + // Design Mode $template_manager.renumberMovableElements(); $('div.movable-area').sortable( { placeholder: 'move-helper', handle: '.movable-header', items: 'div.movable-element', connectWith: ['div.movable-area'], tolerance: 'pointer', start: function(e, ui) { + $template_manager.inDrag = true; ui.placeholder.height( ui.item.height() ); + }, + stop: function(e, ui) { + $template_manager.inDrag = false; + + // mouseout doesn't happen while in drag, so compensate it here + var $header = $('.movable-header', ui.item); + $('div.block-edit-block-btn-container', $header).mouseout(); + }, + change: function(e, ui) { + $('div.cms-layout-btn-container').show(); } } ); } + } + ); +} + +TemplateManager.prototype.setupEditTranslationButtons = function ($container) { + $("span[name='cms-translate-phrase']", $container).each( + function() { + var $me = $(this); + var $parent_link = $me.parents('a:first'); + + if ($parent_link.length == 0) { + // span in not inside "a" tag - $('div.cms-edit-btn') + $me.prepend('<div class="cms-edit-btn"><div class="cms-btn-text">Edit</div></div>'); + $('div.cms-edit-btn:first', $me).click(TemplateManager.prototype.translatePhrase); + $me.dblclick( + function ($e) { + $('div.cms-edit-btn:first', this).click(); + return false; + } + ); + + var $effect_element = $me; + } + else { + // span is inside "a" tag + var $clone = $me.clone(); + $clone.empty().attr('title', ''); + + $parent_link.html( $me.html() ).wrap($clone); + $parent_link.before('<div class="cms-edit-btn" title="' + $me.attr('title') + '"><div class="cms-btn-text">Edit</div></div>'); + $parent_link.prev('div.cms-edit-btn:first').click(TemplateManager.prototype.translatePhrase); + + var $effect_element = $parent_link.parents("span[name='cms-translate-phrase']:first"); + } + + $effect_element .mouseover( - function(e) { - $(this).css('opacity', 1); + function($e) { + $('div.cms-edit-btn', this).css('display', 'inline'); } ) .mouseout( - function(e) { - $(this).css('opacity', 0.5); + function($e) { + $('div.cms-edit-btn', this).hide(); } ); } ); } +TemplateManager.prototype.translatePhrase = function ($e) { + var $translate_url = $(this).parents("span[name='cms-translate-phrase']:first").attr('href'); + + if ($translate_url.match(/javascript:(.*)/)) { + eval(RegExp.$1); + } + else { + window.location.href = RegExp.$1; + } + + return false; +} + TemplateManager.prototype.renumberMovableElements = function () { var $area_index = 0; // 1. dynamically assign IDs to all movable elements $('div.movable-area').each( function() { var $element_index = 0; $('div.movable-element', this).each( function() { $(this).attr('id', 'target_order_a' + $area_index + 'e' + $element_index); $element_index++; } ); $area_index++; } ); } TemplateManager.prototype.saveLayout = function () { // prepare order string var $sort_order = []; $('div.movable-area').each( function($area_index) { var $order = $(this).sortable('serialize').replace(/target_order\[\]/g, 'target_order[' + $area_index + '][]'); if ($order) { $sort_order.push($order); } } ); $sort_order = $sort_order.join('&'); // save order string var $me = this; var $settings = { url: this._saveLayoutUrl + '&' + $sort_order + '&width=200&height=70&modal=true', caption: 'Layout Saving Result', onDataReceived: function ($data) { var $message = ''; if ($data == 'OK') { $message = 'New Layout Saved'; + $('div.cms-layout-btn-container').hide(); $me.renumberMovableElements(); } else { $message = 'Failed to Save New Layout'; } $data = '<div style="text-align: center;">' + $message + '<br/><br/><input type="button" class="button" value="OK" onclick="TB.remove();"/></div>'; return $data; } }; TB.setWindowTitle( window.top.document.title.replace(main_title + ' :: ', '') ); TB.show($settings); } +TemplateManager.prototype.cancelLayout = function () { + window.location.href = window.location.href; +} + TemplateManager.prototype.onBtnClick = function ($e, $element) { var $id = $element.id.replace(/_btn$/, ''); var $block_info = this._blocks[$id]; var $url = this._editUrl.replace('#BLOCK#', $block_info.block_name + ':' + $block_info.function_name).replace('#EVENT#', 'OnLoadBlock'); openSelector('theme-file', $url); $e.stopPropagation(); } TemplateManager.prototype.onMouseOver = function ($e, $element) { - $($element).addClass('block-edit-btn-container-over'); + if (this.inDrag) { + return ; + } + + $element = $($element); + + if ($element.hasClass('block-edit-design-btn-container')) { + $($element).addClass('block-edit-design-btn-container-over'); + $('div.cms-edit-design-btn:first', $element).show(); + } + else { + $($element).addClass('block-edit-block-btn-container-over'); + $('div.cms-edit-block-btn:first', $element).show(); + } + $e.stopPropagation(); } TemplateManager.prototype.onMouseOut = function ($e, $element) { - $($element).removeClass('block-edit-btn-container-over'); + if (this.inDrag) { + return ; + } + + $element = $($element); + + if ($element.hasClass('block-edit-design-btn-container')) { + $($element).removeClass('block-edit-design-btn-container-over'); + $('div.cms-edit-design-btn:first', $element).hide(); + } + else { + $($element).removeClass('block-edit-block-btn-container-over'); + $('div.cms-edit-block-btn:first', $element).hide(); + } + $e.stopPropagation(); } TemplateManager.prototype.searchBlocks = function () { $('div').each ( function () { var $id = $(this).attr('id'); if (!$id || $id.match(/parser_block\[.*\].*_btn$/) || !$id.match(/parser_block\[.*\]/)) { // skip other divs return true; } TemplateManager.prototype.registerBlock.call(aTemplateManager, this); } ); } TemplateManager.prototype.registerBlock = function ($element) { var $params = $element.getAttribute('params').split(':'); this._blocks[$element.id] = { block_name: $params[0], function_name: $params[1] }; var $btn = document.getElementById($element.id + '_btn'); - $($btn).bind( - 'click', + $($btn).click( function(ev) { TemplateManager.prototype.onBtnClick.call(aTemplateManager, ev, this); } ); - $($element).bind( - 'mouseover', + $($element) + .dblclick( + function(ev) { + TemplateManager.prototype.onBtnClick.call(aTemplateManager, ev, this); + } + ) + .mouseover( function(ev) { TemplateManager.prototype.onMouseOver.call(aTemplateManager, ev, this); } - ); - - $($element).bind( - 'mouseout', + ) + .mouseout( function(ev) { TemplateManager.prototype.onMouseOut.call(aTemplateManager, ev, this); } ); this._blockOrder.push($element.id); } \ No newline at end of file Index: branches/5.0.x/core/admin_templates/incs/cms.css =================================================================== --- branches/5.0.x/core/admin_templates/incs/cms.css (revision 12297) +++ branches/5.0.x/core/admin_templates/incs/cms.css (revision 12298) @@ -1,89 +1,156 @@ /* === Common styles for "Section Properties" and "Edit" buttons === */ div.cms-btn-image { float: left; height: 15px; vertical-align: middle; } div.cms-btn-text { margin-left: 3px; float: left; white-space: nowrap; vertical-align: middle; } div.cms-btn-content { padding: 5px; } -div.cms-section-properties-btn, div.cms-edit-btn, div.cms-save-layout-btn { +div.cms-section-properties-btn, div.cms-edit-btn, div.cms-edit-block-btn, div.cms-edit-design-btn { padding: 2px 5px; font-family: Arial, Verdana; font-size: 13px; font-weight: normal; width: auto; position: absolute; color: black; cursor: pointer; -moz-border-radius: 10px; margin-top: -10px; z-index: 99; } /* === Styles for "Section Properties" button === */ div.cms-section-properties-btn { float: right; position: relative; margin-right: -10px; border: 2px solid #A1D0A1; background-color: #CCFF00; } div.cms-section-properties-btn-container { border: 1px dashed #A1D0A1; margin: 10px; } /* === Styles for "Edit" button === */ div.cms-edit-btn-container { border: 1px dashed #FF6E00; } div.cms-edit-btn { margin-left: -10px; border: 2px solid #FF6E00; background-color: #FFCC00; opacity: 0.5; filter: alpha(opacity=50); } -/* === Styles for "Save Layout" button === */ -div.cms-save-layout-btn { - float: left; - position: absolute; +div.cms-edit-block-btn { + margin-left: -10px; + border: 2px solid #FF6E00; + background-color: #FFCC00; + display: none; +} +div.cms-edit-design-btn { + margin-left: -10px; + border: 2px solid #006E00; + background-color: #00CC00; + /*opacity: 0.5; + filter: alpha(opacity=50);*/ + display: none; +} + +/* === Styles for "Save" and "Cancel" buttons (for layout) === */ +div.cms-layout-btn-container { + position: absolute; + margin-top: -10px; margin-left: -10px; + display: none; + z-index: 99; +} + +div.cms-save-layout-btn, div.cms-cancel-layout-btn { + float: left; + padding: 2px 5px; + font-family: Arial, Verdana; + font-size: 13px; + font-weight: normal; + width: auto; + color: black; + cursor: pointer; + -moz-border-radius: 10px; +} + +div.cms-save-layout-btn { border: 2px solid #A1D0A1; background-color: #CCFF00; } +div.cms-cancel-layout-btn { + border: 2px solid #FF0000; + background-color: #FF6A5D; +} + +div.cms-cancel-layout-btn { + margin-left: 4px; +} + /* === Styles for Template Editor === */ -div.block-edit-btn-container { +div.block-edit-block-btn-container, div.block-edit-design-btn-container { border: 1px dashed transparent; } -div.block-edit-btn-container-over { +div.block-edit-block-btn-container-over { border-color: #FF6E00; } +div.block-edit-design-btn-container-over { + border-color: #006E00; +} + /* === Styles for element moving/sorting in theme === */ div.movable-area { min-height: 200px; } .move-helper { border: 3px dashed #666; /*width: auto !important;*/ +} + +/* === Styles for phrase translation links === */ +span[name='cms-translate-phrase'] { + text-decoration: none; + border: 1px dashed transparent; + padding: 3px; + +} + +span[name='cms-translate-phrase']:hover { + border-color: #FF6E00; +} + +span[name='cms-translate-phrase'] .cms-btn-text { + font-size: 9px; +} + +span[name='cms-translate-phrase'] .cms-edit-btn { + display: none; + opacity: 1; + filter: alpha(opacity=0); } \ No newline at end of file Index: branches/5.0.x/core/admin_templates/regional/phrases_edit.tpl =================================================================== --- branches/5.0.x/core/admin_templates/regional/phrases_edit.tpl (revision 12297) +++ branches/5.0.x/core/admin_templates/regional/phrases_edit.tpl (revision 12298) @@ -1,86 +1,108 @@ <inp2:adm_SetPopupSize width="888" height="415"/> - <inp2:m_include t="incs/header"/> <inp2:m_RenderElement name="combined_header" prefix="lang" section="in-portal:configure_lang" title_preset="phrase_edit"/> <!-- ToolBar --> <table class="toolbar" height="30" cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td> <script type="text/javascript"> a_toolbar = new ToolBar(); a_toolbar.AddButton( new ToolBarButton('select', '<inp2:m_phrase label="la_ToolTip_Save" escape="1"/>', function() { submit_event('phrases','<inp2:phrases_SaveEvent/>'); } ) ); - a_toolbar.AddButton( new ToolBarButton('cancel', '<inp2:m_phrase label="la_ToolTip_Cancel" escape="1"/>', function() { - submit_event('phrases','OnCancel'); + + a_toolbar.AddButton( + new ToolBarButton( + 'cancel', + '<inp2:m_phrase label="la_ToolTip_Cancel" escape="1"/>', + function() { + <inp2:m_if check="m_Get" name="simple_mode"> + window_close(); + <inp2:m_else/> + cancel_edit('phrases', 'OnCancelEdit', '<inp2:phrases_SaveEvent/>', '<inp2:m_Phrase label="la_FormCancelConfirmation" js_escape="1"/>'); + </inp2:m_if> } - ) ); + ) + ); a_toolbar.AddButton( new ToolBarButton('reset_edit', '<inp2:m_phrase label="la_ToolTip_Reset" escape="1"/>', function() { reset_form('phrases', 'OnReset', '<inp2:m_Phrase label="la_FormResetConfirmation" escape="1"/>'); } ) ); <inp2:m_if check="phrases_IsTopmostPrefix"> <inp2:m_if check="phrases_IsSingle" inverse="inverse"> a_toolbar.AddButton( new ToolBarSeparator('sep1') ); </inp2:m_if> a_toolbar.AddButton( new ToolBarButton('prev', '<inp2:m_phrase label="la_ToolTip_Prev" escape="1"/>', function() { go_to_id('phrases', '<inp2:phrases_PrevId/>'); } ) ); a_toolbar.AddButton( new ToolBarButton('next', '<inp2:m_phrase label="la_ToolTip_Next" escape="1"/>', function() { go_to_id('phrases', '<inp2:phrases_NextId/>'); } ) ); </inp2:m_if> a_toolbar.Render(); <inp2:m_RenderElement name="edit_navigation" prefix="phrases"/> </script> </td> </tr> </tbody> </table> <inp2:phrases_SaveWarning name="grid_save_warning"/> <inp2:phrases_ErrorWarning name="form_error_warning"/> +<input type="hidden" name="simple_mode" value="<inp2:m_Get name='simple_mode'/>"/> +<input type="hidden" id="phrases_label" name="phrases_label" value="<inp2:m_Get name='phrases_label'/>"/> + +<inp2:m_if check="phrases_ShowHiddenLanguage"> + <inp2:m_RenderElement name="inp_edit_hidden" prefix="phrases" field="LanguageId" db="db"/> +</inp2:m_if> + +<inp2:m_if check="m_Get" name="simple_mode"> + <inp2:m_RenderElement name="inp_edit_hidden" prefix="phrases" field="Phrase"/> +</inp2:m_if> + +<inp2:m_DefineElement name="phrase_element"> + <inp2:m_if check="m_Get" name="simple_mode"> + <inp2:m_RenderElement name="inp_label" prefix="phrases" field="PrimaryTranslation" title="!la_fld_PrimaryTranslation!"/> + <inp2:m_RenderElement name="inp_edit_textarea" prefix="phrases" field="Translation" title="!la_fld_Translation!" rows="7" cols="50" allow_html="0"/> + <inp2:m_else/> + <tr class="subsectiontitle"> + <td colspan="3"><inp2:phrases_Field name="Phrase"/></td> + </tr> + + <inp2:m_if check="m_Get" name="phrases_label"> + <inp2:m_RenderElement name="inp_edit_options" prefix="phrases" field="LanguageId" title="la_fld_LanguageId" has_empty="1"/> + </inp2:m_if> + + <inp2:m_RenderElement name="inp_label" prefix="phrases" field="PrimaryTranslation" title="!la_fld_PrimaryTranslation!"/> + <inp2:m_RenderElement name="inp_edit_box" prefix="phrases" field="Phrase" title="!la_fld_Phrase!" size="60"/> + <inp2:m_RenderElement name="inp_edit_textarea" prefix="phrases" field="Translation" title="!la_fld_Translation!" rows="7" cols="50" allow_html="0"/> + + <inp2:m_RenderElement name="inp_edit_radio" prefix="phrases" field="PhraseType" title="!la_fld_PhraseType!"/> + <inp2:m_RenderElement name="inp_edit_options" prefix="phrases" field="Module" title="!la_fld_Module!"/> + </inp2:m_if> +</inp2:m_DefineElement> + <div id="scroll_container"> <table class="edit-form"> - <input type="hidden" id="phrases_label" name="phrases_label" value="<inp2:m_get name="phrases_label"/>"> - <inp2:m_DefineElement name="phrase_element"> - <tr class="subsectiontitle"> - <td colspan="3"><inp2:phrases_Field name="Phrase"/></td> - </tr> - - <inp2:m_if check="m_Get" name="phrases_label"> - <inp2:m_RenderElement name="inp_edit_options" prefix="phrases" field="LanguageId" title="la_fld_LanguageId" has_empty="1"/> - <inp2:m_else/> - <inp2:m_RenderElement name="inp_edit_hidden" prefix="phrases" field="LanguageId"/> - </inp2:m_if> - - <inp2:m_RenderElement name="inp_label" prefix="phrases" field="PrimaryTranslation" title="!la_fld_PrimaryTranslation!"/> - <inp2:m_RenderElement name="inp_edit_box" prefix="phrases" field="Phrase" title="!la_fld_Phrase!" size="60"/> - <inp2:m_RenderElement name="inp_edit_textarea" prefix="phrases" field="Translation" title="!la_fld_Translation!" rows="7" cols="50" allow_html="0"/> - - <inp2:m_RenderElement name="inp_edit_radio" prefix="phrases" field="PhraseType" title="!la_fld_PhraseType!"/> - <inp2:m_RenderElement name="inp_edit_options" prefix="phrases" field="Module" title="!la_fld_Module!"/> - </inp2:m_DefineElement> - - <inp2:m_if check="m_GetEquals" name="phrases_label" value="ALEX, FIX IT!"> + <!--##<inp2:m_if check="m_GetEquals" name="phrases_label" value="ALEX, FIX IT!"> <inp2:phrases_MultipleEditing render_as="phrase_element"/> - <inp2:m_else/> + <inp2:m_else/>##--> <inp2:m_RenderElement name="phrase_element"/> - </inp2:m_if> + <!--##</inp2:m_if>##--> <inp2:m_RenderElement name="inp_edit_filler"/> </table> </div> <inp2:m_include t="incs/footer"/> \ No newline at end of file Index: branches/5.0.x/core/admin_templates/languages/phrase_edit.tpl =================================================================== --- branches/5.0.x/core/admin_templates/languages/phrase_edit.tpl (revision 12297) +++ branches/5.0.x/core/admin_templates/languages/phrase_edit.tpl (revision 12298) @@ -1,79 +1,108 @@ <inp2:adm_SetPopupSize width="888" height="415"/> <inp2:m_include t="incs/header"/> <inp2:m_RenderElement name="combined_header" section="in-portal:phrases" prefix="phrases" title_preset="phrase_edit_single"/> <!-- ToolBar --> <table class="toolbar" height="30" cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td> <script type="text/javascript"> a_toolbar = new ToolBar(); a_toolbar.AddButton( new ToolBarButton('select', '<inp2:m_phrase label="la_ToolTip_Save" escape="1"/>', function() { submit_event('phrases','<inp2:phrases_SaveEvent/>'); } ) ); - a_toolbar.AddButton( new ToolBarButton('cancel', '<inp2:m_phrase label="la_ToolTip_Cancel" escape="1"/>', function() { - cancel_edit('phrases','OnCancelEdit','<inp2:phrases_SaveEvent/>','<inp2:m_Phrase label="la_FormCancelConfirmation" escape="1"/>'); + + a_toolbar.AddButton( + new ToolBarButton( + 'cancel', + '<inp2:m_phrase label="la_ToolTip_Cancel" escape="1"/>', + function() { + <inp2:m_if check="m_Get" name="simple_mode"> + window_close(); + <inp2:m_else/> + cancel_edit('phrases', 'OnCancelEdit', '<inp2:phrases_SaveEvent/>', '<inp2:m_Phrase label="la_FormCancelConfirmation" js_escape="1"/>'); + </inp2:m_if> } - ) ); + ) + ); a_toolbar.AddButton( new ToolBarButton('reset_edit', '<inp2:m_phrase label="la_ToolTip_Reset" escape="1"/>', function() { reset_form('phrases', 'OnReset', '<inp2:m_Phrase label="la_FormResetConfirmation" escape="1"/>'); } ) ); <inp2:m_if check="phrases_IsTopmostPrefix"> <inp2:m_if check="phrases_IsSingle" inverse="inverse"> a_toolbar.AddButton( new ToolBarSeparator('sep1') ); </inp2:m_if> a_toolbar.AddButton( new ToolBarButton('prev', '<inp2:m_phrase label="la_ToolTip_Prev" escape="1"/>', function() { go_to_id('phrases', '<inp2:phrases_PrevId/>'); } ) ); a_toolbar.AddButton( new ToolBarButton('next', '<inp2:m_phrase label="la_ToolTip_Next" escape="1"/>', function() { go_to_id('phrases', '<inp2:phrases_NextId/>'); } ) ); </inp2:m_if> a_toolbar.Render(); <inp2:m_RenderElement name="edit_navigation" prefix="phrases"/> </script> </td> </tr> </tbody> </table> <inp2:phrases_SaveWarning name="grid_save_warning"/> <inp2:phrases_ErrorWarning name="form_error_warning"/> +<input type="hidden" name="simple_mode" value="<inp2:m_Get name='simple_mode'/>"/> +<input type="hidden" id="phrases_label" name="phrases_label" value="<inp2:m_Get name='phrases_label'/>"/> + +<inp2:m_if check="phrases_ShowHiddenLanguage"> + <inp2:m_RenderElement name="inp_edit_hidden" prefix="phrases" field="LanguageId" db="db"/> +</inp2:m_if> + +<inp2:m_if check="m_Get" name="simple_mode"> + <inp2:m_RenderElement name="inp_edit_hidden" prefix="phrases" field="Phrase"/> +</inp2:m_if> + +<inp2:m_DefineElement name="phrase_element"> + <inp2:m_if check="m_Get" name="simple_mode"> + <inp2:m_RenderElement name="inp_label" prefix="phrases" field="PrimaryTranslation" title="!la_fld_PrimaryTranslation!"/> + <inp2:m_RenderElement name="inp_edit_textarea" prefix="phrases" field="Translation" title="!la_fld_Translation!" rows="7" cols="50" allow_html="0"/> + <inp2:m_else/> + <tr class="subsectiontitle"> + <td colspan="3"><inp2:phrases_Field name="Phrase"/></td> + </tr> + + <inp2:m_if check="m_Get" name="phrases_label"> + <inp2:m_RenderElement name="inp_edit_options" prefix="phrases" field="LanguageId" title="la_fld_LanguageId" has_empty="1"/> + </inp2:m_if> + + <inp2:m_RenderElement name="inp_label" prefix="phrases" field="PrimaryTranslation" title="!la_fld_PrimaryTranslation!"/> + <inp2:m_RenderElement name="inp_edit_box" prefix="phrases" field="Phrase" title="!la_fld_Phrase!" size="60"/> + <inp2:m_RenderElement name="inp_edit_textarea" prefix="phrases" field="Translation" title="!la_fld_Translation!" rows="7" cols="50" allow_html="0"/> + + <inp2:m_RenderElement name="inp_edit_radio" prefix="phrases" field="PhraseType" title="!la_fld_PhraseType!"/> + <inp2:m_RenderElement name="inp_edit_options" prefix="phrases" field="Module" title="!la_fld_Module!"/> + </inp2:m_if> +</inp2:m_DefineElement> + <div id="scroll_container"> <table class="edit-form"> - <input type="hidden" id="phrases_label" name="phrases_label" value="<inp2:m_get name="phrases_label"/>"> - <inp2:m_DefineElement name="phrase_element"> - <tr class="subsectiontitle"> - <td colspan="4"><inp2:phrases_Field name="Phrase"/></td> - </tr> - - <inp2:m_RenderElement name="inp_edit_hidden" prefix="phrases" field="LanguageId"/> - <inp2:m_RenderElement name="inp_label" prefix="phrases" field="PrimaryTranslation" title="!la_fld_PrimaryTranslation!"/> - <inp2:m_RenderElement name="inp_edit_box" prefix="phrases" field="Phrase" title="!la_fld_Phrase!" size="60"/> - <inp2:m_RenderElement name="inp_edit_textarea" prefix="phrases" field="Translation" title="!la_fld_Translation!" rows="7" cols="50" allow_html="0"/> - - <inp2:m_RenderElement name="inp_edit_radio" prefix="phrases" field="PhraseType" title="!la_fld_PhraseType!"/> - <inp2:m_RenderElement name="inp_edit_options" prefix="phrases" field="Module" title="!la_fld_Module!"/> - </inp2:m_DefineElement> - - <inp2:m_if check="m_GetEquals" name="phrases_label" value="ALEX, FIX IT!"> + <!--##<inp2:m_if check="m_GetEquals" name="phrases_label" value="ALEX, FIX IT!"> <inp2:phrases_MultipleEditing render_as="phrase_element"/> - <inp2:m_else/> + <inp2:m_else/>##--> <inp2:m_RenderElement name="phrase_element"/> - </inp2:m_if> + <!--##</inp2:m_if>##--> <inp2:m_RenderElement name="inp_edit_filler"/> </table> </div> + <inp2:m_include t="incs/footer"/> \ No newline at end of file