Update Block System

This commit is contained in:
Julian Prieber 2024-06-21 16:48:00 +02:00
parent 25ce01afb8
commit 4d4c947924
23 changed files with 107 additions and 77 deletions

View File

@ -151,3 +151,45 @@ function strip_tags_except_allowed_protocols($str) {
return $str; return $str;
} }
if(!function_exists('setBlockAssetContext')) {
function setBlockAssetContext($type = null) {
static $currentType = null;
if ($type !== null) {
$currentType = $type;
}
return $currentType;
}
}
// Get custom block assets
if(!function_exists('block_asset')) {
function block_asset($file) {
$type = setBlockAssetContext(); // Retrieve the current type context
return url("block-asset/$type?asset=$file");
}
}
if(!function_exists('get_block_file_contents')) {
function get_block_file_contents($file) {
$type = setBlockAssetContext(); // Retrieve the current type context
return file_get_contents(base_path("blocks/$type/$file"));
}
}
function block_text_translation_check($text) {
if (empty($text)) {
return false;
}
$translate = __("messages.$text");
return $translate === "messages.$text" ? true : false;
}
function block_text($text) {
$translate = __("messages.$text");
return $translate === "messages.$text" ? $text : $translate;
}
function bt($text) {
return block_text($text);
}

View File

@ -12,17 +12,16 @@ class LinkTypeViewController extends Controller
public function getParamForm($typename, $linkId = 0) public function getParamForm($typename, $linkId = 0)
{ {
$data = [ $data = [
'link_title' => '', 'title' => '',
'link_url' => '', 'link' => '',
'button_id' => 0, 'button_id' => 0,
'buttons' => [], 'buttons' => [],
]; ];
if ($linkId) { if ($linkId) {
$link = Link::find($linkId); $link = Link::find($linkId);
$typename = $link->type ?? 'predefined'; $data['title'] = $link->title;
$data['link_title'] = $link->title; $data['link'] = $link->link;
$data['link_url'] = $link->link;
if (Route::currentRouteName() != 'showButtons') { if (Route::currentRouteName() != 'showButtons') {
$data['button_id'] = $link->button_id; $data['button_id'] = $link->button_id;
} }
@ -52,4 +51,32 @@ class LinkTypeViewController extends Controller
return view($typename . '.form', $data); return view($typename . '.form', $data);
} }
public function blockAsset(Request $request, $type)
{
$asset = $request->query('asset');
// Prevent directory traversal in $type
if (preg_match('/\.\.|\/|\\\\/', $type)) {
abort(403, 'Unauthorized action.');
}
// Define allowed file extensions
$allowedExtensions = ['js', 'css', 'img', 'svg', 'gif', 'jpg', 'jpeg', 'png', 'mp4', 'mp3'];
$extension = strtolower(pathinfo($asset, PATHINFO_EXTENSION));
if (!in_array($extension, $allowedExtensions)) {
return response('File type not allowed', Response::HTTP_FORBIDDEN);
}
$basePath = realpath(base_path("blocks/$type"));
$fullPath = realpath(base_path("blocks/$type/$asset"));
if (!$fullPath || !file_exists($fullPath) || strpos($fullPath, $basePath) !== 0) {
return response('File not found', Response::HTTP_NOT_FOUND);
}
return response()->file($fullPath);
}
} }

View File

@ -176,7 +176,7 @@ class UserController extends Controller
'title' => "Predefined Site", 'title' => "Predefined Site",
]; ];
$data['typename'] = $link->type ?? 'predefined'; $data['typename'] = $linkData->type ?? 'predefined';
return view('studio/edit-link', $data); return view('studio/edit-link', $data);
} }
@ -209,6 +209,7 @@ class UserController extends Controller
if (file_exists($linkTypePath)) { if (file_exists($linkTypePath)) {
include $linkTypePath; include $linkTypePath;
$linkData = handleLinkType($request, $linkType); $linkData = handleLinkType($request, $linkType);
$linkData['button_id'] = $linkData['button_id'] ?? 1; // Set 'button_id' unless overwritten by handleLinkType
$linkData['type'] = $linkType->typename; // Ensure 'type' is included in $linkData $linkData['type'] = $linkType->typename; // Ensure 'type' is included in $linkData
} else { } else {
abort(404, "Link type logic not found."); abort(404, "Link type logic not found.");
@ -384,7 +385,7 @@ class UserController extends Controller
$userId = Auth::user()->id; $userId = Auth::user()->id;
$data['pagePage'] = 10; $data['pagePage'] = 10;
$data['links'] = Link::select('id', 'link', 'title', 'order', 'click_number', 'up_link', 'links.button_id')->where('user_id', $userId)->orderBy('up_link', 'asc')->orderBy('order', 'asc')->paginate(99999); $data['links'] = Link::select()->where('user_id', $userId)->orderBy('up_link', 'asc')->orderBy('order', 'asc')->paginate(99999);
return view('studio/links', $data); return view('studio/links', $data);
} }

