BxBaseFunctions.php 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup UnaBaseView UNA Base Representation Classes
  7. * @{
  8. */
  9. class BxBaseFunctions extends BxDolFactory implements iBxDolSingleton
  10. {
  11. protected $_oTemplate;
  12. protected $_sDesignBoxMenuTmplDefault;
  13. protected $_sDesignBoxMenuIcon;
  14. protected $_sDesignBoxMenuIconType;
  15. protected $_sDesignBoxMenuClick;
  16. protected function __construct($oTemplate)
  17. {
  18. parent::__construct();
  19. $this->_oTemplate = $oTemplate ? $oTemplate : BxDolTemplate::getInstance();
  20. $this->_sDesignBoxMenuTmplDefault = 'menu_block_submenu_ver.html';
  21. $this->_sDesignBoxMenuIcon = 'ellipsis-v';
  22. $this->_sDesignBoxMenuIconType = 'icon';
  23. $this->_sDesignBoxMenuClick = "bx_menu_popup_inline('#{design_box_menu}', this, " . json_encode(array(
  24. 'moveToDocRoot' => false
  25. )) . ")";
  26. }
  27. /**
  28. * Prevent cloning the instance
  29. */
  30. public function __clone()
  31. {
  32. if (isset($GLOBALS['bxDolClasses'][get_class($this)]))
  33. trigger_error('Clone is not allowed for the class: ' . get_class($this), E_USER_ERROR);
  34. }
  35. public static function getInstanceWithTemplate($oTemplate)
  36. {
  37. $sClassName = 'BxTemplFunctions';
  38. if ($oTemplate){
  39. $sClassName .= get_class($oTemplate);
  40. }
  41. if(!isset($GLOBALS['bxDolClasses'][$sClassName]))
  42. $GLOBALS['bxDolClasses'][$sClassName] = new BxTemplFunctions($oTemplate);
  43. return $GLOBALS['bxDolClasses'][$sClassName];
  44. }
  45. public static function getInstance()
  46. {
  47. return self::getInstanceWithTemplate(null);
  48. }
  49. function TemplPageAddComponent($sKey)
  50. {
  51. $mixedResult = false; // if you have not such component, return false!
  52. switch($sKey) {
  53. case 'sys_header_width':
  54. $mixedResult = 'bx-def-page-width';
  55. break;
  56. }
  57. return $mixedResult;
  58. }
  59. function msgBox($sText, $iTimer = 0, $sOnClose = "")
  60. {
  61. $iId = time() . mt_rand(1, 1000);
  62. if($iTimer > 0)
  63. BxDolTemplate::getInstance()->addJs(array('jquery.anim.js'));
  64. return $this->_oTemplate->parseHtmlByName('messageBox.html', array(
  65. 'id' => $iId,
  66. 'msgText' => $sText,
  67. 'bx_if:timer' => array(
  68. 'condition' => $iTimer > 0,
  69. 'content' => array(
  70. 'id' => $iId,
  71. 'time' => 1000 * $iTimer,
  72. 'on_close' => $sOnClose,
  73. )
  74. )
  75. ));
  76. }
  77. /**
  78. * Get standard popup box with title.
  79. *
  80. * @param string $sName - unique name
  81. * @param string $sTitle - translated title
  82. * @param string $sContent - content of the box
  83. * @return HTML string
  84. */
  85. function popupBox($sName, $sTitle, $sContent, $isHiddenByDefault = false)
  86. {
  87. $iId = !empty($sName) ? $sName : time();
  88. return $this->_oTemplate->parseHtmlByName('popup_box.html', array(
  89. 'id' => $iId,
  90. 'wrapper_style' => $isHiddenByDefault ? 'display:none;' : '',
  91. 'title' => $sTitle,
  92. 'content' => $sContent
  93. ));
  94. }
  95. /**
  96. * Get popup box without title.
  97. *
  98. * @param string $sName - unique name
  99. * @param string $sContent - content of the box
  100. * @return HTML string
  101. */
  102. function transBox($sName, $sContent, $isHiddenByDefault = false, $isPlaceInCenter = false)
  103. {
  104. return $this->simpleBox($sName, $sContent, $isHiddenByDefault, $isPlaceInCenter, 'popup_trans.html');
  105. }
  106. function slideBox($sName, $sContent, $isHiddenByDefault = false)
  107. {
  108. return $this->simpleBox($sName, $sContent, $isHiddenByDefault, false, 'popup_slide.html');
  109. }
  110. function inlineBox($sName, $sContent, $isHiddenByDefault = false)
  111. {
  112. return $this->simpleBox($sName, $sContent, $isHiddenByDefault, false, 'popup_inline.html');
  113. }
  114. protected function simpleBox($sName, $sContent, $isHiddenByDefault, $isPlaceInCenter, $sTemplate)
  115. {
  116. $iId = !empty($sName) ? $sName : time();
  117. if(!is_array($sContent))
  118. $sContent = array('content' => $sContent);
  119. $sContent = $this->_oTemplate->parseHtmlByName($sTemplate, array_merge(array(
  120. 'id' => $iId,
  121. 'wrapper_class' => '',
  122. 'wrapper_style' => $isHiddenByDefault ? 'display:none;' : '',
  123. 'content' => ''
  124. ), $sContent));
  125. if($isPlaceInCenter)
  126. $sContent = '<div class="login_ajax_wrap">' . $sContent . '</div>';
  127. return $sContent;
  128. }
  129. function simpleBoxContent($sContent, $bWithIndent = true)
  130. {
  131. if(!$bWithIndent)
  132. return $sContent;
  133. return $this->_oTemplate->parseHtmlByName('popup_content_indent.html', array(
  134. 'content' => $sContent
  135. ));
  136. }
  137. function getIcon($sCode, $aAttrs = array())
  138. {
  139. $sIconFont = false;
  140. $sIconA = false;
  141. $sIconUrl = false;
  142. $sIconHtml = false;
  143. $sIconFontWithHtml = false;
  144. $sClass = '';
  145. if(!empty($aAttrs['class'])) {
  146. $sClass = ' ' . $aAttrs['class'] .' ';
  147. unset($aAttrs['class']);
  148. }
  149. $sAttrs = '';
  150. foreach($aAttrs as $sKey => $sValue)
  151. $sAttrs .= ' ' . $sKey . '="' . bx_html_attribute($sValue) . '"';
  152. if (!empty($sCode)) {
  153. if (is_numeric($sCode) && (int)$sCode > 0) {
  154. $oStorage = BxDolStorage::getObjectInstance(BX_DOL_STORAGE_OBJ_IMAGES);
  155. $sIconUrl = $oStorage ? $oStorage->getFileUrlById((int)$sCode) : false;
  156. }
  157. else {
  158. //--- Process Inline SVG
  159. if (strpos($sCode, '&lt;svg') !== false || strpos($sCode, '<svg') !== false) {
  160. if(strpos($sCode, '&lt;svg') !== false)
  161. $sIconHtml = htmlspecialchars_decode($sCode);
  162. else
  163. $sIconHtml = $sCode;
  164. $sClass .= 'sys-icon sys-icon-svg ';
  165. $sIconHtmlClear = strip_tags($sIconHtml, '<svg>');
  166. if ($sClass != '' && strpos($sIconHtmlClear, 'class="') !== false)
  167. $sIconHtml = str_replace('class="', 'class="' . $sClass, $sIconHtml);
  168. else
  169. $sIconHtml = str_replace('<svg', '<svg class="' . $sClass . '" ', $sIconHtml);
  170. if ($sAttrs != '')
  171. $sIconHtml = str_replace('<svg', '<svg ' . $sAttrs . ' ', $sIconHtml);
  172. }
  173. else {
  174. $sEmojIsRegex =
  175. '/[\x{0080}-\x{02AF}'
  176. .'\x{0300}-\x{03FF}'
  177. .'\x{0600}-\x{06FF}'
  178. .'\x{0C00}-\x{0C7F}'
  179. .'\x{1DC0}-\x{1DFF}'
  180. .'\x{1E00}-\x{1EFF}'
  181. .'\x{2000}-\x{209F}'
  182. .'\x{20D0}-\x{214F}'
  183. .'\x{2190}-\x{23FF}'
  184. .'\x{2460}-\x{25FF}'
  185. .'\x{2600}-\x{27EF}'
  186. .'\x{2900}-\x{29FF}'
  187. .'\x{2B00}-\x{2BFF}'
  188. .'\x{2C60}-\x{2C7F}'
  189. .'\x{2E00}-\x{2E7F}'
  190. .'\x{3000}-\x{303F}'
  191. .'\x{A490}-\x{A4CF}'
  192. .'\x{E000}-\x{F8FF}'
  193. .'\x{FE00}-\x{FE0F}'
  194. .'\x{FE30}-\x{FE4F}'
  195. .'\x{1F000}-\x{1F02F}'
  196. .'\x{1F0A0}-\x{1F0FF}'
  197. .'\x{1F100}-\x{1F64F}'
  198. .'\x{1F680}-\x{1F6FF}'
  199. .'\x{1F910}-\x{1F96B}'
  200. .'\x{1F980}-\x{1F9E0}]/u';
  201. //--- Process Emoji
  202. if(preg_match($sEmojIsRegex, $sCode, $aTmp))
  203. $sIconHtml = $this->_oTemplate->parseHtmlByName('icon_emoji.html', array(
  204. 'icon' => $sCode,
  205. 'class' => $sClass,
  206. 'attrs' => $sAttrs
  207. ));
  208. else {
  209. if (strpos($sCode, '.') === false) {
  210. //--- Process animated icon
  211. if (strncmp($sCode, 'a:', 2) === 0)
  212. $sIconA = substr($sCode, 2);
  213. //--- Process font icons
  214. else {
  215. $sIconFont = $sCode;
  216. $sIconFontWithHtml = $this->getFontIconAsHtml($sIconFont, $sClass, $sAttrs);
  217. }
  218. }
  219. else {
  220. //--- Process common image
  221. if((!preg_match('/^https?:\/\//', $sCode)))
  222. $sIconUrl = $this->_oTemplate->getIconUrl($sCode);
  223. else
  224. $sIconUrl = $sCode;
  225. }
  226. }
  227. }
  228. }
  229. }
  230. return array ($sIconFont, $sIconUrl, $sIconA, $sIconHtml, $sIconFontWithHtml);
  231. }
  232. function getFontIconAsHtml($sIconFont, $sClass = '', $sAttrs = '')
  233. {
  234. return '<i class="sys-icon ' . $sIconFont .' ' . $sClass . '"' . $sAttrs . '></i>';
  235. }
  236. function getIconAsHtml($sCode, $aAttrs = array())
  237. {
  238. $aIcons = $this->getIcon($sCode, $aAttrs);
  239. return $aIcons[3] . $aIcons[4];
  240. }
  241. function getTemplateIcon($sName)
  242. {
  243. $sUrl = $this->_oTemplate->getIconUrl($sName);
  244. return !empty($sUrl) ? $sUrl : $this->_oTemplate->getIconUrl('spacer.gif');
  245. }
  246. function getTemplateImage($sName)
  247. {
  248. $sUrl = $this->_oTemplate->getImageUrl($sName);
  249. return !empty($sUrl) ? $sUrl : $this->_oTemplate->getImageUrl('spacer.gif');
  250. }
  251. function sysIcon ($sIcon, $sName, $sUrl = '', $iWidth = 0)
  252. {
  253. return '<div class="sys_icon">' . ($sUrl ? '<a title="'.$sName.'" href="'.$sUrl.'">' : '') . '<img alt="'.$sName.'" src="'.$sIcon.'" '.($iWidth ? 'width='.$iWidth : '').' />' . ($sUrl ? '</a>' : '') . '</div>';
  254. }
  255. /**
  256. * functions for limiting maximal string length
  257. */
  258. function getStringWithLimitedLength($sString, $iWidth = 45, $isPopupOnOverflow = false, $bReturnString = true)
  259. {
  260. if (empty($sString) || mb_strlen($sString, 'UTF-8') <= $iWidth)
  261. return $bReturnString ? $sString : array($sString);
  262. $sResult = '';
  263. $aWords = mb_split("[\s\r\n]", $sString);
  264. $iPosition = 0;
  265. $iWidthReal = $iWidth - 3;
  266. $iWidthMin = $iWidth - 15;
  267. foreach($aWords as $sWord) {
  268. $sWord = trim($sWord);
  269. $iWord = mb_strlen($sWord, 'UTF-8');
  270. if ($iPosition + $iWord > $iWidthReal)
  271. break;
  272. // add word and continue
  273. $sResult .= ' ' . $sWord;
  274. $iPosition += 1 + $iWord;
  275. }
  276. // last word is too long, cut it
  277. if(!$iPosition || $iPosition < $iWidthMin)
  278. $sResult .= ' ' . mb_substr($sWord, 0, $iWidthReal - $iPosition - $iWord, 'UTF-8');
  279. $sResult = trim($sResult);
  280. // add tripple dot
  281. if(!$isPopupOnOverflow) {
  282. $sResult .= '...';
  283. return $bReturnString ? $sResult : array($sResult);
  284. }
  285. // add button width popup
  286. $sId = 'bx-str-limit-' . rand(1, PHP_INT_MAX);
  287. $sPopup = '<span class="bx-str-limit" onclick="$(\'#' . $sId . '\').dolPopup({pointer:{el:$(this), offset:\'10 1\'}})"/><i class="sys-icon ellipsis-h"></i></span>';
  288. $sPopup .= '<div id="' . $sId . '" style="display:none;">' . BxTemplFunctions::getInstance()->transBox('', '<div class="bx-def-padding bx-def-color-bg-block">'.$sString.'</div>') . '</div>';
  289. return $bReturnString ? $sResult . $sPopup : array($sResult, $sPopup);
  290. }
  291. /**
  292. * Display design box with specified title, template, content and menu.
  293. * @param $sTitle - design box title, please note that some templates don't use title.
  294. * @param $sContent - design box content.
  295. * @param $iTemplateNum - number of design box template, use predefined contants only, default is BX_DB_DEF.
  296. * @param $mixedMenu - design box menu, it can be:
  297. * - object: instance of BxTemplMenu class
  298. * - string: menu object identifier
  299. * - array: array of menu links to create menu from
  300. * @param $mixedButtons - design box menu representation, it can be:
  301. * - false: design box menu will be used as horizontal menu (tabs)
  302. * - array: array of menu links to create menu from. If empty array is used and 'design box menu' isn't empty, then 'design box menu' will be added as one of menu items automatically. If non-empty array is used and 'design box menu' isn't empty then it should be added as one of menu items. Use array('menu' => 1) to define menu item for 'design box menu'.
  303. * @return string
  304. *
  305. * @see BX_DB_CONTENT_ONLY
  306. * @see BX_DB_DEF
  307. * @see BX_DB_EMPTY
  308. * @see BX_DB_NO_CAPTION
  309. * @see BX_DB_PADDING_CONTENT_ONLY
  310. * @see BX_DB_PADDING_DEF
  311. * @see BX_DB_PADDING_NO_CAPTION
  312. */
  313. function designBoxContent ($sTitle, $sContent, $iTemplateNum = BX_DB_DEF, $mixedMenu = false, $mixedButtons = array())
  314. {
  315. return $this->_oTemplate->parseHtmlByName('designbox_' . (int)$iTemplateNum . '.html', array(
  316. 'title' => $sTitle,
  317. 'designbox_content' => $sContent,
  318. 'caption_item' => $this->designBoxMenu($mixedMenu, $mixedButtons),
  319. ));
  320. }
  321. function designBoxMenu ($mixedMenu, $mixedButtons = array())
  322. {
  323. $bUseTabs = is_bool($mixedButtons) && $mixedButtons === true;
  324. $sClass = $sMenu = '';
  325. if(!empty($mixedMenu)) {
  326. if(is_string($mixedMenu)) {
  327. if(($oMenu = BxTemplMenu::getObjectInstance($mixedMenu)) !== false) {
  328. $oMenu->setTemplateById($bUseTabs ? BX_DB_MENU_TEMPLATE_TABS : BX_DB_MENU_TEMPLATE_POPUP);
  329. $sMenu = $oMenu->getCode();
  330. }
  331. else
  332. $sMenu = $mixedMenu;
  333. }
  334. else if(is_array($mixedMenu)) {
  335. if(isset($mixedMenu['template']) && isset($mixedMenu['menu_items']))
  336. $aMenu = $mixedMenu;
  337. else
  338. $aMenu = array('template' => $this->_sDesignBoxMenuTmplDefault, 'menu_items' => $mixedMenu);
  339. if(($oMenu = new BxTemplMenu($aMenu, $this->_oTemplate)) !== false) {
  340. $oMenu->setTemplateById($bUseTabs ? BX_DB_MENU_TEMPLATE_TABS : BX_DB_MENU_TEMPLATE_POPUP);
  341. $sMenu = $oMenu->getCode();
  342. }
  343. else
  344. $sMenu = '';
  345. }
  346. else if(is_object($mixedMenu) && is_a($mixedMenu, 'BxTemplMenu')) {
  347. $mixedMenu->setTemplateById($bUseTabs ? BX_DB_MENU_TEMPLATE_TABS : BX_DB_MENU_TEMPLATE_POPUP);
  348. if(($mixedMenu instanceof BxBaseMenuMoreAuto) && $mixedMenu->isMoreAuto())
  349. $sClass = ' bx-db-menu-tab-more-auto';
  350. $sMenu = $mixedMenu->getCode();
  351. }
  352. }
  353. $bMenu = !empty($sMenu);
  354. $sResult = '';
  355. if($bUseTabs && $bMenu)
  356. $sResult = $sMenu;
  357. else if(is_array($mixedButtons)) {
  358. $sPopup = '';
  359. if($bMenu) {
  360. $aButton = array();
  361. if(empty($mixedButtons))
  362. list($aButton, $sPopup) = $this->_designBoxMenuButton($sMenu);
  363. //--- For backward compatibility
  364. else if(!empty($mixedButtons['menu']) && is_array($mixedButtons['menu'])) {
  365. list($aButton, $sPopup) = $this->_designBoxMenuButton($sMenu, $mixedButtons['menu']);
  366. unset($mixedButtons['menu']);
  367. }
  368. if(!empty($aButton))
  369. $mixedButtons[] = $aButton;
  370. }
  371. foreach($mixedButtons as $aButton) {
  372. if($bMenu && isset($aButton['menu'])) {
  373. if(is_numeric($aButton['menu']) && (int)$aButton['menu'] == 1)
  374. list($aButton, $sPopup) = $this->_designBoxMenuButton($sMenu);
  375. else if(is_array($aButton['menu']))
  376. list($aButton, $sPopup) = $this->_designBoxMenuButton($sMenu, $aButton['menu']);
  377. if(isset($aButton['menu']))
  378. continue;
  379. }
  380. $aAttrs = array();
  381. if(!empty($aButton['onclick']))
  382. $aAttrs['onclick'] = $aButton['onclick'];
  383. $aAttrs['class'] = 'bx-btn bx-btn-small';
  384. if(!empty($aButton['class']))
  385. $aAttrs['class'] .= ' ' . trim($aButton['class']);
  386. $bTmplVarsButtonIcon = !empty($aButton['icon']);
  387. $aTmplVarsButtonIcon = !$bTmplVarsButtonIcon ? array() : array(
  388. 'icon' => $aButton['icon']
  389. );
  390. $bTmplVarsButtonIconA = !empty($aButton['icon-a']);
  391. $aTmplVarsButtonIconA = !$bTmplVarsButtonIconA ? array() : array(
  392. 'icon_a' => $aButton['icon-a']
  393. );
  394. $bTmplVarsButtonTitle = !empty($aButton['title']);
  395. $aTmplVarsButtonTitle = !$bTmplVarsButtonTitle ? array() : array(
  396. 'title' => $aButton['title']
  397. );
  398. $sResult .= $this->_oTemplate->parseHtmlByName('designbox_menu_button.html', array(
  399. 'attrs' => bx_convert_array2attrs($aAttrs),
  400. 'bx_if:show_icon' => array(
  401. 'condition' => $bTmplVarsButtonIcon,
  402. 'content' => $aTmplVarsButtonIcon
  403. ),
  404. 'bx_if:show_icon_a' => array(
  405. 'condition' => $bTmplVarsButtonIconA,
  406. 'content' => $aTmplVarsButtonIconA
  407. ),
  408. 'bx_if:show_title' => array(
  409. 'condition' => $bTmplVarsButtonTitle,
  410. 'content' => $aTmplVarsButtonTitle
  411. )
  412. ));
  413. }
  414. $sResult .= $sPopup;
  415. }
  416. if(!empty($sResult))
  417. $sResult = $this->_oTemplate->parseHtmlByName('designbox_menu.html', array(
  418. 'class' => $sClass,
  419. 'content' => $sResult
  420. ));
  421. return $sResult;
  422. }
  423. protected function _designBoxMenuId ()
  424. {
  425. return 'bx-menu-db-' . time() . rand(0, PHP_INT_MAX);
  426. }
  427. protected function _designBoxMenuButton ($sMenu, $aParams = array())
  428. {
  429. $sId = $this->_designBoxMenuId();
  430. $aButton = array($this->_sDesignBoxMenuIconType => $this->_sDesignBoxMenuIcon, 'onclick' => $this->_sDesignBoxMenuClick);
  431. if(!empty($aParams)) {
  432. if(!empty($aParams['id']))
  433. $sId = $aParams['id'];
  434. $aButton = array_merge($aButton, $aParams);
  435. }
  436. $aButton['onclick'] = bx_replace_markers($aButton['onclick'], array(
  437. 'design_box_menu' => $sId
  438. ));
  439. $sMenu = $this->_oTemplate->parseHtmlByName('designbox_menu_popup.html', array(
  440. 'content' => $sMenu
  441. ));
  442. return array($aButton, $this->transBox($sId, $sMenu, true));
  443. }
  444. /**
  445. * Get logo URL.
  446. * @return string
  447. */
  448. function getMainLogoUrl()
  449. {
  450. return BxDolDesigns::getInstance()->getSiteLogoUrl();
  451. }
  452. /**
  453. * Get mark URL.
  454. * @return string
  455. */
  456. function getMainMarkUrl()
  457. {
  458. return BxDolDesigns::getInstance()->getSiteMarkUrl();
  459. }
  460. /**
  461. * Get logo HTML.
  462. * @return string
  463. */
  464. function getMainLogo($aParams = array())
  465. {
  466. $oDesigns = BxDolDesigns::getInstance();
  467. $sAlt = $oDesigns->getSiteLogoAlt();
  468. if(empty($sAlt))
  469. $sAlt = getParam('site_title');
  470. $sLogo = '<span>' . $sAlt . '</span>';
  471. if(($mixedFileUrl = $this->getMainLogoUrl()) && !empty($mixedFileUrl)) {
  472. if(!is_array($mixedFileUrl))
  473. $mixedFileUrl = ['light' => $mixedFileUrl];
  474. foreach($mixedFileUrl as $sName => $sFileUrl) {
  475. $iLogoWidth = (int)$oDesigns->getSiteLogoWidth();
  476. $sWidth = $iLogoWidth > 0 ? 'width:' . round($iLogoWidth/16, 3) . 'rem;' : '';
  477. $iLogoHeight = (int)$oDesigns->getSiteLogoHeight();
  478. $sHeight = $iLogoHeight > 0 ? 'height:' . round($iLogoHeight/16, 3) . 'rem;' : '';
  479. $sLogo = '<img style="' . $sWidth . ' ' . $sHeight . '" src="' . $sFileUrl . '" id="bx-logo" alt="' . bx_html_attribute($sAlt, BX_ESCAPE_STR_QUOTE) . '" />';
  480. }
  481. }
  482. $aAttrs = array(
  483. 'class' => 'bx-def-font-contrasted',
  484. 'href' => BX_DOL_URL_ROOT,
  485. 'title' => bx_html_attribute($sAlt, BX_ESCAPE_STR_QUOTE)
  486. );
  487. if(!empty($aParams['attrs']) && is_array($aParams['attrs']))
  488. $aAttrs = array_merge($aAttrs, $aParams['attrs']);
  489. return '<a' . bx_convert_array2attrs($aAttrs) . '>' . $sLogo . '</a>';
  490. }
  491. /**
  492. * Get HTML code for manifests.
  493. * @return HTML string to insert into HEAD section
  494. */
  495. function getManifests()
  496. {
  497. return '<link rel="manifest" href="' . BX_DOL_URL_ROOT . 'manifest.json.php" crossorigin="use-credentials" />';
  498. }
  499. /**
  500. * Get HTML code for meta icons.
  501. * @return HTML string to insert into HEAD section
  502. */
  503. function getMetaIcons()
  504. {
  505. // favicon icon
  506. $sImageUrlFav = '';
  507. if(($iId = (int)getParam('sys_site_icon')) != 0)
  508. $sImageUrlFav = BxDolStorage::getObjectInstance(BX_DOL_STORAGE_OBJ_FILES)->getFileUrlById($iId);
  509. // svg icon
  510. $sImageUrlSvg = '';
  511. if(($iId = (int)getParam('sys_site_icon_svg')) != 0)
  512. $sImageUrlSvg = BxDolStorage::getObjectInstance(BX_DOL_STORAGE_OBJ_IMAGES)->getFileUrlById($iId);
  513. if(empty($sImageUrlFav) && empty($sImageUrlSvg))
  514. $sImageUrlFav = $sImageUrlSvg = $this->_oTemplate->getIconUrl('favicon.svg');
  515. // apple device icon
  516. $sImageUrlApl = '';
  517. if(($iId = (int)getParam('sys_site_icon_apple')) != 0)
  518. $sImageUrlApl = BxDolTranscoderImage::getObjectInstance(BX_DOL_TRANSCODER_OBJ_ICON_APPLE)->getFileUrl($iId);
  519. if(empty($sImageUrlApl))
  520. $sImageUrlApl = $this->_oTemplate->getIconUrl('apple-touch-icon.png');
  521. /*
  522. * TODO:
  523. * 1. Remove commented code later if it won't be used.
  524. * 2. Remove 'sys_icon_favicon' and 'sys_icon_facebook' transcoders and related transcoder filters.
  525. *
  526. // facebook icon
  527. $sImageUrlFcb = '';
  528. $oTranscoder = BxDolTranscoderImage::getObjectInstance(BX_DOL_TRANSCODER_OBJ_ICON_FACEBOOK);
  529. $sImageUrlFcb = $oTranscoder->getFileUrl($iId);
  530. if(empty($sImageUrlFcb))
  531. $sImageUrlFcb = $this->_oTemplate->getIconUrl('facebook-icon.png');
  532. */
  533. $sRet = '';
  534. if($sImageUrlFav)
  535. $sRet .= '<link rel="icon" href="' . $sImageUrlFav . '" sizes="any" />';
  536. if($sImageUrlFav)
  537. $sRet .= '<link rel="icon" href="' . $sImageUrlSvg . '" type="image/svg+xml" />';
  538. $sRet .= '<link rel="apple-touch-icon" href="' . $sImageUrlApl . '" />';
  539. /*
  540. $sRet .= '<link rel="image_src" sizes="100x100" href="' . $sImageUrlFcb . '" />';
  541. */
  542. return $sRet;
  543. }
  544. function getInjectionHead()
  545. {
  546. return $this->getInjection('getInjHead');
  547. }
  548. function getInjectionHeader()
  549. {
  550. return $this->getInjection('getInjHeader');
  551. }
  552. function getInjectionFooter()
  553. {
  554. return $this->getInjection('getInjFooter');
  555. }
  556. public function getPopupAlert()
  557. {
  558. return $this->transBox('bx-popup-alert', $this->_oTemplate->parseHtmlByName('popup_trans_alert_cnt.html', array()), true);
  559. }
  560. public function getPopupConfirm()
  561. {
  562. return $this->transBox('bx-popup-confirm', $this->_oTemplate->parseHtmlByName('popup_trans_confirm_cnt.html', array()), true);
  563. }
  564. public function getPopupPrompt()
  565. {
  566. $sInputText = 'bx-popup-prompt-value';
  567. $aInputText = array(
  568. 'type' => 'text',
  569. 'name' => $sInputText,
  570. 'attrs' => array(
  571. 'id' => $sInputText,
  572. ),
  573. 'value' => '',
  574. 'caption' => ''
  575. );
  576. $oForm = new BxTemplFormView(array(), $this->_oTemplate);
  577. return $this->transBox('bx-popup-prompt', $this->_oTemplate->parseHtmlByName('popup_trans_prompt_cnt.html', array(
  578. 'input' => $oForm->genRow($aInputText)
  579. )), true);
  580. }
  581. /**
  582. * Output time wrapped in <time> tag in HTML.
  583. * Then time is autoformatted using JS upon page load, this is aumatically converted to user's timezone and
  584. * updated in realtime in case of short periods of 'from now' time format.
  585. *
  586. * Short version of this function:
  587. * @see bx_time_js
  588. *
  589. * @param $iUnixTimestamp time as unixtimestamp
  590. * @param $sFormatIdentifier output format identifier
  591. * @see BX_FORMAT_DATE
  592. * @see BX_FORMAT_TIME
  593. * @see BX_FORMAT_DATE_TIME
  594. * @param $bForceFormat force provided format and don't use "from now" time autoformat.
  595. */
  596. function timeForJs ($iUnixTimestamp, $sFormatIdentifier = BX_FORMAT_DATE, $bForceFormat = false)
  597. {
  598. $sDateUTC = bx_time_utc ($iUnixTimestamp);
  599. return $this->timeForJsFullDate ($sDateUTC, $sFormatIdentifier, $bForceFormat);
  600. }
  601. /**
  602. * Same as @see timeForJs but instead of unxtimestamp full date format is used (ex: 2005-08-15T15:52:01) as passec date param
  603. */
  604. function timeForJsFullDate ($sDateUTC, $sFormatIdentifier = BX_FORMAT_DATE, $bForceFormat = false, $bUTC = false)
  605. {
  606. return '<time datetime="' . $sDateUTC . '" data-bx-format="' . getParam($sFormatIdentifier) . '" data-bx-autoformat="' . ($bForceFormat ? 0 : getParam('sys_format_timeago')) . '" data-bx-utc="' . ($bUTC ? 1 : 0) . '">' . $sDateUTC . '</time>';
  607. }
  608. function statusOnOff ($mixed, $isMsg = false)
  609. {
  610. if ((is_bool($mixed) && !$mixed) || (is_string($mixed) && 'fail' == $mixed))
  611. return '<i class="sys-icon circle col-red2"></i> ' . ($isMsg ? _t('_sys_off') : '');
  612. elseif (is_string($mixed) && 'warn' == $mixed)
  613. return '<i class="sys-icon circle col-red3"></i> ' . ($isMsg ? _t('_sys_warn') : '');
  614. elseif (is_string($mixed) && 'undef' == $mixed)
  615. return '<i class="sys-icon circle col-gray"></i> ' . ($isMsg ? _t('_undefined') : '');
  616. else
  617. return '<i class="sys-icon circle col-green1"></i> ' . ($isMsg ? _t('_sys_on') : '');
  618. }
  619. /**
  620. * Ouputs HTML5 video player.
  621. * @param $sUrlPoster video poster image
  622. * @param $sUrlMP4 .mp4 video
  623. * @param $sUrlMP4Hd .mp4 video in better quality
  624. * @param $aAttrs custom attributes, defaults are: controls="" preload="none" autobuffer=""
  625. * @param $sStyles custom styles, defaults are: width:100%; height:auto;
  626. */
  627. function videoPlayer ($sUrlPoster, $sUrlMP4, $sUrlMP4Hd = '', $aAttrs = false, $sStyles = false, $bDynamicMode = false)
  628. {
  629. $oPlayer = BxDolPlayer::getObjectInstance();
  630. if(!$oPlayer)
  631. return '';
  632. if($sStyles === false)
  633. $sStyles = 'width:100%; height:auto;';
  634. return $oPlayer->getCodeVideo (BX_PLAYER_STANDARD, array(
  635. 'poster' => $sUrlPoster,
  636. 'mp4' => array('sd' => $sUrlMP4, 'hd' => $sUrlMP4Hd),
  637. 'attrs' => $aAttrs,
  638. 'styles' => $sStyles,
  639. ), $bDynamicMode);
  640. }
  641. protected function getInjection($sPrefix)
  642. {
  643. $sContent = '';
  644. $aMethods = get_class_methods($this);
  645. foreach($aMethods as $sMethod)
  646. if(preg_match("/^(" . $sPrefix . ")[A-Z].+$/", $sMethod))
  647. $sContent .= $this->$sMethod();
  648. return $sContent;
  649. }
  650. protected function getInjHeadLiveUpdates()
  651. {
  652. $sContent = '';
  653. if(($oLiveUpdates = BxDolLiveUpdates::getInstance()) !== false)
  654. $sContent .= $oLiveUpdates->init();
  655. return $sContent;
  656. }
  657. protected function getInjHeaderPushNotifications()
  658. {
  659. $iProfileId = bx_get_logged_profile_id();
  660. if(empty($iProfileId))
  661. return '';
  662. $sAppId = getParam('sys_push_app_id');
  663. if(empty($sAppId))
  664. return '';
  665. $aTags = BxDolPush::getTags($iProfileId);
  666. if (!$aTags)
  667. return '';
  668. $sShortName = getParam('sys_push_short_name');
  669. $sSafariWebId = getParam('sys_push_safari_id');
  670. $sSubfolder = '/plugins_public/onesignal/';
  671. $aUrl = parse_url(BX_DOL_URL_ROOT);
  672. if(!empty($aUrl['path'])) {
  673. $sPath = trim($aUrl['path'], '/');
  674. if(!empty($sPath))
  675. $sSubfolder = '/' . $sPath . $sSubfolder;
  676. }
  677. $this->_oTemplate->addJs(array(
  678. 'https://cdn.onesignal.com/sdks/OneSignalSDK.js',
  679. 'BxDolPush.js',
  680. ));
  681. $sJsClass = 'BxDolPush';
  682. $sJsObject = 'oBxDolPush';
  683. $sContent = "var " . $sJsObject . " = new " . $sJsClass . "(" . json_encode(array(
  684. 'sObjName' => $sJsObject,
  685. 'sSiteName' => getParam('site_title'),
  686. 'aTags' => $aTags,
  687. 'sAppId' => $sAppId,
  688. 'sShortName' => $sShortName,
  689. 'sSafariWebId' => $sSafariWebId,
  690. 'sSubfolder' => $sSubfolder,
  691. 'sNotificationUrl' => BX_DOL_URL_ROOT,
  692. 'sTxtNotificationRequest' => _t('_sys_push_notification_request', getParam('site_title')),
  693. 'sTxtNotificationRequestYes' => _t('_sys_push_notification_request_yes'),
  694. 'sTxtNotificationRequestNo' => _t('_sys_push_notification_request_no'),
  695. )) . ");";
  696. return $this->_oTemplate->_wrapInTagJsCode($sContent);
  697. }
  698. protected function getInjHeaderPopupLoading()
  699. {
  700. return $this->transBox('bx-popup-loading', $this->_oTemplate->parsePageByName('popup_loading.html', array()), true);
  701. }
  702. protected function getInjFooterMenuLoading()
  703. {
  704. return $this->_oTemplate->parsePageByName('menu_loading.html', array());
  705. }
  706. protected function getInjFooterPopupMenus()
  707. {
  708. $sContent = '';
  709. $oSearch = new BxTemplSearch();
  710. $oSearch->setLiveSearch(true);
  711. $sContent .= $this->_oTemplate->parsePageByName('search.html', array(
  712. 'search_form' => $oSearch->getForm(BX_DB_CONTENT_ONLY),
  713. 'results' => $oSearch->getResultsContainer(),
  714. ));
  715. $sContent .= $this->_oTemplate->getMenu ('sys_site');
  716. if(isLogged()) {
  717. $sContent .= $this->_oTemplate->getMenu ('sys_add_content');
  718. $sContent .= $this->_oTemplate->getMenu ('sys_account_popup');
  719. }
  720. return $sContent;
  721. }
  722. protected function getInjFooterPopupApps()
  723. {
  724. if($this->_oTemplate->getPageType() != BX_PAGE_TYPE_APPLICATION)
  725. return '';
  726. $oMenu = BxDolMenu::getObjectInstance('sys_homepage');
  727. if(!$oMenu)
  728. return '';
  729. $this->_oTemplate->addJs(['popper.js']);
  730. return $this->_oTemplate->parsePageByName('menu_apps.html', [
  731. 'name' => 'sys-menu-apps',
  732. 'title' => _t('_apps'),
  733. 'bx_repeat:menu_items' => $oMenu->getMenuItems(),
  734. ]);
  735. }
  736. protected function getInjFooterPopups()
  737. {
  738. $sContent = '';
  739. $sContent .= $this->getPopupAlert();
  740. $sContent .= $this->getPopupConfirm();
  741. $sContent .= $this->getPopupPrompt();
  742. return $sContent;
  743. }
  744. protected function getInjFooterEmbed()
  745. {
  746. // Load embed files
  747. $oEmbed = BxDolEmbed::getObjectInstance(false);
  748. if ($oEmbed)
  749. return $oEmbed->addJsCss() . $oEmbed->addProcessLinkMethod();
  750. return '';
  751. }
  752. }
  753. /** @} */