Enth\u00e4lt gemischt: Laravel-10-Upgrade + Phase 1 (Contacts-Modul, Duplicats-Commands, Soft-Delete+Merge-Fields) + Phase 2 Code-Umstellungen (inquiry_id, $table='contacts'/'inquiries') + Offers-Modul (Migrationen, Models, offer_id in Booking, offer-Disk in filesystems.php). Phase 2 + Offers werden im folgenden Commit nach dev/backups/phase2-offers-2026-04-17/ verschoben, damit der Workspace auf Phase-1-only (= Test-System-Stand) reduziert ist und direkt auf Live deploybar wird. Tarball-Backup zus\u00e4tzlich unter: ../backups-safety/workspace-pre-phase1-rollback-2026-04-17.tar.gz Made-with: Cursor
387 lines
12 KiB
PHP
387 lines
12 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use Carbon\Carbon;
|
|
|
|
class Util
|
|
{
|
|
|
|
public static function isTestSystem($dev = false)
|
|
{
|
|
if (\Config::get('app.domain_tld') === 'test') {
|
|
if ($dev && config('app.debug') !== true) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static function formatDate()
|
|
{
|
|
if (\App::getLocale() == "en") {
|
|
return 'yyyy-mm-dd';
|
|
}
|
|
return 'dd.mm.yyyy';
|
|
}
|
|
|
|
public static function formatDateDB()
|
|
{
|
|
if (\App::getLocale() == "en") {
|
|
return 'Y-m-d';
|
|
}
|
|
return 'd.m.Y';
|
|
}
|
|
|
|
public static function formatDateTimeDB()
|
|
{
|
|
if (\App::getLocale() == "en") {
|
|
return 'Y-m-d - H:i';
|
|
}
|
|
return 'd.m.Y - H:i';
|
|
}
|
|
public static function _format_text($text, $opt = 'html')
|
|
{
|
|
|
|
if ($opt === 'html') {
|
|
return html_entity_decode(nl2br($text));
|
|
}
|
|
return $text;
|
|
}
|
|
|
|
public static function _format_date($date, $to = 'date')
|
|
{
|
|
if ($to === 'datetime') {
|
|
return Carbon::parse($date)->format(self::formatDateTimeDB());
|
|
}
|
|
return Carbon::parse($date)->format(self::formatDateDB());
|
|
}
|
|
|
|
public static function _reformat_date($date, $to = 'date')
|
|
{
|
|
if ($to === 'datetime') {
|
|
return Carbon::parse($date)->format('Y-m-d - H:i');
|
|
}
|
|
return Carbon::parse($date)->format('Y-m-d');
|
|
}
|
|
|
|
public static function _format_number($value)
|
|
{
|
|
return preg_replace("/[^0-9,]/", "", $value);
|
|
}
|
|
|
|
public static function _number_format($value, $dec = 2)
|
|
{
|
|
return number_format(($value), $dec, ',', '.');
|
|
}
|
|
|
|
public static function _first_replace($value, $search = 're:', $replace = '')
|
|
{
|
|
do {
|
|
$before = strlen($value);
|
|
$value = trim(preg_replace('/^' . $search . '/i', $replace, $value));
|
|
} while ($before !== strlen($value));
|
|
return $value;
|
|
}
|
|
public static function _explodeLines($value = false)
|
|
{
|
|
if ($value) {
|
|
return explode('#', str_replace(array("\r\n", "\r", "\n"), "#", $value));
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static function _implodeLines($value, $glue = PHP_EOL)
|
|
{
|
|
if (is_array($value)) {
|
|
return implode($glue, $value);
|
|
}
|
|
return $value;
|
|
}
|
|
public static function _clean_float($value)
|
|
{
|
|
|
|
$groups = explode(".", preg_replace("/[^0-9.-]/", "", str_replace(',', '.', $value)));
|
|
$lastGroup = 0;
|
|
if (count($groups) > 1) {
|
|
$lastGroup = array_pop($groups);
|
|
}
|
|
$number = implode('', $groups);
|
|
return (strlen($lastGroup) < 3) ? floatval($number . '.' . $lastGroup) : floatval($number . $lastGroup);
|
|
}
|
|
|
|
|
|
public static function sanitize($string, $force_lowercase = true, $anal = false, $substr = false)
|
|
{
|
|
$strip = array(
|
|
"~",
|
|
"`",
|
|
"!",
|
|
"@",
|
|
"#",
|
|
"$",
|
|
"%",
|
|
"^",
|
|
"&",
|
|
"*",
|
|
"(",
|
|
")",
|
|
"_",
|
|
"=",
|
|
"+",
|
|
"[",
|
|
"{",
|
|
"]",
|
|
"}",
|
|
"\\",
|
|
"|",
|
|
";",
|
|
":",
|
|
"\"",
|
|
"'",
|
|
"‘",
|
|
"’",
|
|
"“",
|
|
"”",
|
|
"–",
|
|
"—",
|
|
"—",
|
|
"–",
|
|
",",
|
|
"<",
|
|
".",
|
|
">",
|
|
"/",
|
|
"?"
|
|
);
|
|
$clean = trim(str_replace($strip, "", strip_tags($string)));
|
|
$clean = preg_replace('/\s+/', "_", $clean);
|
|
$clean = ($anal) ? preg_replace("/[^a-zA-Z0-9]/", "", $clean) : $clean;
|
|
|
|
if ($substr) {
|
|
$clean = (strlen($clean) > 33) ? substr($clean, 0, 33) : $clean;
|
|
}
|
|
return ($force_lowercase) ?
|
|
(function_exists('mb_strtolower')) ?
|
|
mb_strtolower($clean, 'UTF-8') :
|
|
strtolower($clean) :
|
|
$clean;
|
|
}
|
|
|
|
public static function replacePlaceholders($search, $replace)
|
|
{
|
|
preg_match_all("/\{{(.+?)\}}/", $search, $matches);
|
|
if (isset($matches[1]) && count($matches[1]) > 0) {
|
|
foreach ($matches[1] as $key => $value) {
|
|
$kvalue = trim($value);
|
|
if (array_key_exists($kvalue, $replace)) {
|
|
$search = preg_replace("/\{\{$value\}\}/", $replace[$kvalue], $search);
|
|
}
|
|
}
|
|
}
|
|
return $search;
|
|
}
|
|
|
|
public static function cleanHTML($html)
|
|
{
|
|
$html = str_replace('font-size: 14px;', ' ', $html);
|
|
$html = str_replace('font-weight: lighter; ', ' ', $html);
|
|
$html = str_replace('font-family: Helvetica, Arial, sans-serif; ', ' ', $html);
|
|
$html = str_replace('font-family: Verdana, sans-serif; ', ' ', $html);
|
|
$html = str_replace('color: rgb(60, 60, 60); ', ' ', $html);
|
|
$html = str_replace(' style=" padding: 0px; margin-right: 0px; margin-left: 0px; margin-bottom: 20px !important; line-height: 20px !important;"', ' ', $html);
|
|
$html = str_replace('property="article"', ' ', $html);
|
|
$html = str_replace(' ', ' ', $html);
|
|
$html = str_replace('https://www.aegypten-online.de', 'https://www.sterntours.de', $html);
|
|
$html = str_replace('https://www.sterntours.de/uploads', 'https://www.sterntours.de/_uploads', $html);
|
|
$html = str_replace('<div class="contentTextPicText"><br></div>', '', $html);
|
|
$html = str_replace('<p><br></p>', '', $html);
|
|
$html = str_replace('src="/docs/', 'src="https://www.sterntours.de/docs/', $html);
|
|
|
|
|
|
$html = str_replace('<figure class="sun-img-figure">', '<div class="mediaA">', $html);
|
|
$html = str_replace('</figure>', '</div>', $html);
|
|
|
|
$html = str_replace('https://www.youtube.com', 'https://www.youtube-nocookie.com', $html);
|
|
|
|
|
|
|
|
// $html = preg_replace("/(</?)div/", "$1p", $html);
|
|
|
|
$html = str_replace('<p> </p>', '', $html);
|
|
$html = str_replace('<p></p>', '', $html);
|
|
|
|
$html = preg_replace('/(<[^>]+) style=".*?"/i', '$1', $html);
|
|
$html = preg_replace('/<p[^>]*>Autor dieses Artikels.*?<\/p[^>]*>/i', '', $html);
|
|
|
|
$html = str_replace('class="contentImage"', 'class="mediaA"', $html);
|
|
|
|
$html = str_replace(' class="MsoNormal"', '', $html);
|
|
|
|
|
|
|
|
$dom = new \DOMDocument('1.0', 'utf-8');
|
|
@$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
|
|
|
|
$removeStyleTags = ['ul', 'li', 'h1', 'h2', 'br'];
|
|
foreach ($removeStyleTags as $removeStyleTag) {
|
|
$elements = $dom->getElementsByTagName($removeStyleTag);
|
|
foreach ($elements as $element) {
|
|
$element->removeAttribute('style');
|
|
}
|
|
}
|
|
|
|
$removeFullTags = ['span', 'a'];
|
|
foreach ($removeFullTags as $removeFullTag) {
|
|
$domElemsToRemove = [];
|
|
$elements = $dom->getElementsByTagName($removeFullTag);
|
|
foreach ($elements as $element) {
|
|
$domElemsToRemove[] = $element;
|
|
}
|
|
foreach ($domElemsToRemove as $domElem) {
|
|
if ($removeFullTag == 'span' && strpos($domElem->getAttribute('style'), 'font-weight: 700') !== false) {
|
|
$new_node = $dom->createTextNode("<strong>" . $domElem->nodeValue . "</strong>");
|
|
} else {
|
|
$new_node = $dom->createTextNode($domElem->nodeValue);
|
|
}
|
|
$domElem->parentNode->replaceChild($new_node, $domElem);
|
|
}
|
|
}
|
|
|
|
|
|
//replace div to p
|
|
|
|
$elements = $dom->getElementsByTagName('div');
|
|
foreach ($elements as $element) {
|
|
$domElemsToRemove[] = $element;
|
|
/* if($element->getAttribute('class') === 'contentTextPicText'){
|
|
$new_node = $dom->createTextNode("<p>".$element->nodeValue."</p>");
|
|
$element->parentNode->replaceChild($new_node, $element);
|
|
} */
|
|
if ($element->getAttribute('class') === 'imageCaption') {
|
|
|
|
$new_node = $dom->createTextNode($element->nodeValue . "</p>");
|
|
$p = $dom->createElement('p', $element->nodeValue);
|
|
$div = $dom->createElement('div');
|
|
// $new_node = $dom->createElement('div', $new_node);
|
|
$div->setAttribute('class', 'mediaInfo');
|
|
$div->appendChild($p);
|
|
|
|
// dump($element);
|
|
// die();
|
|
//
|
|
$element->parentNode->replaceChild($div, $element);
|
|
}
|
|
}
|
|
|
|
$elements = $dom->getElementsByTagName('figcaption');
|
|
foreach ($elements as $element) {
|
|
$domElemsToRemove[] = $element;
|
|
/* if($element->getAttribute('class') === 'contentTextPicText'){
|
|
$new_node = $dom->createTextNode("<p>".$element->nodeValue."</p>");
|
|
$element->parentNode->replaceChild($new_node, $element);
|
|
} */
|
|
|
|
$new_node = $dom->createTextNode($element->nodeValue . "</p>");
|
|
$p = $dom->createElement('p', $element->nodeValue);
|
|
$div = $dom->createElement('div');
|
|
// $new_node = $dom->createElement('div', $new_node);
|
|
$div->setAttribute('class', 'mediaInfo');
|
|
$div->appendChild($p);
|
|
|
|
// dump($element);
|
|
// die();
|
|
//
|
|
$element->parentNode->replaceChild($div, $element);
|
|
}
|
|
|
|
$html = $dom->saveHTML();
|
|
return $html;
|
|
}
|
|
|
|
public static function prepareCollapseValues()
|
|
{
|
|
if (\Session::has('collapse_shows')) {
|
|
$collapse_shows = \Session::get('collapse_shows');
|
|
if (strpos($collapse_shows, ',')) {
|
|
$collapse_shows = explode(',', $collapse_shows);
|
|
return json_encode($collapse_shows);
|
|
}
|
|
return json_encode([0 => $collapse_shows]);
|
|
}
|
|
|
|
return json_encode([0 => 'non']);
|
|
}
|
|
|
|
public static function convertArrayWindowsCharset($values)
|
|
{
|
|
foreach ($values as $key => $string) {
|
|
$values[$key] = self::convertStringWindowsCharset($string);
|
|
}
|
|
return $values;
|
|
}
|
|
|
|
public static function convertStringWindowsCharset($value)
|
|
{
|
|
|
|
$charset = mb_detect_encoding($value, "UTF-8, ISO-8859-1, ISO-8859-15", true);
|
|
return mb_convert_encoding($value, "Windows-1252", $charset);
|
|
}
|
|
|
|
|
|
public static function getMimeFromHeader($http_response_header)
|
|
{
|
|
$pattern = "/^content-type\s*:\s*(.*)$/i";
|
|
if (($header = array_values(preg_grep($pattern, $http_response_header))) &&
|
|
(preg_match($pattern, $header[0], $match) !== false)
|
|
) {
|
|
return $match[1];
|
|
}
|
|
return "";
|
|
}
|
|
|
|
public static function getExtensionFromMime($mine)
|
|
{
|
|
$mime_types = [
|
|
'application/pdf' => 'pdf',
|
|
'image/png' => 'png',
|
|
'image/jpg' => 'jpg',
|
|
'image/jpeg' => 'jpg',
|
|
'text/html; charset=UTF-8' => 'html',
|
|
'text/html' => 'html',
|
|
|
|
];
|
|
return isset($mime_types[$mine]) ? $mime_types[$mine] : "";
|
|
}
|
|
|
|
public static function getURLasContent($url, $base = false)
|
|
{
|
|
$arrContextOptions = array(
|
|
"ssl" => array(
|
|
"verify_peer" => false,
|
|
"verify_peer_name" => false,
|
|
),
|
|
);
|
|
$content = file_get_contents($url, false, stream_context_create($arrContextOptions));
|
|
if ($base) {
|
|
$type = pathinfo($url, PATHINFO_EXTENSION);
|
|
$base64Data = base64_encode($content);
|
|
return 'data:image/' . $type . ';base64,' . $base64Data;
|
|
}
|
|
return $content;
|
|
}
|
|
|
|
public static function _formatBytes($size, $precision = 2)
|
|
{
|
|
if ($size > 0) {
|
|
$size = (int) $size;
|
|
$base = log($size) / log(1024);
|
|
$suffixes = array(' bytes', ' KB', ' MB', ' GB', ' TB');
|
|
|
|
return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
|
|
} else {
|
|
return $size;
|
|
}
|
|
}
|
|
}
|