View File

@ -1,5 +1,4 @@
id: 6 id: 6
typename: email typename: email
title: "Custom Link"
icon: "bi bi-envelope-fill" icon: "bi bi-envelope-fill"
custom_html: false custom_html: false

View File

@ -3,11 +3,11 @@
<select style="display:none" name="button" class="form-control"><option class="button button-default email" value="default email">{{__('messages.Default Email')}}</option></select> <select style="display:none" name="button" class="form-control"><option class="button button-default email" value="default email">{{__('messages.Default Email')}}</option></select>
<label for='title' class='form-label'>{{__('messages.Custom Title')}}</label> <label for='title' class='form-label'>{{__('messages.Custom Title')}}</label>
<input type='text' name='title' value='{{$link_title}}' class='form-control' /> <input type='text' name='title' value='{{$title}}' class='form-control' />
<span class='small text-muted'>{{__('messages.Leave blank for default title')}}</span><br> <span class='small text-muted'>{{__('messages.Leave blank for default title')}}</span><br>
<label for='link' class='form-label'>{{__('messages.E-Mail address')}}</label> <label for='link' class='form-label'>{{__('messages.E-Mail address')}}</label>
<input type='email' name='link' value='{{str_replace("mailto:", "", $link_url)}}' class='form-control' required /> <input type='email' name='link' value='{{str_replace("mailto:", "", $link)}}' class='form-control' required />
<span class='small text-muted'>{{__('messages.Enter your E-Mail')}}</span> <span class='small text-muted'>{{__('messages.Enter your E-Mail')}}</span>
<script> <script>

View File

@ -1,5 +1,4 @@
id: 3 id: 3
typename: heading typename: heading
title: "Custom Link"
icon: "bi bi-card-heading" icon: "bi bi-card-heading"
custom_html: true custom_html: true

View File

@ -1,2 +1,2 @@
<label for='title' class='form-label'>{{__('messages.Heading Text:')}}</label> <label for='title' class='form-label'>{{__('messages.Heading Text:')}}</label>
<input type='text' name='title' value='{{$link_title}}' class='form-control' /> <input type='text' name='title' value='{{$title}}' class='form-control' />

View File

@ -1,5 +1,4 @@
id: 2 id: 2
typename: link typename: link
title: "Custom Link"
icon: "bi bi-link" icon: "bi bi-link"
custom_html: false custom_html: false

View File

@ -1,8 +1,8 @@
<label for='title' class='form-label'>{{__('messages.Title')}}</label> <label for='title' class='form-label'>{{__('messages.Title')}}</label>
<input type='text' name='title' value='{{$link_title}}' class='form-control' required /> <input type='text' name='title' value='{{$title}}' class='form-control' required />
<label for='title' class='form-label'>{{__('messages.URL')}}</label> <label for='title' class='form-label'>{{__('messages.URL')}}</label>
<input type='url' name='link' value='{{$link_url}}' class='form-control' required /> <input type='url' name='link' value='{{$link}}' class='form-control' required />
<div class="custom-control custom-checkbox m-2"> <div class="custom-control custom-checkbox m-2">
<input type="checkbox" class="custom-control-input" value='1' {{((isset($params->GetSiteIcon) ? boolval($params->GetSiteIcon) : false) ? 'checked': '') }} name='GetSiteIcon' id="GetSiteIcon" @if($button_id == 2)checked @endif> <input type="checkbox" class="custom-control-input" value='1' {{((isset($params->GetSiteIcon) ? boolval($params->GetSiteIcon) : false) ? 'checked': '') }} name='GetSiteIcon' id="GetSiteIcon" @if($button_id == 2)checked @endif>

