PageRenderTime 59ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/web/nvweb_templates.php

https://bitbucket.org/navigatecms/navigatecms
PHP | 1604 lines | 1144 code | 216 blank | 244 comment | 185 complexity | 6313ee8f97d2a178126c3b1a939468ba MD5 | raw file
Possible License(s): GPL-2.0, MIT, LGPL-2.1, BSD-3-Clause, AGPL-3.0, Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * Return the contents of the physical template file from the website private folder or from theme folder.
  4. *
  5. * The file is determined by the URL requested and the information in the database.
  6. *
  7. * @return string $template
  8. */
  9. function nvweb_template_load($template_id=null)
  10. {
  11. global $current;
  12. global $DB;
  13. global $website;
  14. $template = '';
  15. if(empty($template_id))
  16. $template_id = $current['template'];
  17. if(!empty($template_id))
  18. {
  19. $template = new template();
  20. $template->load($template_id);
  21. if(!$template->enabled)
  22. nvweb_clean_exit();
  23. if($template->permission == 2)
  24. nvweb_clean_exit();
  25. else if($template->permission == 1 && empty($_SESSION['APP_USER#'.APP_UNIQUE]))
  26. nvweb_clean_exit();
  27. if(file_exists($template->file))
  28. $template->file_contents = @file_get_contents($template->file); // from theme
  29. else if(file_exists(NAVIGATE_PRIVATE.'/'.$website->id.'/templates/'.$template->file))
  30. $template->file_contents = @file_get_contents(NAVIGATE_PRIVATE.'/'.$website->id.'/templates/'.$template->file);
  31. else
  32. $template->file_contents = 'NV error: template file not found! ('.$template->file.')';
  33. }
  34. return $template;
  35. }
  36. /**
  37. * Loads the webdictionary for the current website
  38. *
  39. * The function takes the current language for the source
  40. *
  41. * @return array $dictionary
  42. */
  43. function nvweb_dictionary_load()
  44. {
  45. global $DB;
  46. global $session;
  47. global $website;
  48. global $theme;
  49. $dictionary = array();
  50. // the dictionary is an array merged from the following sources (- to + preference)
  51. // theme dictionary (json)
  52. // theme dictionary on database
  53. // webdictionary custom entries
  54. // theme dictionary
  55. if(!empty($theme))
  56. {
  57. $theme->dictionary = array(); // clear previous loaded dictionary
  58. $theme->t(); // force theme dictionary load
  59. }
  60. if(!empty($theme->dictionary))
  61. $dictionary = $theme->dictionary;
  62. // webdictionary custom entries
  63. $DB->query('SELECT node_id, text
  64. FROM nv_webdictionary
  65. WHERE node_type = "global"
  66. AND lang = '.protect($session['lang']).'
  67. AND website = '.$website->id.'
  68. UNION
  69. SELECT subtype AS node_id, text
  70. FROM nv_webdictionary
  71. WHERE node_type = "theme"
  72. AND theme = '.protect($website->theme).'
  73. AND lang = '.protect($session['lang']).'
  74. AND website = '.$website->id
  75. );
  76. $data = $DB->result();
  77. if(!is_array($data)) $data = array();
  78. foreach($data as $item)
  79. {
  80. $dictionary[$item->node_id] = $item->text;
  81. }
  82. return $dictionary;
  83. }
  84. /**
  85. * Sets or prints a certain code that will be placed just before closing the </body> tag
  86. *
  87. * @param string $type "js" or "html", depending on the code type to return / append
  88. * @param string $code actual source code that will be appended, if empty all source code saved will be returned
  89. * @return string the source code previously appended or empty
  90. */
  91. function nvweb_after_body($type="js", $code="")
  92. {
  93. global $current;
  94. if(empty($code))
  95. {
  96. if(!empty($current[$type.'_after_body']))
  97. {
  98. switch($type)
  99. {
  100. case 'js':
  101. array_unshift($current[$type.'_after_body'], '<script language="javascript" type="text/javascript">');
  102. $current[$type.'_after_body'][] = '</script>';
  103. break;
  104. case 'php':
  105. foreach($current[$type.'_after_body'] as $code)
  106. call_user_func($code);
  107. $current[$type.'_after_body'] = array();
  108. break;
  109. case 'html':
  110. default:
  111. break;
  112. }
  113. return implode("\n", $current[$type.'_after_body']);
  114. }
  115. }
  116. else
  117. $current[$type.'_after_body'][] = $code;
  118. return "";
  119. }
  120. /**
  121. * Parses a template looking for nv tags and replacing them with the generated HTML code
  122. *
  123. * @param $template string HTML code to parse
  124. * @return string HTML page generated
  125. */
  126. function nvweb_template_parse($template)
  127. {
  128. global $dictionary;
  129. global $DB;
  130. global $current;
  131. global $website;
  132. global $structure;
  133. global $theme;
  134. global $idn;
  135. global $session;
  136. $html = $template;
  137. // now parse autoclosing tags
  138. $tags = nvweb_tags_extract($html, 'nv', true, true, 'UTF-8');
  139. foreach($tags as $tag)
  140. {
  141. $content = '';
  142. switch($tag['attributes']['object'])
  143. {
  144. // MAIN OBJECT TYPES
  145. case 'nvweb':
  146. case 'widget':
  147. case 'webget':
  148. case '':
  149. debugger::timer('nvweb-templates-nvweb-'.$tag['attributes']['name']);
  150. // webgets on lib/webgets have priority over private/webgets
  151. nvweb_webget_load($tag['attributes']['name']);
  152. $fname = 'nvweb_'.$tag['attributes']['name'];
  153. $tag['attributes']['nvweb_html'] = $html; // always pass the current buffered output to the webget
  154. if(function_exists($fname))
  155. $content = $fname($tag['attributes']);
  156. debugger::stop_timer('nvweb-templates-webget-'.$tag['attributes']['name'].'[mode="'.$tag['attributes']['mode'].'"]');
  157. break;
  158. case 'root':
  159. $content = NVWEB_ABSOLUTE;
  160. break;
  161. case 'nvajax':
  162. $content = NVWEB_AJAX;
  163. break;
  164. case 'url':
  165. $content = '';
  166. if(!empty($tag['attributes']['lang']))
  167. $lang = $tag['attributes']['lang'];
  168. else
  169. $lang = $current['lang'];
  170. if(!empty($tag['attributes']['type']) && !empty($tag['attributes']['id']))
  171. {
  172. $url = nvweb_source_url($tag['attributes']['type'], $tag['attributes']['id'], $lang);
  173. if(!empty($url)) $content .= $url;
  174. }
  175. else if(!empty($tag['attributes']['type']) && !empty($tag['attributes']['property']))
  176. {
  177. $tag['attributes']['id'] = nvweb_properties(array('property' => $tag['attributes']['property']));
  178. $url = nvweb_source_url($tag['attributes']['type'], $tag['attributes']['id'], $lang);
  179. if(!empty($url)) $content .= $url;
  180. }
  181. else if(!empty($tag['attributes']['type']) && empty($tag['attributes']['id']))
  182. {
  183. // get structure parent for this element and return its path
  184. if($current['type']=='structure')
  185. {
  186. $category = $current['object']->parent;
  187. if(empty($category))
  188. $category = $current['object']->id;
  189. }
  190. else
  191. $category = $current['object']->category;
  192. $url = nvweb_source_url($tag['attributes']['type'], $category, $lang);
  193. if(!empty($url)) $content .= $url;
  194. }
  195. else
  196. {
  197. $content .= '/'.$current['route'];
  198. }
  199. $content = nvweb_prepare_link($content);
  200. break;
  201. case 'd':
  202. case 'dict':
  203. case 'dictionary':
  204. if(!empty($tag['attributes']['type']))
  205. {
  206. if($tag['attributes']['type']=='structure' || $tag['attributes']['type']=='category')
  207. {
  208. // force loading dictionary for all elements in structure (for the current language)
  209. nvweb_menu_load_dictionary();
  210. if(!is_numeric($tag['attributes']['id']))
  211. {
  212. // maybe it's a property name instead of a category id
  213. $tag['attributes']['id'] = nvweb_properties(array('property' => $tag['attributes']['property']));
  214. }
  215. $content = $structure['dictionary'][$tag['attributes']['id']];
  216. }
  217. else if($tag['attributes']['type']=='item')
  218. {
  219. $tmp = webdictionary::load_element_strings('item', $tag['attributes']['id']);
  220. $content = $tmp[$current['lang']]['title'];
  221. }
  222. }
  223. else
  224. $content = $dictionary[$tag['attributes']['id']];
  225. if(empty($content))
  226. $content = $tag['attributes']['label'];
  227. if(empty($content))
  228. $content = $tag['attributes']['default'];
  229. break;
  230. case 'request':
  231. if(!empty($tag['attributes']['name']))
  232. $content = $_REQUEST[$tag['attributes']['name']];
  233. else // deprecated: use "request" as attribute [will be removed on navigate cms 2.0]
  234. $content = $_REQUEST[$tag['attributes']['request']];
  235. if(is_array($content))
  236. $content = implode(',', $content);
  237. break;
  238. case 'constant':
  239. case 'variable':
  240. switch($tag['attributes']['name'])
  241. {
  242. case "structure":
  243. case "category":
  244. // retrieve the category ID from current session
  245. $tmp = NULL;
  246. if($current['type']=='structure')
  247. $tmp = $current['id'];
  248. else if(!empty($current['category']))
  249. $tmp = $current['category'];
  250. else if(!empty($current['object']->category))
  251. $tmp = $current['object']->category;
  252. if(empty($tmp))
  253. $content = '';
  254. else
  255. {
  256. $content = $DB->query_single(
  257. 'text',
  258. 'nv_webdictionary', '
  259. node_type = "structure"
  260. AND subtype = "title"
  261. AND node_id = '.$tmp.'
  262. AND lang = '.protect($current['lang']).'
  263. AND website = '.$website->id
  264. );
  265. }
  266. break;
  267. case "year":
  268. $content = date('Y');
  269. break;
  270. case "website_name":
  271. $content = $website->name;
  272. break;
  273. case "website_description":
  274. $content = $website->metatag_description[$current['lang']];
  275. break;
  276. case "lang_code":
  277. $content = $current['lang'];
  278. break;
  279. default:
  280. break;
  281. }
  282. break;
  283. case 'php':
  284. if(!empty($tag['attributes']['code']))
  285. eval('$content = '.$tag['attributes']['code'].';');
  286. break;
  287. case 'theme':
  288. // compatibility with Navigate < 1.8.9
  289. // deprecated! code will be removed in Navigate 3.0
  290. if($tag['attributes']['name']=='url')
  291. {
  292. $tag['attributes']['mode'] = 'url';
  293. }
  294. else if($tag['attributes']['name']=='style')
  295. {
  296. $tag['attributes']['name'] = $tag['attributes']['mode'];
  297. $tag['attributes']['mode'] = 'style';
  298. }
  299. // new syntax ("mode" first)
  300. switch($tag['attributes']['mode'])
  301. {
  302. case "style":
  303. $content = $website->theme_options->style;
  304. if(!empty($tag['attributes']['name']))
  305. {
  306. switch($tag['attributes']['name'])
  307. {
  308. case 'name':
  309. $content = $website->theme_options->style;
  310. break;
  311. case 'color':
  312. default:
  313. // return theme definition file location for the requested substyle
  314. if(!empty($website->theme_options->style))
  315. $content = $theme->styles->{$website->theme_options->style}->{$tag['attributes']['name']};
  316. if(empty($content))
  317. {
  318. // return first available
  319. $theme_styles = array_keys(get_object_vars($theme->styles));
  320. $content = $theme->styles->{$theme_styles[0]}->{$tag['attributes']['name']};
  321. }
  322. break;
  323. }
  324. }
  325. break;
  326. case "url":
  327. $content = $website->absolute_path();
  328. try
  329. {
  330. $content = $idn->encodeUri($content);
  331. }
  332. catch (\InvalidArgumentException $e)
  333. {
  334. // do nothing, the domain is already in punycode
  335. }
  336. $content.= NAVIGATE_FOLDER.'/themes/'.$theme->name.'/';
  337. break;
  338. }
  339. break;
  340. default:
  341. //var_dump($tag['attributes']['object']);
  342. break;
  343. }
  344. $html = str_replace($tag['full_tag'], $content, $html);
  345. }
  346. return $html;
  347. }
  348. /**
  349. * Parse special Navigate CMS tags like:
  350. * <ul>
  351. * <li>&lt;nv object="include" file="" id="" /&gt;</li>
  352. * <li>curly bracket tags {{nv object=""}}</li>
  353. * </ul>
  354. *
  355. * Generate the final HTML code for these special tags or convert them
  356. * to a simpler nv tags.
  357. *
  358. * @param $html
  359. * @return mixed
  360. */
  361. function nvweb_template_parse_special($html)
  362. {
  363. global $website;
  364. global $current;
  365. // find <pre> and <code> tags, save its contents and leave a placeholder to restore the content later
  366. $tags_pre = nvweb_tags_extract($html, 'pre', false, true, 'UTF-8');
  367. for($t=count($tags_pre); $t--; $t >= 0) // need to process the tags upwards, to keep the offsets found
  368. {
  369. $tag = $tags_pre[$t];
  370. if(empty($tag)) continue;
  371. $tag_uid = uniqid('nv-tags-pre-');
  372. $current['delayed_tags_pre'][$tag_uid] = $tag['full_tag'];
  373. $html = substr_replace($html, '<!--#'.$tag_uid.'#-->', $tag['offset'], strlen($tag['full_tag']));
  374. }
  375. $tags_code = nvweb_tags_extract($html, 'code', false, true, 'UTF-8');
  376. for($t=count($tags_code); $t--; $t >= 0) // need to process the tags upwards, to keep the offsets found
  377. {
  378. $tag = $tags_code[$t];
  379. if(empty($tag)) continue;
  380. $tag_uid = uniqid('nv-tags-code-');
  381. $current['delayed_tags_code'][$tag_uid] = $tag['full_tag'];
  382. $html = substr_replace($html, '<!--#'.$tag_uid.'#-->', $tag['offset'], strlen($tag['full_tag']));
  383. }
  384. $changed = false;
  385. // translate "{{nv object='list' " tags to "<nv object='list' " version
  386. preg_match_all("/{{nv\s object=[\"']list[\"'] ([^}]+)}}/ixsm", $html, $curly_tags);
  387. for($c=0; $c < count($curly_tags[0]); $c++)
  388. {
  389. if(stripos($curly_tags[0], 'object="list"'))
  390. {
  391. $tmp = str_ireplace(array('{{nv object="list" ', '}}'), array('<nv object="list" ', '>'), $curly_tags[0][$c]);
  392. $html = str_ireplace($curly_tags[0][$c], $tmp, $html);
  393. }
  394. else
  395. {
  396. $tmp = str_ireplace(array("{{nv object='list' ", '}}'), array('<nv object="list" ', '>'), $curly_tags[0][$c]);
  397. $html = str_ireplace($curly_tags[0][$c], $tmp, $html);
  398. }
  399. $changed = true;
  400. }
  401. // translate "{{/nv}}" tags to "</nv>" version
  402. $html = str_ireplace('{{/nv}}', '</nv>', $html);
  403. // translate "{{nvlist_conditional }}" tags to "<nvlist_conditional >" version
  404. preg_match_all("/{{nvlist_conditional \s([^}]+)}}/ixsm", $html, $curly_tags);
  405. for($c=0; $c < count($curly_tags[0]); $c++)
  406. {
  407. $tmp = str_replace(array('{{nvlist_conditional ', '}}'), array('<nvlist_conditional ', '>'), $curly_tags[0][$c]);
  408. $html = str_ireplace($curly_tags[0][$c], $tmp, $html);
  409. $changed = true;
  410. }
  411. // translate "{{/nvlist_conditional}}" tags to "</nvlist_conditional>" version
  412. $html = str_ireplace('{{/nvlist_conditional}}', '</nvlist_conditional>', $html);
  413. // translate "{{nv }}" tags to "<nv />" version
  414. preg_match_all("/{{nv\s([^}]+)}}/ixsm", $html, $curly_tags);
  415. for($c=0; $c < count($curly_tags[0]); $c++)
  416. {
  417. $tmp = str_replace(array('{{nv ', '}}'), array('<nv ', ' />'), $curly_tags[0][$c]);
  418. $html = str_ireplace($curly_tags[0][$c], $tmp, $html);
  419. $changed = true;
  420. }
  421. // translate "{{nvlist }}" tags to "<nvlist />" version
  422. preg_match_all("/{{nvlist\s([^}]+)}}/ixsm", $html, $curly_tags);
  423. for($c=0; $c < count($curly_tags[0]); $c++)
  424. {
  425. $tmp = str_replace(array('{{nvlist ', '}}'), array('<nvlist ', ' />'), $curly_tags[0][$c]);
  426. $html = str_ireplace($curly_tags[0][$c], $tmp, $html);
  427. $changed = true;
  428. }
  429. if($changed)
  430. return nvweb_template_parse_special($html);
  431. // parse includes (we must do it before parsing list or search)
  432. $tags = nvweb_tags_extract($html, 'nv', true, true, 'UTF-8');
  433. foreach($tags as $tag)
  434. {
  435. $content = '';
  436. $changed = false;
  437. $tag['length'] = strlen($tag['full_tag']);
  438. if($tag['attributes']['object']=='include')
  439. {
  440. $tid = $tag['attributes']['id'];
  441. $file = $tag['attributes']['file'];
  442. if(!empty($tid))
  443. {
  444. $template = new template();
  445. $template->load($tid);
  446. if($template->website == $website->id) // cross-website security
  447. {
  448. $content = file_get_contents(NAVIGATE_PRIVATE.'/'.$website->id.'/templates/'.$template->file);
  449. }
  450. }
  451. else if(!empty($file))
  452. {
  453. $content = file_get_contents(NAVIGATE_PATH.'/themes/'.$website->theme.'/'.$file);
  454. }
  455. $html = substr_replace($html, $content, $tag['offset'], $tag['length']);
  456. $changed = true;
  457. }
  458. // if an object="include" has been found, we need to restart the parse_special tags function
  459. // as it may contain other "includes" or "{{nv" tags that need transformation
  460. if($changed)
  461. {
  462. $html = nvweb_template_parse_special($html);
  463. break;
  464. }
  465. }
  466. return $html;
  467. }
  468. function nvweb_template_restore_special($html)
  469. {
  470. global $current;
  471. foreach($current['delayed_tags_code'] as $tag_uid => $tag_code)
  472. {
  473. $html = str_replace('<!--#'.$tag_uid.'#-->', $current['delayed_tags_code'][$tag_uid], $html);
  474. $current['delayed_tags_code'][$tag_uid] = NULL;
  475. }
  476. foreach($current['delayed_tags_pre'] as $tag_uid => $tag_code)
  477. {
  478. $html = str_replace('<!--#'.$tag_uid.'#-->', $current['delayed_tags_pre'][$tag_uid], $html);
  479. $current['delayed_tags_pre'][$tag_uid] = NULL;
  480. }
  481. return $html;
  482. }
  483. /**
  484. * Parse Navigate CMS tags like:
  485. * <ul>
  486. * <li>&lt;nv object="list"&gt;&lt;/nv&gt;</li>
  487. * <li>&lt;nv object="search"&gt;&lt;/nv&gt;</li>
  488. * <li>&lt;nv object="conditional"&gt;&lt;/nv&gt;</li>
  489. * </ul>
  490. *
  491. * Generate the final HTML code for these special tags or convert them
  492. * to a simpler nv tags.
  493. *
  494. * @param $html
  495. * @return mixed
  496. */
  497. function nvweb_template_parse_lists($html, $process_delayed=false)
  498. {
  499. global $current;
  500. if($process_delayed)
  501. {
  502. // time to process delayed nvlists and nvsearches
  503. foreach($current['delayed_nvlists'] as $uid => $vars)
  504. {
  505. debugger::timer('nvweb-templates-list-[source="'.$vars['source'].'"]');
  506. $content = nvweb_list($vars);
  507. $html = str_replace('<!--#'.$uid.'#-->', $content, $html);
  508. debugger::stop_timer('nvweb-templates-list-[source="'.$vars['source'].'"]');
  509. }
  510. foreach($current['delayed_nvsearches'] as $uid => $vars)
  511. {
  512. debugger::timer('nvweb-templates-search-[source="'.$vars['source'].'"]');
  513. $content = nvweb_search($vars);
  514. $html = str_replace('<!--#'.$uid.'#-->', $content, $html);
  515. debugger::stop_timer('nvweb-templates-search-[source="'.$vars['source'].'"]');
  516. }
  517. return $html;
  518. }
  519. // parse special navigate tags (includes, lists, searches...)
  520. $tags = nvweb_tags_extract($html, 'nv', true, true, 'UTF-8');
  521. foreach($tags as $tag)
  522. {
  523. $content = '';
  524. $changed = false;
  525. switch($tag['attributes']['object'])
  526. {
  527. case 'list':
  528. $template_end = nvweb_templates_find_closing_list_tag($html, $tag['offset']);
  529. $tag['length'] = $template_end - $tag['offset'] + strlen('</nv>'); // remove tag characters
  530. $list = substr($html, ($tag['offset'] + strlen($tag['full_tag'])), ($tag['length'] - strlen('</nv>') - strlen($tag['full_tag'])));
  531. $vars = array_merge($tag['attributes'], array('template' => $list));
  532. if($tag['attributes']['delayed']=='true')
  533. {
  534. $list_uid = uniqid('nvlist-');
  535. $current['delayed_nvlists'][$list_uid] = $vars;
  536. $html = substr_replace($html, '<!--#'.$list_uid.'#-->', $tag['offset'], $tag['length']);
  537. $changed = true;
  538. continue;
  539. }
  540. debugger::timer('nvweb-templates-list-[source="'.$vars['source'].'"]');
  541. $content = nvweb_list($vars);
  542. debugger::stop_timer('nvweb-templates-list-[source="'.$vars['source'].'"]');
  543. $html = substr_replace($html, $content, $tag['offset'], $tag['length']);
  544. $changed = true;
  545. break;
  546. case 'search':
  547. $template_end = nvweb_templates_find_closing_list_tag($html, $tag['offset']);
  548. $tag['length'] = $template_end - $tag['offset'] + strlen('</nv>'); // remove tag characters
  549. $search = substr($html, ($tag['offset'] + strlen($tag['full_tag'])), ($tag['length'] - strlen('</nv>') - strlen($tag['full_tag'])));
  550. @include_once(NAVIGATE_PATH.'/lib/webgets/search.php');
  551. $vars = array_merge($tag['attributes'], array('template' => $search));
  552. if($tag['attributes']['delayed']=='true')
  553. {
  554. $search_uid = uniqid('nvsearch-');
  555. $current['delayed_nvsearches'][$search_uid] = $vars;
  556. $html = substr_replace($html, '<!--#'.$search_uid.'#-->', $tag['offset'], $tag['length']);
  557. $changed = true;
  558. continue;
  559. }
  560. debugger::timer('nvweb-templates-search-[source="'.$vars['source'].'"]');
  561. $content = nvweb_search($vars);
  562. debugger::stop_timer('nvweb-templates-search-[source="'.$vars['source'].'"]');
  563. $html = substr_replace($html, $content, $tag['offset'], $tag['length']);
  564. $changed = true;
  565. break;
  566. case 'conditional':
  567. $template_end = nvweb_templates_find_closing_list_tag($html, $tag['offset']);
  568. $tag['length'] = $template_end - $tag['offset'] + strlen('</nv>'); // remove tag characters
  569. $conditional = substr($html, ($tag['offset'] + strlen($tag['full_tag'])), ($tag['length'] - strlen('</nv>') - strlen($tag['full_tag'])));
  570. @include_once(NAVIGATE_PATH.'/lib/webgets/conditional.php');
  571. $vars = array_merge($tag['attributes'], array('_template' => $conditional));
  572. $content = nvweb_conditional($vars);
  573. $html = substr_replace($html, $content, $tag['offset'], $tag['length']);
  574. $changed = true;
  575. break;
  576. }
  577. if($changed)
  578. {
  579. // ok, we've found and processed ONE special tag
  580. // now the HTML has changed, so the original positions of the special <nv> tags have also changed
  581. // we must finish the current loop and start a new one
  582. $html = nvweb_template_parse_lists($html);
  583. break;
  584. }
  585. }
  586. return $html;
  587. }
  588. function nvweb_templates_find_closing_list_tag($html, $offset)
  589. {
  590. $found = false;
  591. $level = 0;
  592. $closing_tag_position = 0;
  593. $loops = 0;
  594. // find next nv object="" tag (opening or closing)
  595. // if it is an opening tag --> level + 1
  596. // if it is a closing tag --> level - 1
  597. // if level = 0, that's the closing tag we were looking for
  598. // else repeat from current offset
  599. while(!$found && $loops < 2000)
  600. {
  601. // check if there is a special '<nv>' opening tag (list, search, conditional) before the next closing found tag
  602. $next_opening = stripos_array(
  603. $html,
  604. array(
  605. '<nv object="list" ',
  606. '<nv object="search" ',
  607. '<nv object="conditional" '
  608. ),
  609. $offset
  610. );
  611. // find next '</nv>' occurrence from offset
  612. $next_closing = stripos($html, '</nv>', $offset);
  613. if($next_opening!==false && $next_opening < $next_closing)
  614. {
  615. // there is an opening tag before a closing tag, so there is an inner nvlist_conditional
  616. // move the offset to the opening tag found
  617. $offset = $next_opening + strlen('<nv object="');
  618. $level++;
  619. }
  620. else
  621. {
  622. // found a closing tag without an inner nvlist_conditional opening tag
  623. $level--;
  624. if($level > 0)
  625. {
  626. $offset = $next_closing + strlen('</nv>');
  627. }
  628. else
  629. {
  630. $closing_tag_position = $next_closing;
  631. $found = true;
  632. }
  633. }
  634. $loops++;
  635. }
  636. if(!$found)
  637. $closing_tag_position = false;
  638. return $closing_tag_position;
  639. /*
  640. // no support for nested lists
  641. // $template_end = strpos($html, '</nv>', $tag['offset']);
  642. // return $template_end;
  643. // supporting nested lists
  644. $loops = 0;
  645. $found = false;
  646. while(!$found)
  647. {
  648. // find next '</nv>' occurrence from offset
  649. $next_closing = stripos($html, '</nv>', $offset);
  650. // check if there is a special '<nv>' opening tag (list, search, conditional) before the next closing found tag
  651. $next_opening = stripos_array(
  652. $html,
  653. array(
  654. '<nv object="list" ',
  655. '<nv object="search" ',
  656. '<nv object="conditional" '
  657. ),
  658. $offset
  659. );
  660. if(!$next_opening)
  661. {
  662. $found = true;
  663. }
  664. else
  665. {
  666. $found = $next_opening > $next_closing;
  667. if(!$found)
  668. {
  669. $offset = $next_closing + strlen('</nv>');
  670. $loops++;
  671. }
  672. }
  673. if(!$found && ($offset > strlen($html) || $loops > 1000))
  674. break;
  675. }
  676. if(!$found)
  677. $next_closing = false;
  678. return $next_closing;
  679. */
  680. }
  681. function nvweb_replace_tag_contents($tag_id, $content, $html_source_code)
  682. {
  683. brasofilo_suSetHtmlById( $html_source_code, $tag_id, $content );
  684. return $html_source_code;
  685. }
  686. /**
  687. * Apply current website theme settings
  688. *
  689. * Example: <HORIZON_LOGO /> --> Theme logo URL
  690. *
  691. * @param $template string HTML of the current page
  692. * @return string $template HTML of the current page with the theme settings applied
  693. */
  694. function nvweb_theme_settings($template)
  695. {
  696. global $website;
  697. if(!empty($website->theme))
  698. {
  699. nvweb_webget_load($website->theme);
  700. if(function_exists('nvweb_'.$website->theme))
  701. {
  702. $out = call_user_func(
  703. 'nvweb_'.$website->theme,
  704. array(
  705. 'mode' => 'theme',
  706. 'html' => $template
  707. )
  708. );
  709. if(!empty($out))
  710. $template = $out;
  711. }
  712. }
  713. return $template;
  714. }
  715. /**
  716. * Returns the current visitor real IP or false if couldn't be located
  717. *
  718. * @return mixed|mixed Real IP of the current visitor or false
  719. */
  720. function nvweb_real_ip()
  721. {
  722. $ip = false;
  723. if(!empty($_SERVER['HTTP_CLIENT_IP']))
  724. $ip = $_SERVER['HTTP_CLIENT_IP'];
  725. if(!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
  726. {
  727. $ips = explode(", ", $_SERVER['HTTP_X_FORWARDED_FOR']);
  728. if($ip)
  729. {
  730. array_unshift($ips, $ip);
  731. $ip = false;
  732. }
  733. for($i = 0; $i < count($ips); $i++)
  734. {
  735. if(!preg_match("/^(10|172\.16|192\.168)\./i", $ips[$i]))
  736. {
  737. if(version_compare(phpversion(), "5.0.0", ">="))
  738. {
  739. if(ip2long($ips[$i]) != false)
  740. {
  741. $ip = $ips[$i];
  742. break;
  743. }
  744. }
  745. else
  746. {
  747. if(ip2long($ips[$i]) != - 1)
  748. {
  749. $ip = $ips[$i];
  750. break;
  751. }
  752. }
  753. }
  754. }
  755. }
  756. return ($ip ? $ip : $_SERVER['REMOTE_ADDR']);
  757. }
  758. /**
  759. * Determine the default language to show to the user reading its browser preferences
  760. *
  761. * Note: if the language is already setted in a cookie or in the session this function is never called
  762. *
  763. * @return string $lang 2-letter code of the language
  764. */
  765. function nvweb_country_language()
  766. {
  767. global $website;
  768. $lang = '';
  769. if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
  770. {
  771. preg_match_all( '/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i',
  772. $_SERVER['HTTP_ACCEPT_LANGUAGE'],
  773. $lang_parse);
  774. if(count($lang_parse[1]))
  775. {
  776. $langs = array_combine($lang_parse[1], $lang_parse[4]);
  777. foreach ($langs as $lang => $val)
  778. if($val === '') $langs[$lang] = 1;
  779. arsort($langs, SORT_NUMERIC);
  780. }
  781. $found = false;
  782. if(is_array($langs))
  783. {
  784. foreach($langs as $language_browser => $val)
  785. {
  786. foreach($website->languages_published as $language_available)
  787. {
  788. if($language_available == $language_browser)
  789. {
  790. $lang = $language_browser;
  791. $found = true;
  792. break;
  793. }
  794. }
  795. if($found)
  796. break;
  797. }
  798. }
  799. }
  800. if(empty($lang))
  801. {
  802. // no user defined language matches the website available languages, so take the website's default one
  803. $lang = $website->languages_list[0];
  804. }
  805. return $lang;
  806. }
  807. /**
  808. * Replace "navigate_download.php" paths for base_domain/object uris
  809. *
  810. * @param $html string HTML content
  811. * @return string HTML content without "navigate_download.php" requests
  812. */
  813. function nvweb_template_fix_download_paths($in)
  814. {
  815. $regex = '/https?\:\/\/[^\" ]+/i';
  816. preg_match_all($regex, $in, $data);
  817. $out = $in;
  818. $nv_download = basename(NAVIGATE_DOWNLOAD);
  819. if(is_array($data[0]))
  820. {
  821. foreach($data[0] as $url)
  822. {
  823. $url_decoded = html_entity_decode($url, ENT_QUOTES, 'UTF-8');
  824. $url_parsed = parse_url($url_decoded);
  825. if(strpos($url_parsed['path'], $nv_download) !== false)
  826. {
  827. $new_url = NVWEB_OBJECT.'?'.$url_parsed['query'];
  828. $out = str_replace($url, $new_url, $out, $c);
  829. }
  830. }
  831. }
  832. return $out;
  833. }
  834. /**
  835. * Apply some template tweaks to improve Navigate CMS theme developing experience like:
  836. *
  837. * <ul>
  838. * <li>Guess absolute paths to images, stylesheets, videos and scripts (even on urls without http, "//")</li>
  839. * <li>Convert &lt;a rel="video"&gt; and &lt;a rel="audio"&gt; to &lt;video&gt; and &lt;audio&gt; tags</li>
  840. * <li>Process &lt;img&gt; tags to generate optimized images</li>
  841. * <li>Add Navigate CMS content default styles</li>
  842. * </ul>
  843. *
  844. * @param $html string Original HTML template content
  845. * @return string HTML template tweaked
  846. */
  847. function nvweb_template_tweaks($html)
  848. {
  849. global $website;
  850. // apply some tweaks to the generated html code
  851. // tweak 1: try to make absolute all image, css and script paths not starting by http
  852. if(!empty($website->theme))
  853. $website_absolute_path = NAVIGATE_URL.'/themes/'.$website->theme;
  854. else
  855. $website_absolute_path = $website->absolute_path(false);
  856. // stylesheets
  857. $replacements = array();
  858. $tags = nvweb_tags_extract($html, 'link', NULL, true, 'UTF-8');
  859. foreach($tags as $tag)
  860. {
  861. if(!isset($tag['attributes']['href'])) continue;
  862. if(substr($tag['attributes']['href'], 0, 7)!='http://' &&
  863. substr($tag['attributes']['href'], 0, 8)!='https://')
  864. {
  865. // treat "//" paths (without http or https)
  866. if(substr($tag['attributes']['href'], 0, 2)=='//')
  867. $src = $website->protocol.substr($tag['attributes']['href'], 2);
  868. else
  869. $src = $website_absolute_path.'/'.$tag['attributes']['href'];
  870. $tag['new'] = '<link href="'.$src.'" ';
  871. foreach($tag['attributes'] as $name => $value)
  872. {
  873. if($name!='href') $tag['new'] .= $name.'="'.$value.'" ';
  874. }
  875. $tag['new'] .= '/>';
  876. //$html = str_replace($tag['full_tag'], $tag['new'], $html);
  877. $replacements[$tag['full_tag']] = $tag['new'];
  878. }
  879. }
  880. // scripts
  881. $tags = nvweb_tags_extract($html, 'script', NULL, true, 'UTF-8');
  882. foreach($tags as $tag)
  883. {
  884. if(!isset($tag['attributes']['src'])) continue;
  885. if(substr($tag['attributes']['src'], 0, 7)!='http://' &&
  886. substr($tag['attributes']['src'], 0, 8)!='https://')
  887. {
  888. if(substr($tag['attributes']['src'], 0, 2)=='//')
  889. $src = $website->protocol.substr($tag['attributes']['src'], 2);
  890. else
  891. $src = $website_absolute_path.'/'.$tag['attributes']['src'];
  892. $tag['new'] = '<script src="'.$src.'" ';
  893. foreach($tag['attributes'] as $name => $value)
  894. {
  895. if($name!='src') $tag['new'] .= $name.'="'.$value.'" ';
  896. }
  897. $tag['new'] .= '></script>';
  898. //$html = str_replace($tag['full_tag'], $tag['new'], $html);
  899. $replacements[$tag['full_tag']] = $tag['new'];
  900. }
  901. }
  902. $html = str_replace(
  903. array_keys($replacements),
  904. array_values($replacements),
  905. $html
  906. );
  907. // poster attribute (<video>)
  908. $replacements = array();
  909. $tags = nvweb_tags_extract($html, array('video'), false, true, 'UTF-8');
  910. foreach($tags as $tag)
  911. {
  912. if(!isset($tag['attributes']['poster'])) continue;
  913. if(substr($tag['attributes']['poster'], 0, 7)!='http://' &&
  914. substr($tag['attributes']['poster'], 0, 8)!='https://')
  915. {
  916. if(substr($tag['attributes']['poster'], 0, 2)=='//')
  917. $src = $website->protocol.substr($tag['attributes']['poster'], 2);
  918. else
  919. $src = $website_absolute_path.'/'.$tag['attributes']['poster'];
  920. $tag['new'] = '<video poster="'.$src.'" ';
  921. foreach($tag['attributes'] as $name => $value)
  922. {
  923. if($name!='poster')
  924. $tag['new'] .= $name.'="'.$value.'" ';
  925. }
  926. $tag['new'] .= '>'.$tag['contents'].'</video>';
  927. //$html = str_replace($tag['full_tag'], $tag['new'], $html);
  928. $replacements[$tag['full_tag']] = $tag['new'];
  929. }
  930. }
  931. $html = str_replace(
  932. array_keys($replacements),
  933. array_values($replacements),
  934. $html
  935. );
  936. // sources (video, audio)
  937. $replacements = array();
  938. $tags = nvweb_tags_extract($html, array('video', 'audio'), false, true, 'UTF-8');
  939. foreach($tags as $tag)
  940. {
  941. $tag_sources = nvweb_tags_extract($tag['contents'], 'source', true, true, 'UTF-8');
  942. foreach($tag_sources as $source)
  943. {
  944. if(!isset($source['attributes']['src'])) continue;
  945. if(substr($source['attributes']['src'], 0, 7)!='http://' &&
  946. substr($source['attributes']['src'], 0, 8)!='https://')
  947. {
  948. if(substr($source['attributes']['src'], 0, 2)=='//')
  949. $src = $website->protocol.substr($source['attributes']['src'], 2);
  950. else
  951. $src = $website_absolute_path.'/'.$source['attributes']['src'];
  952. $source['new'] = '<source src="'.$src.'" ';
  953. foreach($source['attributes'] as $name => $value)
  954. {
  955. if($name!='poster')
  956. $source['new'] .= $name.'="'.$value.'" ';
  957. }
  958. $source['new'] .= '>'.$source['contents'].'</source>';
  959. //$html = str_replace($source['full_tag'], $source['new'], $html);
  960. $replacements[$tag['full_tag']] = $tag['new'];
  961. }
  962. }
  963. }
  964. $html = str_replace(
  965. array_keys($replacements),
  966. array_values($replacements),
  967. $html
  968. );
  969. // images
  970. $replacements = array();
  971. $tags = nvweb_tags_extract($html, 'img', NULL, true, 'UTF-8');
  972. foreach($tags as $tag)
  973. {
  974. if(isset($tag['attributes']['srcset']))
  975. {
  976. $srcset_old = explode(",", $tag['attributes']['srcset']);
  977. $srcset_new = array();
  978. foreach($srcset_old as $src)
  979. {
  980. $src = trim($src);
  981. $src = explode(" ", $src);
  982. if( substr($src[0], 0, 7)!='http://' &&
  983. substr($src[0], 0, 8)!='https://' &&
  984. substr($src[0], 0, 2)!='//')
  985. {
  986. $src[0] = $website_absolute_path.'/'.$src[0];
  987. }
  988. if(substr($src[0], 0, 2)=='//')
  989. $src[0] = $website->protocol.substr($src[0], 2);
  990. $srcset_new[] = implode(" ", $src);
  991. $tag['attributes']['srcset'] = implode(", ", $srcset_new);
  992. }
  993. $tag['new'] = '<img ';
  994. foreach($tag['attributes'] as $name => $value)
  995. $tag['new'] .= $name.'="'.$value.'" ';
  996. $tag['new'] .= '/>';
  997. //$html = str_replace($tag['full_tag'], $tag['new'], $html);
  998. $replacements[$tag['full_tag']] = $tag['new'];
  999. }
  1000. if(!isset($tag['attributes']['src'])) continue;
  1001. if(substr($tag['attributes']['src'], 0, 7)!='http://' &&
  1002. substr($tag['attributes']['src'], 0, 8)!='https://' &&
  1003. substr($tag['attributes']['src'], 0, 5)!='data:')
  1004. {
  1005. if(substr($tag['attributes']['src'], 0, 2)=='//')
  1006. $src = $website->protocol.substr($tag['attributes']['src'], 2);
  1007. else
  1008. $src = $website_absolute_path.'/'.$tag['attributes']['src'];
  1009. $tag['new'] = '<img src="'.$src.'" ';
  1010. foreach($tag['attributes'] as $name => $value)
  1011. {
  1012. if($name!='src') $tag['new'] .= $name.'="'.$value.'" ';
  1013. }
  1014. $tag['new'] .= '/>';
  1015. //$html = str_replace($tag['full_tag'], $tag['new'], $html);
  1016. $replacements[$tag['full_tag']] = $tag['new'];
  1017. }
  1018. }
  1019. $html = str_replace(
  1020. array_keys($replacements),
  1021. array_values($replacements),
  1022. $html
  1023. );
  1024. // replace any "navigate_download.php" request for "/object" request
  1025. $html = nvweb_template_fix_download_paths($html);
  1026. // tweak 2: convert <a rel="video"> to <video> and <a rel="audio"> to <audio> tags
  1027. $replacements = array();
  1028. $tags = nvweb_tags_extract($html, 'a', NULL, true, 'UTF-8');
  1029. foreach($tags as $tag)
  1030. {
  1031. if($tag['attributes']['rel']=='video' && $tag['attributes']['navigate']=='navigate')
  1032. {
  1033. $preload = 'metadata';
  1034. if(!empty($tag['attributes']['preload']))
  1035. $preload = $tag['attributes']['preload'];
  1036. $content = array();
  1037. $content[] = '<video controls="controls" preload="'.$preload.'">';
  1038. $content[] = ' <source src="'.$tag['attributes']['href'].'" />';
  1039. $content[] = ' '.$tag['full_tag'];
  1040. $content[] = '</video>';
  1041. //$html = str_replace($tag['full_tag'], implode("\n", $content), $html);
  1042. $replacements[$tag['full_tag']] = implode("\n", $content);
  1043. }
  1044. if($tag['attributes']['rel']=='audio' && $tag['attributes']['navigate']=='navigate')
  1045. {
  1046. $preload = 'metadata';
  1047. if(!empty($tag['attributes']['preload']))
  1048. $preload = $tag['attributes']['preload'];
  1049. $content = array();
  1050. $content[] = '<audio controls="controls" preload="'.$preload.'">';
  1051. $content[] = ' <source src="'.$tag['attributes']['href'].'" type="'.$tag['attributes']['type'].'" />';
  1052. $content[] = ' '.$tag['full_tag'];
  1053. $content[] = '</audio>';
  1054. //$html = str_replace($tag['full_tag'], implode("\n", $content), $html);
  1055. $replacements[$tag['full_tag']] = implode("\n", $content);
  1056. }
  1057. }
  1058. $html = str_replace(
  1059. array_keys($replacements),
  1060. array_values($replacements),
  1061. $html
  1062. );
  1063. // tweak 3: let navigate generate a resized image/thumbnail if width/height is given in the img tag
  1064. $tags = nvweb_tags_extract($html, 'img', NULL, true, 'UTF-8');
  1065. $replacements = array();
  1066. foreach($tags as $tag)
  1067. {
  1068. if(!isset($tag['attributes']['src'])) continue;
  1069. $src = $tag['attributes']['src'];
  1070. $tag['new'] = '';
  1071. foreach($tag['attributes'] as $name => $value)
  1072. {
  1073. if($name!='src')
  1074. $tag['new'] .= $name.'="'.$value.'" ';
  1075. // width attribute, the image is retrieved from a dynamic source, the width is not expressed in percentage, the width is not already given in the url parameters
  1076. if($name=='width' && strpos($src, '?')!==false && strpos($value, "%")===false && strpos($src, "&width=")===false)
  1077. $src .= '&width='.$value;
  1078. if($name=='height' && strpos($src, '?')!==false && strpos($value, "%")===false && strpos($src, "&height=")===false)
  1079. $src .= '&height='.$value;
  1080. }
  1081. $tag['new'] = '<img src="'.$src.'" '.$tag['new'].'/>';
  1082. $replacements[$tag['full_tag']] = $tag['new'];
  1083. //$html = str_replace($tag['full_tag'], $tag['new'], $html);
  1084. }
  1085. // more efficient than replacing one by one
  1086. $html = str_replace(
  1087. array_keys($replacements),
  1088. array_values($replacements),
  1089. $html
  1090. );
  1091. // tweak 4: add Navigate CMS content default styles
  1092. $default_css = file_get_contents(NAVIGATE_PATH.'/css/tools/tinymce.defaults.css');
  1093. $default_css = str_replace(array("\n", "\r", "\s\s", " "), " ", $default_css);
  1094. $default_css = substr($default_css, strpos($default_css, '/* nvweb */')+11);
  1095. $default_css = '<style type="text/css">'.$default_css.'</style>';
  1096. $html = str_replace('</title>', "</title>\n\t".$default_css."\n", $html);
  1097. return $html;
  1098. }
  1099. /*
  1100. convert nv:// paths to real links
  1101. right now there are two possibilities (ID is a numeric value)
  1102. nv://element/ID (or elements, or item)
  1103. nv://structure/ID (or category)
  1104. */
  1105. function nvweb_template_convert_nv_paths($html)
  1106. {
  1107. preg_match_all("/nv:\/\/(element|elements|structure|category)\/([0-9]+)+/", $html, $matches);
  1108. if(!empty($matches) && !empty($matches[0]))
  1109. {
  1110. $matches = $matches[0];
  1111. foreach($matches as $match)
  1112. {
  1113. $parts = explode('/', str_replace('nv://', '', $match));
  1114. $url = "";
  1115. switch($parts[0])
  1116. {
  1117. case 'element':
  1118. case 'item':
  1119. case 'elements':
  1120. $url = nvweb_source_url("element", $parts[1]);
  1121. break;
  1122. case 'structure':
  1123. case 'category':
  1124. $url = nvweb_source_url("structure", $parts[1]);
  1125. break;
  1126. default:
  1127. // ignore this url
  1128. }
  1129. if(!empty($url))
  1130. $html = str_replace(
  1131. array('"'.$match.'"', "'".$match."'"),
  1132. array('"'.$url.'"', "'".$url."'"),
  1133. $html
  1134. );
  1135. }
  1136. }
  1137. return $html;
  1138. }
  1139. function nvweb_template_oembed_parse($html)
  1140. {
  1141. $reg_exUrl = '/[-a-zA-Z0-9@:%_\+.~#?&\/\/=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&\/\/=]*)?/i';
  1142. foreach(array('div', 'p', 'span', 'strong') as $tag_name)
  1143. {
  1144. $tags = nvweb_tags_extract($html, $tag_name, false, true);
  1145. foreach($tags as $tag)
  1146. {
  1147. $text = $tag['contents'];
  1148. if(strpos(@$tag['attributes']['class'], 'nv_oembedded')!==false)
  1149. continue;
  1150. // find all urls in content as PLAIN TEXT urls
  1151. if(preg_match_all($reg_exUrl, strip_tags($text), $url))
  1152. {
  1153. $matches = array_unique($url[0]);
  1154. foreach($matches as $match)
  1155. {
  1156. $replacement = nvweb_template_oembed_url($match);
  1157. if($replacement!=$match)
  1158. $text = str_replace($match, '<div class="nv_oembedded">'.$replacement.'</div>', $text);
  1159. }
  1160. }
  1161. if($text!=$tag['contents'])
  1162. {
  1163. $fragment = str_replace($tag['contents'], $text, $tag['full_tag']);
  1164. $html = str_replace($tag['full_tag'], $fragment, $html);
  1165. }
  1166. }
  1167. }
  1168. return $html;
  1169. }
  1170. function nvweb_template_oembed_url($url)
  1171. {
  1172. global $current;
  1173. // TODO: implement more oembed services
  1174. $out = $url;
  1175. // Twitter: https://twitter.com/username/status/status_id
  1176. if(strpos($url, 'twitter.com/')!==false && strpos($url, '/status')!==false)
  1177. {
  1178. $oembed_url = 'https://api.twitter.com/1/statuses/oembed.json?lang='.$current['lang'].'&url='.urlencode($url); // &omit_script=true
  1179. $response = nvweb_template_oembed_cache('twitter', $oembed_url);
  1180. if(!empty($response->html))
  1181. $out = $response->html;
  1182. }
  1183. // Youtube: http://www.youtube.com?watch=3MteSlpxCpo
  1184. else if(strpos($url, 'www.youtube.com/watch'))
  1185. {
  1186. $oembed_url = 'https://www.youtube.com/oembed?url='.urlencode($url).'&format=json';
  1187. $response = nvweb_template_oembed_cache('youtube', $oembed_url);
  1188. if(!empty($response->html))
  1189. $out = $response->html;
  1190. }
  1191. // Vimeo: http://vimeo.com/channels/staffpicks/113397445
  1192. else if(strpos($url, 'www.vimeo.com/') || strpos($url, 'vimeo.com/'))
  1193. {
  1194. $oembed_url = 'https://vimeo.com/api/oembed.json?url='.urlencode($url);
  1195. $response = nvweb_template_oembed_cache('vimeo', $oembed_url);
  1196. if(!empty($response->html))
  1197. $out = $response->html;
  1198. }
  1199. // Instagram: https://www.instagram.com/p/BInLvYQDSHe/
  1200. else if( strpos($url, 'www.instagram.com/p/') ||
  1201. strpos($url, 'instagram.com/p/') ||
  1202. strpos($url, 'instagr.am/p/')
  1203. )
  1204. {
  1205. $oembed_url = 'https://api.instagram.com/oembed?url='.urlencode($url);
  1206. $response = nvweb_template_oembed_cache('instagram', $oembed_url);
  1207. if(!empty($response->html))
  1208. $out = $response->html;
  1209. }
  1210. // Flickr: http://www.flickr.com/photos/bees/2362225867
  1211. else if(strpos($url, 'www.flickr.com/photos/'))
  1212. {
  1213. $oembed_url = 'https://www.flickr.com/services/oembed.json?url='.urlencode($url);
  1214. $response = nvweb_template_oembed_cache('flickr', $oembed_url);
  1215. if(!empty($response->html))
  1216. $out = $response->html;
  1217. }
  1218. // DailyMotion: http://www.dailymotion.com/video/x40gjsb_stock-video-category-nature-landscapes-corsican-nature-island-of-beauty-sea-beach_shortfilms
  1219. else if(strpos($url, 'www.dailymotion.com/video/'))
  1220. {
  1221. $oembed_url = 'https://www.dailymotion.com/services/oembed?format=json&url='.urlencode($url);
  1222. $response = nvweb_template_oembed_cache('dailymotion', $oembed_url);
  1223. if(!empty($response->html))
  1224. $out = $response->html;
  1225. }
  1226. // Scribd: https://www.scribd.com/doc/110799637
  1227. else if(strpos($url, 'www.scribd.com/doc/'))
  1228. {
  1229. $oembed_url = 'https://www.scribd.com/services/oembed?format=json&url='.urlencode($url);
  1230. $response = nvweb_template_oembed_cache('scribd', $oembed_url);
  1231. if(!empty($response->html))
  1232. $out = $response->html;
  1233. }
  1234. // Soundcloud: https://soundcloud.com/elvenlied/ivan-torrent-icarus-feat-julie
  1235. else if(strpos($url, 'soundcloud.com/'))
  1236. {
  1237. $oembed_url = 'https://soundcloud.com/oembed?format=json&url='.urlencode($url);
  1238. $response = nvweb_template_oembed_cache('soundcloud', $oembed_url);
  1239. if(!empty($response->html))
  1240. $out = $response->html;
  1241. }
  1242. return $out;
  1243. }
  1244. // default cache 43200 minutes (30 days)
  1245. function nvweb_template_oembed_cache($provider, $oembed_url, $minutes=43200)
  1246. {
  1247. $file = NAVIGATE_PRIVATE.'/oembed/'.$provider.'.'.md5($oembed_url).'.json';
  1248. if(file_exists($file) && filemtime($file) > (time() - ($minutes * 60)))
  1249. {
  1250. // a previous request has already been posted in the last xx minutes
  1251. $response = file_get_contents($file);
  1252. }
  1253. else
  1254. {
  1255. // request has not been cached or it has expired
  1256. $response = core_curl_post($oembed_url, NULL, NULL, 60, "get");
  1257. if($response=='Not found')
  1258. $response = '';
  1259. if(!empty($response))
  1260. file_put_contents($file, $response);
  1261. }
  1262. if(!empty($response))
  1263. $response = json_decode($response);
  1264. return $response;
  1265. }
  1266. function nvweb_template_processes($html)
  1267. {
  1268. global $session;
  1269. global $theme;
  1270. if(isset($session['nv.webuser/verify:email_confirmed']))
  1271. {
  1272. unset($session['nv.webuser/verify:email_confirmed']);
  1273. $text = $theme->t("subscribed_ok");
  1274. if(empty($text) || $text=="subscribed_ok")
  1275. $text = t(37, "E-Mail confirmed");
  1276. nvweb_after_body(
  1277. "html",
  1278. '<div id="nv_webuser_verify_email_confirmed" style=" transition: all 1s; text-align: center; width: 40%; padding: 12px; margin: -48px 30% 0 30%; top: 50%; color: #555; position: fixed; z-index: 1000000; background: rgba(240, 255, 240, 0.7); box-shadow: 0 0 7px -2px #777; ">
  1279. <span style="vertical-align: middle; font-size: 200%; ">&#10003;</span>
  1280. &nbsp;&nbsp;
  1281. <span style="font-size: 125%; vertical-align: middle; ">'.$text.'</span>
  1282. </div>'
  1283. );
  1284. nvweb_after_body(
  1285. "js",
  1286. 'setTimeout(function() {
  1287. document.getElementById("nv_webuser_verify_email_confirmed").style.opacity = 0;
  1288. setTimeout(function()
  1289. {
  1290. document.getElementById("nv_webuser_verify_email_confirmed").style.display = "none";
  1291. },
  1292. 1000);
  1293. }, 8000);'
  1294. );
  1295. }
  1296. if(isset($session['nv.comments/unsubscribe']))
  1297. {
  1298. unset($session['nv.comments/unsubscribe']);
  1299. $text = $theme->t("unsubscribed_ok");
  1300. if(empty($text) || $text=="unsubscribed_ok")
  1301. $text = t(654, "Cancelled subscription");
  1302. nvweb_after_body(

Large files files are truncated, but you can click here to view the full file