This commit is contained in:
2026-05-13 23:15:51 +02:00
parent d8c793b84c
commit 7d00544ec1
8 changed files with 237 additions and 56 deletions

View File

@@ -7,7 +7,7 @@ ob_start();
?> ?>
<div id="settings-tabs"> <div id="settings-tabs">
<ul class="resp-tabs-list settings-tabs"> <ul class="resp-tabs-list settings-tabs">
<li><i class="fa fa-file"></i>Treść</li> <li><i class="fa fa-file"></i>Treść</li>
<li><i class="fa fa-wrench"></i>Ustawienia</li> <li><i class="fa fa-wrench"></i>Ustawienia</li>
<li><i class="fa fa-globe"></i>SEO</li> <li><i class="fa fa-globe"></i>SEO</li>
</ul> </ul>
@@ -17,7 +17,7 @@ ob_start();
<ul class="resp-tabs-list languages-main htabs"> <ul class="resp-tabs-list languages-main htabs">
<? if ( is_array( $this -> languages ) ): foreach ( $this -> languages as $lg ):?> <? if ( is_array( $this -> languages ) ): foreach ( $this -> languages as $lg ):?>
<? if ( $lg['status'] ):?> <? if ( $lg['status'] ):?>
<li><? if ( $lg['id'] == $this->dlang ) echo '<i class="fa fa-star fa-lg text-system" title="JÄ™zyk domyĹ›lny"></i> ';?><?= $lg['name'];?></a></li> <li><? if ( $lg['id'] == $this->dlang ) echo '<i class="fa fa-star fa-lg text-system" title="Język domyślny"></i> ';?><?= $lg['name'];?></a></li>
<? endif;?> <? endif;?>
<? endforeach; endif;?> <? endforeach; endif;?>
</ul> </ul>
@@ -45,7 +45,7 @@ ob_start();
);?> );?>
<?= \Shared\Html\Html::textarea( <?= \Shared\Html\Html::textarea(
array( array(
'label' => 'Opis kategorii (rozwiniÄ™cie)', 'label' => 'Opis kategorii (rozwinięcie)',
'name' => 'text_hidden[' . $lg['id'] . ']', 'name' => 'text_hidden[' . $lg['id'] . ']',
'id' => 'text_hidden_' . $lg['id'], 'id' => 'text_hidden_' . $lg['id'],
'value' => $this -> category['languages'][ $lg['id'] ]['text_hidden'], 'value' => $this -> category['languages'][ $lg['id'] ]['text_hidden'],
@@ -84,7 +84,7 @@ ob_start();
);?> );?>
<?= \Shared\Html\Html::select( <?= \Shared\Html\Html::select(
[ [
'label' => 'Sortowanie produktĂłw', 'label' => 'Sortowanie produktów',
'name' => 'sort_type', 'name' => 'sort_type',
'id' => 'sort_type', 'id' => 'sort_type',
'values' => is_array( $this -> sort_types ) ? $this -> sort_types : [], 'values' => is_array( $this -> sort_types ) ? $this -> sort_types : [],
@@ -93,7 +93,7 @@ ob_start();
);?> );?>
<?= \Shared\Html\Html::input_switch( <?= \Shared\Html\Html::input_switch(
array( array(
'label' => 'WyĹ›wietlić podkategorie', 'label' => 'Wyświetlić podkategorie',
'name' => 'view_subcategories', 'name' => 'view_subcategories',
'checked' => $this -> category['view_subcategories'] == 1 ? true : false 'checked' => $this -> category['view_subcategories'] == 1 ? true : false
) )
@@ -104,7 +104,7 @@ ob_start();
<ul class="resp-tabs-list languages-seo htabs"> <ul class="resp-tabs-list languages-seo htabs">
<? if ( is_array( $this -> languages ) ): foreach ( $this -> languages as $lg ):?> <? if ( is_array( $this -> languages ) ): foreach ( $this -> languages as $lg ):?>
<? if ( $lg['status'] ):?> <? if ( $lg['status'] ):?>
<li><? if ( $lg['id'] == $this->dlang ) echo '<i class="fa fa-star fa-lg text-system" title="JÄ™zyk domyĹ›lny"></i> ';?><?= $lg['name'];?></a></li> <li><? if ( $lg['id'] == $this->dlang ) echo '<i class="fa fa-star fa-lg text-system" title="Język domyślny"></i> ';?><?= $lg['name'];?></a></li>
<? endif;?> <? endif;?>
<? endforeach; endif;?> <? endforeach; endif;?>
</ul> </ul>
@@ -124,7 +124,7 @@ ob_start();
);?> );?>
<?= \Shared\Html\Html::input( <?= \Shared\Html\Html::input(
array( array(
'label' => 'TytuĹ‚ kategorii (h1)', 'label' => 'Tytuł kategorii (h1)',
'name' => 'category_title[' . $lg['id'] . ']', 'name' => 'category_title[' . $lg['id'] . ']',
'id' => 'category_title_' . $lg['id'], 'id' => 'category_title_' . $lg['id'],
'value' => $this -> category['languages' ][ $lg['id'] ]['category_title'] 'value' => $this -> category['languages' ][ $lg['id'] ]['category_title']
@@ -156,7 +156,7 @@ ob_start();
);?> );?>
<?= \Shared\Html\Html::select( <?= \Shared\Html\Html::select(
array( array(
'label' => 'Blokuj indeksacjÄ™', 'label' => 'Blokuj indeksację',
'name' => 'noindex[' . $lg['id'] . ']', 'name' => 'noindex[' . $lg['id'] . ']',
'id' => 'noindex_' . $lg['id'], 'id' => 'noindex_' . $lg['id'],
'values' => array( 'values' => array(

View File

@@ -52,15 +52,6 @@
</div> </div>
<? endif; ?> <? endif; ?>
<div class="panel">
<div class="panel-heading">
<span class="panel-title">Changelog</span>
</div>
<div class="panel-body">
<?= @file_get_contents( 'https://shoppro.project-dc.pl/updates/changelog.php?ver=' . $this->ver ); ?>
</div>
</div>
<script type="text/javascript"> <script type="text/javascript">
$(function() { $(function() {
var version_current = <?= $this->ver; ?>; var version_current = <?= $this->ver; ?>;
@@ -138,3 +129,17 @@ $(function() {
} }
}); });
</script> </script>
<div class="panel">
<div class="panel-heading">
<span class="panel-title">Changelog</span>
</div>
<div class="panel-body">
<?php
$changelog = (string) @file_get_contents( 'https://shoppro.project-dc.pl/updates/changelog.php?ver=' . $this->ver );
$changelog = preg_replace( '/<!--.*?-->/s', '', $changelog );
$changelog = strip_tags( $changelog, '<p><br><b><strong><i><em><u><ul><ol><li><h1><h2><h3><h4><h5><h6><span><div><a><pre><code><hr>' );
echo $changelog;
?>
</div>
</div>

View File

@@ -1335,8 +1335,9 @@ class ProductRepository
$this->saveImagesOrder( $productId, $d['gallery_order'] ); $this->saveImagesOrder( $productId, $d['gallery_order'] );
} }
// Zapisz custom fields tylko gdy jawnie podane (partial update przez API może nie zawierać tego klucza) // Zapisz custom fields tylko gdy formularz edycji renderował sekcję (marker hidden field)
if ( array_key_exists( 'custom_field_name', $d ) ) { // API partial update nie zawiera tego markera — custom fields pominięte
if ( array_key_exists( 'custom_field_name_present', $d ) ) {
$this->saveCustomFields( $productId, $d['custom_field_name'] ?? [], $d['custom_field_type'] ?? [], $d['custom_field_required'] ?? [] ); $this->saveCustomFields( $productId, $d['custom_field_name'] ?? [], $d['custom_field_type'] ?? [], $d['custom_field_required'] ?? [] );
} }
@@ -2204,6 +2205,44 @@ class ProductRepository
] ); ] );
} }
/**
* Pobiera nazwy etykiet custom_label_0..4 z bazy ustawien.
*
* @return array<string, string>
*/
public function customLabelNames(): array
{
$names = [];
for ( $index = 0; $index < 5; $index++ ) {
$fieldName = 'custom_label_' . $index;
$names[$fieldName] = 'Custom label ' . $index;
}
$settingsKeys = [];
for ( $index = 0; $index < 5; $index++ ) {
$settingsKeys[] = 'custom_label_' . $index . '_name';
$settingsKeys[] = 'google_custom_label_' . $index . '_name';
}
$settingsRows = $this->db->select( 'pp_settings', [ 'param', 'value' ], [ 'param' => $settingsKeys ] );
if ( is_array( $settingsRows ) ) {
foreach ( $settingsRows as $settingRow ) {
$param = (string) ( $settingRow['param'] ?? '' );
$value = trim( (string) ( $settingRow['value'] ?? '' ) );
if ( $value === '' ) {
continue;
}
if ( preg_match( '/^(?:google_)?custom_label_([0-4])_name$/', $param, $match ) ) {
$names[ 'custom_label_' . $match[1] ] = $value;
}
}
}
return $names;
}
/** /**
* Pobiera sugestie custom label. * Pobiera sugestie custom label.
*/ */
@@ -2330,9 +2369,9 @@ class ProductRepository
$itemNode->appendChild( $doc->createElement( 'g:description', html_entity_decode( strip_tags( $desc ) ) ) ); $itemNode->appendChild( $doc->createElement( 'g:description', html_entity_decode( strip_tags( $desc ) ) ) );
if ( $product['language']['seo_link'] ) { if ( $product['language']['seo_link'] ) {
$link = $domainPrefix . '://' . $url . '/' . \Shared\Helpers\Helpers::seo( $product['language']['seo_link'] ) . '/' . str_replace( '|', '/', $combination['permutation_hash'] ); $link = $domainPrefix . '://' . $url . '/' . \Shared\Helpers\Helpers::seo( $product['language']['seo_link'] ) . '/' . str_replace( '|', '_', $combination['permutation_hash'] );
} else { } else {
$link = $domainPrefix . '://' . $url . '/p-' . $product['id'] . '-' . \Shared\Helpers\Helpers::seo( $product['language']['name'] ) . '/' . str_replace( '|', '/', $combination['permutation_hash'] ); $link = $domainPrefix . '://' . $url . '/p-' . $product['id'] . '-' . \Shared\Helpers\Helpers::seo( $product['language']['name'] ) . '/' . str_replace( '|', '_', $combination['permutation_hash'] );
} }
$itemNode->appendChild( $doc->createElement( 'link', $link ) ); $itemNode->appendChild( $doc->createElement( 'link', $link ) );

View File

@@ -691,12 +691,12 @@ class Helpers
if ( $row2['seo_link'] ) if ( $row2['seo_link'] )
{ {
$mdb->insert( 'pp_routes', [ 'product_id' => $row2['product_id'], 'lang_id' => $row['id'], 'pattern' => '^' . $language_link . self::seo( $row2['seo_link'] ) . '$', 'destination' => 'index.php?product=' . $row2['product_id'] ] ); $mdb->insert( 'pp_routes', [ 'product_id' => $row2['product_id'], 'lang_id' => $row['id'], 'pattern' => '^' . $language_link . self::seo( $row2['seo_link'] ) . '$', 'destination' => 'index.php?product=' . $row2['product_id'] ] );
$mdb->insert( 'pp_routes', [ 'product_id' => $row2['product_id'], 'lang_id' => $row['id'], 'pattern' => '^' . $language_link . self::seo( $row2['seo_link'] ) . '/([0-9-]+)$', 'destination' => 'index.php?product=' . $row2['product_id'] . '&permutation_hash=$1' ] ); $mdb->insert( 'pp_routes', [ 'product_id' => $row2['product_id'], 'lang_id' => $row['id'], 'pattern' => '^' . $language_link . self::seo( $row2['seo_link'] ) . '/([0-9_-]+)$', 'destination' => 'index.php?product=' . $row2['product_id'] . '&permutation_hash=$1' ] );
} }
else else
{ {
$mdb->insert( 'pp_routes', [ 'product_id' => $row2['product_id'], 'lang_id' => $row['id'], 'pattern' => '^' . $language_link . 'p-' . $row2['product_id'] . '-' . self::seo( $row2['name'] ) . '$', 'destination' => 'index.php?product=' . $row2['product_id'] ] ); $mdb->insert( 'pp_routes', [ 'product_id' => $row2['product_id'], 'lang_id' => $row['id'], 'pattern' => '^' . $language_link . 'p-' . $row2['product_id'] . '-' . self::seo( $row2['name'] ) . '$', 'destination' => 'index.php?product=' . $row2['product_id'] ] );
$mdb->insert( 'pp_routes', [ 'product_id' => $row2['product_id'], 'lang_id' => $row['id'], 'pattern' => '^' . $language_link . 'p-' . $row2['product_id'] . '-' . self::seo( $row2['name'] ) . '/([0-9-]+)$', 'destination' => 'index.php?product=' . $row2['product_id'] . '&permutation_hash=$1' ] ); $mdb->insert( 'pp_routes', [ 'product_id' => $row2['product_id'], 'lang_id' => $row['id'], 'pattern' => '^' . $language_link . 'p-' . $row2['product_id'] . '-' . self::seo( $row2['name'] ) . '/([0-9_-]+)$', 'destination' => 'index.php?product=' . $row2['product_id'] . '&permutation_hash=$1' ] );
} }
} }
} }