View File

@ -1,5 +1,4 @@
id: 4 id: 4
typename: spacer typename: spacer
title: "Custom Link"
icon: "bi bi-distribute-vertical" icon: "bi bi-distribute-vertical"
custom_html: true custom_html: true

View File

@ -1,5 +1,4 @@
id: 7 id: 7
typename: telephone typename: telephone
title: "Custom Link"
icon: "bi bi-telephone-fill" icon: "bi bi-telephone-fill"
custom_html: false custom_html: false

View File

@ -3,11 +3,11 @@
<select style="display:none" name="button" class="form-control"><option class="button button-default email" value="phone">{{__('messages.Phone')}}</option></select> <select style="display:none" name="button" class="form-control"><option class="button button-default email" value="phone">{{__('messages.Phone')}}</option></select>
<label for='title' class='form-label'>{{__('messages.Custom Title')}}</label> <label for='title' class='form-label'>{{__('messages.Custom Title')}}</label>
<input type='text' name='title' value='{{$link_title}}' class='form-control' /> <input type='text' name='title' value='{{$title}}' class='form-control' />
<span class='small text-muted'>{{__('messages.Leave blank for default title')}}</span><br> <span class='small text-muted'>{{__('messages.Leave blank for default title')}}</span><br>
<label for='link' class='form-label'>{{__('messages.Telephone number')}}</label> <label for='link' class='form-label'>{{__('messages.Telephone number')}}</label>
<input type='tel' name='link' value='{{str_replace("tel:", "", $link_url)}}' class='form-control' required /> <input type='tel' name='link' value='{{str_replace("tel:", "", $link)}}' class='form-control' required />
<span class='small text-muted'>{{__('messages.Enter your telephone number')}}</span> <span class='small text-muted'>{{__('messages.Enter your telephone number')}}</span>
<script> <script>

View File

@ -1,5 +1,4 @@
id: 5 id: 5
typename: text typename: text
title: "Custom Link"
icon: "bi bi-fonts" icon: "bi bi-fonts"
custom_html: true custom_html: true

View File

@ -1,5 +1,5 @@
<label for='text' class='form-label'>{{__('messages.Text to display')}}</label> <label for='text' class='form-label'>{{__('messages.Text to display')}}</label>
<textarea class="form-control @if(env('ALLOW_USER_HTML') === true) ckeditor @endif" name="text" rows="6">{{ $link_title ?? '' }}</textarea> <textarea class="form-control @if(env('ALLOW_USER_HTML') === true) ckeditor @endif" name="text" rows="6">{{ $title ?? '' }}</textarea>
@if(env('ALLOW_USER_HTML') === true) @if(env('ALLOW_USER_HTML') === true)
<script src="{{ asset('assets/external-dependencies/ckeditor.js') }}"></script> <script src="{{ asset('assets/external-dependencies/ckeditor.js') }}"></script>
<script> <script>

View File

@ -1,4 +1,3 @@
id: 8 id: 8
typename: vcard typename: vcard
title: "Custom Link"
icon: "bi bi-person-square" icon: "bi bi-person-square"

View File

