diff --git a/resources/views/formfields/relationship.blade.php b/resources/views/formfields/relationship.blade.php index f5ccb704e6..2dbfdcef28 100644 --- a/resources/views/formfields/relationship.blade.php +++ b/resources/views/formfields/relationship.blade.php @@ -13,9 +13,9 @@ $model = app($options->model); $query = $model::where($options->key,$relationshipData->{$options->column})->first(); @endphp - + @if(isset($query)) -

{{ $query->{$options->label} }}

+

{{ strip_tags(html_entity_decode($query->{$options->label})) }}

@else

{{ __('voyager::generic.no_results') }}

@endif @@ -40,7 +40,7 @@ class="form-control select2-ajax" name="{{ $options->column }}" @endif @foreach($query as $relationshipData) - + @endforeach @@ -57,7 +57,7 @@ class="form-control select2-ajax" name="{{ $options->column }}" @endphp @if(isset($query)) -

{{ $query->{$options->label} }}

+

{{ strip_tags(html_entity_decode($query->{$options->label})) }}

@else

{{ __('voyager::generic.no_results') }}

@endif @@ -83,7 +83,7 @@ class="form-control select2-ajax" name="{{ $options->column }}" @if(empty($selected_values))

{{ __('voyager::generic.no_results') }}

@else -

{{ $string_values }}

+

{{ strip_tags(html_entity_decode($string_values)) }}

@endif @else @if(empty($selected_values)) @@ -136,7 +136,7 @@ class="form-control select2-ajax" name="{{ $options->column }}" @if(empty($selected_values))

{{ __('voyager::generic.no_results') }}

@else -

{{ $string_values }}

+

{{ strip_tags(html_entity_decode($string_values)) }}