View File

@@ -184,8 +184,16 @@ class ScontainersController
} }
$data = $result['data']; $data = $result['data'];
$containerId = (int)($data['id'] ?? 0);
if ($containerId <= 0) {
$routeId = (int)\Shared\Helpers\Helpers::get('id');
if ($routeId > 0) {
$containerId = $routeId;
}
}
$savedId = $this->repository->save([ $savedId = $this->repository->save([
'id' => (int)($data['id'] ?? 0), 'id' => $containerId,
'status' => $data['status'] ?? 0, 'status' => $data['status'] ?? 0,
'show_title' => $data['show_title'] ?? 0, 'show_title' => $data['show_title'] ?? 0,
'translations' => $data['translations'] ?? [], 'translations' => $data['translations'] ?? [],
@@ -240,7 +248,6 @@ class ScontainersController
]; ];
$fields = [ $fields = [
FormField::hidden('id', $id),
FormField::langSection('translations', 'content', [ FormField::langSection('translations', 'content', [
FormField::text('title', [ FormField::text('title', [
'label' => 'Tytul', 'label' => 'Tytul',
@@ -283,7 +290,7 @@ class ScontainersController
$actionUrl, $actionUrl,
'/admin/scontainers/list/', '/admin/scontainers/list/',
true, true,
[], ['id' => $id],
$languages, $languages,
$errors $errors
); );

View File

@@ -18,6 +18,8 @@ use admin\Support\TableListRequestFactory;
*/ */
class ShopProductController class ShopProductController
{ {
private const CUSTOM_LABELS_SESSION_KEY = 'shop_product_show_custom_labels';
private ProductRepository $repository; private ProductRepository $repository;
private IntegrationsRepository $integrationsRepository; private IntegrationsRepository $integrationsRepository;
private LanguagesRepository $languagesRepository; private LanguagesRepository $languagesRepository;
@@ -39,6 +41,8 @@ class ShopProductController
$apiloEnabled = $this->integrationsRepository->getSetting( 'apilo', 'enabled' ); $apiloEnabled = $this->integrationsRepository->getSetting( 'apilo', 'enabled' );
$shopproEnabled = $this->integrationsRepository->getSetting( 'shoppro', 'enabled' ); $shopproEnabled = $this->integrationsRepository->getSetting( 'shoppro', 'enabled' );
$dlang = $this->languagesRepository->defaultLanguage(); $dlang = $this->languagesRepository->defaultLanguage();
$customLabelsEnabled = $this->customLabelsEnabled();
$customLabelNames = $this->repository->customLabelNames();
$sortableColumns = [ 'id', 'name', 'price_brutto', 'status', 'promoted', 'quantity' ]; $sortableColumns = [ 'id', 'name', 'price_brutto', 'status', 'promoted', 'quantity' ];
@@ -98,6 +102,10 @@ class ShopProductController
. '<small class="text-muted product-categories product-categories--cats" title="' . $categories . '">' . $categories . '</small>' . '<small class="text-muted product-categories product-categories--cats" title="' . $categories . '">' . $categories . '</small>'
. '<small class="text-muted product-categories">SKU: ' . $sku . ', EAN: ' . $ean . '</small>'; . '<small class="text-muted product-categories">SKU: ' . $sku . ', EAN: ' . $ean . '</small>';
if ( $customLabelsEnabled ) {
$nameHtml .= $this->renderCustomLabelsEditor( $product, $id, $customLabelNames );
}
$priceHtml = '<input type="text" class="product-price form-control text-right" product-id="' . $id . '" value="' . htmlspecialchars( (string) $product['price_brutto'], ENT_QUOTES, 'UTF-8' ) . '" style="width: 75px;">'; $priceHtml = '<input type="text" class="product-price form-control text-right" product-id="' . $id . '" value="' . htmlspecialchars( (string) $product['price_brutto'], ENT_QUOTES, 'UTF-8' ) . '" style="width: 75px;">';
$promoHtml = '<input type="text" class="product-price-promo form-control text-right" product-id="' . $id . '" value="' . htmlspecialchars( (string) $product['price_brutto_promo'], ENT_QUOTES, 'UTF-8' ) . '" style="width: 75px;">'; $promoHtml = '<input type="text" class="product-price-promo form-control text-right" product-id="' . $id . '" value="' . htmlspecialchars( (string) $product['price_brutto_promo'], ENT_QUOTES, 'UTF-8' ) . '" style="width: 75px;">';
$promotedHtml = $product['promoted'] ? '<span class="text-success text-bold">tak</span>' : 'nie'; $promotedHtml = $product['promoted'] ? '<span class="text-success text-bold">tak</span>' : 'nie';
@@ -195,11 +203,25 @@ class ShopProductController
'viewModel' => $viewModel, 'viewModel' => $viewModel,
'apilo_enabled' => $apiloEnabled, 'apilo_enabled' => $apiloEnabled,
'shoppro_enabled' => $shopproEnabled, 'shoppro_enabled' => $shopproEnabled,
'custom_labels_enabled' => $customLabelsEnabled,
] ); ] );
} }
// ─── Krok 7: Edycja i zapis ───────────────────────────────────── // ─── Krok 7: Edycja i zapis ─────────────────────────────────────
/**
* AJAX: przelacza widok custom labels na liscie produktow i zapisuje stan w sesji.
*/
public function product_custom_labels_toggle(): void
{
$currentState = $this->customLabelsEnabled();
$newState = $currentState ? 0 : 1;
\Shared\Helpers\Helpers::set_session( self::CUSTOM_LABELS_SESSION_KEY, $newState );
echo json_encode( [ 'status' => 'ok', 'enabled' => (bool) $newState ] );
exit;
}
/** /**
* Formularz edycji produktu. * Formularz edycji produktu.
*/ */
@@ -699,7 +721,8 @@ class ShopProductController
private function renderCustomFieldsBox( array $product ): string private function renderCustomFieldsBox( array $product ): string
{ {
$html = '<a href="#" class="btn btn-success" id="add_custom_field"><i class="fa fa-plus"></i> dodaj niestandardowe pole</a>'; $html = '<input type="hidden" name="custom_field_name_present" value="1">';
$html .= '<a href="#" class="btn btn-success" id="add_custom_field"><i class="fa fa-plus"></i> dodaj niestandardowe pole</a>';
$html .= '<div class="additional_fields pt-3">'; $html .= '<div class="additional_fields pt-3">';
$customFields = is_array( $product['custom_fields'] ?? null ) ? $product['custom_fields'] : []; $customFields = is_array( $product['custom_fields'] ?? null ) ? $product['custom_fields'] : [];
@@ -896,9 +919,15 @@ class ShopProductController
public function product_custom_label_suggestions(): void public function product_custom_label_suggestions(): void
{ {
$response = [ 'status' => 'error', 'msg' => 'Podczas pobierania sugestii dla custom label wystąpił błąd. Proszę spróbować ponownie.' ]; $response = [ 'status' => 'error', 'msg' => 'Podczas pobierania sugestii dla custom label wystąpił błąd. Proszę spróbować ponownie.' ];
$labelType = (string) \Shared\Helpers\Helpers::get( 'label_type' );
$suggestions = $this->repository->customLabelSuggestions( \Shared\Helpers\Helpers::get( 'custom_label' ), \Shared\Helpers\Helpers::get( 'label_type' ) ); if ( !$this->isAllowedCustomLabelType( $labelType ) ) {
if ( $suggestions ) { echo json_encode( $response );
exit;
}
$suggestions = $this->repository->customLabelSuggestions( (string) \Shared\Helpers\Helpers::get( 'custom_label' ), $labelType );
if ( is_array( $suggestions ) ) {
$response = [ 'status' => 'ok', 'suggestions' => $suggestions ]; $response = [ 'status' => 'ok', 'suggestions' => $suggestions ];
} }
@@ -912,8 +941,14 @@ class ShopProductController
public function product_custom_label_save(): void public function product_custom_label_save(): void
{ {
$response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania custom label wystąpił błąd. Proszę spróbować ponownie.' ]; $response = [ 'status' => 'error', 'msg' => 'Podczas zapisywania custom label wystąpił błąd. Proszę spróbować ponownie.' ];
$labelType = (string) \Shared\Helpers\Helpers::get( 'label_type' );
if ( $this->repository->saveCustomLabel( (int) \Shared\Helpers\Helpers::get( 'product_id' ), \Shared\Helpers\Helpers::get( 'custom_label' ), \Shared\Helpers\Helpers::get( 'label_type' ) ) ) { if ( !$this->isAllowedCustomLabelType( $labelType ) ) {
echo json_encode( $response );
exit;
}
if ( $this->repository->saveCustomLabel( (int) \Shared\Helpers\Helpers::get( 'product_id' ), (string) \Shared\Helpers\Helpers::get( 'custom_label' ), $labelType ) ) {
$response = [ 'status' => 'ok' ]; $response = [ 'status' => 'ok' ];
} }
@@ -1196,4 +1231,36 @@ class ShopProductController
echo json_encode( [ 'status' => 'ok', 'products' => $products ] ); echo json_encode( [ 'status' => 'ok', 'products' => $products ] );
exit; exit;
} }
private function customLabelsEnabled(): bool
{
return isset( $_SESSION[ self::CUSTOM_LABELS_SESSION_KEY ] ) && (int) $_SESSION[ self::CUSTOM_LABELS_SESSION_KEY ] === 1;
}
private function isAllowedCustomLabelType(string $labelType): bool
{
return in_array( $labelType, [ 'custom_label_0', 'custom_label_1', 'custom_label_2', 'custom_label_3', 'custom_label_4' ], true );
}
private function renderCustomLabelsEditor(array $product, int $productId, array $customLabelNames): string
{
$customLabelsHtml = '<div class="custom-labels mt10">';
for ( $index = 0; $index < 5; $index++ ) {
$fieldName = 'custom_label_' . $index;
$labelText = htmlspecialchars( (string) ( $customLabelNames[$fieldName] ?? 'Custom label ' . $index ), ENT_QUOTES, 'UTF-8' );
$valueText = htmlspecialchars( (string) ( $product[$fieldName] ?? '' ), ENT_QUOTES, 'UTF-8' );
$customLabelsHtml .= '<div class="' . $fieldName . '_container">';
$customLabelsHtml .= '<small class="text-muted">' . $labelText . '</small>';
$datalistId = 'custom-label-list-' . $productId . '-' . $fieldName;
$customLabelsHtml .= '<input type="text" class="form-control input-sm product-custom-label" data-label-type="' . $fieldName . '" data-product-id="' . $productId . '" data-datalist-id="' . $datalistId . '" list="' . $datalistId . '" value="' . $valueText . '" placeholder="' . $labelText . '">';
$customLabelsHtml .= '<datalist id="' . $datalistId . '"></datalist>';
$customLabelsHtml .= '<div class="' . $fieldName . '_suggestions custom-label-suggestions"></div>';
$customLabelsHtml .= '</div>';
}
$customLabelsHtml .= '</div>';
return $customLabelsHtml;
}
} }

View File

@@ -280,20 +280,71 @@ class ShopBasketController
$client = \Shared\Helpers\Helpers::get_session( 'client' ); $client = \Shared\Helpers\Helpers::get_session( 'client' );
$orderSubmitToken = $this->createOrderSubmitToken(); $orderSubmitToken = $this->createOrderSubmitToken();
$basket = \Shared\Helpers\Helpers::get_session( 'basket' );
$coupon = \Shared\Helpers\Helpers::get_session( 'coupon' );
$transport = ( new \Domain\Transport\TransportRepository( $GLOBALS['mdb'] ) )->findActiveByIdCached( \Shared\Helpers\Helpers::get_session( 'basket-transport-method-id' ) );
$productsSummary = (float)\Domain\Basket\BasketCalculator::summaryPrice( $basket, $coupon );
$freeDeliveryThreshold = isset( $settings['free_delivery'] ) ? (float)$settings['free_delivery'] : 0.0;
$transportCalc = $this->calculateTransportCostForSummary( $transport, $productsSummary, $freeDeliveryThreshold );
return \Shared\Tpl\Tpl::view( 'shop-basket/summary-view', [ return \Shared\Tpl\Tpl::view( 'shop-basket/summary-view', [
'lang_id' => $lang_id, 'lang_id' => $lang_id,
'client' => \Shared\Helpers\Helpers::get_session( 'client' ), 'client' => \Shared\Helpers\Helpers::get_session( 'client' ),
'basket' => \Shared\Helpers\Helpers::get_session( 'basket' ), 'basket' => $basket,
'transport' => ( new \Domain\Transport\TransportRepository( $GLOBALS['mdb'] ) )->findActiveByIdCached( \Shared\Helpers\Helpers::get_session( 'basket-transport-method-id' ) ), 'transport' => $transport,
'transport_cost_effective' => $transportCalc['transport_cost_effective'],
'free_delivery_applies' => $transportCalc['free_delivery_applies'],
'payment_method' => $this->paymentMethodRepository->paymentMethodCached( (int)\Shared\Helpers\Helpers::get_session( 'basket-payment-method-id' ) ), 'payment_method' => $this->paymentMethodRepository->paymentMethodCached( (int)\Shared\Helpers\Helpers::get_session( 'basket-payment-method-id' ) ),
'addresses' => ( new \Domain\Client\ClientRepository( $GLOBALS['mdb'] ) )->clientAddresses( (int)$client['id'] ), 'addresses' => ( new \Domain\Client\ClientRepository( $GLOBALS['mdb'] ) )->clientAddresses( (int)$client['id'] ),
'settings' => $settings, 'settings' => $settings,
'coupon' => \Shared\Helpers\Helpers::get_session( 'coupon' ), 'coupon' => $coupon,
'basket_message' => \Shared\Helpers\Helpers::get_session( 'basket_message' ), 'basket_message' => \Shared\Helpers\Helpers::get_session( 'basket_message' ),
'order_submit_token' => $orderSubmitToken 'order_submit_token' => $orderSubmitToken
] ); ] );
} }
/**
* Wylicza efektywny koszt transportu dla widoku /koszyk-podsumowanie.
* Koszt spada do 0, gdy transport ma flage delivery_free=1 ORAZ wartosc koszyka
* (po kuponie) osiaga prog darmowej dostawy $freeDeliveryThreshold.
*
* @param array|null $transport Aktywny transport (lub null gdy nie wybrany)
* @param float $productsSummary Wartosc koszyka po kuponie
* @param float $freeDeliveryThreshold Prog darmowej dostawy z settings.free_delivery
* @return array{transport_cost_effective: float, free_delivery_applies: bool}
*/
protected function calculateTransportCostForSummary( $transport, $productsSummary, $freeDeliveryThreshold )
{
if ( !is_array( $transport ) )
{
return [
'transport_cost_effective' => 0.0,
'free_delivery_applies' => false,
];
}
$deliveryFree = isset( $transport['delivery_free'] ) ? (int)$transport['delivery_free'] : 0;
$cost = isset( $transport['cost'] ) ? (float)$transport['cost'] : 0.0;
$applies = false;
if ( $deliveryFree === 1 && $freeDeliveryThreshold > 0 )
{
$summaryNormalized = \Shared\Helpers\Helpers::normalize_decimal( $productsSummary );
$thresholdNormalized = \Shared\Helpers\Helpers::normalize_decimal( $freeDeliveryThreshold );
if ( $summaryNormalized >= $thresholdNormalized )
{
$applies = true;
}
}
return [
'transport_cost_effective' => $applies ? 0.0 : $cost,
'free_delivery_applies' => $applies,
];
}
public function basketSave() public function basketSave()
{ {
$orderSubmitToken = (string)\Shared\Helpers\Helpers::get( 'order_submit_token', true ); $orderSubmitToken = (string)\Shared\Helpers\Helpers::get( 'order_submit_token', true );

View File

@@ -153,15 +153,9 @@ class LayoutEngine
{ {
$category = $categoryRepo->frontCategoryDetails( (int)\Shared\Helpers\Helpers::get( 'category' ), $lang_id ); $category = $categoryRepo->frontCategoryDetails( (int)\Shared\Helpers\Helpers::get( 'category' ), $lang_id );
if ( $category['language']['meta_title'] ) $page = self::applyEntityMetaToPage( $page, isset( $category['language'] ) ? $category['language'] : null, isset( $category['language']['title'] ) ? $category['language']['title'] : '' );
$page['language']['title'] = $category['language']['meta_title'];
else
$page['language']['title'] = $category['language']['title'];
$page['show_title'] = true; $page['show_title'] = true;
$page['language']['meta_keywords'] = $category['language']['meta_keywords']; $page['language']['page_title'] = !empty( $category['language']['category_title'] ) ? $category['language']['category_title'] : ( isset( $category['language']['title'] ) ? $category['language']['title'] : '' );
$page['language']['meta_description'] = $category['language']['meta_description'];
$page['language']['page_title'] = $category['language']['category_title'] ? $category['language']['category_title'] : $category['language']['title'];
// CANONICAL // CANONICAL
$html = str_replace( '[CANONICAL]', '', $html ); $html = str_replace( '[CANONICAL]', '', $html );
@@ -175,14 +169,8 @@ class LayoutEngine
{ {
$article = $articleRepo->articleDetailsFrontend( (int)\Shared\Helpers\Helpers::get( 'article' ), $lang_id ); $article = $articleRepo->articleDetailsFrontend( (int)\Shared\Helpers\Helpers::get( 'article' ), $lang_id );
if ( $article['language']['meta_title'] ) $page = self::applyEntityMetaToPage( $page, isset( $article['language'] ) ? $article['language'] : null, isset( $article['language']['title'] ) ? $article['language']['title'] : '' );
$page['language']['title'] = $article['language']['meta_title'];
else
$page['language']['title'] = $article['language']['title'];
$page['show_title'] = false; $page['show_title'] = false;
$page['language']['meta_keywords'] = $article['language']['meta_keywords'];
$page['language']['meta_description'] = $article['language']['meta_description'];
// CANONICAL // CANONICAL
$html = str_replace( '[CANONICAL]', '', $html ); $html = str_replace( '[CANONICAL]', '', $html );
@@ -193,16 +181,11 @@ class LayoutEngine
// //
if ( \Shared\Helpers\Helpers::get( 'product' ) ) if ( \Shared\Helpers\Helpers::get( 'product' ) )
{ {
$product = ( new \Domain\Product\ProductRepository( $GLOBALS['mdb'] ) )->findCached( \Shared\Helpers\Helpers::get( 'product' ), $lang_id, $_GET['permutation_hash'] ?? null ); $permutation_hash = isset( $_GET['permutation_hash'] ) ? str_replace( '_', '|', $_GET['permutation_hash'] ) : null;
$product = ( new \Domain\Product\ProductRepository( $GLOBALS['mdb'] ) )->findCached( \Shared\Helpers\Helpers::get( 'product' ), $lang_id, $permutation_hash );
if ( $product['language']['meta_title'] )
$page['language']['title'] = $product['language']['meta_title'];
else
$page['language']['title'] = $product['language']['name'];
$page = self::applyEntityMetaToPage( $page, isset( $product['language'] ) ? $product['language'] : null, isset( $product['language']['name'] ) ? $product['language']['name'] : '' );
$page['show_title'] = false; $page['show_title'] = false;
$page['language']['meta_keywords'] = $product['language']['meta_keywords'];
$page['language']['meta_description'] = $product['language']['meta_description'];
// CANONICAL // CANONICAL
if ( $product['language']['canonical'] ) if ( $product['language']['canonical'] )
@@ -439,6 +422,35 @@ class LayoutEngine
] ); ] );
} }
/**
* Przepisuje meta encji (kategoria/artykuł/produkt) do $page['language'].
*
* Dlaczego: domyślne $page jest stroną główną CMS. Jeśli nie nadpiszemy
* meta_title encji (nawet pustym), meta_title homepage wycieka do <title>
* na podstronie kategorii/produktu (linia podstawienia [TITLE]).
*
* @param array $page obecne $page (z homepage lub session)
* @param array|null $entityLanguage wiersz *_langs encji (może być null)
* @param string $fallbackTitle nazwa encji używana jako $page.language.title
* @return array zmodyfikowany $page
*/
public static function applyEntityMetaToPage( $page, $entityLanguage, $fallbackTitle )
{
if ( !is_array( $page ) ) {
$page = [];
}
if ( !isset( $page['language'] ) or !is_array( $page['language'] ) ) {
$page['language'] = [];
}
$page['language']['title'] = $fallbackTitle;
$page['language']['meta_title'] = is_array( $entityLanguage ) && isset( $entityLanguage['meta_title'] ) ? $entityLanguage['meta_title'] : null;
$page['language']['meta_keywords'] = is_array( $entityLanguage ) && isset( $entityLanguage['meta_keywords'] ) ? $entityLanguage['meta_keywords'] : null;
$page['language']['meta_description'] = is_array( $entityLanguage ) && isset( $entityLanguage['meta_description'] ) ? $entityLanguage['meta_description'] : null;
return $page;
}
public static function alert() public static function alert()
{ {
if ( $alert = \Shared\Helpers\Helpers::get_session( 'alert' ) ) if ( $alert = \Shared\Helpers\Helpers::get_session( 'alert' ) )