@ -4,7 +4,7 @@
@php @php
try { try {
$data = json_decode($link_url); $data = json_decode($link);
$prefix = $data->prefix; $prefix = $data->prefix;
$firstName = $data->first_name; $firstName = $data->first_name;
@ -38,7 +38,7 @@ catch (exception $e) {}
@endphp @endphp
<label for='title' class='form-label'>{{__('messages.Custom Title')}}</label> <label for='title' class='form-label'>{{__('messages.Custom Title')}}</label>
<input type='text' name='link_title' value='{{ $link_title }}' class='form-control' /> <input type='text' name='link_title' value='{{ $title }}' class='form-control' />
<span class='small text-muted'>{{__('messages.Leave blank for default title')}}</span><br> <span class='small text-muted'>{{__('messages.Leave blank for default title')}}</span><br>
{{-- <br><h5>Upload existing file</h5> {{-- <br><h5>Upload existing file</h5>

View File

@ -11,10 +11,10 @@
</select> </select>
<label for='title' class='form-label'>{{__('messages.Custom Title')}}</label> <label for='title' class='form-label'>{{__('messages.Custom Title')}}</label>
<input type='text' name='title' value='{{$link_title}}' class='form-control' /> <input type='text' name='title' value='{{$title}}' class='form-control' />
<span class='small text-muted'>{{__('messages.Leave blank for default title')}}</span><br> <span class='small text-muted'>{{__('messages.Leave blank for default title')}}</span><br>
<label for='link' class='form-label'>{{__('messages.URL')}}</label> <label for='link' class='form-label'>{{__('messages.URL')}}</label>
<input type='url' name='link' value='{{$link_url}}' class='form-control' required /> <input type='url' name='link' value='{{$link}}' class='form-control' required />
<span class='small text-muted'>{{__('messages.Enter the link URL')}}</span> <span class='small text-muted'>{{__('messages.Enter the link URL')}}</span>

View File

@ -1,3 +1,3 @@
<div class='button-text'> {{$link_title}}</div> <div class='button-text'> {{$title}}</div>

View File

@ -1,7 +1,7 @@
<label for='title' class='form-label'>{{__('messages.Title')}}</label> <label for='title' class='form-label'>{{__('messages.Title')}}</label>
<input type='text' name='title' value='{{$link_title}}' placeholder="Leave blank for default video title" class='form-control' /> <input type='text' name='title' value='{{$title}}' placeholder="Leave blank for default video title" class='form-control' />
<label for='link' class='form-label'>{{__('messages.URL')}}</label> <label for='link' class='form-label'>{{__('messages.URL')}}</label>
<input type='url' name='link' value='{{$link_url}}' class='form-control' /> <input type='url' name='link' value='{{$link}}' class='form-control' />
<span class='small text-muted'>{{__('messages.URL to the video')}}</span> <span class='small text-muted'>{{__('messages.URL to the video')}}</span>

View File

@ -1,10 +1,13 @@
<?php use App\Models\UserData; ?> <?php use App\Models\UserData; ?>
@php $initial = 1; @endphp @php
$initial = 1;
@endphp
@foreach($links as $link) @foreach($links as $link)
@if(isset($link->custom_html) && $link->custom_html) @if(isset($link->custom_html) && $link->custom_html)
@include('blocks::' . $link->name . '.display', ['link' => $link, 'initial' => $initial++]) @php setBlockAssetContext($link->type); @endphp
@include('blocks::' . $link->type . '.display', ['link' => $link, 'initial' => $initial++])
@else @else
@switch($link->name) @switch($link->name)
@case('icon') @case('icon')

View File

@ -6,7 +6,7 @@
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-lg-12">
<div class="card rounded"> <div class="card rounded">
<div class="card-body"> <div class="card-body">
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
@ -26,7 +26,6 @@
<input type='hidden' name='linkid' value="{{ $LinkID }}" /> <input type='hidden' name='linkid' value="{{ $LinkID }}" />
<div class="form-group col-lg-8 flex justify-around"> <div class="form-group col-lg-8 flex justify-around">
{{-- <label class='font-weight-bold'>{{__('messages.Blocks')}}</label> --}}
<div class="btn-group shadow m-2"> <div class="btn-group shadow m-2">
<button type="button" id='btnLinkType' class="btn btn-primary rounded-pill" title='{{__('messages.Click to change link blocks')}}' data-toggle="modal" data-target="#SelectLinkType">{{__('messages.Select Block')}} <button type="button" id='btnLinkType' class="btn btn-primary rounded-pill" title='{{__('messages.Click to change link blocks')}}' data-toggle="modal" data-target="#SelectLinkType">{{__('messages.Select Block')}}
<span class="btn-inner"> <span class="btn-inner">
@ -34,30 +33,13 @@
</span> </span>
</button>{{infoIcon(__('messages.Click for a list of available link blocks'))}} </button>{{infoIcon(__('messages.Click for a list of available link blocks'))}}
{{-- <button type="button" class="dropdown-toggle border-0 border-left-1 px-2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="sr-only">{{__('messages.Toggle Dropdown')}}</span>
</button> --}}
{{-- <div class="dropdown-menu">
@foreach ( $LinkTypes as $lt )
<a data-typeid='{{$lt['id']}}' data-typename='{{__('messages.title.'.$ltt)}}' class="dropdown-item doSelectLinkType" href="#">
<i class="{{$lt['icon']}}"></i> {{__('messages.title.'.$ltt)}}
</a>
@endforeach
</div> --}}
<input type='hidden' name='typename' value='{{$typename}}'> <input type='hidden' name='typename' value='{{$typename}}'>
</div> </div>
</div> </div>
{{-- @include("components.pageitems.".$SelectedLinkType['typename']."-form", ['some' => 'data']) --}}
<div id='link_params' class='col-lg-8'></div> <div id='link_params' class='col-lg-8'></div>
<div class="d-flex align-items-center pt-4"> <div class="d-flex align-items-center pt-4">
<a class="btn btn-danger me-3" href="{{ url('studio/links') }}">{{__('messages.Cancel')}}</a> <a class="btn btn-danger me-3" href="{{ url('studio/links') }}">{{__('messages.Cancel')}}</a>
<button type="submit" class="btn btn-primary me-3">{{__('messages.Save')}}</button> <button type="submit" class="btn btn-primary me-3">{{__('messages.Save')}}</button>
@ -67,15 +49,6 @@
// get the form element // get the form element
var form = document.getElementById("my-form"); var form = document.getElementById("my-form");
// check if all required fields are filled out
var requiredFields = form.querySelectorAll("[required]");
for (var i = 0; i < requiredFields.length; i++) {
if (!requiredFields[i].value) {
alert("Please fill out all required fields.");
return false;
}
}
// create a hidden input field with the parameter value // create a hidden input field with the parameter value
var paramField = document.createElement("input"); var paramField = document.createElement("input");
paramField.setAttribute("type", "hidden"); paramField.setAttribute("type", "hidden");
@ -93,18 +66,6 @@
</div> </div>
</section> </section>
<br><br> <br><br>
{{-- <details>
<summary>{{__('messages.More information')}}</summary>
<pre style="color: grey;">
{{__('messages.editlink.description.1-5')}}
{{__('messages.editlink.description.2-5')}}
{{__('messages.editlink.description.3-5')}}
{{__('messages.editlink.description.4-5')}}
{{__('messages.editlink.description.5-5')}}
</pre>
</details> --}}
<!-- Modal --> <!-- Modal -->
<style>.modal-title{color:#000!important;}</style> <style>.modal-title{color:#000!important;}</style>
@ -113,8 +74,8 @@
<div class="d-flex flex-row flex-wrap p-3"> <div class="d-flex flex-row flex-wrap p-3">
@foreach ($LinkTypes as $lt) @foreach ($LinkTypes as $lt)
@php @php
$title = __('messages.block.title.'.$lt['typename']); if(block_text_translation_check($lt['title'])) {$title = bt($lt['title']);} else {$title = __('messages.block.title.'.$lt['typename']);}
$description = __('messages.block.description.'.$lt['typename']); $description = bt($lt['description']) ?? __('messages.block.description.'.$lt['typename']);
@endphp @endphp
<a href="#" data-dismiss="modal" data-typeid="{{$lt['typename']}}" data-typename="{{$title}}" class="hvr-grow m-2 w-100 d-block doSelectLinkType"> <a href="#" data-dismiss="modal" data-typeid="{{$lt['typename']}}" data-typename="{{$title}}" class="hvr-grow m-2 w-100 d-block doSelectLinkType">
<div class="rounded mb-3 shadow-lg"> <div class="rounded mb-3 shadow-lg">

View File

@ -101,8 +101,8 @@ if (isset($_COOKIE['LinkCount'])) {
<span class="bg-soft-secondary" style="border: 1px solid #d0d4d7 !important;border-radius:5px;width:25px!important;height:25px!important;"><i style="margin-left:2.83px;margin-right:-1px;color:#fff;" class='bi bi-card-heading'>&nbsp;</i></span> <span class="bg-soft-secondary" style="border: 1px solid #d0d4d7 !important;border-radius:5px;width:25px!important;height:25px!important;"><i style="margin-left:2.83px;margin-right:-1px;color:#fff;" class='bi bi-card-heading'>&nbsp;</i></span>
@elseif($button->name == "text") @elseif($button->name == "text")
<span class="bg-soft-secondary" style="border: 1px solid #d0d4d7 !important;border-radius:5px;width:25px!important;height:25px!important;"><i style="margin-left:2.83px;margin-right:-1px;color:#fff;" class='bi bi-fonts'>&nbsp;</i></span> <span class="bg-soft-secondary" style="border: 1px solid #d0d4d7 !important;border-radius:5px;width:25px!important;height:25px!important;"><i style="margin-left:2.83px;margin-right:-1px;color:#fff;" class='bi bi-fonts'>&nbsp;</i></span>
@elseif($button->name == "buy me a coffee") @elseif($link->custom_icon && $link->type && $link->type !== 'predefined')
<span class="bg-soft-secondary" style="border: 1px solid #d0d4d7 !important;border-radius:5px;width:25px!important;height:25px!important;"><img style="margin-left:6px!important;margin-right:6px!important;" alt="button-icon" height="15" class="m-1 " src="{{ asset('\/assets/linkstack/icons\/') . "coffee" }}.svg "></span> <span class="bg-soft-secondary" style="border: 1px solid #d0d4d7 !important;border-radius:5px;width:25px!important;height:25px!important;"><i style="width:20px;margin:1px;color:#fff;" class='fa {{$link->custom_icon}}'>&nbsp;</i></span>
@else @else
<span class="bg-soft-secondary" style="border: 1px solid #d0d4d7 !important;border-radius:5px;width:25px!important;height:25px!important;"><img style="max-width:15px !important;" alt="button-icon" height="15" class="m-1 " src="{{ asset('\/assets/linkstack/icons\/') . $buttonName }}.svg "></span> <span class="bg-soft-secondary" style="border: 1px solid #d0d4d7 !important;border-radius:5px;width:25px!important;height:25px!important;"><img style="max-width:15px !important;" alt="button-icon" height="15" class="m-1 " src="{{ asset('\/assets/linkstack/icons\/') . $buttonName }}.svg "></span>
@endif @endif
@ -164,7 +164,7 @@ if (isset($_COOKIE['LinkCount'])) {
</a> </a>
@if(env('ENABLE_BUTTON_EDITOR') === true) @if(env('ENABLE_BUTTON_EDITOR') === true)
@if($link->button_id == '1' or $link->button_id == '2') @if(($link->button_id == '1' || $link->button_id == '2') && $link->type == 'link')
<a style="float: right;" href="{{ route('editCSS', $link->id ) }}" class="btn btn-sm me-1 btn-icon btn-success" data-bs-toggle="tooltip" data-bs-placement="top" aria-label="Add" data-bs-placement="top" data-original-title="{{__('messages.Customize')}}"> <a style="float: right;" href="{{ route('editCSS', $link->id ) }}" class="btn btn-sm me-1 btn-icon btn-success" data-bs-toggle="tooltip" data-bs-placement="top" aria-label="Add" data-bs-placement="top" data-original-title="{{__('messages.Customize')}}">
<span class="btn-inner"> <span class="btn-inner">
<svg class="icon-20" width="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" stroke="currentColor"> <svg class="icon-20" width="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" stroke="currentColor">

View File

@ -84,6 +84,9 @@ Route::post('/report', [UserController::class, 'report'])->name('report');
Route::get('/demo-page', [App\Http\Controllers\HomeController::class, 'demo'])->name('demo')->middleware('disableCookies'); Route::get('/demo-page', [App\Http\Controllers\HomeController::class, 'demo'])->name('demo')->middleware('disableCookies');
Route::get('/block-asset/{type}', [LinkTypeViewController::class, 'blockAsset'])
->name('block.asset')->where(['type' => '[a-zA-Z0-9_-]+']);
} }
Route::middleware(['auth', 'blocked', 'impersonate'])->group(function () { Route::middleware(['auth', 'blocked', 'impersonate'])->group(function () {