Startseiten-Reisen im CMS steuerbar machen

This commit is contained in:
Kevin Adametz 2026-05-28 15:06:22 +00:00
parent ba48745809
commit 313f0dbf4e
5 changed files with 446 additions and 22 deletions

View file

@ -32,6 +32,10 @@ use Illuminate\Database\Eloquent\Model;
*/
class SidebarWidget extends Model
{
const HOMEPAGE_PLANNABLE_TRIPS = 'homepagePlannableTrips';
const HOMEPAGE_POPULAR_TRIPS = 'homepagePopularTrips';
const NEWS_SIDEBAR_WIDGET = 'newsSidebarWidget';
protected static $shows = [
'home' => 'Startseite',
@ -54,7 +58,9 @@ class SidebarWidget extends Model
'travelGuideSidebarWidget' => 'Reiseführer',
'travelMagazineSidebarWidget' => 'Reisemagazin',
'offersSidebarWidget' => 'Angebote',
'newsSidebarWidget' => 'News',
self::NEWS_SIDEBAR_WIDGET => 'News',
self::HOMEPAGE_PLANNABLE_TRIPS => 'Startseite: Aktuell planbare Reisen',
self::HOMEPAGE_POPULAR_TRIPS => 'Startseite: Beliebte Kulturreisen',
];
@ -105,23 +111,256 @@ class SidebarWidget extends Model
return rtrim($ret, ", ");
}
public function getComponentLabel()
{
if (!$this->component) {
return 'Nur HTML';
}
return isset(self::$components[$this->component]) ? self::$components[$this->component] : $this->component;
}
public function isHomepageTripsComponent()
{
return in_array($this->component, [self::HOMEPAGE_PLANNABLE_TRIPS, self::HOMEPAGE_POPULAR_TRIPS]);
}
public function isNewsComponent()
{
return $this->component === self::NEWS_SIDEBAR_WIDGET;
}
public function isStructuredConfigComponent()
{
return $this->isHomepageTripsComponent() || $this->isNewsComponent();
}
public function getConfig()
{
$config = json_decode($this->html, true);
if (!is_array($config)) {
$config = [];
}
$config['page_ids'] = isset($config['page_ids']) && is_array($config['page_ids'])
? array_values(array_filter($config['page_ids']))
: [];
$config['new_page_ids'] = isset($config['new_page_ids']) && is_array($config['new_page_ids'])
? array_values(array_filter($config['new_page_ids']))
: [];
$config['new_badge_active'] = !empty($config['new_badge_active']);
$config['news_limit'] = isset($config['news_limit']) ? max(1, min(12, (int) $config['news_limit'])) : 3;
return $config;
}
public function getHomepageConfig()
{
return $this->getConfig();
}
public function getHomepagePageIds()
{
return $this->getHomepageConfig()['page_ids'];
}
public function getHomepageNewPageIds()
{
return array_map('intval', $this->getHomepageConfig()['new_page_ids']);
}
public function getHomepageNewBadgeActive()
{
return $this->getHomepageConfig()['new_badge_active'];
}
public function getHomepageNewsLimit()
{
return $this->getConfig()['news_limit'];
}
public static function getHomepageTravelPageOptions($selectedIds = [])
{
$selectedIds = array_map('intval', (array) $selectedIds);
$items = self::getHomepageTravelPageItems($selectedIds);
$groupedItems = [];
foreach ($items as $item) {
$groupedItems[$item['country_group']][] = $item;
}
uksort($groupedItems, function ($a, $b) {
return strnatcasecmp(self::getHomepageSortValue($a), self::getHomepageSortValue($b));
});
$ret = '';
foreach ($groupedItems as $countryGroup => $groupItems) {
$ret .= '<optgroup label="'.e($countryGroup).'">'."\n";
foreach ($groupItems as $item) {
$attr = $item['selected'] ? 'selected="selected"' : '';
$label = e($item['label']);
$ret .= '<option value="'.$item['id'].'" data-label="'.$label.'" '.$attr.'>'.$label.'</option>'."\n";
}
$ret .= '</optgroup>'."\n";
}
return $ret;
}
public static function getHomepageTravelPageItems($selectedIds = [])
{
$selectedIds = array_map('intval', (array) $selectedIds);
$pages = Page::with([
'travel_program_content.travel_program_countries.travel_country',
'travel_program_content.travel_country_content',
])
->where('status', 1)
->whereNotNull('travel_program')
->where('travel_program', '>', 0)
->whereHas('travel_program_content', function ($query) {
$query->where('status', 1);
})
->orderBy('title')
->get()
->unique('travel_program');
$items = [];
foreach ($pages as $page) {
$countryGroup = self::getHomepageTravelPageCountryLabel($page);
$items[] = [
'id' => (int) $page->id,
'label' => self::getHomepageTravelPageLabel($page),
'country_group' => $countryGroup,
'sort_title' => $page->title,
'selected' => in_array((int) $page->id, $selectedIds),
];
}
usort($items, function ($a, $b) {
$countryCompare = strnatcasecmp(
self::getHomepageSortValue($a['country_group']),
self::getHomepageSortValue($b['country_group'])
);
if ($countryCompare !== 0) {
return $countryCompare;
}
return strnatcasecmp(self::getHomepageSortValue($a['sort_title']), self::getHomepageSortValue($b['sort_title']));
});
return $items;
}
public function getHomepageSelectedTravelPageItems()
{
$selectedIds = array_map('intval', $this->getHomepagePageIds());
if (empty($selectedIds)) {
return [];
}
$newPageIds = $this->getHomepageNewPageIds();
$pages = Page::with([
'travel_program_content.travel_program_countries.travel_country',
'travel_program_content.travel_country_content',
])
->whereIn('id', $selectedIds)
->where('status', 1)
->whereHas('travel_program_content', function ($query) {
$query->where('status', 1);
})
->get()
->keyBy('id');
$items = [];
$usedTravelPrograms = [];
foreach ($selectedIds as $pageId) {
if (!$pages->has($pageId)) {
continue;
}
$page = $pages->get($pageId);
$travelProgramId = (int) $page->travel_program;
if (in_array($travelProgramId, $usedTravelPrograms)) {
continue;
}
$usedTravelPrograms[] = $travelProgramId;
$items[] = [
'id' => (int) $page->id,
'label' => self::getHomepageTravelPageLabel($page),
'is_new' => in_array((int) $page->id, $newPageIds),
];
}
return $items;
}
protected static function getHomepageTravelPageLabel(Page $page)
{
$country = self::getHomepageTravelPageCountryLabel($page);
$travelProgram = $page->travel_program_content;
$programId = $travelProgram ? $travelProgram->id : $page->travel_program;
return $country.' | Reise, '.$page->title.' (#'.$programId.')';
}
protected static function getHomepageTravelPageCountryLabel(Page $page)
{
$countryNames = self::getHomepageTravelPageCountryNames($page);
return !empty($countryNames) ? implode(', ', $countryNames) : 'Ohne Reiseland';
}
protected static function getHomepageTravelPageCountryNames(Page $page)
{
$travelProgram = $page->travel_program_content;
$countryNames = [];
if ($travelProgram && $travelProgram->travel_program_countries) {
foreach ($travelProgram->travel_program_countries as $programCountry) {
if ($programCountry->travel_country && $programCountry->travel_country->name) {
$countryNames[] = $programCountry->travel_country->name;
}
}
}
if (empty($countryNames) && $travelProgram && $travelProgram->travel_country_content) {
$countryNames[] = $travelProgram->travel_country_content->name;
}
$countryNames = array_unique($countryNames);
usort($countryNames, function ($a, $b) {
return strnatcasecmp(self::getHomepageSortValue($a), self::getHomepageSortValue($b));
});
return $countryNames;
}
protected static function getHomepageSortValue($value)
{
return str_replace(
['Ä', 'Ö', 'Ü', 'ä', 'ö', 'ü', 'ß'],
['Ae', 'Oe', 'Ue', 'ae', 'oe', 'ue', 'ss'],
(string) $value
);
}
/*
* public function getVotesDetailAttribute($details)
{
return json_decode($details, true);
}
then when you will call $store->votes_detail you will get the expected result.
After that you can use mutators to convert an array back to JSON when it is saved back in the DB. Define the method setVotesDetailAttribute($value) as follows:
public function setVotesDetailsAttribute($value)
{
$this->attributes['votes_detail'] = json_encode($value);
}
*/
{
* return json_decode($details, true);
}
* then when you will call $store->votes_detail you will get the expected result.
*
* After that you can use mutators to convert an array back to JSON when it is saved back in the DB. Define the method setVotesDetailAttribute($value) as follows:
*
* public function setVotesDetailsAttribute($value)
* {
* $this->attributes['votes_detail'] = json_encode($value);
* }
*/
}