@endif @else @if(empty($selected_values)) diff --git a/src/Http/Controllers/VoyagerBaseController.php b/src/Http/Controllers/VoyagerBaseController.php index 399ec82cd8..e4f3f5d7b9 100644 --- a/src/Http/Controllers/VoyagerBaseController.php +++ b/src/Http/Controllers/VoyagerBaseController.php @@ -15,6 +15,8 @@ use TCG\Voyager\Events\BreadImagesDeleted; use TCG\Voyager\Facades\Voyager; use TCG\Voyager\Http\Controllers\Traits\BreadRelationshipParser; +use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Model; class VoyagerBaseController extends Controller { @@ -63,9 +65,9 @@ public function index(Request $request) if (strlen($dataType->model_name) != 0) { $model = app($dataType->model_name); - $query = $model::select($dataType->name.'.*'); + $query = $model::select($dataType->name . '.*'); - if ($dataType->scope && $dataType->scope != '' && method_exists($model, 'scope'.ucfirst($dataType->scope))) { + if ($dataType->scope && $dataType->scope != '' && method_exists($model, 'scope' . ucfirst($dataType->scope))) { $query->{$dataType->scope}(); } @@ -84,9 +86,9 @@ public function index(Request $request) if ($search->value != '' && $search->key && $search->filter) { $search_filter = ($search->filter == 'equals') ? '=' : 'LIKE'; - $search_value = ($search->filter == 'equals') ? $search->value : '%'.$search->value.'%'; + $search_value = ($search->filter == 'equals') ? $search->value : '%' . $search->value . '%'; - $searchField = $dataType->name.'.'.$search->key; + $searchField = $dataType->name . '.' . $search->key; if ($row = $this->findSearchableRelationshipRow($dataType->rows->where('type', 'relationship'), $search->key)) { $query->whereIn( $searchField, @@ -104,12 +106,12 @@ public function index(Request $request) $querySortOrder = (!empty($sortOrder)) ? $sortOrder : 'desc'; if (!empty($row)) { $query->select([ - $dataType->name.'.*', - 'joined.'.$row->details->label.' as '.$orderBy, + $dataType->name . '.*', + 'joined.' . $row->details->label . ' as ' . $orderBy, ])->leftJoin( - $row->details->table.' as joined', - $dataType->name.'.'.$row->details->column, - 'joined.'.$row->details->key + $row->details->table . ' as joined', + $dataType->name . '.' . $row->details->column, + 'joined.' . $row->details->key ); } @@ -183,6 +185,9 @@ public function index(Request $request) $view = "voyager::$slug.browse"; } + // Modify dataTypeContent collection with HTML tags stripped from string attributes + $dataTypeContent = $this->stripTagsFromCollection($dataTypeContent); + return Voyager::view($view, compact( 'actions', 'dataType', @@ -230,7 +235,7 @@ public function show(Request $request, $id) if ($model && in_array(SoftDeletes::class, class_uses_recursive($model))) { $query = $query->withTrashed(); } - if ($dataType->scope && $dataType->scope != '' && method_exists($model, 'scope'.ucfirst($dataType->scope))) { + if ($dataType->scope && $dataType->scope != '' && method_exists($model, 'scope' . ucfirst($dataType->scope))) { $query = $query->{$dataType->scope}(); } $dataTypeContent = call_user_func([$query, 'findOrFail'], $id); @@ -263,6 +268,9 @@ public function show(Request $request, $id) $view = "voyager::$slug.read"; } + // Modify dataTypeContent collection with HTML tags stripped from string attributes + $dataTypeContent = $this->stripTagsFromObject($dataTypeContent); + return Voyager::view($view, compact('dataType', 'dataTypeContent', 'isModelTranslatable', 'isSoftDeleted')); } @@ -292,7 +300,7 @@ public function edit(Request $request, $id) if ($model && in_array(SoftDeletes::class, class_uses_recursive($model))) { $query = $query->withTrashed(); } - if ($dataType->scope && $dataType->scope != '' && method_exists($model, 'scope'.ucfirst($dataType->scope))) { + if ($dataType->scope && $dataType->scope != '' && method_exists($model, 'scope' . ucfirst($dataType->scope))) { $query = $query->{$dataType->scope}(); } $dataTypeContent = call_user_func([$query, 'findOrFail'], $id); @@ -338,7 +346,7 @@ public function update(Request $request, $id) $model = app($dataType->model_name); $query = $model->query(); - if ($dataType->scope && $dataType->scope != '' && method_exists($model, 'scope'.ucfirst($dataType->scope))) { + if ($dataType->scope && $dataType->scope != '' && method_exists($model, 'scope' . ucfirst($dataType->scope))) { $query = $query->{$dataType->scope}(); } if ($model && in_array(SoftDeletes::class, class_uses_recursive($model))) { @@ -358,7 +366,7 @@ public function update(Request $request, $id) ->filter(function ($item, $key) use ($request) { return $request->hasFile($item->field); }); - $original_data = clone($data); + $original_data = clone ($data); $this->insertUpdateData($request, $slug, $dataType->editRows, $data); @@ -374,7 +382,7 @@ public function update(Request $request, $id) } return $redirect->with([ - 'message' => __('voyager::generic.successfully_updated')." {$dataType->getTranslatedAttribute('display_name_singular')}", + 'message' => __('voyager::generic.successfully_updated') . " {$dataType->getTranslatedAttribute('display_name_singular')}", 'alert-type' => 'success', ]); } @@ -402,8 +410,8 @@ public function create(Request $request) $this->authorize('add', app($dataType->model_name)); $dataTypeContent = (strlen($dataType->model_name) != 0) - ? new $dataType->model_name() - : false; + ? new $dataType->model_name() + : false; foreach ($dataType->addRows as $key => $row) { $dataType->addRows[$key]['col_width'] = $row->details->width ?? 100; @@ -457,7 +465,7 @@ public function store(Request $request) } return $redirect->with([ - 'message' => __('voyager::generic.successfully_added_new')." {$dataType->getTranslatedAttribute('display_name_singular')}", + 'message' => __('voyager::generic.successfully_added_new') . " {$dataType->getTranslatedAttribute('display_name_singular')}", 'alert-type' => 'success', ]); } else { @@ -494,7 +502,7 @@ public function destroy(Request $request, $id) } $affected = 0; - + foreach ($ids as $id) { $data = call_user_func([$dataType->model_name, 'findOrFail'], $id); @@ -519,11 +527,11 @@ public function destroy(Request $request, $id) $data = $affected ? [ - 'message' => __('voyager::generic.successfully_deleted')." {$displayName}", + 'message' => __('voyager::generic.successfully_deleted') . " {$displayName}", 'alert-type' => 'success', ] : [ - 'message' => __('voyager::generic.error_deleting')." {$displayName}", + 'message' => __('voyager::generic.error_deleting') . " {$displayName}", 'alert-type' => 'error', ]; @@ -542,7 +550,7 @@ public function restore(Request $request, $id) // Get record $query = $model->withTrashed(); - if ($dataType->scope && $dataType->scope != '' && method_exists($model, 'scope'.ucfirst($dataType->scope))) { + if ($dataType->scope && $dataType->scope != '' && method_exists($model, 'scope' . ucfirst($dataType->scope))) { $query = $query->{$dataType->scope}(); } $data = $query->findOrFail($id); @@ -552,11 +560,11 @@ public function restore(Request $request, $id) $res = $data->restore($id); $data = $res ? [ - 'message' => __('voyager::generic.successfully_restored')." {$displayName}", + 'message' => __('voyager::generic.successfully_restored') . " {$displayName}", 'alert-type' => 'success', ] : [ - 'message' => __('voyager::generic.error_restoring')." {$displayName}", + 'message' => __('voyager::generic.error_restoring') . " {$displayName}", 'alert-type' => 'error', ]; @@ -617,7 +625,7 @@ public function remove_media(Request $request) // Check if we're dealing with a nested array for the case of multiple files if (is_array($fieldData[0])) { - foreach ($fieldData as $index=>$file) { + foreach ($fieldData as $index => $file) { // file type has a different structure than images if (!empty($file['original_name'])) { if ($file['original_name'] == $filename) { @@ -769,13 +777,13 @@ public function deleteBreadImages($data, $rows, $single_image = null) if (isset($row->details->thumbnails)) { foreach ($row->details->thumbnails as $thumbnail) { $ext = explode('.', $image); - $extension = '.'.$ext[count($ext) - 1]; + $extension = '.' . $ext[count($ext) - 1]; $path = str_replace($extension, '', $image); $thumb_name = $thumbnail->name; - $this->deleteFileIfExists($path.'-'.$thumb_name.$extension); + $this->deleteFileIfExists($path . '-' . $thumb_name . $extension); } } } @@ -805,11 +813,11 @@ public function order(Request $request) if (empty($dataType->order_column) || empty($dataType->order_display_column)) { return redirect() - ->route("voyager.{$dataType->slug}.index") - ->with([ - 'message' => __('voyager::bread.ordering_not_set'), - 'alert-type' => 'error', - ]); + ->route("voyager.{$dataType->slug}.index") + ->with([ + 'message' => __('voyager::bread.ordering_not_set'), + 'alert-type' => 'error', + ]); } $model = app($dataType->model_name); @@ -829,6 +837,9 @@ public function order(Request $request) $view = "voyager::$slug.order"; } + // Modify results collection with HTML tags stripped from string attributes + $results = $this->stripTagsFromCollection($results); + return Voyager::view($view, compact( 'dataType', 'display_column', @@ -899,7 +910,7 @@ public function relation(Request $request) $this->authorize($method, $model); - $rows = $dataType->{$method.'Rows'}; + $rows = $dataType->{$method . 'Rows'}; foreach ($rows as $key => $row) { if ($row->field === $request->input('type')) { $options = $row->details; @@ -909,7 +920,7 @@ public function relation(Request $request) $additional_attributes = $model->additional_attributes ?? []; // Apply local scope if it is defined in the relationship-options - if (isset($options->scope) && $options->scope != '' && method_exists($model, 'scope'.ucfirst($options->scope))) { + if (isset($options->scope) && $options->scope != '' && method_exists($model, 'scope' . ucfirst($options->scope))) { $model = $model->{$options->scope}(); } @@ -924,9 +935,9 @@ public function relation(Request $request) $total_count = $relationshipOptions->count(); $relationshipOptions = $relationshipOptions->forPage($page, $on_page); } else { - $total_count = $model->where($options->label, 'LIKE', '%'.$search.'%')->count(); + $total_count = $model->where($options->label, 'LIKE', '%' . $search . '%')->count(); $relationshipOptions = $model->take($on_page)->skip($skip) - ->where($options->label, 'LIKE', '%'.$search.'%') + ->where($options->label, 'LIKE', '%' . $search . '%') ->get(); } } else { @@ -955,7 +966,8 @@ public function relation(Request $request) foreach ($relationshipOptions as $relationshipOption) { $results[] = [ 'id' => $relationshipOption->{$options->key}, - 'text' => $relationshipOption->{$options->label}, + // Strip tags and entity codes for relation texts + 'text' => strip_tags(html_entity_decode($relationshipOption->{$options->label})), ]; } @@ -998,12 +1010,57 @@ protected function getSortableColumns($rows) return !$this->relationIsUsingAccessorAsLabel($item->details); }) - ->pluck('field') - ->toArray(); + ->pluck('field') + ->toArray(); } protected function relationIsUsingAccessorAsLabel($details) { return in_array($details->label, app($details->model)->additional_attributes ?? []); } + + /** + * Strip HTML tags from string attributes of each model in a collection. + * + * @param \Illuminate\Support\Collection $collection The collection of models to process. + * @return \Illuminate\Support\Collection The modified collection with HTML tags stripped from string attributes. + */ + private function stripTagsFromCollection(Collection $collection) + { + return $collection->map(function ($item) { + // Get the attributes of the model + $attributes = $item->getAttributes(); + + // Loop through each attribute + foreach ($attributes as $key => $value) { + // Check if the value is a string + if (is_string($value)) { + // Strip HTML tags from the value + $item->{$key} = strip_tags(html_entity_decode($value)); + } + } + return $item; + }); + } + + /** + * Strip HTML tags from string attributes of an object. + * + * @param mixed $object The object whose attributes need HTML tags stripped. + * @return mixed The modified object with HTML tags stripped from string attributes. + */ + private function stripTagsFromObject(Model $model) + { + // Get the object's attributes + $attributes = $model->getAttributes(); + // Loop through each attribute + foreach ($attributes as $key => $value) { + // Check if the value is a string + if (is_string($value)) { + // Strip HTML tags from the value + $model->$key = strip_tags(html_entity_decode($value)); + } + } + return $model; + } }