Warning: chmod(): Operation not permitted in /var/www/hopeinstoughton_www/wp-content/plugins/simple-universal-google-analytics/main.php on line 8 [0] in function chmod in /var/www/hopeinstoughton_www/wp-content/plugins/simple-universal-google-analytics/main.php on line 8 [1] in function include_once in /var/www/hopeinstoughton_www/wp-settings.php on line 560 [2] in function require_once in /var/www/hopeinstoughton_www/wp-config.php on line 85 [3] in function require_once in /var/www/hopeinstoughton_www/wp-load.php on line 50 [4] in function require_once in /var/www/hopeinstoughton_www/wp-blog-header.php on line 13 [5] in function require in /var/www/hopeinstoughton_www/index.php on line 17
| Server IP : 94.177.8.99 / Your IP : 216.73.217.165 Web Server : Apache/2.4.58 (Ubuntu) System : Linux aries 6.8.0-134-generic #134-Ubuntu SMP PREEMPT_DYNAMIC Fri Jun 26 18:43:11 UTC 2026 x86_64 User : www-data ( 33) PHP Version : 8.1.34 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/patientapps_beta/include/ |
Upload File : |
<?php
// to do: pass landing page lang_id to procedure guide
if (SERVER == 'TUCANA') {
// define('PUBLISHED_VERSION2', '/var/www/tucana_api/.download');
// define('BOUNCE', 'https://tucana.cc/');
// define('APIURL', 'https://api.tucana.cc/');
define('PUBLISHED_VERSION2', '/var/www/vela_api/.download');
define('BOUNCE', 'https://vela.work/');
define('APIURL', 'https://api.vela.work/');
} elseif (SERVER == 'VELA') {
define('PUBLISHED_VERSION2', '/var/www/vela_api/.download');
define('BOUNCE', 'https://vela.work/');
define('APIURL', 'https://api.vela.work/');
} else {
define('PUBLISHED_VERSION2', '/var/www/patientapps_www/.download');
define('BOUNCE', 'https://patientapps.com/');
define('APIURL', 'https://patientapps.net/');
}
function isVersion2($product) {
$dir = PUBLISHED_VERSION2;
$product = strtolower($product);
return file_exists("$dir/{$product}.json");
}
function guideHash($procedurecode) {
return md5('0L=K37.HCw<JE]FdJa$:' . $procedurecode);
}
function _addVersionDetails(&$products) {
foreach($products as $item) {
$item->md5 = guideHash($item->product);
$base_product = strtolower($item->product);
$item->version = isVersion2($item->product) ? 2 : 1;
}
}
function getShortCode($db, $shortcode) {
$data = $db->Lookup('select sl_full from shortlink where sl_short=%s', $shortcode);
if ($data['__existing']) { // found short code
$data['__element'] = parse_url($data['sl_full']);
return $data;
}
return NULL;
}
function getPreferredLanguage() {
// if specific language specified, use it, if it is present
// choose best langs from browser
}
function _includePreviewData($parameters, $layout) {
$layout = ($layout == '') ? [] : json_decode($layout, TRUE);
$parameters->theme = $layout['preview_theme'] ?? 1;
if (!isset($layout['landing']) || !count($layout['landing'])) return; // no preview
$language = $layout['active_lang'] ?? 'en';
$parameters->language = $language;
$landing = $layout['landing'];
$original = [];
foreach($parameters->products as $item) {
$original[$item->md5] = $item;
}
if ($language != 'en' && isset($landing['title'][$language])) {
$parameters->title = $landing['title'][$language];
} elseif (isset($landing['title']['en'])) {
$parameters->title = $landing['title']['en'];
}
if ($language != 'en' && isset($landing['subtitle'][$language])) {
$parameters->subtitle = $landing['subtitle'][$language];
} elseif (isset($landing['title']['en'])) {
$parameters->subtitle = $landing['subtitle']['en'];
}
$parameters->theme = $layout['preview_theme'] ?? 1;
// error_log(json_encode($layout));
$output = [];
foreach($landing['items'] as $item) {
$hash = $item['hash'];
if (isset($original[$hash])) {
$entry = $original[$hash];
} else {
$entry = new \StdClass;
$entry->md5 = $hash;
}
$entry->active = 1;
if ($language != 'en' && !empty($item['items'][$language])) {
$entry->caption = $item['items'][$language];
} elseif (!empty($item['items']['en'])) {
$entry->caption = $item['items']['en'];
}
$output[] = $entry;
}
$parameters->products = $output;
}
function _getTranslation($data, $language, $fieldname) { // fieldname = ['title','subtitle']
$langs = empty($data['languages']) ? [] : json_decode($data['languages'], TRUE);
if (!empty($langs[$language])) { // the specified non-english (or english) translation is found
if (isset($langs[$language]['title'])) $data['description'] = $langs[$language]['title'] ;
if (isset($langs[$language]['subtitle'])) $data['subtitle'] = $langs[$language]['subtitle'];
}
if ($fieldname == 'title') {
return empty($data['description']) ? 'Untitled' : $data['description'];
} elseif ($fieldname == 'subtitle') {
return empty($data['subtitle']) ? 'Please select a procedure from the list below' : $data['subtitle'];
}
return '';
}
function _loadLandingPageInfo($data, $client_language, $preview) {
$parameters = new \StdClass;
$parameters->preview = $preview;
$parameters->hilite = ''; // nothing to be hilited. only for Preview mode
$parameters->language = $client_language;
$parameters->title = _getTranslation($data, $client_language, 'title');
$parameters->subtitle = _getTranslation($data, $client_language, 'subtitle');
$parameters->products = json_decode($data['products']);
$parameters->theme = (int) $data['theme'];
_addVersionDetails($parameters->products); // which of these are version2?
if ($preview) {
_includePreviewData($parameters, $data['layout']);
}
switch($parameters->theme) {
case 2:
$parameters->renderpage = 'renderProductList_theme2';
$parameters->renderitem = 'renderItem_theme2';
$parameters->renderlang = 'renderLanguage';
break;
case 1:
default:
$parameters->renderpage = 'renderProductList_theme1';
$parameters->renderitem = 'renderItem_theme1';
$parameters->renderlang = 'renderLanguage';
break;
}
return $parameters;
}
// display just a single item from the menu using the active theme - used when adding a guide
function displayProductItem($db, $customer, $shortcode, $hash) {
$data = $db->Lookup('select * from `product_group` where guid_client=%s and shortcode=%s', [$customer, $shortcode]);
$client_language = 'en';
$params = _loadLandingPageInfo($data, $client_language, TRUE);
$entry = NULL;
foreach($params->products as $product) {
if ($product->md5 == $hash) {
$entry = $product;
break;
}
}
if (!is_null($entry)) {
$params->products = [$entry];
return productListAsHtml($params, '', FALSE);
}
return '';
}
function byPriority($list) {
$optionlist = explode(',', $list);
$output = [];
foreach($optionlist as $langitem) { // nl,en-us;q=0.7,en;q=0.3 // qualifier
$elements = explode(';', $langitem);
$langid = array_shift($elements);
$langid = strtolower(trim($langid));
$qualifier = '';
$value = '1.0';
foreach($elements as $element) {
list($type, $x) = explode('=', trim($element), 2);
if ($type == 'q') {
$value = $x;
}
}
if (!isset($output[$langid])) $output[$langid] = intval($value * 100);
}
// sort by the qualifier
asort($output, SORT_NUMERIC);
$output = array_reverse($output);
return $output;
}
function _determineBestLanguage($languages) {
$languages = array_column($languages, 'lang_id');
// language from query string
$lang_id = $_GET['lang'] ?? '';
if ($lang_id != '') {
if (in_array($lang_id, $languages)) return $lang_id;
}
// choose language based on browser
$list = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? 'en;q=0.5';
$langs = byPriority($list);
foreach($langs as $lang_id => $value) {
if (in_array($lang_id, $languages)) return $lang_id;
}
return 'en';
}
function _getActiveLanguages($languages) {
$languages = empty($languages) ? ['en' => [ 'active' => 1]] : json_decode($languages, TRUE);
$result = [];
foreach($languages as $lang_id => $langinfo) {
if ($langinfo['active']) $result[] = [
'lang_id' => $lang_id,
'lang_abbr' => $langinfo['lang_abbr'],
'lang_desc' => $langinfo['lang_desc'],
];
}
return $result;
}
function displayProductList($db, $customer, $shortcode, $preview = FALSE, $hilite = '') {
$v = isset($_GET['v']) ? $_GET['v'] : '';
$emulator = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
$emulator = strpos($emulator, 'sdk_gphone_x86_arm') !== FALSE ? 1 : 0;
$data = $db->Lookup('select * from `product_group` where guid_client=%s and shortcode=%s', [$customer, $shortcode]);
$active_languages = _getActiveLanguages($data['languages']);
if (empty($data['__existing'])) {
redirect(BOUNCE);
exit;
}
if (!$preview) {
$client_language = _determineBestLanguage($active_languages);
} else {
$client_language = 'en';
}
$parameters = _loadLandingPageInfo($data, $client_language, $preview);
$parameters->languages = $active_languages;
$parameters->hilite = $hilite;
$parameters->itemlist = productListAsHtml($parameters, $v, $emulator);
$callback = $parameters->renderpage;
echo $callback($parameters);
}
function productListAsHtml($parameters, $v, $emulator = FALSE) {
$itemlist = '';
$deeplink = version_compare($v, '1.9.36') >= 0;
$preview = $parameters->preview;
$callback = $parameters->renderitem;
$key = $parameters->language == 'en' ? 'caption' : 'caption.' . $parameters->language;
foreach($parameters->products as $product) {
$active = $product->active ?? 0;
if ($active) {
if (property_exists($product, $key) && !$preview) {
$caption = $product->$key;
} else {
$caption = $product->caption;
}
if ($deeplink && $product->version >= 2) {
$p = rawurlencode($product->shortcode);
if ($emulator) {
$url = "exp://192.168.1.216:19000/--/external?p={$p}";
} else {
$url = APIURL . "external?p={$p}";
}
} else {
if (SERVER == 'TUCANA') {
$url = "https://hub.tucana.cc/{$product->shortcode}";
} elseif (SERVER == 'VELA') {
$url = "https://hub.vela.work/{$product->shortcode}";
} else {
$url = "https://myapp.care/{$product->shortcode}";
}
}
$safe_caption = htmlspecialchars($caption);
if ($preview) {
$element = "<span class=\"bind-medium ver{$product->version}\">{$safe_caption}</span>";
} else {
$element = "<a class=\"ver{$product->version}\" href=\"{$url}\">{$safe_caption}</a>";
}
$item = $callback($parameters, $product, $element);
$itemlist .= $item;
}
}
return $itemlist;
}
function readerLanguageSelection($parameters) {
$callback = $parameters->renderlang;
$item = $callback($parameters);
return $item;
}
function renderHeader($parameters, $styles, $extra = '') {
$preview = $parameters->preview;
$header = '';
if ($preview) {
$time = '?_=' . time();
$header .= <<<BLOCK
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.js"></script>
<script type="text/javascript" src="https://code.jquery.com/ui/1.13.0/jquery-ui.min.js"></script>
<link type="text/css" rel="stylesheet" href="//cdn.jsdelivr.net/npm/medium-editor@5.23.2/dist/css/medium-editor.min.css">
<link type="text/css" rel="stylesheet" href="/static/preview.css{$time}">
<script type="text/javascript" src="//cdn.jsdelivr.net/npm/medium-editor@5.23.2/dist/js/medium-editor.min.js"></script>
<script type="text/javascript" src="/static/preview.js{$time}"></script>
BLOCK;
}
return <<<BLOCK
<!DOCTYPE html><html lang="{$parameters->language}" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Exo+2:wght@300;600&display=swap" rel="stylesheet">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png">
<link rel="shortcut icon" href="/favicon.ico">
<link rel="apple-touch-icon" sizes="180x180" href="/pwa/apple-touch-icon/apple-touch-icon-180.png">
$header
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function(event) {
const languages = document.querySelectorAll('.action-language');
languages.forEach(icon => {
icon.addEventListener('click', function handleClick(event) {
event.preventDefault();
let lang_id = this.dataset.lang;
document.location.href = '?lang=' + lang_id;
});
});
});
</script>
$extra <style type="text/css">
$styles
</style>
</head>
BLOCK;
}
function renderProductList_theme1($parameters) {
$styles = <<<'BLOCK'
html {
width: 100%;
height: 100%;
}
body {
width: 100%;
height: 100%;
overflow: hidden;
margin: 0;
padding: 0;
background: #004e60 no-repeat url("/static/title_background.jpg");
position: relative;
}
.inner-frame {
position: absolute;
top: 10px;
left: 10px;
bottom: 10px;
right: 10px;
background-color: rgba(89, 160, 207, 0.3);
flex-flow: column nowrap;
justify-content: stretch;
display: flex;
}
.landing-container {
display: table;
width: 100%;
height: 100%;
position: relative;
}
.language-container {
position: absolute;
top: -12px;
right: 0;
display: inline-block;
}
.language-list {
display: inline-block;
padding: 10px 5px;
}
.language-container .handle {
display: inline-block;
background-color: #000;
color: #ffff00;
margin: 0 2px;
padding: 2px 5px 4px;
font-family: 'Exo 2', sans-serif;
font-weight: bold;
}
.language-container .handle.active {
background-color: #ffff00;
color: #000;
}
.language-container .handle .icon {
pointer-events: none;
}
.landing-row {
display: table-row;
}
.sec-header {
display: table-cell;
padding: 6pt;
font-family: 'Exo 2', sans-serif;
font-size: 20pt;
color: #ffff00;
font-weight: 600;
}
.sec-tagline {
display: table-cell;
padding: 6pt;
font-family: 'Exo 2', sans-serif;
font-size: 10pt;
color: #ffff00;
}
.sec-body {
display: table-cell;
vertical-align: top;
position: relative;
height: 100%;
}
ul.product-list {
list-style: none;
padding-left: 0;
overflow-y: auto;
width: 100%;
margin-top: 6px;
}
.product-list {
position: absolute;
z-index: 30;
top: 0;
bottom: 0;
left: 0
right: 0;
font-family: 'Exo 2', sans-serif;
font-size: 16pt;
color: #fff;
font-weight: 400;
}
.col-wrapper {
display: inline-block;
width: 290px;
background-color: rgba(255,255,255,0.3);
padding: 0 10px;
border-radius: 5px;
}
.page-footer {
position: absolute;
right: 0;
bottom: 0;
margin: 10px;
font-family: 'Exo 2', sans-serif;
font-weight: 300;
font-size: 12pt;
}
.product-item {
width: 460px;
border: 1px solid #999;
background-color: rgba(255,255,255,0.8);
border-radius: 10px;
margin: 5px;
padding: 5px;
display: table;
}
.product-item div {
vertical-align: middle;
display: table-cell;
}
.product-item .handle {
width:50px;
}
.product-item .icon {
background-image: url(/static/read-book.svg);
width: 48px;
height: 39px;
display: inline-block;
}
.product-item .link {
padding-left: 5px;
}
.product-item a:hover,
.product-item a:link {
text-decoration: none;
}
@media (orientation: landscape) {
body {
background-size: cover;
}
.sec-header {
font-size: 32px;
}
}
@media (orientation: portrait) {
body {
background-size: auto 100%;
}
}
@media screen and (max-width: 2048px) {
.sec-header {
font-size: calc(21.3px + (100vw - 512px) / 143.55);
}
.product-list {
}
}
@media screen and (min-width: 512.01px) and (max-width: 964px) {
.product-list {
width: calc(100vw - 25px);
}
.product-item {
width: calc(50vw - 49px);
min-width: 360px;
}
}
@media screen and (max-width: 512px) {
.sec-header {
font-size: 21.3px;
padding: 3pt;
}
.sec-tagline {
font-size: 10.7px;
padding: 3pt;
}
.product-list {
font-size: 12pt;
padding: 3pt;
}
.col-wrapper {
width: 170px;
font-size: 9pt;
}
.product-list {
width: calc(100vw - 25px);
}
.product-item {
width: calc(100vw - 64px);
}
}
BLOCK;
$header = renderHeader($parameters, $styles);
$safe_title = htmlspecialchars($parameters->title);
$safe_subtitle = htmlspecialchars($parameters->subtitle); // this should allow some basic html tags
$safe_preview = $parameters->preview ? ' class="preview"' : '';
$html_languages = readerLanguageSelection($parameters);
return <<<BLOCK
$header
<body{$safe_preview}>
<div class="inner-frame">
<div class="landing-container">
<div class="language-container">{$html_languages}</div>
<div class="landing-row">
<div class="sec-header bind-medium" data-key="title">{$safe_title}</div>
</div>
<div class="landing-row">
<div class="sec-tagline bind-medium" data-key="subtitle">{$safe_subtitle}</div>
</div>
<div class="landing-row" style="height: 100%">
<div class="sec-body">
<ul class="product-list bind-sortable">
{$parameters->itemlist}
</ul>
</div>
</div>
</div>
<div class="page-footer">
<div class="col-wrapper">
<div class="smalltext">Powered by</div>
<a href="https://patientapps.com/" target="_blank"><img src="https://patientapps.com/static/images/patientappslogo-big.svg"></a>
</div>
</div>
</div>
</body>
</html>
BLOCK;
}
function renderItem_theme1($parameters, $product, $element) {
$hash = $product->md5;
$item = <<<BLOCK
<li class="product-item" data-key="{$hash}">
<div class="handle">
<span class="icon"></span>
</div>
<div class="link">$element</div>
</li>
BLOCK;
return $item;
}
function renderProductList_theme2($parameters) {
$extra = <<<BLOCK
<link type="text/css" rel="stylesheet" href="/static/icomoon.css">
BLOCK;
$styles = <<<BLOCK
html {
height: 100%;
}
body {
box-sizing: border-box;
background-color: rgba(208, 229, 250, 0.8);
width: 100%;
margin: 0;
padding: 0;
height: 100%;
position: relative;
}
.product-container {
width: 600px;
max-width: 100%;
margin: 0 auto;
box-sizing: border-box;
padding: 5px;
}
ul.product-list {
box-sizing: border-box;
list-style: none;
padding-left: 0;
overflow-y: auto;
margin-top: 6px;
}
.product-list .product-item {
margin: 8px 0;
background-color: #fff;
border-radius: 50px;
align-self: stretch;
align-items: flex-start;
justify-content: flex-start;
flex-direction: row;
padding: 10px;
flex: 1 1 0%;
display: flex;
}
.product-list .product-item .handle {
width: 50px;
min-width: 50px;
height: 50px;
background-color: rgb(243, 113, 33);
align-self: center;
border-radius: 25px;
}
.product-list .product-item .icon {
font-size: 28px;
color: #fff;
font-weight: normal;
font-style: normal;
margin-left: 11px;
margin-top: 9px;
display: inline-block;
}
.product-list .product-item .link {
font: 20px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
color: #000;
margin: 0px;
padding: 0 0 0 10px;
text-align: inherit;
text-decoration: none;
white-space: pre-wrap;
overflow-wrap: break-word;
align-self: center;
}
.product-list .product-item .link a,
.product-list .product-item .link a:link,
.product-list .product-item .link a:visited {
text-decoration: none;
color: #333;
}
.product-list .product-item .link a:hover {
text-decoration: underline;
}
.sec-header {
font-style: normal;
font-weight: normal;
color: #666;
font: 28px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
.sec-tagline {
font-style: normal;
font-weight: normal;
color: rgb(89, 160, 207);
font: 18px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
.language-container {
position: absolute;
bottom: 5px;
width: 100%;
text-align: center;
}
.language-list {
background-color: #fff;
border-radius: 50px;
display: inline-block;
padding: 10px 5px;
}
.language-container .handle {
display: inline-block;
margin: 0 5px;
text-align: center;
width: 50px;
min-width: 50px;
height: 50px;
border: 1px solid rgb(243, 113, 33);
background-color: #fff;
align-self: center;
border-radius: 25px;
cursor: pointer;
}
.language-container .icon {
color: rgb(243, 113, 33);
font-weight: normal;
font-style: normal;
margin-top: 3px;
margin-left: 0;
display: inline-block;
pointer-events: none;
font: 28px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
.language-container .handle.active {
background-color: rgb(243, 113, 33);
}
.language-container .handle.active .icon {
color: #fff;
}
BLOCK;
$header = renderHeader($parameters, $styles, $extra);
$safe_preview = $parameters->preview ? ' class="preview"' : '';
$safe_title = htmlspecialchars($parameters->title);
$safe_subtitle = htmlspecialchars($parameters->subtitle); // this should allow some basic html tags
$html_languages = readerLanguageSelection($parameters);
return <<<BLOCK
$header
<body{$safe_preview}>
<div class="product-container">
<div class="landing-row">
<div class="sec-header bind-medium" data-key="title">{$safe_title}</div>
</div>
<div class="landing-row">
<div class="sec-tagline bind-medium" data-key="subtitle">{$safe_subtitle}</div>
</div>
<ul class="product-list bind-sortable">
{$parameters->itemlist}
</ul>
</div>
<div class="language-container">$html_languages</div>
</body>
</html>
BLOCK;
// return '<pre>' . htmlspecialchars(var_export($parameters, 1)) . '</pre>';
}
function renderItem_theme2($parameters, $product, $element) {
$hash = $product->md5;
$hilite = ($product->shortcode == $parameters->hilite && $parameters->hilite != '') ? ' hilite' : '';
$item = <<<BLOCK
<li class="product-item{$hilite}" data-key="{$hash}">
<div class="handle">
<span class="icon icomoon-doctor"></span>
</div>
<div class="link">$element</div>
</li>
BLOCK;
return $item;
}
function renderLanguage($parameters) {
if (!$parameters->preview && count($parameters->languages) > 1) {
// only if more than 1 language
$output = '';
foreach($parameters->languages as $langinfo) {
$lang_id = $langinfo['lang_id'];
$active = $parameters->language == $lang_id ? ' active' : '';
$output .= "<div class=\"action-language handle{$active}\" data-lang=\"{$lang_id}\" title=\"{$langinfo['lang_desc']} [{$lang_id}]\"><span class=\"icon\">{$langinfo['lang_abbr']}</span></div>";
}
return '<div class="language-list">' . $output . '</div>';
}
return '';
}