Add Wasserrad demo content seed script

Replaces the "Hotel Prime" demo data: hotel texts and address, room
types with 2026 prices (gross incl. 7 % VAT), logo, header slides, room
photos and interior gallery; disables auto-added demo service fees and
hides the invented demo testimonials.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
DanielS
2026-11-11 00:20:06 +01:00
parent b888634fd7
commit c76dd44f16
21 changed files with 171 additions and 0 deletions

View File

@@ -0,0 +1,171 @@
<?php
/**
* Demo content "Zum alten Wasserrad – L'Antica Ruota" for a local QloApps install.
* Replaces the "Hotel Prime" demo data: shop/hotel texts, room types and prices,
* logo, header slides, room photos and interior gallery.
*
* Run (as www-data so generated files stay writable):
* docker compose exec -u www-data app php docker/seed-wasserrad-demo.php
*
* Local demo only. Photos in docker/wasserrad-demo/ come from www.zum-alten-wasserrad.de.
*/
if (PHP_SAPI !== 'cli') {
exit("CLI only\n");
}
define('_PS_ADMIN_DIR_', __DIR__);
require __DIR__.'/../config/config.inc.php';
require_once _PS_MODULE_DIR_.'hotelreservationsystem/define.php';
$src = __DIR__.'/wasserrad-demo/';
$langs = Language::getLanguages(false);
$ml = function ($text) use ($langs) {
$out = array();
foreach ($langs as $l) {
$out[(int)$l['id_lang']] = $text;
}
return $out;
};
$log = function ($msg) { echo ' - '.$msg.PHP_EOL; };
echo "Shop & header texts\n";
Configuration::updateValue('PS_SHOP_NAME', 'Zum alten Wasserrad');
Configuration::updateValue('PS_SHOP_EMAIL', 'info@hotel.test');
Configuration::updateValue('WK_CUSTOMER_SUPPORT_EMAIL', 'info@hotel.test');
Configuration::updateValue('PS_SHOP_ADDR1', 'Am Storchentor 8');
Configuration::updateValue('PS_SHOP_CODE', '76855');
Configuration::updateValue('PS_SHOP_CITY', 'Annweiler am Trifels');
Configuration::updateValue('PS_SHOP_PHONE', '+49 6346 93344');
Configuration::updateValue('WK_CUSTOMER_SUPPORT_PHONE_NUMBER', '+49 6346 93344');
Configuration::updateValue('WK_TITLE_HEADER_BLOCK', "L'Antica Ruota");
Configuration::updateValue('WK_CONTENT_HEADER_BLOCK', 'Familiengeführtes Hotel-Ristorante in der Altstadt von Annweiler, zu Füßen der Burg Trifels.');
Configuration::updateValue('HOTEL_ROOM_DISPLAY_HEADING', $ml('Unsere Zimmer'));
Configuration::updateValue('HOTEL_ROOM_DISPLAY_DESCRIPTION', $ml('Zehn liebevoll eingerichtete Zimmer mit Dusche/WC, Fön, Flatscreen-TV und WLAN – Frühstücksbuffet inklusive.'));
Configuration::updateValue('HOTEL_INTERIOR_HEADING', $ml('Mediterranes Flair'));
Configuration::updateValue('HOTEL_INTERIOR_DESCRIPTION', $ml('Warme Sandtöne, Holz und italienischer Marmor: die Toskana Deutschlands trifft auf italienische Gastfreundschaft.'));
Configuration::updateValue('HOTEL_AMENITIES_HEADING', $ml('Rund um Ihren Aufenthalt'));
Configuration::updateValue('HOTEL_AMENITIES_DESCRIPTION', $ml('Ristorante mit Gartenterrasse, Frühstücksbuffet und der Pfälzerwald direkt vor der Tür.'));
$log('done');
echo "Logo\n";
copy($src.'rad.png', _PS_IMG_DIR_.'wasserrad-logo.png');
Configuration::updateValue('PS_LOGO', 'wasserrad-logo.png');
list($w, $h) = getimagesize(_PS_IMG_DIR_.'wasserrad-logo.png');
Configuration::updateValue('SHOP_LOGO_WIDTH', (int)$w);
Configuration::updateValue('SHOP_LOGO_HEIGHT', (int)$h);
$log("wasserrad-logo.png ({$w}x{$h})");
echo "Hotel\n";
$hotel = new HotelBranchInformation(1);
$hotel->email = 'info@hotel.test';
$hotel->check_in = '15:00';
$hotel->check_out = '11:00';
$hotel->rating = 3;
$hotel->hotel_name = $ml("L'Antica Ruota – Zum alten Wasserrad");
$hotel->short_description = $ml("Familiengeführtes Hotel-Ristorante inmitten der Altstadt des Luftkurortes Annweiler, zu Füßen der Felsenburg Trifels.");
$hotel->description = $ml(
'<h4><strong>Benvenuti – Herzlich willkommen!</strong></h4>'
.'<p>L’Antica Ruota ist ein familiengeführtes Hotel-Ristorante inmitten der Altstadt des Luftkurortes Annweiler, zu Füßen der Felsenburg Trifels. '
.'Unser Haus eröffnete im März 1997 und bietet mit seinem mediterranen Flair eine ganz besondere Urlaubsatmosphäre, umgeben von den Wäldern des Biosphärenreservates Pfälzerwald.</p>'
.'<p>Ob Aktiv-Urlaub, Kurztrip zum Auftanken, Familienfeier oder Ausflug zu zweit – bei uns lassen Sie den Alltag für eine Weile hinter sich.</p>'
.'<p><em>Herzlichst, Ihre Familie Mirabile und Team</em></p>'
);
$hotel->policies = $ml(
'<ul><li>Check-in ab 15:00 Uhr, Check-out bis 11:00 Uhr.</li>'
.'<li>Alle Zimmerpreise inklusive Frühstücksbuffet.</li>'
.'<li>Restaurant: Montag und Dienstag Ruhetag (08.11.2026 – 31.03.2027).</li></ul>'
);
$hotel->save();
Db::getInstance()->update('address', array(
'address1' => 'Am Storchentor 8',
'postcode' => '76855',
'city' => 'Annweiler am Trifels',
'id_country' => (int)Country::getByIso('DE'),
'id_state' => 0,
'phone' => '+49 6346 93344',
), 'id_hotel = 1');
$log("L'Antica Ruota – Zum alten Wasserrad");
echo "Room types (gross incl. 7 % VAT, breakfast included)\n";
$rooms = array(
1 => array('Einzelzimmer', 115, 'Gemütliches Einzelzimmer mit Dusche/WC, Fön, Flatscreen-TV und WLAN. Inklusive Frühstücksbuffet.', array('zimmer62', 'bild3', 'terrasse', 'galerie1')),
2 => array('Doppelzimmer', 145, 'Geräumiges Doppelzimmer mit Dusche/WC, Fön, Flatscreen-TV und WLAN. Inklusive Frühstücksbuffet.', array('zimmer71', 'gebaeude', 'galerie2', 'galerie3')),
3 => array('Doppelzimmer 3. Etage', 125, 'Doppelzimmer unter dem Dach mit Blick über die Altstadt. Inklusive Frühstücksbuffet.', array('zimmer71', 'zimmer80', 'bild38', 'galerie4')),
4 => array('Dreibettzimmer', 175, 'Ideal für Familien: Dreibettzimmer mit Dusche/WC, Flatscreen-TV und WLAN. Inklusive Frühstücksbuffet.', array('zimmer62', 'zimmer71', 'zimmer80', 'galerie6', 'galerie7')),
);
// Demo service products ("Zimmerwartungsgebühren" etc.) are auto-added to every night: switch them off.
// Breakfast is already part of the room rate.
$services = Db::getInstance()->executeS('SELECT id_product FROM '._DB_PREFIX_.'product WHERE booking_product = 0');
foreach ($services as $s) {
Db::getInstance()->update('product', array('active' => 0, 'auto_add_to_cart' => 0), 'id_product = '.(int)$s['id_product']);
Db::getInstance()->update('product_shop', array('active' => 0, 'auto_add_to_cart' => 0), 'id_product = '.(int)$s['id_product']);
}
$log(count($services).' Demo-Zusatzleistungen deaktiviert');
$imageTypes = ImageType::getImagesTypes('products');
foreach ($rooms as $idProduct => $r) {
list($name, $gross, $desc, $photos) = $r;
$p = new Product($idProduct);
$p->name = $ml($name);
$p->link_rewrite = $ml(Tools::str2url($name));
$p->description_short = $ml('<p>'.$desc.'</p>');
$p->id_tax_rules_group = 2; // DE Reduced Rate (7%)
$p->price = round($gross / 1.07, 6);
$p->save();
$images = Image::getImages((int)Configuration::get('PS_LANG_DEFAULT'), $idProduct);
foreach ($images as $i => $row) {
$file = $src.$photos[$i % count($photos)].'.jpg';
$img = new Image((int)$row['id_image']);
$base = $img->getPathForCreation();
ImageManager::resize($file, $base.'.jpg');
foreach ($imageTypes as $t) {
ImageManager::resize($file, $base.'-'.stripslashes($t['name']).'.jpg', (int)$t['width'], (int)$t['height']);
}
}
$log(sprintf('%s: %d € (%d Fotos)', $name, $gross, count($images)));
}
echo "Header slides\n";
$slides = array(
array('drohne', "L'Antica Ruota", 'Hotel-Ristorante in der Altstadt von Annweiler am Trifels'),
array('gebaeude', 'Benvenuti', 'Mediterranes Flair im Herzen der Pfalz'),
array('terrasse', 'Gartenterrasse', 'Italienische Küche unter freiem Himmel'),
);
$dir = _PS_IMG_DIR_.'hotel_header_media/';
$existing = Db::getInstance()->executeS('SELECT id_header_image FROM '._DB_PREFIX_.'htl_header_image ORDER BY position');
foreach ($slides as $pos => $s) {
$obj = isset($existing[$pos]) ? new HotelHeaderImage((int)$existing[$pos]['id_header_image']) : new HotelHeaderImage();
$obj->name = 'wasserrad-'.$s[0].'.jpg';
copy($src.$s[0].'.jpg', $dir.$obj->name);
$obj->title = $ml($s[1]);
$obj->description = $ml($s[2]);
$obj->description_color = '#ffffff';
$obj->description_font_size = 18;
$obj->description_font_weight = '400';
$obj->position = $pos;
$obj->active = 1;
$obj->save();
$log($obj->name);
}
echo "Interior gallery\n";
$gallery = array('bild3', 'terrasse', 'galerie1', 'gebaeude', 'galerie2', 'bild38', 'galerie3', 'start1', 'galerie4', 'galerie5', 'galerie6', 'galerie7');
$galleryDir = _PS_MODULE_DIR_.'wkabouthotelblock/views/img/hotel_interior/';
foreach (Db::getInstance()->executeS('SELECT id_interior_image, name FROM '._DB_PREFIX_.'htl_interior_image ORDER BY position') as $i => $row) {
$pick = $gallery[$i % count($gallery)];
// copy as-is: ImageManager::resize would pad to 4:3 with white bars
copy($src.$pick.'.jpg', $galleryDir.$row['name'].'.jpg');
Db::getInstance()->update('htl_interior_image', array('display_name' => pSQL('L’Antica Ruota '.($i + 1))), 'id_interior_image = '.(int)$row['id_interior_image']);
}
$log(count($gallery).' Bilder');
echo "Testimonials\n";
// Demo reviews mention "Hotel Prime": hide them instead of showing invented guest quotes.
Db::getInstance()->update('htl_testimonials_block_data', array('active' => 0));
$log('Demo-Bewertungen ausgeblendet (echte Bewertungen im Backend unter Testimonials pflegen)');
Tools::clearSmartyCache();
Tools::clearCache();
echo "Fertig.\n";

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB