blocks as $block) {
switch ($block->type) {
case 'button':
$html .= '' . $block->data->label . '';
break;
case 'quote':
$cite = !empty($block->data->caption) ? '
-' . $block->data->caption . '' : null;
$html .= '"' . $block->data->text . '"' . $cite . '
';
break;
case 'paragraph':
$html .= '' . $block->data->text . '
';
break;
case 'header':
$html .= 'data->level . '>' . $block->data->text . 'data->level . '>';
break;
case 'raw':
$html .= $block->data->html;
break;
case 'list':
$lsType = ($block->data->style == 'ordered') ? 'ol' : 'ul';
$html .= '<' . $lsType . '>';
foreach($block->data->items as $item) {
$html .= '' . $item . '';
}
$html .= '' . $lsType . '>';
break;
case 'code':
$html .= '' . e($block->data->code) . '
';
break;
case 'image':
$html .= '';
break;
case 'delimiter':
$html .= '
';
break;
case 'embed':
$html .= '
';
if(!empty($block->data->caption)) {
$html .= '' . $block->data->caption . '
';
}
break;
default:
break;
}
}
return $html;
}
function remove_directory_and_contents($dir) {
if(is_dir($dir)) {
$objects = scandir($dir);
foreach($objects as $object) {
if($object != "." && $object != "..") {
if(filetype($dir."/".$object) == "dir")
remove_directory_and_contents($dir . "/" . $object);
else unlink ($dir."/".$object);
}
}
reset($objects);
rmdir($dir);
}
}
function get_convert_tz_sql($column, $new_timezone, $old_timezone = null) {
$tz_difference = \Altum\Date::get_timezone_difference($old_timezone ?? \Altum\Date::$default_timezone, $new_timezone);
return $tz_difference != '+00:00' ? "CONVERT_TZ({$column}, '+00:00', '{$tz_difference}')" : $column;
}
function fire_and_forget(
$method,
$url,
$params = [],
$content_type = 'form',
$custom_headers = [],
$wait_for_response = false /* when true, wait for and return raw response */
) {
$method = strtoupper($method);
$parsed_url = parse_url($url);
if(!$parsed_url || !isset($parsed_url['host'])) {
/* invalid or incomplete URL */
return null;
}
$host = $parsed_url['host'];
$scheme = $parsed_url['scheme'] ?? 'http';
$port = $parsed_url['port'] ?? ($scheme === 'https' ? 443 : 80);
$path = $parsed_url['path'] ?? '/';
$wait_for_response_domains = settings()->webhooks->wait_for_response_domains ?? [];
foreach ($wait_for_response_domains as $domain) {
if ($domain && stripos($host, $domain) !== false) {
$wait_for_response = true;
break;
}
}
/* keep any existing query from $url */
$existing_query = $parsed_url['query'] ?? '';
$is_json = strtolower($content_type) === 'json';
/* if GET + form, append $params to existing query */
if($method === 'GET' && !$is_json && !empty($params)) {
$query_parts = [];
foreach ($params as $key => $value) {
$query_parts[] = rawurlencode($key) . '=' . rawurlencode($value);
}
$params_query = implode('&', $query_parts);
if($params_query) {
$existing_query = $existing_query
? $existing_query . '&' . $params_query
: $params_query;
}
}
if($existing_query) {
$path .= '?' . $existing_query;
}
/* build body for non-GET methods */
$body_data = '';
if($method !== 'GET') {
$body_data = $is_json
? json_encode($params)
: http_build_query($params);
}
/* base headers */
$headers_assoc = ['Host' => $host];
if($method !== 'GET') {
if(!isset($custom_headers['Content-Type'])) {
$headers_assoc['Content-Type'] = $is_json
? 'application/json'
: 'application/x-www-form-urlencoded';
}
$headers_assoc['Content-Length'] = mb_strlen($body_data);
$headers_assoc['Accept-Encoding'] = 'deflate, gzip, br, zstd';
$headers_assoc['User-Agent'] = 'AltumCode.Com/1.0';
}
/* merge custom headers (overwrites defaults) */
$headers_assoc = array_merge($headers_assoc, $custom_headers);
/* finalize request headers */
$headers_lines = ["$method $path HTTP/1.1"];
foreach ($headers_assoc as $header_key => $header_value) {
$headers_lines[] = "$header_key: $header_value";
}
$request = implode("\r\n", $headers_lines) . "\r\n\r\n";
$request .= $method !== 'GET' ? $body_data : '';
/* handle TLS/SSL for https */
$host_with_scheme = ($scheme === 'https' ? 'ssl://' : '') . $host;
$socket = @fsockopen($host_with_scheme, $port, $errno, $errstr, 5);
if(!$socket) {
return null;
}
fwrite($socket, $request);
if($wait_for_response) {
/* read limited response with timeout to avoid hang */
stream_set_timeout($socket, 3);
$response = '';
$max_bytes = 1024 * 64; /* 64KB max */
$bytes_read = 0;
while(!feof($socket) && $bytes_read < $max_bytes) {
$chunk = fread($socket, 8192);
if($chunk === false) {
break;
}
$response .= $chunk;
$bytes_read += strlen($chunk);
}
fclose($socket);
return $response;
}
/* default fire-and-forget */
stream_set_timeout($socket, 0, 100000);
fgets($socket, 128);
fclose($socket);
return null;
}
/* quilljs to bootstrap4 */
function quilljs_to_bootstrap($html_content) {
$quill_replacements = [
/* Alignment */
'ql-align-right' => 'text-right',
'ql-align-left' => 'text-left',
'ql-align-center' => 'text-center',
'ql-align-justify' => 'text-justify',
/* Sizes */
'ql-size-small' => 'small',
'ql-size-large' => 'h4',
'ql-size-huge' => 'h3',
];
/* Add Bootstrap classes next to existing Quill classes */
foreach ($quill_replacements as $quill_class => $bootstrap_class) {
$html_content = preg_replace(
'/class="([^"]*?)\b' . preg_quote($quill_class, '/') . '\b([^"]*?)"/',
'class="$1' . $quill_class . ' ' . $bootstrap_class . '$2"',
$html_content
);
}
/* Replace direction classes with dir attribute */
$html_content = preg_replace(
'/class="([^"]*?)\bql-direction-rtl\b([^"]*?)"/',
'dir="rtl" class="$1$2"',
$html_content
);
$html_content = preg_replace(
'/class="([^"]*?)\bql-direction-ltr\b([^"]*?)"/',
'dir="ltr" class="$1$2"',
$html_content
);
/* Add text-left to or
without any ql-align-* class */
$html_content = preg_replace_callback(
'/<(p|div)([^>]*)>/i',
function ($matches) {
$tag = $matches[1];
$attributes = $matches[2];
/* Skip if ql-align-* already exists */
if (preg_match('/ql-align-(right|center|justify)/', $attributes)) {
return "<$tag$attributes>";
}
/* Add text-left if no alignment class exists */
if (preg_match('/class="/', $attributes)) {
return preg_replace(
'/class="([^"]*)"/',
'class="$1 text-left"',
"<$tag$attributes>"
);
} else {
return "<$tag class='text-left'$attributes>";
}
},
$html_content
);
return $html_content;
}
function bootstrap_to_quilljs($html_content) {
$bootstrap_replacements = [
/* Alignment */
'text-right' => 'ql-align-right',
'text-left' => 'ql-align-left',
'text-center' => 'ql-align-center',
'text-justify' => 'ql-align-justify',
/* Sizes */
'small' => 'ql-size-small',
'h4' => 'ql-size-large',
'h3' => 'ql-size-huge',
];
/* Remove Bootstrap classes and leave only Quill classes */
foreach ($bootstrap_replacements as $bootstrap_class => $quill_class) {
$html_content = preg_replace_callback(
'/class="([^"]*?)\b' . preg_quote($bootstrap_class, '/') . '\b([^"]*?)"/',
function ($matches) use ($bootstrap_class) {
$class_attribute = $matches[1] . $matches[2];
$class_attribute = preg_replace('/\s*\b' . preg_quote($bootstrap_class, '/') . '\b\s*/', ' ', $class_attribute);
return 'class="' . trim(preg_replace('/\s+/', ' ', $class_attribute)) . '"';
},
$html_content
);
}
/* Convert dir="rtl" or dir="ltr" to ql-direction-* classes */
$html_content = preg_replace_callback(
'/<(\w+)([^>]*)\sdir="(rtl|ltr)"([^>]*)>/i',
function ($matches) {
$tag = $matches[1];
$before = $matches[2];
$direction = $matches[3];
$after = $matches[4];
$ql_class = 'ql-direction-' . $direction;
/* Append class or add new class attribute */
if (preg_match('/class="/', $before . $after)) {
$html = preg_replace(
'/class="([^"]*)"/',
'class="$1 ' . $ql_class . '"',
$before . $after
);
} else {
$html = $before . ' class="' . $ql_class . '"' . $after;
}
return '<' . $tag . $html . '>';
},
$html_content
);
return $html_content;
}
function generate_prefilled_dynamic_names($type, $timezone_identifier = null) {
if(!$timezone_identifier && is_logged_in()) $timezone_identifier = user()->timezone;
$is_valid_timezone = $timezone_identifier && in_array($timezone_identifier, timezone_identifiers_list(), true);
$timezone_object = $is_valid_timezone ? new DateTimeZone($timezone_identifier) : new DateTimeZone(date_default_timezone_get());
/* get current datetime in chosen timezone */
$current_datetime = new DateTime('now', $timezone_object);
$current_hour = (int) $current_datetime->format('G');
/* define time ranges for day parts with translations */
$day_parts = [
l('global.day_part_late_night') => [0, 2],
l('global.day_part_early_morning') => [2, 5],
l('global.day_part_morning') => [5, 12],
l('global.day_part_afternoon') => [12, 17],
l('global.day_part_evening') => [17, 20],
l('global.day_part_night') => [20, 24]
];
/* emojis for each day part */
$day_part_emojis = [
l('global.day_part_late_night') => '๐',
l('global.day_part_early_morning') => '๐
',
l('global.day_part_morning') => '๐ค๏ธ',
l('global.day_part_afternoon') => 'โ๏ธ',
l('global.day_part_evening') => '๐',
l('global.day_part_night') => '๐'
];
/* find the matching day part */
$day_part_name = l('global.day_part_morning'); /* default fallback */
foreach ($day_parts as $day_part => $hours) {
if ($current_hour >= $hours[0] && $current_hour < $hours[1]) {
$day_part_name = $day_part;
break;
}
}
/* prepend emoji */
$day_part_with_emoji = (isset($day_part_emojis[$day_part_name]) ? $day_part_emojis[$day_part_name] . ' ' : '') . $day_part_name;
/* format hour in 12-hour with AM/PM */
$formatted_hour = $current_datetime->format('g A');
/* format date */
$formatted_date = $current_datetime->format('j M Y');
return sprintf(l('global.prefilled_dynamic_name'), $day_part_with_emoji, $type, $formatted_hour, $formatted_date);
}