Compare commits

..

7 Commits

Author SHA1 Message Date
Jacek
9bbcc032c2 fix: getProductLayout używał layoutu kategorii zamiast domyślnego (v0.331)
Fallback w LayoutsRepository::getProductLayout() zmieniony z
categories_default=1 na status=1 — produkty bez przypisanego layoutu
pobierają teraz właściwy domyślny szablon zamiast szablonu kategorii.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 00:42:41 +01:00
c9cb10950f update 2026-02-28 12:08:31 +01:00
1cd18c052f update 2026-02-27 23:42:35 +01:00
d60e335ca6 build: update package v0.329 — routing przez pp_routes + eliminacja htaccess.conf
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 23:05:24 +01:00
eb7badab65 docs: update CHANGELOG for v0.329 and v0.330
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 22:50:24 +01:00
d83d0ecdea feat: eliminate htaccess.conf, move all URL routes to pp_routes (v0.329-0.330)
- Add category_id, page_id, article_id, type columns to pp_routes (migration 0.329)
- Move routing block in index.php before checkUrlParams() with Redis cache
- Routes for categories, pages, articles now stored in pp_routes instead of .htaccess
- Delete category/page/article routes on entity delete in respective repositories
- Eliminate libraries/htaccess.conf: generate .htaccess content entirely from PHP
- Move 32 static system routes (koszyk, logowanie, newsletter, AJAX modules, etc.)
  plus dynamic language/producer routes to pp_routes with type='system'
- Invalidate pp_routes Redis cache on every htacces() regeneration

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 22:06:33 +01:00
b8ed7a46d8 build: update package v0.328 — copy icon for order attribute values
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 20:51:20 +01:00
25 changed files with 1359 additions and 579 deletions

205
.htaccess
View File

@@ -7,67 +7,25 @@ Options -Indexes
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
# Przekierowanie z http na https, jeśli nie zawiera www
# Przekierowanie z http na https, jesli nie zawiera www
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} !^/(tpay-status|platnosc-status|przelewy24-status)$ [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Usuwanie końcowego slash'a dla niekatalogów
# Usuwanie koncowego slasha dla niekatalogów
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/admin/.*$ [NC] # Wyklucza ścieżki rozpoczynające się od "admin/"
RewriteCond %{REQUEST_URI} !^/admin/.*$ [NC]
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [R=301,L]
ErrorDocument 404 /index.php
RewriteCond %{REQUEST_URI} !^(.*)/libraries/(.*) [NC]
RewriteCond %{REQUEST_URI} !^(.*)/layout/(.*) [NC]
RewriteRule ^admin/([^/]*)/([^/]*)/(.*)$ admin/index.php?module=$1&action=$2&$3 [QSA,L]
RewriteRule ^admin/([^/]*)/([^/]*)/(.*)$ admin/index.php?module=$1&action=$2&$3 [L]
RewriteRule ^admin/$ admin/index.php [L]
RewriteRule ^wyszukiwarka/(.*)/([0-9]*)$ index.php?module=search&action=search_results&query=$1&bs=$2 [L]
RewriteRule ^wyszukiwarka/(.*)$ index.php?module=search&action=search_results&query=$1&bs=1 [L]
RewriteRule ^zamowienie/([a-zA-Z0-9-]*)$ index.php?module=shop_order&action=order_details&order_hash=$1 [L]
RewriteRule ^potwierdzenie-platnosci/([a-zA-Z0-9-]*)$ index.php?module=shop_order&action=payment_confirmation&order_hash=$1 [L]
RewriteRule ^tpay-status$ index.php?module=shop_order&action=payment_status_tpay%{QUERY_STRING} [L]
RewriteRule ^platnosc-status$ index.php?module=shop_order&action=payment_status_hotpay%{QUERY_STRING} [L]
RewriteRule ^przelewy24-status$ index.php?module=shop_order&action=payment_status_przelewy24pl%{QUERY_STRING} [L]
RewriteRule ^koszyk$ index.php?module=shop_basket&action=main_view [L]
RewriteRule ^koszyk-podsumowanie$ index.php?module=shop_basket&action=summary_view [L]
RewriteRule ^zloz-zamowienie$ index.php?module=shop_basket&action=basket_save [L]
RewriteRule ^rejestracja$ index.php?module=shop_client&action=register_form [L]
RewriteRule ^logowanie$ index.php?module=shop_client&action=login_form [L]
RewriteRule ^wylogowanie$ index.php?module=shop_client&action=logout [L]
RewriteRule ^odzyskiwanie-hasla$ index.php?module=shop_client&action=recover_password [L]
RewriteRule ^panel-klienta/zamowienia$ index.php?module=shop_client&action=client_orders [L]
RewriteRule ^panel-klienta/adresy$ index.php?module=shop_client&action=client_addresses [L]
RewriteRule ^panel-klienta/nowy-adres$ index.php?module=shop_client&action=address_edit [L]
RewriteRule ^panel-klienta/edytuj-adres/([0-9]*)$ index.php?module=shop_client&action=address_edit&id=$1 [L]
RewriteRule ^panel-klienta/usun-adres/([0-9]*)$ index.php?module=shop_client&action=address_delete&id=$1 [L]
RewriteRule ^thumb/([0-9]*)/([0-9]*)/(.*)$ /libraries/thumb.php?img=$3&w=$1&h=$2 [L]
RewriteCond %{REQUEST_URI} ^/shopBasket/(.*)/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)/(.*)$ index.php?module=$1&action=$2&$3 [L]
RewriteCond %{REQUEST_URI} ^/shopClient/(.*)/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)/(.*)$ index.php?module=$1&action=$2&$3 [L]
RewriteCond %{REQUEST_URI} ^/shopProduct/(.*)/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)/(.*)$ index.php?module=$1&action=$2&$3 [L]
RewriteCond %{REQUEST_URI} ^/shopCoupon/(.*)/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)/(.*)$ index.php?module=$1&action=$2&$3 [L]
RewriteCond %{REQUEST_URI} ^/search/(.*)/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)/(.*)$ index.php?module=$1&action=$2&$3 [L]
RewriteCond %{REQUEST_URI} ^/shopBasket/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)$ index.php?module=$1&action=$2 [L]
RewriteCond %{REQUEST_URI} ^/shopClient/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)$ index.php?module=$1&action=$2 [L]
RewriteCond %{REQUEST_URI} ^/shopProduct/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)$ index.php?module=$1&action=$2 [L]
RewriteCond %{REQUEST_URI} ^/shopCoupon/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)$ index.php?module=$1&action=$2 [L]
RewriteCond %{REQUEST_URI} ^/search/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)$ index.php?module=$1&action=$2 [L]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index.php
RewriteRule ^ /%1 [R=301,L]
<IfModule mod_deflate.c>
@@ -116,168 +74,17 @@ ExpiresByType image/svg+xml "access plus 1 month"
Order Deny,Allow
Deny from all
</Files>
RewriteRule ^pl/$ index.php?a=change_language&id=pl [L]
RewriteRule ^en/$ index.php?a=change_language&id=en [L]
RewriteRule ^newsletter/signin/$ index.php?module=newsletter&action=signin [L]
RewriteRule ^newsletter/confirm/hash=(.*)$ index.php?module=newsletter&action=confirm&hash=$1 [L]
RewriteRule ^newsletter/unsubscribe/hash=(.*)$ index.php?module=newsletter&action=unsubscribe&hash=$1 [L]
RewriteRule ^producenci$ index.php?module=shop_producer&action=list&layout_id=2&%{QUERY_STRING} [L]
RewriteRule ^producent/bibs$ index.php?module=shop_producer&action=products&producer_id=3&layout_id=2&%{QUERY_STRING} [L]
RewriteRule ^producent/bibs/([0-9]+)$ index.php?module=shop_producer&action=products&producer_id=3&layout_id=2&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^sen-i-otulenie$ index.php?category=10&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^sen-i-otulenie/([0-9]+)$ index.php?category=10&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^sen-i-otulenie/1$ sen-i-otulenie [R=301,L]
RewriteRule ^kocyki-minky$ index.php?category=5&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^kocyki-minky/([0-9]+)$ index.php?category=5&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^kocyki-minky/1$ kocyki-minky [R=301,L]
RewriteRule ^kocyki-niemowlece-minky-50x70$ index.php?category=6&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^kocyki-niemowlece-minky-50x70/([0-9]+)$ index.php?category=6&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^kocyki-niemowlece-minky-50x70/1$ kocyki-niemowlece-minky-50x70 [R=301,L]
RewriteRule ^kocyki-sredniaka-minky-75x100$ index.php?category=7&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^kocyki-sredniaka-minky-75x100/([0-9]+)$ index.php?category=7&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^kocyki-sredniaka-minky-75x100/1$ kocyki-sredniaka-minky-75x100 [R=301,L]
RewriteRule ^kocyki-przedszkolaka-minky-100x130$ index.php?category=8&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^kocyki-przedszkolaka-minky-100x130/([0-9]+)$ index.php?category=8&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^kocyki-przedszkolaka-minky-100x130/1$ kocyki-przedszkolaka-minky-100x130 [R=301,L]
RewriteRule ^poduszki$ index.php?category=2&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^poduszki/([0-9]+)$ index.php?category=2&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^poduszki/1$ poduszki [R=301,L]
RewriteRule ^poduszki-niemowlaka-minky-25x35$ index.php?category=18&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^poduszki-niemowlaka-minky-25x35/([0-9]+)$ index.php?category=18&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^poduszki-niemowlaka-minky-25x35/1$ poduszki-niemowlaka-minky-25x35 [R=301,L]
RewriteRule ^poduszki/gwiazdki-40x40$ index.php?category=9&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^poduszki/gwiazdki-40x40/([0-9]+)$ index.php?category=9&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^poduszki/gwiazdki-40x40/1$ poduszki/gwiazdki-40x40 [R=301,L]
RewriteRule ^rozki$ index.php?category=1&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^rozki/([0-9]+)$ index.php?category=1&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^rozki/1$ rozki [R=301,L]
RewriteRule ^akcesoria$ index.php?category=4&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^akcesoria/([0-9]+)$ index.php?category=4&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^akcesoria/1$ akcesoria [R=301,L]
RewriteRule ^metryczki-dzieciece$ index.php?category=11&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^metryczki-dzieciece/([0-9]+)$ index.php?category=11&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^metryczki-dzieciece/1$ metryczki-dzieciece [R=301,L]
RewriteRule ^metryczki-ze-zdjeciem$ index.php?category=39&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^metryczki-ze-zdjeciem/([0-9]+)$ index.php?category=39&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^metryczki-ze-zdjeciem/1$ metryczki-ze-zdjeciem [R=301,L]
RewriteRule ^metryczki-dla-dziewczynki$ index.php?category=40&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^metryczki-dla-dziewczynki/([0-9]+)$ index.php?category=40&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^metryczki-dla-dziewczynki/1$ metryczki-dla-dziewczynki [R=301,L]
RewriteRule ^metryczki-dla-chlopca$ index.php?category=41&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^metryczki-dla-chlopca/([0-9]+)$ index.php?category=41&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^metryczki-dla-chlopca/1$ metryczki-dla-chlopca [R=301,L]
RewriteRule ^termofory-dla-dzieci$ index.php?category=17&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^termofory-dla-dzieci/([0-9]+)$ index.php?category=17&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^termofory-dla-dzieci/1$ termofory-dla-dzieci [R=301,L]
RewriteRule ^zawieszki$ index.php?category=43&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^zawieszki/([0-9]+)$ index.php?category=43&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^zawieszki/1$ zawieszki [R=301,L]
RewriteRule ^zawieszki-dekoracyjne$ index.php?category=32&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^zawieszki-dekoracyjne/([0-9]+)$ index.php?category=32&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^zawieszki-dekoracyjne/1$ zawieszki-dekoracyjne [R=301,L]
RewriteRule ^zawieszki-do-smoczkow-i-gryzakow$ index.php?category=44&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^zawieszki-do-smoczkow-i-gryzakow/([0-9]+)$ index.php?category=44&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^zawieszki-do-smoczkow-i-gryzakow/1$ zawieszki-do-smoczkow-i-gryzakow [R=301,L]
RewriteRule ^zawieszki-do-wozka$ index.php?category=45&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^zawieszki-do-wozka/([0-9]+)$ index.php?category=45&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^zawieszki-do-wozka/1$ zawieszki-do-wozka [R=301,L]
RewriteRule ^odziez-dziecieca$ index.php?category=12&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^odziez-dziecieca/([0-9]+)$ index.php?category=12&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^odziez-dziecieca/1$ odziez-dziecieca [R=301,L]
RewriteRule ^apaszki$ index.php?category=35&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^apaszki/([0-9]+)$ index.php?category=35&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^apaszki/1$ apaszki [R=301,L]
RewriteRule ^kominy-dzieciece$ index.php?category=15&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^kominy-dzieciece/([0-9]+)$ index.php?category=15&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^kominy-dzieciece/1$ kominy-dzieciece [R=301,L]
RewriteRule ^opaski$ index.php?category=37&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^opaski/([0-9]+)$ index.php?category=37&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^opaski/1$ opaski [R=301,L]
RewriteRule ^opaski-pin-up$ index.php?category=38&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^opaski-pin-up/([0-9]+)$ index.php?category=38&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^opaski-pin-up/1$ opaski-pin-up [R=301,L]
RewriteRule ^turbany$ index.php?category=14&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^turbany/([0-9]+)$ index.php?category=14&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^turbany/1$ turbany [R=301,L]
RewriteRule ^ubrania-dla-dziewczynek$ index.php?category=13&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^ubrania-dla-dziewczynek/([0-9]+)$ index.php?category=13&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^ubrania-dla-dziewczynek/1$ ubrania-dla-dziewczynek [R=301,L]
RewriteRule ^zestawy-i-kolekcje$ index.php?category=16&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^zestawy-i-kolekcje/([0-9]+)$ index.php?category=16&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^zestawy-i-kolekcje/1$ zestawy-i-kolekcje [R=301,L]
RewriteRule ^zestawy$ index.php?category=20&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^zestawy/([0-9]+)$ index.php?category=20&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^zestawy/1$ zestawy [R=301,L]
RewriteRule ^komplet-niemowlaka$ index.php?category=24&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^komplet-niemowlaka/([0-9]+)$ index.php?category=24&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^komplet-niemowlaka/1$ komplet-niemowlaka [R=301,L]
RewriteRule ^komplet-sredniaka$ index.php?category=28&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^komplet-sredniaka/([0-9]+)$ index.php?category=28&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^komplet-sredniaka/1$ komplet-sredniaka [R=301,L]
RewriteRule ^kolekcje$ index.php?category=29&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^kolekcje/([0-9]+)$ index.php?category=29&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^kolekcje/1$ kolekcje [R=301,L]
RewriteRule ^mama-bear-chmurki-mietowe$ index.php?category=36&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^mama-bear-chmurki-mietowe/([0-9]+)$ index.php?category=36&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^mama-bear-chmurki-mietowe/1$ mama-bear-chmurki-mietowe [R=301,L]
RewriteRule ^koniki-na-biegunach$ index.php?category=31&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^koniki-na-biegunach/([0-9]+)$ index.php?category=31&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^koniki-na-biegunach/1$ koniki-na-biegunach [R=301,L]
RewriteRule ^kroliki-na-hustawkach$ index.php?category=30&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^kroliki-na-hustawkach/([0-9]+)$ index.php?category=30&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^kroliki-na-hustawkach/1$ kroliki-na-hustawkach [R=301,L]
RewriteRule ^wyprzedaz$ index.php?category=27&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^wyprzedaz/([0-9]+)$ index.php?category=27&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^wyprzedaz/1$ wyprzedaz [R=301,L]
RewriteRule ^en/kocyk-minky-niemowlaka-50x70-en$ index.php?category=6&lang=en&%{QUERY_STRING} [L]
RewriteRule ^en/kocyk-minky-niemowlaka-50x70-en/([0-9]+)$ index.php?category=6&lang=en&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^en/kocyk-minky-niemowlaka-50x70-en/1$ en/kocyk-minky-niemowlaka-50x70-en [R=301,L]
RewriteCond %{REQUEST_URI} ^/home$
RewriteRule ^(.*)$ http://www.shoppro.project-dc.pl/ [R=permanent,L]
RewriteCond %{REQUEST_URI} ^/home-1$
RewriteRule ^(.*)$ http://www.shoppro.project-dc.pl/ [R=permanent,L]
RewriteRule ^$ index.php?a=page&id=6&lang=pl [L]
RewriteRule ^home$ index.php?a=page&id=6&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^home/([0-9]+)$ index.php?a=page&id=6&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^home/1$ home [R=301,L]
RewriteRule ^regulamin$ index.php?a=page&id=12&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^regulamin/([0-9]+)$ index.php?a=page&id=12&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^regulamin/1$ regulamin [R=301,L]
RewriteRule ^formy-platnosci$ index.php?a=page&id=13&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^formy-platnosci/([0-9]+)$ index.php?a=page&id=13&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^formy-platnosci/1$ formy-platnosci [R=301,L]
RewriteRule ^koszty-dostawy$ index.php?a=page&id=14&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^koszty-dostawy/([0-9]+)$ index.php?a=page&id=14&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^koszty-dostawy/1$ koszty-dostawy [R=301,L]
RewriteRule ^zwroty-i-reklamacje$ index.php?a=page&id=15&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^zwroty-i-reklamacje/([0-9]+)$ index.php?a=page&id=15&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^zwroty-i-reklamacje/1$ zwroty-i-reklamacje [R=301,L]
RewriteRule ^o-nas$ index.php?a=page&id=4&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^o-nas/([0-9]+)$ index.php?a=page&id=4&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^o-nas/1$ o-nas [R=301,L]
RewriteRule ^blog$ index.php?a=page&id=9&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^blog/([0-9]+)$ index.php?a=page&id=9&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^blog/1$ blog [R=301,L]
RewriteRule ^kontakt$ index.php?a=page&id=5&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^kontakt/([0-9]+)$ index.php?a=page&id=5&lang=pl&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^kontakt/1$ kontakt [R=301,L]
RewriteRule ^kolka-u-niemowlat-przyczyny-objawy-leczenie$ index.php?article=11&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^spacery-z-niemowlakiem-jak-sie-do-nich-przygotowac$ index.php?article=12&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^jak-wybrac-kocyk-i-poduszke-niemowlaka$ index.php?article=10&lang=pl&%{QUERY_STRING} [L]
RewriteRule ^jak-wzmocnic-odpornosc-dziecka-w-trakcie-zimy-sprawdzone-sposoby-na-odpornosc$ index.php?article=13&lang=pl&%{QUERY_STRING} [L]
RewriteCond %{REQUEST_URI} ^/home-en$
RewriteRule ^(.*)$ http://www.shoppro.project-dc.pl/en/ [R=permanent,L]
RewriteCond %{REQUEST_URI} ^/home-en-1$
RewriteRule ^(.*)$ http://www.shoppro.project-dc.pl/en/ [R=permanent,L]
RewriteRule ^$ index.php?a=page&id=6&lang=en [L]
RewriteRule ^en/home-en$ index.php?a=page&id=6&lang=en&%{QUERY_STRING} [L]
RewriteRule ^en/home-en/([0-9]+)$ index.php?a=page&id=6&lang=en&bs=$1&%{QUERY_STRING} [L]
RewriteRule ^en/home-en/1$ en/home-en [R=301,L]
RewriteRule ^en/tytul-en$ index.php?article=13&lang=en&%{QUERY_STRING} [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
# <FilesMatch "\.(php4|php5|php3|php2|php|phtml)$">
# SetHandler application/x-lsphp83 /opt/alt/php83 usr/bin/lsphp
# </FilesMatch>
RewriteRule ^ index.php [L]

File diff suppressed because one or more lines are too long

View File

@@ -360,6 +360,9 @@ class ArticleRepository
public function archive(int $articleId): bool
{
$result = $this->db->update('pp_articles', ['status' => -1], ['id' => $articleId]);
if ($result) {
$this->db->delete('pp_routes', ['article_id' => $articleId]);
}
return (bool)$result;
}
@@ -381,6 +384,7 @@ class ArticleRepository
$this->db->delete('pp_articles_langs', ['article_id' => $articleId]);
$this->db->delete('pp_articles_images', ['article_id' => $articleId]);
$this->db->delete('pp_articles_files', ['article_id' => $articleId]);
$this->db->delete('pp_routes', ['article_id' => $articleId]);
$this->db->delete('pp_articles', ['id' => $articleId]);
\Shared\Helpers\Helpers::delete_dir('../upload/article_images/article_' . $articleId . '/');

View File

@@ -174,6 +174,7 @@ class CategoryRepository
$deleted = (bool)$this->db->delete('pp_shop_categories', ['id' => $id]);
if ($deleted) {
$this->db->delete('pp_routes', ['category_id' => $id]);
$this->refreshCategoryArtifacts();
}

View File

@@ -296,7 +296,7 @@ class LayoutsRepository
if (is_array($layoutRows) && isset($layoutRows[0])) {
$layout = $layoutRows[0];
} else {
$layout = $this->db->get('pp_layouts', '*', ['categories_default' => 1]);
$layout = $this->db->get('pp_layouts', '*', ['status' => 1]);
}
}

View File

@@ -134,7 +134,11 @@ class PagesRepository
return false;
}
return (bool)$this->db->delete('pp_pages', ['id' => $pageId]);
$deleted = (bool)$this->db->delete('pp_pages', ['id' => $pageId]);
if ($deleted) {
$this->db->delete('pp_routes', ['page_id' => $pageId]);
}
return $deleted;
}
/**

View File

@@ -425,42 +425,206 @@ class Helpers
$site_map .= '<priority>1</priority>' . PHP_EOL;
$site_map .= '</url>' . PHP_EOL;
$htaccess_data = file_get_contents( $dir . 'libraries/htaccess.conf' );
$htaccess_data = str_replace( '{PAGE}', $url, $htaccess_data );
//
// SYSTEM ROUTES — delete all and reinsert
//
$mdb->delete( 'pp_routes', [ 'type' => 'system' ] );
$results = $mdb -> select( 'pp_langs', [ 'id' ], [ 'status' => 1, 'ORDER' => [ 'o' => 'ASC' ] ] );
// Static system routes (hardcoded, never change)
$systemRoutes = [
// Wyszukiwarka
[ 'pattern' => '^wyszukiwarka/([^/]+)/([0-9]+)$', 'destination' => 'index.php?module=search&action=search_results&query=$1&bs=$2' ],
[ 'pattern' => '^wyszukiwarka/([^/]+)$', 'destination' => 'index.php?module=search&action=search_results&query=$1&bs=1' ],
// Zamowienia
[ 'pattern' => '^zamowienie/([a-zA-Z0-9-]+)$', 'destination' => 'index.php?module=shop_order&action=order_details&order_hash=$1' ],
[ 'pattern' => '^potwierdzenie-platnosci/([a-zA-Z0-9-]+)$', 'destination' => 'index.php?module=shop_order&action=payment_confirmation&order_hash=$1' ],
// Platnosci
[ 'pattern' => '^tpay-status$', 'destination' => 'index.php?module=shop_order&action=payment_status_tpay' ],
[ 'pattern' => '^platnosc-status$', 'destination' => 'index.php?module=shop_order&action=payment_status_hotpay' ],
[ 'pattern' => '^przelewy24-status$', 'destination' => 'index.php?module=shop_order&action=payment_status_przelewy24pl' ],
// Koszyk
[ 'pattern' => '^koszyk$', 'destination' => 'index.php?module=shop_basket&action=main_view' ],
[ 'pattern' => '^koszyk-podsumowanie$', 'destination' => 'index.php?module=shop_basket&action=summary_view' ],
[ 'pattern' => '^zloz-zamowienie$', 'destination' => 'index.php?module=shop_basket&action=basket_save' ],
// Klient
[ 'pattern' => '^rejestracja$', 'destination' => 'index.php?module=shop_client&action=register_form' ],
[ 'pattern' => '^logowanie$', 'destination' => 'index.php?module=shop_client&action=login_form' ],
[ 'pattern' => '^wylogowanie$', 'destination' => 'index.php?module=shop_client&action=logout' ],
[ 'pattern' => '^odzyskiwanie-hasla$', 'destination' => 'index.php?module=shop_client&action=recover_password' ],
[ 'pattern' => '^panel-klienta/zamowienia$', 'destination' => 'index.php?module=shop_client&action=client_orders' ],
[ 'pattern' => '^panel-klienta/adresy$', 'destination' => 'index.php?module=shop_client&action=client_addresses' ],
[ 'pattern' => '^panel-klienta/nowy-adres$', 'destination' => 'index.php?module=shop_client&action=address_edit' ],
[ 'pattern' => '^panel-klienta/edytuj-adres/([0-9]+)$', 'destination' => 'index.php?module=shop_client&action=address_edit&id=$1' ],
[ 'pattern' => '^panel-klienta/usun-adres/([0-9]+)$', 'destination' => 'index.php?module=shop_client&action=address_delete&id=$1' ],
// Newsletter
[ 'pattern' => '^newsletter/signin$', 'destination' => 'index.php?module=newsletter&action=signin' ],
[ 'pattern' => '^newsletter/confirm/hash=(.+)$', 'destination' => 'index.php?module=newsletter&action=confirm&hash=$1' ],
[ 'pattern' => '^newsletter/unsubscribe/hash=(.+)$', 'destination' => 'index.php?module=newsletter&action=unsubscribe&hash=$1' ],
// Moduły AJAX (shopBasket, shopClient, shopProduct, shopCoupon, search)
[ 'pattern' => '^shopBasket/([^/]+)/(.+)$', 'destination' => 'index.php?module=shopBasket&action=$1&$2' ],
[ 'pattern' => '^shopBasket/([^/]+)$', 'destination' => 'index.php?module=shopBasket&action=$1' ],
[ 'pattern' => '^shopClient/([^/]+)/(.+)$', 'destination' => 'index.php?module=shopClient&action=$1&$2' ],
[ 'pattern' => '^shopClient/([^/]+)$', 'destination' => 'index.php?module=shopClient&action=$1' ],
[ 'pattern' => '^shopProduct/([^/]+)/(.+)$', 'destination' => 'index.php?module=shopProduct&action=$1&$2' ],
[ 'pattern' => '^shopProduct/([^/]+)$', 'destination' => 'index.php?module=shopProduct&action=$1' ],
[ 'pattern' => '^shopCoupon/([^/]+)/(.+)$', 'destination' => 'index.php?module=shopCoupon&action=$1&$2' ],
[ 'pattern' => '^shopCoupon/([^/]+)$', 'destination' => 'index.php?module=shopCoupon&action=$1' ],
[ 'pattern' => '^search/([^/]+)/(.+)$', 'destination' => 'index.php?module=search&action=$1&$2' ],
[ 'pattern' => '^search/([^/]+)$', 'destination' => 'index.php?module=search&action=$1' ],
];
foreach ( $systemRoutes as $route )
{
$mdb->insert( 'pp_routes', [
'type' => 'system',
'lang_id' => 0,
'pattern' => $route['pattern'],
'destination' => $route['destination'],
] );
}
// Dynamic system routes — languages
$results = $mdb->select( 'pp_langs', [ 'id' ], [ 'status' => 1, 'ORDER' => [ 'o' => 'ASC' ] ] );
if ( is_array( $results ) ) foreach ( $results as $row )
{
$htaccess_data .= PHP_EOL . 'RewriteRule ^' . $row['id'] . '/$ index.php?a=change_language&id=' . $row['id'] . ' [L]';
$mdb->insert( 'pp_routes', [
'type' => 'system',
'lang_id' => 0,
'pattern' => '^' . $row['id'] . '$',
'destination' => 'index.php?a=change_language&id=' . $row['id'],
] );
}
//
// INNE
//
$htaccess_data .= PHP_EOL;
$htaccess_data .= 'RewriteRule ^newsletter/signin/$ index.php?module=newsletter&action=signin [L]' . PHP_EOL;
$htaccess_data .= 'RewriteRule ^newsletter/confirm/hash=(.*)$ index.php?module=newsletter&action=confirm&hash=$1 [L]' . PHP_EOL;
$htaccess_data .= 'RewriteRule ^newsletter/unsubscribe/hash=(.*)$ index.php?module=newsletter&action=unsubscribe&hash=$1 [L]' . PHP_EOL;
//
// PRODUCENCI
//
// Dynamic system routes — producenci
$categoryDefaultLayoutId = ( new \Domain\Layouts\LayoutsRepository( $mdb ) )->categoryDefaultLayoutId();
$htaccess_data .= 'RewriteRule ^producenci$ index.php?module=shop_producer&action=list&layout_id=' . $categoryDefaultLayoutId . '&%{QUERY_STRING} [L]' . PHP_EOL;
$rows = $mdb -> select( 'pp_shop_producer', '*', [ 'status' => 1 ] );
$mdb->insert( 'pp_routes', [
'type' => 'system',
'lang_id' => 0,
'pattern' => '^producenci$',
'destination' => 'index.php?module=shop_producer&action=list&layout_id=' . $categoryDefaultLayoutId,
] );
$rows = $mdb->select( 'pp_shop_producer', '*', [ 'status' => 1 ] );
if ( self::is_array_fix( $rows ) ) foreach ( $rows as $row )
{
$htaccess_data .= 'RewriteRule ^producent/' . self::seo( $row['name'] ) . '$ index.php?module=shop_producer&action=products&producer_id=' . $row['id'] . '&layout_id=' . $categoryDefaultLayoutId . '&%{QUERY_STRING} [L]' . PHP_EOL;
$htaccess_data .= 'RewriteRule ^producent/' . self::seo( $row['name'] ) . '/([0-9]+)$ index.php?module=shop_producer&action=products&producer_id=' . $row['id'] . '&layout_id=' . $categoryDefaultLayoutId . '&bs=$1&%{QUERY_STRING} [L]' . PHP_EOL;
$mdb->insert( 'pp_routes', [
'type' => 'system',
'lang_id' => 0,
'pattern' => '^producent/' . self::seo( $row['name'] ) . '$',
'destination' => 'index.php?module=shop_producer&action=products&producer_id=' . $row['id'] . '&layout_id=' . $categoryDefaultLayoutId,
] );
$mdb->insert( 'pp_routes', [
'type' => 'system',
'lang_id' => 0,
'pattern' => '^producent/' . self::seo( $row['name'] ) . '/([0-9]+)$',
'destination' => 'index.php?module=shop_producer&action=products&producer_id=' . $row['id'] . '&layout_id=' . $categoryDefaultLayoutId . '&bs=$1',
] );
}
$results = $mdb -> select( 'pp_langs', [ 'id', 'start' ], [ 'status' => 1, 'ORDER' => [ 'o' => 'ASC' ] ] );
//
// HTACCESS — generuj z PHP (bez szablonu htaccess.conf)
//
$htaccess_data = 'RewriteEngine On' . PHP_EOL;
$htaccess_data .= 'RewriteBase /' . PHP_EOL;
$htaccess_data .= 'Options +FollowSymlinks' . PHP_EOL;
$htaccess_data .= 'Options -Indexes' . PHP_EOL;
$htaccess_data .= PHP_EOL;
$htaccess_data .= '# Przekierowanie z www na bez www i z http na https w jednym kroku' . PHP_EOL;
$htaccess_data .= 'RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]' . PHP_EOL;
$htaccess_data .= 'RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]' . PHP_EOL;
$htaccess_data .= PHP_EOL;
$htaccess_data .= '# Przekierowanie z http na https, jesli nie zawiera www' . PHP_EOL;
$htaccess_data .= 'RewriteCond %{HTTPS} off' . PHP_EOL;
$htaccess_data .= 'RewriteCond %{REQUEST_URI} !^/(tpay-status|platnosc-status|przelewy24-status)$ [NC]' . PHP_EOL;
$htaccess_data .= 'RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]' . PHP_EOL;
$htaccess_data .= PHP_EOL;
$htaccess_data .= '# Usuwanie koncowego slasha dla niekatalogów' . PHP_EOL;
$htaccess_data .= 'RewriteCond %{REQUEST_FILENAME} !-d' . PHP_EOL;
$htaccess_data .= 'RewriteCond %{REQUEST_URI} !^/admin/.*$ [NC]' . PHP_EOL;
$htaccess_data .= 'RewriteCond %{REQUEST_URI} (.+)/$' . PHP_EOL;
$htaccess_data .= 'RewriteRule ^ %1 [R=301,L]' . PHP_EOL;
$htaccess_data .= PHP_EOL;
$htaccess_data .= 'RewriteCond %{REQUEST_URI} !^(.*)/libraries/(.*) [NC]' . PHP_EOL;
$htaccess_data .= 'RewriteCond %{REQUEST_URI} !^(.*)/layout/(.*) [NC]' . PHP_EOL;
$htaccess_data .= 'RewriteRule ^admin/([^/]*)/([^/]*)/(.*)$ admin/index.php?module=$1&action=$2&$3 [L]' . PHP_EOL;
$htaccess_data .= PHP_EOL;
$htaccess_data .= 'RewriteRule ^admin/$ admin/index.php [L]' . PHP_EOL;
$htaccess_data .= PHP_EOL;
$htaccess_data .= 'RewriteRule ^thumb/([0-9]*)/([0-9]*)/(.*)$ /libraries/thumb.php?img=$3&w=$1&h=$2 [L]' . PHP_EOL;
$htaccess_data .= PHP_EOL;
$htaccess_data .= 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index.php' . PHP_EOL;
$htaccess_data .= 'RewriteRule ^ /%1 [R=301,L]' . PHP_EOL;
/* cache block */
if ( $settings['htaccess_cache'] )
{
$htaccess_data .= '<IfModule mod_deflate.c>' . PHP_EOL
. 'AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml application/xhtml+xml text/css text/javascript application/javascript application/x-javascript' . PHP_EOL
. '</IfModule>' . PHP_EOL
. '<IfModule mod_headers.c>' . PHP_EOL
. 'Header set Access-Control-Allow-Origin "*"' . PHP_EOL
. '</IfModule>' . PHP_EOL
. '<IfModule mod_expires.c>' . PHP_EOL
. 'ExpiresActive on' . PHP_EOL
. 'ExpiresDefault "access plus 1 month"' . PHP_EOL
. 'ExpiresByType text/css "access plus 1 year"' . PHP_EOL
. 'ExpiresByType application/json "access plus 0 seconds"' . PHP_EOL
. 'ExpiresByType application/xml "access plus 0 seconds"' . PHP_EOL
. 'ExpiresByType text/xml "access plus 0 seconds"' . PHP_EOL
. 'ExpiresByType image/x-icon "access plus 1 week"' . PHP_EOL
. 'ExpiresByType text/x-component "access plus 1 month"' . PHP_EOL
. 'ExpiresByType text/html "access plus 0 seconds"' . PHP_EOL
. 'ExpiresByType application/javascript "access plus 1 year"' . PHP_EOL
. 'ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"' . PHP_EOL
. 'ExpiresByType text/cache-manifest "access plus 0 seconds"' . PHP_EOL
. 'ExpiresByType audio/ogg "access plus 1 month"' . PHP_EOL
. 'ExpiresByType image/gif "access plus 1 month"' . PHP_EOL
. 'ExpiresByType image/jpeg "access plus 1 month"' . PHP_EOL
. 'ExpiresByType image/png "access plus 1 month"' . PHP_EOL
. 'ExpiresByType video/mp4 "access plus 1 month"' . PHP_EOL
. 'ExpiresByType video/ogg "access plus 1 month"' . PHP_EOL
. 'ExpiresByType video/webm "access plus 1 month"' . PHP_EOL
. 'ExpiresByType application/atom+xml "access plus 1 hour"' . PHP_EOL
. 'ExpiresByType application/rss+xml "access plus 1 hour"' . PHP_EOL
. 'ExpiresByType application/font-woff "access plus 1 month"' . PHP_EOL
. 'ExpiresByType application/vnd.ms-fontobject "access plus 1 month"' . PHP_EOL
. 'ExpiresByType application/x-font-ttf "access plus 1 month"' . PHP_EOL
. 'ExpiresByType font/opentype "access plus 1 month"' . PHP_EOL
. 'ExpiresByType image/svg+xml "access plus 1 month"' . PHP_EOL
. '</IfModule>' . PHP_EOL;
}
else
{
$htaccess_data .= '<IfModule mod_headers.c>' . PHP_EOL
. 'Header set Cache-Control "no-cache, no-store, must-revalidate"' . PHP_EOL
. 'Header set Pragma "no-cache"' . PHP_EOL
. 'Header set Expires 0' . PHP_EOL
. '</IfModule>' . PHP_EOL;
}
$htaccess_data .= '<Files *.conf>' . PHP_EOL;
$htaccess_data .= ' Order Deny,Allow' . PHP_EOL;
$htaccess_data .= ' Deny from all' . PHP_EOL;
$htaccess_data .= '</Files>' . PHP_EOL;
$htaccess_data .= '<Files *.log>' . PHP_EOL;
$htaccess_data .= ' Order Deny,Allow' . PHP_EOL;
$htaccess_data .= ' Deny from all' . PHP_EOL;
$htaccess_data .= '</Files>' . PHP_EOL;
$htaccess_data .= '<Files *.ini>' . PHP_EOL;
$htaccess_data .= ' Order Deny,Allow' . PHP_EOL;
$htaccess_data .= ' Deny from all' . PHP_EOL;
$htaccess_data .= '</Files>' . PHP_EOL;
//
// KATEGORIE — sitemap + pp_routes (bez zmian)
//
$results = $mdb->select( 'pp_langs', [ 'id', 'start' ], [ 'status' => 1, 'ORDER' => [ 'o' => 'ASC' ] ] );
if ( is_array( $results ) ) foreach ( $results as $row )
{
!$row['start'] ? $language_link = $row['id'] . '/' : $language_link = '';
$results2 = $mdb -> select( 'pp_shop_categories_langs', [ '[><]pp_shop_categories' => [ 'category_id' => 'id' ] ], [ 'seo_link', 'title', 'category_id' ], [ 'lang_id' => $row['id'], 'ORDER' => [ 'o' => 'ASC' ] ] );
$results2 = $mdb->select( 'pp_shop_categories_langs', [ '[><]pp_shop_categories' => [ 'category_id' => 'id' ] ], [ 'seo_link', 'title', 'category_id' ], [ 'lang_id' => $row['id'], 'ORDER' => [ 'o' => 'ASC' ] ] );
if ( is_array( $results2 ) ) foreach ( $results2 as $row2 )
{
if ( $row2['title'] )
@@ -475,35 +639,42 @@ class Helpers
$site_map .= '<priority>1</priority>' . PHP_EOL;
$site_map .= '</url>' . PHP_EOL;
if ( $row2['seo_link'] )
{
$htaccess_data .= PHP_EOL . 'RewriteRule ^' . $language_link . self::seo( $row2['seo_link'] ) . '$ index.php?category=' . $row2['category_id'] . '&lang=' . $row['id'] . '&%{QUERY_STRING} [L]';
$htaccess_data .= PHP_EOL . 'RewriteRule ^' . $language_link . self::seo( $row2['seo_link'] ) . '/([0-9]+)$ index.php?category=' . $row2['category_id'] . '&lang=' . $row['id'] . '&bs=$1&%{QUERY_STRING} [L]';
$htaccess_data .= PHP_EOL . 'RewriteRule ^' . $language_link . self::seo( $row2['seo_link'] ) . '/1$ ' . $language_link . self::seo( $row2['seo_link'] ) . ' [R=301,L]';
}
else
{
$htaccess_data .= PHP_EOL . 'RewriteRule ^' . $language_link . 'k-' . $row2['category_id'] . '-' . self::seo( $row2['title'] ) . '$ index.php?category=' . $row2['category_id'] . '&lang=' . $row['id'] . '&%{QUERY_STRING} [L]';
$htaccess_data .= PHP_EOL . 'RewriteRule ^' . $language_link . 'k-' . $row2['category_id'] . '-' . self::seo( $row2['title'] ) . '/([0-9]+)$ index.php?category=' . $row2['category_id'] . '&lang=' . $row['id'] . '&bs=$1&%{QUERY_STRING} [L]';
$htaccess_data .= PHP_EOL . 'RewriteRule ^' . $language_link . 'k-' . $row2['category_id'] . '-' . self::seo( $row2['title'] ) . '/1$ ' . $language_link . 'k-' . $row2['category_id'] . '-' . self::seo( $row2['title'] ) . ' [R=301,L]';
}
$seoSlug = $row2['seo_link'] ? self::seo( $row2['seo_link'] ) : 'k-' . $row2['category_id'] . '-' . self::seo( $row2['title'] );
$mdb->delete( 'pp_routes', [ 'AND' => [ 'category_id' => $row2['category_id'], 'lang_id' => $row['id'] ] ] );
$mdb->insert( 'pp_routes', [
'category_id' => $row2['category_id'],
'lang_id' => $row['id'],
'pattern' => '^' . $language_link . $seoSlug . '$',
'destination' => 'index.php?category=' . $row2['category_id'] . '&lang=' . $row['id'],
] );
$mdb->insert( 'pp_routes', [
'category_id' => $row2['category_id'],
'lang_id' => $row['id'],
'pattern' => '^' . $language_link . $seoSlug . '/([0-9]+)$',
'destination' => 'index.php?category=' . $row2['category_id'] . '&lang=' . $row['id'] . '&bs=$1',
] );
}
}
}
$results = $mdb -> select( 'pp_langs', [ 'id', 'start' ], [ 'status' => 1, 'ORDER' => [ 'o' => 'ASC' ] ] );
//
// PRODUKTY — sitemap + pp_routes (bez zmian)
//
$results = $mdb->select( 'pp_langs', [ 'id', 'start' ], [ 'status' => 1, 'ORDER' => [ 'o' => 'ASC' ] ] );
if ( is_array( $results ) )
{
foreach ( $results as $row )
{
!$row['start'] ? $language_link = $row['id'] . '/' : $language_link = '';
$results2 = $mdb -> select( 'pp_shop_products_langs', [ '[><]pp_shop_products' => [ 'product_id' => 'id' ] ], [ 'seo_link', 'name', 'product_id' ], [ 'lang_id' => $row['id'], 'ORDER' => [ 'name' => 'ASC' ] ] );
$results2 = $mdb->select( 'pp_shop_products_langs', [ '[><]pp_shop_products' => [ 'product_id' => 'id' ] ], [ 'seo_link', 'name', 'product_id' ], [ 'lang_id' => $row['id'], 'ORDER' => [ 'name' => 'ASC' ] ] );
if ( is_array( $results2 ) )
{
foreach ( $results2 as $row2 )
{
$mdb -> delete( 'pp_routes', [ 'AND' => [ 'product_id' => $row2['product_id'], 'lang_id' => $row['id'] ] ] );
$mdb->delete( 'pp_routes', [ 'AND' => [ 'product_id' => $row2['product_id'], 'lang_id' => $row['id'] ] ] );
if ( $row2['name'] )
{
@@ -519,27 +690,13 @@ class Helpers
if ( $row2['seo_link'] )
{
$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' => $pattern, 'destination' => $destination ] );
$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' => $pattern, 'destination' => $destination ] );
$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' ] );
}
else
{
$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' => $pattern, 'destination' => $destination ] );
$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' => $pattern, 'destination' => $destination ] );
$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' ] );
}
}
}
@@ -547,13 +704,16 @@ class Helpers
}
}
$results = $mdb -> select( 'pp_langs', [ 'id', 'start' ], [ 'status' => 1, 'ORDER' => [ 'o' => 'ASC' ] ] );
//
// STRONY + ARTYKULY — sitemap + pp_routes (bez zmian)
//
$results = $mdb->select( 'pp_langs', [ 'id', 'start' ], [ 'status' => 1, 'ORDER' => [ 'o' => 'ASC' ] ] );
if ( is_array( $results ) )
foreach ( $results as $row )
{
( !$row['start'] and count( $results ) > 1 ) ? $language_link = $row['id'] . '/' : $language_link = '';
$results2 = $mdb -> select( 'pp_pages_langs', [ '[><]pp_pages' => [ 'page_id' => 'id' ] ], [ 'seo_link', 'title', 'page_id', 'noindex', 'start', 'link', 'page_type' ], [ 'lang_id' => $row['id'], 'ORDER' => [ 'start' => 'DESC', 'o' => 'ASC' ] ] );
$results2 = $mdb->select( 'pp_pages_langs', [ '[><]pp_pages' => [ 'page_id' => 'id' ] ], [ 'seo_link', 'title', 'page_id', 'noindex', 'start', 'link', 'page_type' ], [ 'lang_id' => $row['id'], 'ORDER' => [ 'start' => 'DESC', 'o' => 'ASC' ] ] );
if ( is_array( $results2 ) )
foreach ( $results2 as $row2 )
{
@@ -590,44 +750,39 @@ class Helpers
{
$htaccess_data .= PHP_EOL . 'RewriteCond %{REQUEST_URI} ^/s-' . $row2['page_id'] . '-' . self::seo( $row2['title'] ) . '$';
$htaccess_data .= PHP_EOL . 'RewriteRule ^(.*)$ http://www.' . $url . '/' . $language_link . ' [R=permanent,L]';
$htaccess_data .= PHP_EOL . 'RewriteCond %{REQUEST_URI} ^/s-' . $row2['page_id'] . '-' . self::seo( $row2['title'] ) . '-1$';
$htaccess_data .= PHP_EOL . 'RewriteRule ^(.*)$ http://www.' . $url . '/' . $language_link . ' [R=permanent,L]';
}
$htaccess_data .= PHP_EOL . 'RewriteRule ^$ index.php?a=page&id=' . $row2['page_id'] . '&lang=' . $row['id'] . ' [L]';
}
if ( $row2['seo_link'] )
{
$htaccess_data .= PHP_EOL . 'RewriteRule ^' . $language_link . self::seo( $row2['seo_link'] ) . '$ index.php?a=page&id=' . $row2['page_id'] . '&lang=' . $row['id'] . '&%{QUERY_STRING} [L]';
$htaccess_data .= PHP_EOL . 'RewriteRule ^' . $language_link . self::seo( $row2['seo_link'] ) . '/([0-9]+)$ index.php?a=page&id=' . $row2['page_id'] . '&lang=' . $row['id'] . '&bs=$1&%{QUERY_STRING} [L]';
$htaccess_data .= PHP_EOL . 'RewriteRule ^' . $language_link . self::seo( $row2['seo_link'] ) . '/1$ ' . $language_link . self::seo( $row2['seo_link'] ) . ' [R=301,L]';
}
else
{
$htaccess_data .= PHP_EOL . 'RewriteRule ^' . $language_link . 's-' . $row2['page_id'] . '-' . self::seo( $row2['title'] ) . '$ index.php?a=page&id=' . $row2['page_id'] . '&lang=' . $row['id'] . '&%{QUERY_STRING} [L]';
$htaccess_data .= PHP_EOL . 'RewriteRule ^' . $language_link . 's-' . $row2['page_id'] . '-' . self::seo( $row2['title'] ) . '/([0-9]+)$ index.php?a=page&id=' . $row2['page_id'] . '&lang=' . $row['id'] . '&bs=$1&%{QUERY_STRING} [L]';
$htaccess_data .= PHP_EOL . 'RewriteRule ^' . $language_link . 's-' . $row2['page_id'] . '-' . self::seo( $row2['title'] ) . '/1$ ' . $language_link . 's-' . $row2['page_id'] . '-' . self::seo( $row2['title'] ) . ' [R=301,L]';
}
$seoSlug = $row2['seo_link'] ? self::seo( $row2['seo_link'] ) : 's-' . $row2['page_id'] . '-' . self::seo( $row2['title'] );
$langPrefix = $row2['start'] ? '' : $language_link;
$mdb->delete( 'pp_routes', [ 'AND' => [ 'page_id' => $row2['page_id'], 'lang_id' => $row['id'] ] ] );
$mdb->insert( 'pp_routes', [
'page_id' => $row2['page_id'],
'lang_id' => $row['id'],
'pattern' => '^' . $langPrefix . $seoSlug . '$',
'destination' => 'index.php?a=page&id=' . $row2['page_id'] . '&lang=' . $row['id'],
] );
$mdb->insert( 'pp_routes', [
'page_id' => $row2['page_id'],
'lang_id' => $row['id'],
'pattern' => '^' . $langPrefix . $seoSlug . '/([0-9]+)$',
'destination' => 'index.php?a=page&id=' . $row2['page_id'] . '&lang=' . $row['id'] . '&bs=$1',
] );
}
}
$results2 = $mdb -> select( 'pp_articles_langs', [ '[><]pp_articles' => [ 'article_id' => 'id' ] ], [ 'seo_link', 'title', 'article_id', 'noindex', 'copy_from' ], [ 'AND' => [ 'status' => 1, 'lang_id' => $row['id'], 'block_direct_access' => 0 ] ] );
$results2 = $mdb->select( 'pp_articles_langs', [ '[><]pp_articles' => [ 'article_id' => 'id' ] ], [ 'seo_link', 'title', 'article_id', 'noindex', 'copy_from' ], [ 'AND' => [ 'status' => 1, 'lang_id' => $row['id'], 'block_direct_access' => 0 ] ] );
if ( is_array( $results2 ) )
foreach ( $results2 as $row2 )
{
if ( $row2['copy_from'] != null )
{
$results_tmp = $mdb -> get( 'pp_articles_langs', [
'seo_link',
'title'
], [
'AND' => [
'article_id' => $row2['article_id'],
'lang_id' => $row2['copy_from']
]
] );
$results_tmp = $mdb->get( 'pp_articles_langs', [ 'seo_link', 'title' ], [ 'AND' => [ 'article_id' => $row2['article_id'], 'lang_id' => $row2['copy_from'] ] ] );
$row2['seo_link'] = $results_tmp['seo_link'];
$row2['title'] = $results_tmp['title'];
}
@@ -650,81 +805,52 @@ class Helpers
$robots .= 'Disallow: /' . $row2['seo_link'] . PHP_EOL;
}
$mdb->delete( 'pp_routes', [ 'AND' => [ 'article_id' => $row2['article_id'], 'lang_id' => $row['id'] ] ] );
if ( $row2['seo_link'] )
$htaccess_data .= PHP_EOL . 'RewriteRule ^' . $language_link . self::seo( $row2['seo_link'] ) . '$ index.php?article=' . $row2['article_id'] . '&lang=' . $row['id'] . '&%{QUERY_STRING} [L]';
{
$mdb->insert( 'pp_routes', [
'article_id' => $row2['article_id'],
'lang_id' => $row['id'],
'pattern' => '^' . $language_link . self::seo( $row2['seo_link'] ) . '$',
'destination' => 'index.php?article=' . $row2['article_id'] . '&lang=' . $row['id'],
] );
}
else if ( $row2['title'] != null )
$htaccess_data .= PHP_EOL . 'RewriteRule ^' . $language_link . 'a-' . $row2['article_id'] . '-' . self::seo( $row2['title'] ) . '$ index.php?article=' . $row2['article_id'] . '&lang=' . $row['id'] . '&%{QUERY_STRING} [L]';
{
$mdb->insert( 'pp_routes', [
'article_id' => $row2['article_id'],
'lang_id' => $row['id'],
'pattern' => '^' . $language_link . 'a-' . $row2['article_id'] . '-' . self::seo( $row2['title'] ) . '$',
'destination' => 'index.php?article=' . $row2['article_id'] . '&lang=' . $row['id'],
] );
}
}
}
$results = $mdb -> get( 'pp_settings', 'value', [ 'param' => 'htaccess' ] );
// Invalidacja cache tras
try {
( new \Shared\Cache\CacheHandler() )->delete( 'pp_routes:all' );
} catch ( \Exception $e ) {
// Redis niedostepny — ignorujemy
}
$results = $mdb->get( 'pp_settings', 'value', [ 'param' => 'htaccess' ] );
if ( $results )
$htaccess_data .= PHP_EOL . $results;
$results = $mdb -> get( 'pp_settings', 'value', [ 'param' => 'robots' ] );
$results = $mdb->get( 'pp_settings', 'value', [ 'param' => 'robots' ] );
if ( $results )
$robots .= PHP_EOL . $results;
$robots .= PHP_EOL . $results;
$site_map .= '</urlset>';
/* cache */
if ( $settings['htaccess_cache'] )
{
$htaccess_data = str_replace( '{HTACCESS_CACHE}',
'<IfModule mod_deflate.c>' . PHP_EOL
. 'AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml application/xhtml+xml text/css text/javascript application/javascript application/x-javascript' . PHP_EOL
. '</IfModule>' . PHP_EOL
. '<IfModule mod_headers.c>' . PHP_EOL
. 'Header set Access-Control-Allow-Origin "*"' . PHP_EOL
. '</IfModule>' . PHP_EOL
. '<IfModule mod_expires.c>' . PHP_EOL
. 'ExpiresActive on' . PHP_EOL
. 'ExpiresDefault "access plus 1 month"' . PHP_EOL
. 'ExpiresByType text/css "access plus 1 year"' . PHP_EOL
. 'ExpiresByType application/json "access plus 0 seconds"' . PHP_EOL
. 'ExpiresByType application/xml "access plus 0 seconds"' . PHP_EOL
. 'ExpiresByType text/xml "access plus 0 seconds"' . PHP_EOL
. 'ExpiresByType image/x-icon "access plus 1 week"' . PHP_EOL
. 'ExpiresByType text/x-component "access plus 1 month"' . PHP_EOL
. 'ExpiresByType text/html "access plus 0 seconds"' . PHP_EOL
. 'ExpiresByType application/javascript "access plus 1 year"' . PHP_EOL
. 'ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"' . PHP_EOL
. 'ExpiresByType text/cache-manifest "access plus 0 seconds"' . PHP_EOL
. 'ExpiresByType audio/ogg "access plus 1 month"' . PHP_EOL
. 'ExpiresByType image/gif "access plus 1 month"' . PHP_EOL
. 'ExpiresByType image/jpeg "access plus 1 month"' . PHP_EOL
. 'ExpiresByType image/png "access plus 1 month"' . PHP_EOL
. 'ExpiresByType video/mp4 "access plus 1 month"' . PHP_EOL
. 'ExpiresByType video/ogg "access plus 1 month"' . PHP_EOL
. 'ExpiresByType video/webm "access plus 1 month"' . PHP_EOL
. 'ExpiresByType application/atom+xml "access plus 1 hour"' . PHP_EOL
. 'ExpiresByType application/rss+xml "access plus 1 hour"' . PHP_EOL
. 'ExpiresByType application/font-woff "access plus 1 month"' . PHP_EOL
. 'ExpiresByType application/vnd.ms-fontobject "access plus 1 month"' . PHP_EOL
. 'ExpiresByType application/x-font-ttf "access plus 1 month"' . PHP_EOL
. 'ExpiresByType font/opentype "access plus 1 month"' . PHP_EOL
. 'ExpiresByType image/svg+xml "access plus 1 month"' . PHP_EOL
. '</IfModule>'
, $htaccess_data );
}
else
{
$htaccess_data = str_replace( '{HTACCESS_CACHE}',
'<IfModule mod_headers.c>' . PHP_EOL
. 'Header set Cache-Control "no-cache, no-store, must-revalidate"' . PHP_EOL
. 'Header set Pragma "no-cache"' . PHP_EOL
. 'Header set Expires 0' . PHP_EOL
. '</IfModule>',
$htaccess_data );
}
$htaccess_data .= PHP_EOL;
$htaccess_data .= 'RewriteCond %{REQUEST_FILENAME} !-f' . PHP_EOL;
$htaccess_data .= 'RewriteCond %{REQUEST_FILENAME} !-d' . PHP_EOL;
$htaccess_data .= 'RewriteRule ^ index.php [L]';
// Niektore hostingi blokuja zmiane wersji PHP przez .htaccess.
// Automatycznie komentujemy niedozwolone dyrektywy, aby generowany plik byl kompatybilny.
$htaccess_data = preg_replace( '/^(\\s*)(AddHandler|SetHandler|ForceType)\\b/im', '$1# $2', $htaccess_data );
$fp = fopen( $dir . '.htaccess', 'w' );

View File

@@ -4,6 +4,38 @@ Logi zmian z migracji na Domain-Driven Architecture. Najnowsze na gorze.
---
## ver. 0.331 (2026-03-01) - Bugfix: strona produktu używała layoutu kategorii zamiast domyślnego
- **FIX**: `LayoutsRepository::getProductLayout()` — fallback gdy produkt i jego kategorie nie mają przypisanego layoutu zmieniany z `categories_default = 1` na `status = 1`; wcześniej produkty bez layoutu pobierały szablon "Podstrony - kategorie" zamiast właściwego domyślnego
---
## ver. 0.330 (2026-02-27) - Eliminacja htaccess.conf — wszystkie trasy URL w pp_routes
- **REFACTOR**: `Helpers::htacces()` — generowanie `.htaccess` w całości z PHP (usunięty `file_get_contents('htaccess.conf')` i placeholder `{HTACCESS_CACHE}`)
- **NEW**: 32 statyczne trasy systemowe wstawiane do `pp_routes` z `type='system'` przy każdym `htacces()` (koszyk, logowanie, wylogowanie, panel klienta, newsletter, zamówienia, płatności, moduły AJAX: shopBasket/shopClient/shopProduct/shopCoupon/search)
- **NEW**: Dynamiczne trasy językowe i producentów (producenci + per-producent z paginacją) przenoszone do `pp_routes` zamiast `.htaccess`
- **NEW**: Kolumna `type VARCHAR(20) NULL` w `pp_routes``NULL` dla encji, `'system'` dla tras systemowych
- **REMOVED**: `libraries/htaccess.conf` — plik szablonu usunięty, treść wbudowana w PHP
- **PERF**: Invalidacja cache Redis `pp_routes:all` po każdym `htacces()` — świeże trasy przy kolejnym żądaniu
- **MIGRATION**: `migrations/0.329.sql` (dodano `type` column)
- **DOCS**: `docs/DATABASE_STRUCTURE.md` — zaktualizowana sekcja `pp_routes` o kolumnę `type`
---
## ver. 0.329 (2026-02-27) - Routing kategorii, stron i artykułów przez pp_routes
- **REFACTOR**: `index.php` — blok routingu przez `pp_routes` przeniesiony PRZED `checkUrlParams()` (poprawna kolejność: lang/a=page dostępne w checkUrlParams)
- **PERF**: Cache Redis dla tras (`pp_routes:all`, TTL 86400s) w `index.php` — jeden SELECT na 24h zamiast przy każdym żądaniu
- **NEW**: Kategorie, strony i artykuły zapisywane do `pp_routes` zamiast `.htaccess` w `Helpers::htacces()`
- **NEW**: `CategoryRepository::categoryDelete()` — usuwa powiązane `pp_routes` przed odświeżeniem
- **NEW**: `PagesRepository::pageDelete()` — usuwa powiązane `pp_routes`
- **NEW**: `ArticleRepository::archive()` i `deletePermanently()` — usuwa powiązane `pp_routes`
- **MIGRATION**: `migrations/0.329.sql``ALTER TABLE pp_routes ADD COLUMN category_id, page_id, article_id`
- **TESTS**: Zaktualizowane `CategoryRepositoryTest` i `ArticleRepositoryTest` (nowe asercje na `pp_routes` delete)
---
## ver. 0.328 (2026-02-27) - Ikona kopiowania wartości atrybutów w szczegółach zamówienia
- **NEW**: `order-details-custom-script.php` — JS parsuje `.atributes` div i wstrzykuje przycisk `fa-copy` przy każdej wartości atrybutu

View File

@@ -700,3 +700,28 @@ Harmonogram cyklicznych zadań cron.
**Używane w:** `Domain\CronJob\CronJobRepository`, `Domain\CronJob\CronJobProcessor`
**Dodano w wersji 0.324.**
## pp_routes
Tabela tras URL — mapowanie wzorców URL (regex) na parametry GET. Zastępuje reguły `RewriteRule` w `.htaccess` dla wszystkich URL-i aplikacji: produktów, kategorii, stron, artykułów oraz systemowych (koszyk, logowanie, newsletter, itp.).
| Kolumna | Opis |
|---------|------|
| id | Klucz główny (AUTO_INCREMENT) |
| product_id | ID produktu (INT NULL) — wypełnione dla tras produktów |
| category_id | ID kategorii (INT NULL) — wypełnione dla tras kategorii |
| page_id | ID strony (INT NULL) — wypełnione dla tras stron |
| article_id | ID artykułu (INT NULL) — wypełnione dla tras artykułów |
| type | Typ trasy: NULL = encja (produkt/kategoria/strona/artykuł), `'system'` = trasa systemowa (koszyk, logowanie, newsletter, AJAX moduły, itp.) |
| lang_id | ID języka (0 dla tras systemowych niezwiązanych z językiem) |
| pattern | Wyrażenie regularne dopasowywane do REQUEST_URI |
| destination | Docelowy query string, np. `index.php?category=5&lang=1` |
**Mechanizm:** `index.php` ładuje wszystkie trasy (z cache Redis `pp_routes:all`) przed `checkUrlParams()`, dopasowuje `pattern` do ścieżki żądania i ustawia `$_GET` z `destination`. Obsługuje grupy przechwytujące (np. `$1` dla paginacji).
**Trasy systemowe:** Przy każdym wywołaniu `Helpers::htacces()` wszystkie rekordy z `type='system'` są usuwane i wstawiane na nowo (32 statycznych + dynamiczne trasy językowe i producentów). Zarządzane automatycznie — nie edytować ręcznie.
**Cache:** Redis klucz `pp_routes:all`, TTL 86400s. Invalidowany automatycznie przy każdym wywołaniu `Helpers::htacces()`.
**Używane w:** `index.php`, `Shared\Helpers\Helpers::htacces()`, `Domain\Product\ProductRepository`, `Domain\Category\CategoryRepository`, `Domain\Pages\PagesRepository`, `Domain\Article\ArticleRepository`
**Dodano w wersji 0.329. Kolumna `type` i trasy systemowe dodane w wersji 0.330.**

View File

@@ -1,3 +1,6 @@
1. Dodać przycisk kopiowania przy atrybutach produktu w zamówieniu
2. Poprawić htaccess, żeby w nim nie było w ogóle adresów strona wszystko z bazy.
3. Dodać uwierzytelnienie dwuskładnikowe za pomocą aplikacji.
3. Dodać uwierzytelnienie dwuskładnikowe za pomocą aplikacji.
4. Dodać zarządzanie uprawnieniami na poziomie urzytkownika, na razie uprawnienia do poszczególnych modułów.
naprawić działanie newslettera i zapis do bazy newslettera
program lojalnościowy
proponowane produkty w koszyku
Do zamówień w statusie: realizowane lub oczekuje na wpłatę. Opcja tylko dla zarejestrowanych klientów. https://royal-stone.pl/pl/order1.html

View File

@@ -0,0 +1,658 @@
# htaccess.conf Elimination — Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Eliminate `libraries/htaccess.conf` as a template file and move all remaining hardcoded URL routes into `pp_routes`, leaving only true Apache-level directives in the generated `.htaccess`.
**Architecture:** `Helpers::htacces()` generates the full `.htaccess` content from PHP strings instead of loading a template. All URL→PHP mappings (static system routes + dynamic per language/producer) are inserted into `pp_routes` with `type='system'`, deleted and reinserted on every `htacces()` call. Apache-level rules (HTTPS redirect, admin routing, thumb.php) stay in `.htaccess` only.
**Tech Stack:** PHP 7.4, Medoo ORM (`$mdb`), Redis (CacheHandler), PHPUnit 9.6
---
## Context
### Current `Helpers::htacces()` structure (before this plan)
1. Loads `libraries/htaccess.conf` template (contains many hardcoded URL routes)
2. Appends language switch rules to `$htaccess_data`
3. Appends newsletter and producer rules to `$htaccess_data`
4. Inserts category/product/page/article routes into `pp_routes` (done in v0.329)
5. Replaces `{HTACCESS_CACHE}` placeholder
6. Appends catch-all, writes files
### What stays in `.htaccess` after this plan
- `RewriteEngine On`, `RewriteBase /`, `Options`
- www→https redirect
- http→https redirect (with tpay/przelewy24/hotpay exclusion)
- Trailing slash removal (excluding `/admin/`)
- Admin routing: `^admin/([^/]*)/([^/]*)/(.*)$`
- `^admin/$`
- Thumbnail: `^thumb/([0-9]*)/([0-9]*)/(.*)$``/libraries/thumb.php` (different PHP file, cannot use pp_routes)
- `THE_REQUEST` index.php redirect
- Cache headers block (gzip/expires or no-cache based on `$settings['htaccess_cache']`)
- File protection: `<Files *.conf>`, `<Files *.log>`, `<Files *.ini>`
- Start page 301 redirects (generated dynamically in pages loop)
- Custom htaccess from `pp_settings` (param=htaccess)
- Catch-all: `RewriteRule ^ index.php [L]`
### New `type` column in `pp_routes`
- `NULL` = entity route (product/category/page/article)
- `'system'` = system route (all routes in this plan)
- On every `htacces()` call: `DELETE WHERE type='system'`, then reinsert all
---
## Task 1: Update SQL migration — add `type` column
**Files:**
- Modify: `migrations/0.329.sql`
**Step 1: Add `type` column to the migration**
Open `migrations/0.329.sql` (currently has 4 lines). Append the `type` column:
```sql
ALTER TABLE pp_routes
ADD COLUMN category_id INT NULL AFTER product_id,
ADD COLUMN page_id INT NULL AFTER category_id,
ADD COLUMN article_id INT NULL AFTER page_id,
ADD COLUMN type VARCHAR(20) NULL AFTER article_id;
```
**Step 2: Apply migration on server**
Run on the production/staging database:
```sql
ALTER TABLE pp_routes ADD COLUMN type VARCHAR(20) NULL AFTER article_id;
```
(The other 3 columns from 0.329 should already be applied from the previous deployment.)
**Step 3: No test needed** — pure schema change, verified when routes are inserted in Task 2.
---
## Task 2: Refactor `Helpers::htacces()` — replace template + move all routes to pp_routes
**Files:**
- Modify: `autoload/Shared/Helpers/Helpers.php` (method `htacces()`, lines ~408773)
This is the core task. The entire method is refactored. Here is the complete new body:
**Step 1: Replace the method body**
Find the opening of `htacces()` at line ~408. Replace everything from the start of the method body through the end (line ~773) with the code below.
The key structural changes:
- Remove `file_get_contents(htaccess.conf)` and `str_replace('{PAGE}', ...)`
- Remove `str_replace('{HTACCESS_CACHE}', ...)` — cache block is now inline
- Build `$htaccess_data` directly as PHP string
- Delete all `type='system'` routes, then reinsert static + dynamic ones
- Language switch → `pp_routes` (remove from `$htaccess_data`)
- Newsletter → `pp_routes` (remove from `$htaccess_data`)
- Producenci/producent → `pp_routes` (remove from `$htaccess_data`)
**New `htacces()` method body** — replace lines 409773 with:
```php
{
global $mdb;
$settings = ( new \Domain\Settings\SettingsRepository( $mdb ) )->allSettings( true );
$url = preg_replace( '#^(http(s)?://)?w{3}\.#', '$1', $_SERVER['SERVER_NAME'] );
$robots = 'User-agent: *' . PHP_EOL;
$robots .= 'Allow: /' . PHP_EOL;
$site_map = '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL;
$site_map .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . PHP_EOL;
$site_map .= '<url>' . PHP_EOL;
$site_map .= '<loc>https://' . $url . '</loc>' . PHP_EOL;
$site_map .= '<lastmod>' . date( 'Y-m-d' ) . '</lastmod>' . PHP_EOL;
$site_map .= '<changefreq>daily</changefreq>' . PHP_EOL;
$site_map .= '<priority>1</priority>' . PHP_EOL;
$site_map .= '</url>' . PHP_EOL;
//
// SYSTEM ROUTES — delete all and reinsert
//
$mdb->delete( 'pp_routes', [ 'type' => 'system' ] );
// Static system routes (hardcoded, never change)
$systemRoutes = [
// Wyszukiwarka
[ 'pattern' => '^wyszukiwarka/([^/]+)/([0-9]+)$', 'destination' => 'index.php?module=search&action=search_results&query=$1&bs=$2' ],
[ 'pattern' => '^wyszukiwarka/([^/]+)$', 'destination' => 'index.php?module=search&action=search_results&query=$1&bs=1' ],
// Zamowienia
[ 'pattern' => '^zamowienie/([a-zA-Z0-9-]+)$', 'destination' => 'index.php?module=shop_order&action=order_details&order_hash=$1' ],
[ 'pattern' => '^potwierdzenie-platnosci/([a-zA-Z0-9-]+)$', 'destination' => 'index.php?module=shop_order&action=payment_confirmation&order_hash=$1' ],
// Platnosci
[ 'pattern' => '^tpay-status$', 'destination' => 'index.php?module=shop_order&action=payment_status_tpay' ],
[ 'pattern' => '^platnosc-status$', 'destination' => 'index.php?module=shop_order&action=payment_status_hotpay' ],
[ 'pattern' => '^przelewy24-status$', 'destination' => 'index.php?module=shop_order&action=payment_status_przelewy24pl' ],
// Koszyk
[ 'pattern' => '^koszyk$', 'destination' => 'index.php?module=shop_basket&action=main_view' ],
[ 'pattern' => '^koszyk-podsumowanie$', 'destination' => 'index.php?module=shop_basket&action=summary_view' ],
[ 'pattern' => '^zloz-zamowienie$', 'destination' => 'index.php?module=shop_basket&action=basket_save' ],
// Klient
[ 'pattern' => '^rejestracja$', 'destination' => 'index.php?module=shop_client&action=register_form' ],
[ 'pattern' => '^logowanie$', 'destination' => 'index.php?module=shop_client&action=login_form' ],
[ 'pattern' => '^wylogowanie$', 'destination' => 'index.php?module=shop_client&action=logout' ],
[ 'pattern' => '^odzyskiwanie-hasla$', 'destination' => 'index.php?module=shop_client&action=recover_password' ],
[ 'pattern' => '^panel-klienta/zamowienia$', 'destination' => 'index.php?module=shop_client&action=client_orders' ],
[ 'pattern' => '^panel-klienta/adresy$', 'destination' => 'index.php?module=shop_client&action=client_addresses' ],
[ 'pattern' => '^panel-klienta/nowy-adres$', 'destination' => 'index.php?module=shop_client&action=address_edit' ],
[ 'pattern' => '^panel-klienta/edytuj-adres/([0-9]+)$', 'destination' => 'index.php?module=shop_client&action=address_edit&id=$1' ],
[ 'pattern' => '^panel-klienta/usun-adres/([0-9]+)$', 'destination' => 'index.php?module=shop_client&action=address_delete&id=$1' ],
// Newsletter
[ 'pattern' => '^newsletter/signin$', 'destination' => 'index.php?module=newsletter&action=signin' ],
[ 'pattern' => '^newsletter/confirm/hash=(.+)$', 'destination' => 'index.php?module=newsletter&action=confirm&hash=$1' ],
[ 'pattern' => '^newsletter/unsubscribe/hash=(.+)$', 'destination' => 'index.php?module=newsletter&action=unsubscribe&hash=$1' ],
// Moduły AJAX (shopBasket, shopClient, shopProduct, shopCoupon, search)
[ 'pattern' => '^shopBasket/([^/]+)/(.+)$', 'destination' => 'index.php?module=shopBasket&action=$1&$2' ],
[ 'pattern' => '^shopBasket/([^/]+)$', 'destination' => 'index.php?module=shopBasket&action=$1' ],
[ 'pattern' => '^shopClient/([^/]+)/(.+)$', 'destination' => 'index.php?module=shopClient&action=$1&$2' ],
[ 'pattern' => '^shopClient/([^/]+)$', 'destination' => 'index.php?module=shopClient&action=$1' ],
[ 'pattern' => '^shopProduct/([^/]+)/(.+)$', 'destination' => 'index.php?module=shopProduct&action=$1&$2' ],
[ 'pattern' => '^shopProduct/([^/]+)$', 'destination' => 'index.php?module=shopProduct&action=$1' ],
[ 'pattern' => '^shopCoupon/([^/]+)/(.+)$', 'destination' => 'index.php?module=shopCoupon&action=$1&$2' ],
[ 'pattern' => '^shopCoupon/([^/]+)$', 'destination' => 'index.php?module=shopCoupon&action=$1' ],
[ 'pattern' => '^search/([^/]+)/(.+)$', 'destination' => 'index.php?module=search&action=$1&$2' ],
[ 'pattern' => '^search/([^/]+)$', 'destination' => 'index.php?module=search&action=$1' ],
];
foreach ( $systemRoutes as $route )
{
$mdb->insert( 'pp_routes', [
'type' => 'system',
'lang_id' => 0,
'pattern' => $route['pattern'],
'destination' => $route['destination'],
] );
}
// Dynamic system routes — languages
$results = $mdb->select( 'pp_langs', [ 'id' ], [ 'status' => 1, 'ORDER' => [ 'o' => 'ASC' ] ] );
if ( is_array( $results ) ) foreach ( $results as $row )
{
$mdb->insert( 'pp_routes', [
'type' => 'system',
'lang_id' => 0,
'pattern' => '^' . $row['id'] . '$',
'destination' => 'index.php?a=change_language&id=' . $row['id'],
] );
}
// Dynamic system routes — producenci
$categoryDefaultLayoutId = ( new \Domain\Layouts\LayoutsRepository( $mdb ) )->categoryDefaultLayoutId();
$mdb->insert( 'pp_routes', [
'type' => 'system',
'lang_id' => 0,
'pattern' => '^producenci$',
'destination' => 'index.php?module=shop_producer&action=list&layout_id=' . $categoryDefaultLayoutId,
] );
$rows = $mdb->select( 'pp_shop_producer', '*', [ 'status' => 1 ] );
if ( self::is_array_fix( $rows ) ) foreach ( $rows as $row )
{
$mdb->insert( 'pp_routes', [
'type' => 'system',
'lang_id' => 0,
'pattern' => '^producent/' . self::seo( $row['name'] ) . '$',
'destination' => 'index.php?module=shop_producer&action=products&producer_id=' . $row['id'] . '&layout_id=' . $categoryDefaultLayoutId,
] );
$mdb->insert( 'pp_routes', [
'type' => 'system',
'lang_id' => 0,
'pattern' => '^producent/' . self::seo( $row['name'] ) . '/([0-9]+)$',
'destination' => 'index.php?module=shop_producer&action=products&producer_id=' . $row['id'] . '&layout_id=' . $categoryDefaultLayoutId . '&bs=$1',
] );
}
//
// HTACCESS — generuj z PHP (bez szablonu htaccess.conf)
//
$htaccess_data = 'RewriteEngine On' . PHP_EOL;
$htaccess_data .= 'RewriteBase /' . PHP_EOL;
$htaccess_data .= 'Options +FollowSymlinks' . PHP_EOL;
$htaccess_data .= 'Options -Indexes' . PHP_EOL;
$htaccess_data .= PHP_EOL;
$htaccess_data .= '# Przekierowanie z www na bez www i z http na https w jednym kroku' . PHP_EOL;
$htaccess_data .= 'RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]' . PHP_EOL;
$htaccess_data .= 'RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]' . PHP_EOL;
$htaccess_data .= PHP_EOL;
$htaccess_data .= '# Przekierowanie z http na https, jesli nie zawiera www' . PHP_EOL;
$htaccess_data .= 'RewriteCond %{HTTPS} off' . PHP_EOL;
$htaccess_data .= 'RewriteCond %{REQUEST_URI} !^/(tpay-status|platnosc-status|przelewy24-status)$ [NC]' . PHP_EOL;
$htaccess_data .= 'RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]' . PHP_EOL;
$htaccess_data .= PHP_EOL;
$htaccess_data .= '# Usuwanie koncowego slasha dla niekatalogów' . PHP_EOL;
$htaccess_data .= 'RewriteCond %{REQUEST_FILENAME} !-d' . PHP_EOL;
$htaccess_data .= 'RewriteCond %{REQUEST_URI} !^/admin/.*$ [NC]' . PHP_EOL;
$htaccess_data .= 'RewriteCond %{REQUEST_URI} (.+)/$' . PHP_EOL;
$htaccess_data .= 'RewriteRule ^ %1 [R=301,L]' . PHP_EOL;
$htaccess_data .= PHP_EOL;
$htaccess_data .= 'RewriteCond %{REQUEST_URI} !^(.*)/libraries/(.*) [NC]' . PHP_EOL;
$htaccess_data .= 'RewriteCond %{REQUEST_URI} !^(.*)/layout/(.*) [NC]' . PHP_EOL;
$htaccess_data .= 'RewriteRule ^admin/([^/]*)/([^/]*)/(.*)$ admin/index.php?module=$1&action=$2&$3 [L]' . PHP_EOL;
$htaccess_data .= PHP_EOL;
$htaccess_data .= 'RewriteRule ^admin/$ admin/index.php [L]' . PHP_EOL;
$htaccess_data .= PHP_EOL;
$htaccess_data .= 'RewriteRule ^thumb/([0-9]*)/([0-9]*)/(.*)$ /libraries/thumb.php?img=$3&w=$1&h=$2 [L]' . PHP_EOL;
$htaccess_data .= PHP_EOL;
$htaccess_data .= 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index.php' . PHP_EOL;
$htaccess_data .= 'RewriteRule ^ /%1 [R=301,L]' . PHP_EOL;
/* cache — zastąpienie placeholdera {HTACCESS_CACHE} */
if ( $settings['htaccess_cache'] )
{
$htaccess_data .= '<IfModule mod_deflate.c>' . PHP_EOL
. 'AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml application/xhtml+xml text/css text/javascript application/javascript application/x-javascript' . PHP_EOL
. '</IfModule>' . PHP_EOL
. '<IfModule mod_headers.c>' . PHP_EOL
. 'Header set Access-Control-Allow-Origin "*"' . PHP_EOL
. '</IfModule>' . PHP_EOL
. '<IfModule mod_expires.c>' . PHP_EOL
. 'ExpiresActive on' . PHP_EOL
. 'ExpiresDefault "access plus 1 month"' . PHP_EOL
. 'ExpiresByType text/css "access plus 1 year"' . PHP_EOL
. 'ExpiresByType application/json "access plus 0 seconds"' . PHP_EOL
. 'ExpiresByType application/xml "access plus 0 seconds"' . PHP_EOL
. 'ExpiresByType text/xml "access plus 0 seconds"' . PHP_EOL
. 'ExpiresByType image/x-icon "access plus 1 week"' . PHP_EOL
. 'ExpiresByType text/x-component "access plus 1 month"' . PHP_EOL
. 'ExpiresByType text/html "access plus 0 seconds"' . PHP_EOL
. 'ExpiresByType application/javascript "access plus 1 year"' . PHP_EOL
. 'ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"' . PHP_EOL
. 'ExpiresByType text/cache-manifest "access plus 0 seconds"' . PHP_EOL
. 'ExpiresByType audio/ogg "access plus 1 month"' . PHP_EOL
. 'ExpiresByType image/gif "access plus 1 month"' . PHP_EOL
. 'ExpiresByType image/jpeg "access plus 1 month"' . PHP_EOL
. 'ExpiresByType image/png "access plus 1 month"' . PHP_EOL
. 'ExpiresByType video/mp4 "access plus 1 month"' . PHP_EOL
. 'ExpiresByType video/ogg "access plus 1 month"' . PHP_EOL
. 'ExpiresByType video/webm "access plus 1 month"' . PHP_EOL
. 'ExpiresByType application/atom+xml "access plus 1 hour"' . PHP_EOL
. 'ExpiresByType application/rss+xml "access plus 1 hour"' . PHP_EOL
. 'ExpiresByType application/font-woff "access plus 1 month"' . PHP_EOL
. 'ExpiresByType application/vnd.ms-fontobject "access plus 1 month"' . PHP_EOL
. 'ExpiresByType application/x-font-ttf "access plus 1 month"' . PHP_EOL
. 'ExpiresByType font/opentype "access plus 1 month"' . PHP_EOL
. 'ExpiresByType image/svg+xml "access plus 1 month"' . PHP_EOL
. '</IfModule>' . PHP_EOL;
}
else
{
$htaccess_data .= '<IfModule mod_headers.c>' . PHP_EOL
. 'Header set Cache-Control "no-cache, no-store, must-revalidate"' . PHP_EOL
. 'Header set Pragma "no-cache"' . PHP_EOL
. 'Header set Expires 0' . PHP_EOL
. '</IfModule>' . PHP_EOL;
}
$htaccess_data .= '<Files *.conf>' . PHP_EOL;
$htaccess_data .= ' Order Deny,Allow' . PHP_EOL;
$htaccess_data .= ' Deny from all' . PHP_EOL;
$htaccess_data .= '</Files>' . PHP_EOL;
$htaccess_data .= '<Files *.log>' . PHP_EOL;
$htaccess_data .= ' Order Deny,Allow' . PHP_EOL;
$htaccess_data .= ' Deny from all' . PHP_EOL;
$htaccess_data .= '</Files>' . PHP_EOL;
$htaccess_data .= '<Files *.ini>' . PHP_EOL;
$htaccess_data .= ' Order Deny,Allow' . PHP_EOL;
$htaccess_data .= ' Deny from all' . PHP_EOL;
$htaccess_data .= '</Files>' . PHP_EOL;
//
// KATEGORIE — sitemap + pp_routes (bez zmian)
//
$results = $mdb->select( 'pp_langs', [ 'id', 'start' ], [ 'status' => 1, 'ORDER' => [ 'o' => 'ASC' ] ] );
if ( is_array( $results ) ) foreach ( $results as $row )
{
!$row['start'] ? $language_link = $row['id'] . '/' : $language_link = '';
$results2 = $mdb->select( 'pp_shop_categories_langs', [ '[><]pp_shop_categories' => [ 'category_id' => 'id' ] ], [ 'seo_link', 'title', 'category_id' ], [ 'lang_id' => $row['id'], 'ORDER' => [ 'o' => 'ASC' ] ] );
if ( is_array( $results2 ) ) foreach ( $results2 as $row2 )
{
if ( $row2['title'] )
{
$site_map .= '<url>' . PHP_EOL;
if ( $row2['seo_link'] )
$site_map .= '<loc>https://' . $url . '/' . $language_link . self::seo( $row2['seo_link'] ) . '</loc>' . PHP_EOL;
else
$site_map .= '<loc>https://' . $url . '/' . $language_link . 'k-' . $row2['category_id'] . '-' . self::seo( $row2['title'] ) . '</loc>' . PHP_EOL;
$site_map .= '<lastmod>' . date( 'Y-m-d' ) . '</lastmod>' . PHP_EOL;
$site_map .= '<changefreq>daily</changefreq>' . PHP_EOL;
$site_map .= '<priority>1</priority>' . PHP_EOL;
$site_map .= '</url>' . PHP_EOL;
$seoSlug = $row2['seo_link'] ? self::seo( $row2['seo_link'] ) : 'k-' . $row2['category_id'] . '-' . self::seo( $row2['title'] );
$mdb->delete( 'pp_routes', [ 'AND' => [ 'category_id' => $row2['category_id'], 'lang_id' => $row['id'] ] ] );
$mdb->insert( 'pp_routes', [
'category_id' => $row2['category_id'],
'lang_id' => $row['id'],
'pattern' => '^' . $language_link . $seoSlug . '$',
'destination' => 'index.php?category=' . $row2['category_id'] . '&lang=' . $row['id'],
] );
$mdb->insert( 'pp_routes', [
'category_id' => $row2['category_id'],
'lang_id' => $row['id'],
'pattern' => '^' . $language_link . $seoSlug . '/([0-9]+)$',
'destination' => 'index.php?category=' . $row2['category_id'] . '&lang=' . $row['id'] . '&bs=$1',
] );
}
}
}
//
// PRODUKTY — sitemap + pp_routes (bez zmian)
//
$results = $mdb->select( 'pp_langs', [ 'id', 'start' ], [ 'status' => 1, 'ORDER' => [ 'o' => 'ASC' ] ] );
if ( is_array( $results ) )
{
foreach ( $results as $row )
{
!$row['start'] ? $language_link = $row['id'] . '/' : $language_link = '';
$results2 = $mdb->select( 'pp_shop_products_langs', [ '[><]pp_shop_products' => [ 'product_id' => 'id' ] ], [ 'seo_link', 'name', 'product_id' ], [ 'lang_id' => $row['id'], 'ORDER' => [ 'name' => 'ASC' ] ] );
if ( is_array( $results2 ) )
{
foreach ( $results2 as $row2 )
{
$mdb->delete( 'pp_routes', [ 'AND' => [ 'product_id' => $row2['product_id'], 'lang_id' => $row['id'] ] ] );
if ( $row2['name'] )
{
$site_map .= '<url>' . PHP_EOL;
if ( $row2['seo_link'] )
$site_map .= '<loc>https://' . $url . '/' . $language_link . self::seo( $row2['seo_link'] ) . '</loc>' . PHP_EOL;
else
$site_map .= '<loc>https://' . $url . '/' . $language_link . 'p-' . $row2['product_id'] . '-' . self::seo( $row2['name'] ) . '</loc>' . PHP_EOL;
$site_map .= '<lastmod>' . date( 'Y-m-d' ) . '</lastmod>' . PHP_EOL;
$site_map .= '<changefreq>daily</changefreq>' . PHP_EOL;
$site_map .= '<priority>1</priority>' . PHP_EOL;
$site_map .= '</url>' . PHP_EOL;
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'] ) . '/([0-9-]+)$', 'destination' => 'index.php?product=' . $row2['product_id'] . '&permutation_hash=$1' ] );
}
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'] ) . '/([0-9-]+)$', 'destination' => 'index.php?product=' . $row2['product_id'] . '&permutation_hash=$1' ] );
}
}
}
}
}
}
//
// STRONY + ARTYKULY — sitemap + pp_routes (bez zmian)
//
$results = $mdb->select( 'pp_langs', [ 'id', 'start' ], [ 'status' => 1, 'ORDER' => [ 'o' => 'ASC' ] ] );
if ( is_array( $results ) )
foreach ( $results as $row )
{
( !$row['start'] and count( $results ) > 1 ) ? $language_link = $row['id'] . '/' : $language_link = '';
$results2 = $mdb->select( 'pp_pages_langs', [ '[><]pp_pages' => [ 'page_id' => 'id' ] ], [ 'seo_link', 'title', 'page_id', 'noindex', 'start', 'link', 'page_type' ], [ 'lang_id' => $row['id'], 'ORDER' => [ 'start' => 'DESC', 'o' => 'ASC' ] ] );
if ( is_array( $results2 ) )
foreach ( $results2 as $row2 )
{
if ( $row2['title'] and $row2['page_type'] != 3 and $row2['page_type'] != 5 )
{
if ( !$row2['noindex'] )
{
$site_map .= '<url>' . PHP_EOL;
if ( $row2['seo_link'] )
$site_map .= '<loc>https://' . $url . '/' . self::seo( $row2['seo_link'] ) . '</loc>' . PHP_EOL;
else
$site_map .= '<loc>https://' . $url . '/s-' . $row2['page_id'] . '-' . self::seo( $row2['title'] ) . '</loc>' . PHP_EOL;
$site_map .= '<lastmod>' . date( 'Y-m-d' ) . '</lastmod>' . PHP_EOL;
$site_map .= '<changefreq>daily</changefreq>' . PHP_EOL;
$site_map .= '<priority>1</priority>' . PHP_EOL;
$site_map .= '</url>' . PHP_EOL;
}
else if ( $row2['noindex'] and $row2['seo_link'] )
{
$robots .= 'User-agent: GoogleBot' . PHP_EOL;
$robots .= 'Disallow: /' . $row2['seo_link'] . PHP_EOL;
}
if ( $row2['start'] )
{
if ( $row2['seo_link'] )
{
$htaccess_data .= PHP_EOL . 'RewriteCond %{REQUEST_URI} ^/' . self::seo( $row2['seo_link'] ) . '$';
$htaccess_data .= PHP_EOL . 'RewriteRule ^(.*)$ http://www.' . $url . '/' . $language_link . ' [R=permanent,L]';
$htaccess_data .= PHP_EOL . 'RewriteCond %{REQUEST_URI} ^/' . self::seo( $row2['seo_link'] ) . '-1$';
$htaccess_data .= PHP_EOL . 'RewriteRule ^(.*)$ http://www.' . $url . '/' . $language_link . ' [R=permanent,L]';
}
else
{
$htaccess_data .= PHP_EOL . 'RewriteCond %{REQUEST_URI} ^/s-' . $row2['page_id'] . '-' . self::seo( $row2['title'] ) . '$';
$htaccess_data .= PHP_EOL . 'RewriteRule ^(.*)$ http://www.' . $url . '/' . $language_link . ' [R=permanent,L]';
$htaccess_data .= PHP_EOL . 'RewriteCond %{REQUEST_URI} ^/s-' . $row2['page_id'] . '-' . self::seo( $row2['title'] ) . '-1$';
$htaccess_data .= PHP_EOL . 'RewriteRule ^(.*)$ http://www.' . $url . '/' . $language_link . ' [R=permanent,L]';
}
$htaccess_data .= PHP_EOL . 'RewriteRule ^$ index.php?a=page&id=' . $row2['page_id'] . '&lang=' . $row['id'] . ' [L]';
}
$seoSlug = $row2['seo_link'] ? self::seo( $row2['seo_link'] ) : 's-' . $row2['page_id'] . '-' . self::seo( $row2['title'] );
$langPrefix = $row2['start'] ? '' : $language_link;
$mdb->delete( 'pp_routes', [ 'AND' => [ 'page_id' => $row2['page_id'], 'lang_id' => $row['id'] ] ] );
$mdb->insert( 'pp_routes', [
'page_id' => $row2['page_id'],
'lang_id' => $row['id'],
'pattern' => '^' . $langPrefix . $seoSlug . '$',
'destination' => 'index.php?a=page&id=' . $row2['page_id'] . '&lang=' . $row['id'],
] );
$mdb->insert( 'pp_routes', [
'page_id' => $row2['page_id'],
'lang_id' => $row['id'],
'pattern' => '^' . $langPrefix . $seoSlug . '/([0-9]+)$',
'destination' => 'index.php?a=page&id=' . $row2['page_id'] . '&lang=' . $row['id'] . '&bs=$1',
] );
}
}
$results2 = $mdb->select( 'pp_articles_langs', [ '[><]pp_articles' => [ 'article_id' => 'id' ] ], [ 'seo_link', 'title', 'article_id', 'noindex', 'copy_from' ], [ 'AND' => [ 'status' => 1, 'lang_id' => $row['id'], 'block_direct_access' => 0 ] ] );
if ( is_array( $results2 ) )
foreach ( $results2 as $row2 )
{
if ( $row2['copy_from'] != null )
{
$results_tmp = $mdb->get( 'pp_articles_langs', [ 'seo_link', 'title' ], [ 'AND' => [ 'article_id' => $row2['article_id'], 'lang_id' => $row2['copy_from'] ] ] );
$row2['seo_link'] = $results_tmp['seo_link'];
$row2['title'] = $results_tmp['title'];
}
if ( !$row2['noindex'] )
{
$site_map .= '<url>' . PHP_EOL;
if ( $row2['seo_link'] )
$site_map .= '<loc>https://' . $url . '/' . self::seo( $row2['seo_link'] ) . '</loc>' . PHP_EOL;
else
$site_map .= '<loc>https://' . $url . '/a-' . $row2['article_id'] . '-' . self::seo( $row2['title'] ) . '</loc>' . PHP_EOL;
$site_map .= '<lastmod>' . date( 'Y-m-d' ) . '</lastmod>' . PHP_EOL;
$site_map .= '<changefreq>daily</changefreq>' . PHP_EOL;
$site_map .= '<priority>1</priority>' . PHP_EOL;
$site_map .= '</url>' . PHP_EOL;
}
else if ( $row2['noindex'] and $row2['seo_link'] )
{
$robots .= 'User-agent: GoogleBot' . PHP_EOL;
$robots .= 'Disallow: /' . $row2['seo_link'] . PHP_EOL;
}
$mdb->delete( 'pp_routes', [ 'AND' => [ 'article_id' => $row2['article_id'], 'lang_id' => $row['id'] ] ] );
if ( $row2['seo_link'] )
{
$mdb->insert( 'pp_routes', [
'article_id' => $row2['article_id'],
'lang_id' => $row['id'],
'pattern' => '^' . $language_link . self::seo( $row2['seo_link'] ) . '$',
'destination' => 'index.php?article=' . $row2['article_id'] . '&lang=' . $row['id'],
] );
}
else if ( $row2['title'] != null )
{
$mdb->insert( 'pp_routes', [
'article_id' => $row2['article_id'],
'lang_id' => $row['id'],
'pattern' => '^' . $language_link . 'a-' . $row2['article_id'] . '-' . self::seo( $row2['title'] ) . '$',
'destination' => 'index.php?article=' . $row2['article_id'] . '&lang=' . $row['id'],
] );
}
}
}
// Invalidacja cache tras
try {
( new \Shared\Cache\CacheHandler() )->delete( 'pp_routes:all' );
} catch ( \Exception $e ) {
// Redis niedostepny — ignorujemy
}
$results = $mdb->get( 'pp_settings', 'value', [ 'param' => 'htaccess' ] );
if ( $results )
$htaccess_data .= PHP_EOL . $results;
$results = $mdb->get( 'pp_settings', 'value', [ 'param' => 'robots' ] );
if ( $results )
$robots .= PHP_EOL . $results;
$site_map .= '</urlset>';
$htaccess_data .= PHP_EOL;
$htaccess_data .= 'RewriteCond %{REQUEST_FILENAME} !-f' . PHP_EOL;
$htaccess_data .= 'RewriteCond %{REQUEST_FILENAME} !-d' . PHP_EOL;
$htaccess_data .= 'RewriteRule ^ index.php [L]';
// Niektore hostingi blokuja zmiane wersji PHP przez .htaccess.
$htaccess_data = preg_replace( '/^(\\s*)(AddHandler|SetHandler|ForceType)\\b/im', '$1# $2', $htaccess_data );
$fp = fopen( $dir . '.htaccess', 'w' );
fwrite( $fp, $htaccess_data );
fclose( $fp );
$fp = fopen( $dir . 'sitemap.xml', 'w' );
fwrite( $fp, $site_map );
fclose( $fp );
$fp = fopen( $dir . 'robots.txt', 'w' );
fwrite( $fp, $robots );
fclose( $fp );
}
```
**Step 2: Run tests**
```
php phpunit.phar --configuration phpunit.xml
```
Expected: all tests pass (htacces() has no unit tests, covered by integration).
---
## Task 3: Delete `libraries/htaccess.conf`
**Files:**
- Delete: `libraries/htaccess.conf`
**Step 1: Verify htacces() no longer references the file**
Search for any remaining `file_get_contents` referencing `htaccess.conf`:
```bash
grep -r "htaccess.conf" autoload/
```
Expected: no results.
**Step 2: Delete the file**
```bash
rm libraries/htaccess.conf
```
**Step 3: Run tests**
```
php phpunit.phar --configuration phpunit.xml
```
Expected: all tests still pass.
---
## Task 4: Update `docs/DATABASE_STRUCTURE.md`
**Files:**
- Modify: `docs/DATABASE_STRUCTURE.md` (section `## pp_routes`)
**Step 1: Add `type` column to the pp_routes table description**
Find the `## pp_routes` section and add the `type` row to the column table:
```markdown
| type | Typ trasy: NULL = encja (produkt/kategoria/strona/artykuł), 'system' = trasa systemowa |
```
Also update the description paragraph to mention that system routes are managed automatically.
---
## Task 5: Manual integration test on server
**Step 1: Apply migration**
```sql
ALTER TABLE pp_routes ADD COLUMN type VARCHAR(20) NULL AFTER article_id;
```
**Step 2: Trigger `htacces()` regeneration**
Log in to admin panel → save any product or category → this calls `htacces()`.
**Step 3: Verify pp_routes has system routes**
```sql
SELECT COUNT(*) FROM pp_routes WHERE type = 'system';
```
Expected: ~35+ rows (32 static + language rows + producer rows).
**Step 4: Verify .htaccess was generated correctly**
Open `.htaccess` — should NOT contain `RewriteRule ^koszyk$`, `^logowanie$`, etc. Should contain HTTPS redirect, admin routing, thumb routing, cache block.
**Step 5: Test URLs in browser**
- `/koszyk` → koszyk page ✓
- `/logowanie` → login page ✓
- `/wyszukiwarka/test` → search results ✓
- `/zamowienie/abc123` → order details ✓
- `/shopClient/confirm/hash=xyz` → client confirm action ✓
- Category URL → category page ✓
- Product URL → product page ✓
**Step 6: Run full test suite**
```
php phpunit.phar --configuration phpunit.xml
```
Expected: 807 tests, all pass.
---
## Task 6: Commit
**Step 1: Stage and commit**
```bash
git add migrations/0.329.sql
git add autoload/Shared/Helpers/Helpers.php
git add docs/DATABASE_STRUCTURE.md
git add docs/plans/2026-02-27-htaccess-conf-elimination.md
git add docs/plans/2026-02-27-htaccess-to-routes-design.md
git rm libraries/htaccess.conf
git commit -m "feat: eliminate htaccess.conf, move all routes to pp_routes (v0.330)"
```

View File

@@ -0,0 +1,121 @@
# Design: Eliminacja htaccess.conf i przeniesienie wszystkich tras do pp_routes
**Data:** 2026-02-27
**Wersja docelowa:** 0.330
---
## Cel
Wyeliminowanie pliku `libraries/htaccess.conf` jako szablonu i przeniesienie wszystkich URL-i, które dotychczas były wpisane na sztywno w `.htaccess`, do tabeli `pp_routes`. Logika generowania `.htaccess` zostaje w całości w `Helpers::htacces()`.
---
## Co zostaje w `.htaccess` (reguły Apache-level)
Tylko dyrektywy, których PHP nie może obsłużyć:
- `RewriteEngine On`, `Options`
- Redirect HTTPS/www
- Redirect HTTP→HTTPS (z wyłączeniem tpay-status, platnosc-status, przelewy24-status)
- Usuwanie trailing slash (z wyłączeniem `/admin/`)
- Routing `/admin/``admin/index.php`
- `thumb/([0-9]*)/([0-9]*)/(.*)``/libraries/thumb.php` (inny plik PHP — niemożliwe przez pp_routes)
- `RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index.php` — redirect z index.php
- Blok cache headers (gzip, expires) — zależny od `$settings['htaccess_cache']`
- Ochrona plików: `<Files *.conf>`, `<Files *.log>`, `<Files *.ini>`
- Przekierowania 301 stron startowych (generowane dynamicznie w pętli pages)
- Niestandardowe reguły z `pp_settings` (param=htaccess)
- Catch-all: `RewriteCond !-f`, `!-d`, `RewriteRule ^ index.php [L]`
---
## Co przechodzi do `pp_routes`
### Statyczne trasy systemowe (hardcoded, niezmienne)
| Pattern | Destination |
|---------|-------------|
| `^wyszukiwarka/([^/]+)/([0-9]+)$` | `index.php?module=search&action=search_results&query=$1&bs=$2` |
| `^wyszukiwarka/([^/]+)$` | `index.php?module=search&action=search_results&query=$1&bs=1` |
| `^zamowienie/([a-zA-Z0-9-]+)$` | `index.php?module=shop_order&action=order_details&order_hash=$1` |
| `^potwierdzenie-platnosci/([a-zA-Z0-9-]+)$` | `index.php?module=shop_order&action=payment_confirmation&order_hash=$1` |
| `^tpay-status$` | `index.php?module=shop_order&action=payment_status_tpay` |
| `^platnosc-status$` | `index.php?module=shop_order&action=payment_status_hotpay` |
| `^przelewy24-status$` | `index.php?module=shop_order&action=payment_status_przelewy24pl` |
| `^koszyk$` | `index.php?module=shop_basket&action=main_view` |
| `^koszyk-podsumowanie$` | `index.php?module=shop_basket&action=summary_view` |
| `^zloz-zamowienie$` | `index.php?module=shop_basket&action=basket_save` |
| `^rejestracja$` | `index.php?module=shop_client&action=register_form` |
| `^logowanie$` | `index.php?module=shop_client&action=login_form` |
| `^wylogowanie$` | `index.php?module=shop_client&action=logout` |
| `^odzyskiwanie-hasla$` | `index.php?module=shop_client&action=recover_password` |
| `^panel-klienta/zamowienia$` | `index.php?module=shop_client&action=client_orders` |
| `^panel-klienta/adresy$` | `index.php?module=shop_client&action=client_addresses` |
| `^panel-klienta/nowy-adres$` | `index.php?module=shop_client&action=address_edit` |
| `^panel-klienta/edytuj-adres/([0-9]+)$` | `index.php?module=shop_client&action=address_edit&id=$1` |
| `^panel-klienta/usun-adres/([0-9]+)$` | `index.php?module=shop_client&action=address_delete&id=$1` |
| `^newsletter/signin$` | `index.php?module=newsletter&action=signin` |
| `^newsletter/confirm/hash=(.+)$` | `index.php?module=newsletter&action=confirm&hash=$1` |
| `^newsletter/unsubscribe/hash=(.+)$` | `index.php?module=newsletter&action=unsubscribe&hash=$1` |
### Trasy modułów AJAX (shopBasket, shopClient, shopProduct, shopCoupon, search)
Dwa wzorce na moduł — 3-segmentowy (z parametrami) i 2-segmentowy:
| Pattern | Destination |
|---------|-------------|
| `^shopBasket/([^/]+)/(.+)$` | `index.php?module=shopBasket&action=$1&$2` |
| `^shopBasket/([^/]+)$` | `index.php?module=shopBasket&action=$1` |
| `^shopClient/([^/]+)/(.+)$` | `index.php?module=shopClient&action=$1&$2` |
| `^shopClient/([^/]+)$` | `index.php?module=shopClient&action=$1` |
| `^shopProduct/([^/]+)/(.+)$` | `index.php?module=shopProduct&action=$1&$2` |
| `^shopProduct/([^/]+)$` | `index.php?module=shopProduct&action=$1` |
| `^shopCoupon/([^/]+)/(.+)$` | `index.php?module=shopCoupon&action=$1&$2` |
| `^shopCoupon/([^/]+)$` | `index.php?module=shopCoupon&action=$1` |
| `^search/([^/]+)/(.+)$` | `index.php?module=search&action=$1&$2` |
| `^search/([^/]+)$` | `index.php?module=search&action=$1` |
### Dynamiczne trasy systemowe (wstawiane przy każdym `htacces()`)
- **Języki:** `^{lang_id}$``index.php?a=change_language&id={lang_id}` (per każdy aktywny język)
- **Producenci lista:** `^producenci$``index.php?module=shop_producer&action=list&layout_id={id}`
- **Producent detail:** `^producent/{slug}$` i `^producent/{slug}/([0-9]+)$` (per producent z DB)
---
## Nowa kolumna `type` w `pp_routes`
```sql
ADD COLUMN type VARCHAR(20) NULL AFTER article_id
```
| Wartość | Znaczenie |
|---------|-----------|
| `NULL` | Trasa encji (produkt, kategoria, strona, artykuł) |
| `'system'` | Trasa systemowa (wszystkie powyższe) |
**Zarządzanie:** przy każdym `htacces()`:
```php
$mdb->delete('pp_routes', ['type' => 'system']); // usuń wszystkie
// ... wstaw na nowo (statyczne + dynamiczne)
```
---
## Eliminacja `htaccess.conf`
`file_get_contents($dir . 'libraries/htaccess.conf')` zastąpione PHP stringiem z tą samą treścią (tylko Apache-level reguły). Placeholder `{HTACCESS_CACHE}` zastąpiony bezpośrednim `if ($settings['htaccess_cache']) { ... } else { ... }` wbudowanym w odpowiednim miejscu.
Plik `libraries/htaccess.conf` zostaje usunięty.
---
## Pliki do modyfikacji
| Plik | Zmiana |
|------|--------|
| `migrations/0.329.sql` | Dodać `ADD COLUMN type VARCHAR(20) NULL` |
| `Helpers::htacces()` | Usunąć `file_get_contents`, wbudować statyczny header, dodać inserty system routes, usunąć htaccess rules dla języków/newsletter/producenci |
| `libraries/htaccess.conf` | Usunąć plik |
| `docs/DATABASE_STRUCTURE.md` | Dodać kolumnę `type` do opisu pp_routes |

View File

@@ -59,6 +59,49 @@ $mdb = new medoo( [
'time_debug' => $database['time_debug']
] );
// check routes
$parsed_url = parse_url($_SERVER['REQUEST_URI']);
$request_uri = ltrim($parsed_url['path'], '/');
$query_string = isset($parsed_url['query']) ? $parsed_url['query'] : '';
parse_str($query_string, $query_params);
if ($request_uri != '')
{
$cache = new \Shared\Cache\CacheHandler();
$cacheKey = 'pp_routes:all';
$routesCached = $cache->get($cacheKey);
if ($routesCached === false || $routesCached === null)
{
$routes = $mdb->select('pp_routes', '*');
$cache->set($cacheKey, $routes, 86400);
}
else
{
$routes = unserialize($routesCached);
}
foreach ($routes as $route)
{
$pattern = $route['pattern'];
$destination = $route['destination'];
if (preg_match("#^" . $pattern . "#", $request_uri, $matches))
{
// Replace placeholders in the destination with matches from the request URI
$destination = preg_replace("#^" . $pattern . "#", $destination, $request_uri);
// Parse the destination string to extract GET parameters
parse_str(parse_url($destination, PHP_URL_QUERY), $destination_params);
// Merge the destination params with query params from the URL
$_GET = array_merge($destination_params, $query_params);
break;
}
}
}
\front\App::checkUrlParams();
$langRepo = new \Domain\Languages\LanguagesRepository( $mdb );
@@ -99,39 +142,6 @@ if ( $request_uri != '' )
}
}
// check routes
$parsed_url = parse_url($_SERVER['REQUEST_URI']);
$request_uri = ltrim($parsed_url['path'], '/');
$query_string = isset($parsed_url['query']) ? $parsed_url['query'] : '';
parse_str($query_string, $query_params);
if ($request_uri != '')
{
$matched = false;
$routes = $mdb->select('pp_routes', '*');
foreach ($routes as $route)
{
$pattern = $route['pattern'];
$destination = $route['destination'];
if (preg_match("#^" . $pattern . "#", $request_uri, $matches))
{
// Replace placeholders in the destination with matches from the request URI
$destination = preg_replace("#^" . $pattern . "#", $destination, $request_uri);
// Parse the destination string to extract GET parameters
parse_str(parse_url($destination, PHP_URL_QUERY), $destination_params);
// Merge the destination params with query params from the URL
$_GET = array_merge($destination_params, $query_params);
$matched = true;
break;
}
}
}
$pagesRepo = new \Domain\Pages\PagesRepository( $mdb );
if ( \Shared\Helpers\Helpers::get( 'a' ) == 'page' and \Shared\Helpers\Helpers::get( 'id' ) )

View File

@@ -1,84 +0,0 @@
RewriteEngine On
RewriteBase /
Options +FollowSymlinks
Options -Indexes
# Przekierowanie z www na bez www i z http na https w jednym kroku
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
# Przekierowanie z http na https, jeśli nie zawiera www
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} !^/(tpay-status|platnosc-status|przelewy24-status)$ [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Usuwanie końcowego slash'a dla niekatalogów
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/admin/.*$ [NC] # Wyklucza ścieżki rozpoczynające się od "admin/"
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [R=301,L]
RewriteCond %{REQUEST_URI} !^(.*)/libraries/(.*) [NC]
RewriteCond %{REQUEST_URI} !^(.*)/layout/(.*) [NC]
RewriteRule ^admin/([^/]*)/([^/]*)/(.*)$ admin/index.php?module=$1&action=$2&$3 [L]
RewriteRule ^admin/$ admin/index.php [L]
RewriteRule ^wyszukiwarka/(.*)/([0-9]*)$ index.php?module=search&action=search_results&query=$1&bs=$2 [L]
RewriteRule ^wyszukiwarka/(.*)$ index.php?module=search&action=search_results&query=$1&bs=1 [L]
RewriteRule ^zamowienie/([a-zA-Z0-9-]*)$ index.php?module=shop_order&action=order_details&order_hash=$1 [L]
RewriteRule ^potwierdzenie-platnosci/([a-zA-Z0-9-]*)$ index.php?module=shop_order&action=payment_confirmation&order_hash=$1 [L]
RewriteRule ^tpay-status$ index.php?module=shop_order&action=payment_status_tpay [QSA,L]
RewriteRule ^platnosc-status$ index.php?module=shop_order&action=payment_status_hotpay [QSA,L]
RewriteRule ^przelewy24-status$ index.php?module=shop_order&action=payment_status_przelewy24pl [QSA,L]
RewriteRule ^koszyk$ index.php?module=shop_basket&action=main_view [L]
RewriteRule ^koszyk-podsumowanie$ index.php?module=shop_basket&action=summary_view [L]
RewriteRule ^zloz-zamowienie$ index.php?module=shop_basket&action=basket_save [L]
RewriteRule ^rejestracja$ index.php?module=shop_client&action=register_form [L]
RewriteRule ^logowanie$ index.php?module=shop_client&action=login_form [L]
RewriteRule ^wylogowanie$ index.php?module=shop_client&action=logout [L]
RewriteRule ^odzyskiwanie-hasla$ index.php?module=shop_client&action=recover_password [L]
RewriteRule ^panel-klienta/zamowienia$ index.php?module=shop_client&action=client_orders [L]
RewriteRule ^panel-klienta/adresy$ index.php?module=shop_client&action=client_addresses [L]
RewriteRule ^panel-klienta/nowy-adres$ index.php?module=shop_client&action=address_edit [L]
RewriteRule ^panel-klienta/edytuj-adres/([0-9]*)$ index.php?module=shop_client&action=address_edit&id=$1 [L]
RewriteRule ^panel-klienta/usun-adres/([0-9]*)$ index.php?module=shop_client&action=address_delete&id=$1 [L]
RewriteRule ^thumb/([0-9]*)/([0-9]*)/(.*)$ /libraries/thumb.php?img=$3&w=$1&h=$2 [L]
RewriteCond %{REQUEST_URI} ^/shopBasket/(.*)/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)/(.*)$ index.php?module=$1&action=$2&$3 [L]
RewriteCond %{REQUEST_URI} ^/shopClient/(.*)/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)/(.*)$ index.php?module=$1&action=$2&$3 [L]
RewriteCond %{REQUEST_URI} ^/shopProduct/(.*)/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)/(.*)$ index.php?module=$1&action=$2&$3 [L]
RewriteCond %{REQUEST_URI} ^/shopCoupon/(.*)/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)/(.*)$ index.php?module=$1&action=$2&$3 [L]
RewriteCond %{REQUEST_URI} ^/search/(.*)/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)/(.*)$ index.php?module=$1&action=$2&$3 [L]
RewriteCond %{REQUEST_URI} ^/shopBasket/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)$ index.php?module=$1&action=$2 [L]
RewriteCond %{REQUEST_URI} ^/shopClient/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)$ index.php?module=$1&action=$2 [L]
RewriteCond %{REQUEST_URI} ^/shopProduct/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)$ index.php?module=$1&action=$2 [L]
RewriteCond %{REQUEST_URI} ^/shopCoupon/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)$ index.php?module=$1&action=$2 [L]
RewriteCond %{REQUEST_URI} ^/search/(.*) [NC]
RewriteRule ^([^/]*)/([^/]*)$ index.php?module=$1&action=$2 [L]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index.php
RewriteRule ^ /%1 [R=301,L]
{HTACCESS_CACHE}
<Files *.conf>
Order Deny,Allow
Deny from all
</Files>
<Files *.log>
Order Deny,Allow
Deny from all
</Files>
<Files *.ini>
Order Deny,Allow
Deny from all
</Files>

5
migrations/0.329.sql Normal file
View File

@@ -0,0 +1,5 @@
ALTER TABLE pp_routes
ADD COLUMN category_id INT NULL AFTER product_id,
ADD COLUMN page_id INT NULL AFTER category_id,
ADD COLUMN article_id INT NULL AFTER page_id,
ADD COLUMN type VARCHAR(20) NULL AFTER article_id;

View File

@@ -513,7 +513,7 @@ class ArticleRepositoryTest extends TestCase
$mockDb = $this->createMock(\medoo::class);
$deleteCalls = [];
$mockDb->expects($this->exactly(5))
$mockDb->expects($this->exactly(6))
->method('delete')
->willReturnCallback(function ($table, $where) use (&$deleteCalls) {
$deleteCalls[] = ['table' => $table, 'where' => $where];
@@ -524,12 +524,13 @@ class ArticleRepositoryTest extends TestCase
$result = $repository->deletePermanently(77);
$this->assertTrue($result);
$this->assertCount(5, $deleteCalls);
$this->assertCount(6, $deleteCalls);
$this->assertSame('pp_articles_pages', $deleteCalls[0]['table']);
$this->assertSame('pp_articles_langs', $deleteCalls[1]['table']);
$this->assertSame('pp_articles_images', $deleteCalls[2]['table']);
$this->assertSame('pp_articles_files', $deleteCalls[3]['table']);
$this->assertSame('pp_articles', $deleteCalls[4]['table']);
$this->assertSame('pp_routes', $deleteCalls[4]['table']);
$this->assertSame('pp_articles', $deleteCalls[5]['table']);
}
public function testPagesSummaryForArticlesBuildsLabels(): void

View File

@@ -175,14 +175,19 @@ class CategoryRepositoryTest extends TestCase
$mockDb = $this->createMock(\medoo::class);
$mockDb->method('count')->willReturn(0);
$mockDb->expects($this->once())
$deleteCalls = [];
$mockDb->expects($this->exactly(2))
->method('delete')
->with('pp_shop_categories', ['id' => 8])
->willReturn(true);
->willReturnCallback(function ($table, $where) use (&$deleteCalls) {
$deleteCalls[] = ['table' => $table, 'where' => $where];
return true;
});
$repository = new CategoryRepository($mockDb);
$this->assertTrue($repository->categoryDelete(8));
$this->assertSame('pp_shop_categories', $deleteCalls[0]['table']);
$this->assertSame('pp_routes', $deleteCalls[1]['table']);
}
public function testCategoryTitleReturnsEmptyWhenNotFound(): void

BIN
updates/0.30/ver_0.328.zip Normal file

Binary file not shown.

View File

@@ -0,0 +1,23 @@
{
"changelog": "NEW - ikona kopiowania wartosci atrybutow w szczegolach zamowienia",
"version": "0.328",
"files": {
"added": [
],
"deleted": [
],
"modified": [
"admin/templates/shop-order/order-details-custom-script.php"
]
},
"checksum_zip": "sha256:db8ddf18bc08ab7d194fbb8a9949f2366185f13cbfd64bec4ad7c600736ded20",
"sql": [
],
"date": "2026-02-27",
"directories_deleted": [
]
}

BIN
updates/0.30/ver_0.329.zip Normal file

Binary file not shown.

View File

@@ -0,0 +1 @@
F: ../libraries/htaccess.conf

View File

@@ -0,0 +1,27 @@
{
"changelog": "REFACT - routing kategorii, stron i artykulow przez pp_routes; blok routingu w index.php przed checkUrlParams(); Redis cache tras; nowe kolumny category_id/page_id/article_id/type w pp_routes",
"version": "0.329",
"files": {
"added": [
],
"deleted": [
"libraries/htaccess.conf"
],
"modified": [
"autoload/Domain/Article/ArticleRepository.php",
"autoload/Domain/Category/CategoryRepository.php",
"autoload/Domain/Pages/PagesRepository.php",
"autoload/Shared/Helpers/Helpers.php",
"index.php"
]
},
"checksum_zip": "sha256:73b225b9d68d985ce44d79320350b6ef6fe602c30126a6bf322b8ab44eaab230",
"sql": [
"ALTER TABLE pp_routes\n ADD COLUMN category_id INT NULL AFTER product_id,\n ADD COLUMN page_id INT NULL AFTER category_id,\n ADD COLUMN article_id INT NULL AFTER page_id,\n ADD COLUMN type VARCHAR(20) NULL AFTER article_id"
],
"date": "2026-02-27",
"directories_deleted": [
]
}

View File

@@ -0,0 +1,5 @@
ALTER TABLE pp_routes
ADD COLUMN category_id INT NULL AFTER product_id,
ADD COLUMN page_id INT NULL AFTER category_id,
ADD COLUMN article_id INT NULL AFTER page_id,
ADD COLUMN type VARCHAR(20) NULL AFTER article_id

View File

@@ -1,3 +1,9 @@
<b>ver. 0.329 - 27.02.2026</b><br />
REFACT - routing kategorii, stron i artykulow przez pp_routes; blok routingu w index.php przed checkUrlParams(); Redis cache tras; nowe kolumny category_id/page_id/article_id/type w pp_routes
<hr>
<b>ver. 0.328 - 27.02.2026</b><br />
NEW - ikona kopiowania wartosci atrybutow w szczegolach zamowienia
<hr>
<b>ver. 0.327 - 27.02.2026</b><br />
NEW - masowe usuwanie produktow w archiwum
<hr>
@@ -14,28 +20,28 @@ NEW - Endpoint API categories/list: plaska lista aktywnych kategorii (id, parent
FIX - naprawione krzaczki (mojibake) w changelog, limit wyswietlania do 5 wersji wstecz od wersji instancji
<hr>
<b>ver. 0.324 - 27.02.2026</b><br />
NEW - system kolejki zadaÄ‚ââ¬ĹľÄ„…„ cron (DB), priorytetowe przetwarzanie, retry/backoff, ochrona endpointu cron
NEW - system kolejki zadaÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚„…„ cron (DB), priorytetowe przetwarzanie, retry/backoff, ochrona endpointu cron
<hr>
<b>ver. 0.323 - 24.02.2026</b><br />
FIX - refactor importu zdjec w shopPRO import (walidacja HTTP, curl timeouty, logi), FIX - saveCustomFields tylko przy jawnym podaniu, FIX - delete() czysci custom_fields, FIX - sciezka upload w API, NEW - trwale usuwanie produktow z archiwum
<hr>
<b>ver. 0.322 - 24.02.2026</b><br />
FIX - custom_fields: jawne mapowanie kluczy w ProductRepository, spÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šjne !empty w ProductsApiController
FIX - custom_fields: jawne mapowanie kluczy w ProductRepository, spÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šjne !empty w ProductsApiController
<hr>
<b>ver. 0.321 - 24.02.2026</b><br />
NEW - API: obsÄ‚ââ¬ĹľÄ„…â€ĹÇuga custom_fields w create/update produktu
NEW - API: obsÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚„…â€ĹËâ€Ă‡uga custom_fields w create/update produktu
<hr>
<b>ver. 0.320 - 24.02.2026</b><br />
NEW - API: endpoint ensure_producer (znajdÄ‚ââ¬ĹľÄ„…Ĺź lub utwÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šrz producenta); GET product zwraca producer_name
NEW - API: endpoint ensure_producer (znajdÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚„…Ĺź lub utwÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡rz producenta); GET product zwraca producer_name
<hr>
<b>ver. 0.319 - 24.02.2026</b><br />
FIX - usuniÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â‚¬ĹľÄ‹Ă˜cie shopPRO eksportu produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw; API produktu: dodano custom_fields i security_information
FIX - usuniÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…Ä‚ââ¬ĹˇÄ‚Ă˜cie shopPRO eksportu produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w; API produktu: dodano custom_fields i security_information
<hr>
<b>ver. 0.318 - 24.02.2026</b><br />
NEW - shopPRO export produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw + API endpoints (ensure_attribute, ensure_attribute_value, upload_image)
NEW - shopPRO export produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw + API endpoints (ensure_attribute, ensure_attribute_value, upload_image)
<hr>
<b>ver. 0.317 - 23.02.2026</b><br />
FIX - klucz API: fix zapisu (brakowalo w whiteliÄ‚ââ¬ĹľÄ„…›cie), przycisk Generuj losowy klucz, ulepszony routing API
FIX - klucz API: fix zapisu (brakowalo w whiteliÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚„…›cie), przycisk Generuj losowy klucz, ulepszony routing API
<hr>
<b>ver. 0.316 - 23.02.2026</b><br />
FIX - migracja brakujacej kolumny type w pp_shop_products_custom_fields
@@ -44,16 +50,16 @@ FIX - migracja brakujacej kolumny type w pp_shop_products_custom_fields
FIX - PDOException w listowaniu atrybutow admin (SQLSTATE HY093)
<hr>
<b>ver. 0.314 - 23.02.2026</b><br />
FIX - naprawa globalnej wyszukiwarki admin (Content-Type, Cache-Control, POST, try/catch), NEW - title strony z numerem zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šwienia
FIX - naprawa globalnej wyszukiwarki admin (Content-Type, Cache-Control, POST, try/catch), NEW - title strony z numerem zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šwienia
<hr>
<b>ver. 0.313 - 23.02.2026</b><br />
FIX - sync pÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡atnoÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşci Apilo (int cast na apilo_order_id PPxxxxxx dawaÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąË‡ 0) + logowanie decyzji sync do pp_log
FIX - sync pÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€ÇatnoÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźci Apilo (int cast na apilo_order_id PPxxxxxx dawaÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€ˇ 0) + logowanie decyzji sync do pp_log
<hr>
<b>ver. 0.312 - 23.02.2026</b><br />
FIX - krytyczne bugi integracji Apilo: curl_getinfo po curl_close, nieskoÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľczona pÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â‚¬ĹľÄ‹Ă˜tla wysyÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡ki, ceny 0.00 PLN, walidacja cen
FIX - krytyczne bugi integracji Apilo: curl_getinfo po curl_close, nieskoÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬ĹľÄ„Äľczona pÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…Ä‚ââ¬ĹˇÄ‚Ă˜tla wysyÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€Çki, ceny 0.00 PLN, walidacja cen
<hr>
<b>ver. 0.311 - 23.02.2026</b><br />
FIX - race condition callback pÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡atnoÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşci Apilo, persistence filtrÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw tabel admin, poprawki cen zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šwieÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľ
FIX - race condition callback pÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€ÇatnoÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźci Apilo, persistence filtrÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w tabel admin, poprawki cen zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡wieÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬ĹľÄ„Äľ
<hr>
<b>ver. 0.310 - 23.02.2026</b><br />
NEW - Zakladka Logi w sekcji Integracje (podglad pp_log z paginacja, sortowaniem, filtrami)
@@ -83,10 +89,10 @@ FIX - naprawiono wyswietlanie atrybutow produktu na froncie (kolizja kolejnosci)
NEW - REST API wariantow produktow (CRUD), slownik atrybutow, filtrowanie po atrybutach, wzbogacone atrybuty z tlumaczeniami
<hr>
<b>ver. 0.301 - 22.02.2026</b><br />
NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šĂââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šwienia
NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ă„‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€ÇĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡wienia
<hr>
<b>ver. 0.300 - 21.02.2026</b><br />
- NEW - System aktualizacji oparty na manifestach JSON (checksum SHA256, backup plikÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw, automatyczny build)
- NEW - System aktualizacji oparty na manifestach JSON (checksum SHA256, backup plikÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw, automatyczny build)
- NEW - Panel logu aktualizacji w panelu admina
<hr>
<b>ver. 0.299 - 21.02.2026</b><br />
@@ -96,31 +102,31 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
- FIX - kilka poprawek po aktualizacji
<hr>
<b>ver. 0.297 - 19.02.2026</b><br />
- NEW - REST API produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw (lista, szczegÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šĂââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡y, tworzenie, aktualizacja)
- NEW - Endpoint products z filtrowaniem, sortowaniem i paginacjÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æ
- NEW - Partial update produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw (tylko zmienione pola)
- NEW - REST API produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w (lista, szczegÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ă„‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€Çy, tworzenie, aktualizacja)
- NEW - Endpoint products z filtrowaniem, sortowaniem i paginacjÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąË‡Ă„‚˘â‚¬ĹľÄ‚˘â‚¬Â¦
- NEW - Partial update produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw (tylko zmienione pola)
<hr>
<b>ver. 0.296 - 19.02.2026</b><br />
- NEW - REST API zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šwieÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľ dla ordersPRO (lista, szczegÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šĂââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡y, zmiana statusu, pÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡atnoÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşci)
- NEW - Endpointy sÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡ownikowe (statusy, transporty, metody pÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡atnoÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşci)
- NEW - REST API zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡wieÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬ĹľÄ„Äľ dla ordersPRO (lista, szczegÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ă„‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€Çy, zmiana statusu, pÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€ÇatnoÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźci)
- NEW - Endpointy sÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€Çownikowe (statusy, transporty, metody pÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€ÇatnoÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźci)
- NEW - Autentykacja API przez X-Api-Key header
- NEW - Kolumna updated_at w pp_shop_orders (polling zmian)
<hr>
<b>ver. 0.295 - 19.02.2026</b><br />
- NEW - Edycja produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw w zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šwieniu z panelu admina (dodawanie, usuwanie, zmiana iloÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşci/cen)
- NEW - Wyszukiwarka produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw AJAX w formularzu edycji zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šwienia
- NEW - Automatyczna korekta stanÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw magazynowych i przeliczanie kosztu dostawy
- FIX - Cena promo w zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šwieniu = 0 gdy identyczna z cenÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æ bazowÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ă‚¦
- NEW - Edycja produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w w zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡wieniu z panelu admina (dodawanie, usuwanie, zmiana iloÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźci/cen)
- NEW - Wyszukiwarka produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w AJAX w formularzu edycji zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡wienia
- NEW - Automatyczna korekta stanÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw magazynowych i przeliczanie kosztu dostawy
- FIX - Cena promo w zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡wieniu = 0 gdy identyczna z cenÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĄââ¬ĹˇÄ˘â‚¬ĹˇÄ‚ââ¬ĹˇÄ‚æ bazowÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĄââ¬ĹˇÄ˘â‚¬ĹˇÄ‚ââ¬ĹˇÄ‚‚¦
<hr>
<b>ver. 0.294 - 19.02.2026</b><br />
- FIX - Code review zakoÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľczony (96/96 klas, ~1144 metod): 27 fixÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw across all layers
- FIX - Code review zakoÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬ĹľÄ„Äľczony (96/96 klas, ~1144 metod): 27 fixÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w across all layers
- FIX - Domain: null guard na query()->fetchAll() w 8 repozytoriach, redundancja DI w PromotionRepository
- FIX - Admin: null safety find() ?: [] w 10 kontrolerach, null guard w App logowaniu/2FA
- FIX - Front: LayoutEngine undefined $level + $_GET null check, ShopBasketController missing global $lang_id
- FIX - Shared: Helpers $_GET null check + bug 'png' → 'image/png' (Imagick lossless WebP nigdy nie dziaÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡aÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąË‡)
- FIX - Shared: Helpers $_GET null check + bug 'png' → 'image/png' (Imagick lossless WebP nigdy nie dziaÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€ÇaÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€ˇ)
<hr>
<b>ver. 0.293 - 19.02.2026</b><br />
- FIX - ArticleRepository: SQL injection fix (addslashesÄ„ââ¬ĹˇÄ‹Â˜Ä‚˘â‚¬Â Ă˘â‚¬â„˘parameterized), uproszczenie articleDetailsFrontend
- FIX - ArticleRepository: SQL injection fix (addslashesÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚˘â‚¬ĹˇÄ‚‹Â˜Ä‚˘â‚¬Â Ă˘â‚¬â„˘parameterized), uproszczenie articleDetailsFrontend
- FIX - AttributeRepository: martwy class_exists('\S') blokowal czyszczenie cache/temp
- FIX - CategoryRepository: martwy class_exists('\S') blokowal generowanie linkow SEO kategorii
- FIX - BannerRepository: parametryzacja dat w SQL + null guard na query()
@@ -139,12 +145,12 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
- UPDATE - front\controls\Site przemianowany na front\App (router, camelCase: checkUrlParams, pageTitle)
- UPDATE - front\view\Site przemianowany na front\LayoutEngine (layout engine, camelCase: cookieInformation)
- CLEANUP - usuniete autoload/front/controls/ i autoload/front/view/ (puste foldery + pliki legacy)
- UPDATE - usuniecie 12 legacy klas z autoload/shop/ (~2363 linii) — pelna migracja na Domain-Driven Architecture
- UPDATE - usuniecie 12 legacy klas z autoload/shop/ (~2363 linii) — pelna migracja na Domain-Driven Architecture
- UPDATE - class.Order.php: logika Apilo sync i email statusu przeniesiona do OrderAdminService
- UPDATE - class.Product.php: ~20 metod przeniesionych do ProductRepository, calculate_basket_product_price do BasketCalculator
- FIX - findCached(): stale Redis cache z obiektami \shop\Product powodowal ceny 0,00 zl
- FIX - szablony: konwersja object access na array access po migracji Product
- UPDATE - AttributeRepository::getAttributeValueById() — dodano Redis cache
- UPDATE - AttributeRepository::getAttributeValueById() — dodano Redis cache
- CLEANUP - katalog autoload/shop/ pusty, zero referencji \shop\ w aktywnym kodzie
<hr>
<b>ver. 0.291 - 17.02.2026</b><br />
@@ -188,17 +194,17 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
- FIX - Tpl::render() branch 3: sprawdzal templates_user ale ladowal templates
<hr>
<b>ver. 0.284 - 16.02.2026</b><br />
- CLEANUP - usunieta klasa DbModel (base ORM) — logika wbudowana bezposrednio w shop\Promotion
- CLEANUP - usunieta klasa DbModel (base ORM) — logika wbudowana bezposrednio w shop\Promotion
<hr>
<b>ver. 0.283 - 16.02.2026</b><br />
- UPDATE - migracja class.S.php do Shared\Helpers\Helpers (~140 plikow przepietych)
- UPDATE - migracja class.Html.php do Shared\Html\Html
- UPDATE - migracja class.Email.php do Shared\Email\Email
- UPDATE - migracja class.Image.php do Shared\Image\ImageManipulator
- UPDATE - migracja class.Log.php do Shared\Log\Log (usunieta — logika przeniesiona)
- UPDATE - migracja class.Log.php do Shared\Log\Log (usunieta — logika przeniesiona)
- CLEANUP - usunieta class.Mobile_Detect.php (przestarzala detekcja UA)
- CLEANUP - usunieto 12 nieuzywanych metod z klasy S
- FIX - array_cartesian_product() — blad iteracji po niezdefiniowanej zmiennej
- FIX - array_cartesian_product() — blad iteracji po niezdefiniowanej zmiennej
<hr>
<b>ver. 0.282 - 16.02.2026</b><br />
- UPDATE - Cache cleanup: eliminacja legacy class.Cache.php, migracja CacheHandler i RedisConnection do Shared\Cache namespace
@@ -210,7 +216,7 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
<hr>
<b>ver. 0.281 - 16.02.2026</b><br />
- UPDATE - migracja Banners frontend: factory + view do Domain/Views (DI)
- NEW - `front\Views\Banners` — czysty VIEW (banners, mainBanner)
- NEW - `front\Views\Banners` — czysty VIEW (banners, mainBanner)
- UPDATE - `BannerRepository` rozszerzony o 2 metody frontendowe (banners, mainBanner) z Redis cache
- UPDATE - `front\view\Site::show()` przepiety na repo + Views
- CLEANUP - usuniete: front\factory\Banners, front\view\Banners
@@ -218,10 +224,10 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
<hr>
<b>ver. 0.280 - 16.02.2026</b><br />
- UPDATE - migracja Articles frontend: factory + view + encja do Domain/Views (DI)
- NEW - `front\Views\Articles` — czysty VIEW + utility (renderowanie, generateTableOfContents, generateHeadersIds, getImage)
- NEW - `front\Views\Articles` — czysty VIEW + utility (renderowanie, generateTableOfContents, generateHeadersIds, getImage)
- UPDATE - `ArticleRepository` rozszerzony o 8 metod frontendowych (z Redis cache)
- UPDATE - `front\view\Site::show()` — 5 sekcji przepietych na repo + Views
- UPDATE - `front\controls\Site::route()` — single article + page_type switch przepiete na repo + Views
- UPDATE - `front\view\Site::show()` — 5 sekcji przepietych na repo + Views
- UPDATE - `front\controls\Site::route()` — single article + page_type switch przepiete na repo + Views
- UPDATE - 5 szablonow `templates/articles/*` przepietych na `\front\Views\Articles::`
- CLEANUP - usuniete: `class.Article` (encja + metody statyczne), `front\factory\Settings` (fasada)
- FIX - eliminacja `global $lang` z `articleNoindex()`, eliminacja zaleznosci od `front\factory\Pages::page_sort()`
@@ -232,22 +238,22 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
- UPDATE - nowy namespace `front\Controllers` z `NewsletterController` (DI via factory closures)
- UPDATE - nowy namespace `front\Views` z `Languages` i `Newsletter` (czyste VIEW, statyczne metody)
- UPDATE - routing frontend: `Site::getControllerFactories()` z fallback na stare kontrolery
- FIX - `newsletter_unsubscribe()` — poprawiona skladnia medoo `delete()` (2 argumenty zamiast 3)
- UPDATE - eliminacja fasady `front\factory\Languages` — 26 zaleznosci przepietych na `LanguagesRepository`
- FIX - `newsletter_unsubscribe()` — poprawiona skladnia medoo `delete()` (2 argumenty zamiast 3)
- UPDATE - eliminacja fasady `front\factory\Languages` — 26 zaleznosci przepietych na `LanguagesRepository`
- CLEANUP - usuniete: `front\factory\Languages`, `front\factory\Newsletter`, `front\view\Languages`, `front\view\Newsletter`, `front\controls\Newsletter`
- UPDATE - testy: `OK (437 tests, 1398 assertions)`
<hr>
<b>ver. 0.278 - 16.02.2026</b><br />
- UPDATE - migracja Settings + Languages do wspolnych klas Domain (z cache Redis)
- FIX - `get_single_settings_value()` — parametr `$param` poprawnie uzywany (wczesniej hardcoded `firm_name`)
- FIX - `get_single_settings_value()` — parametr `$param` poprawnie uzywany (wczesniej hardcoded `firm_name`)
<hr>
<b>ver. 0.277 - 16.02.2026</b><br />
- NEW - migracja modulu `ShopProduct` (factory) — pelna migracja ~40 metod do `ProductRepository` + ~30 akcji w `ShopProductController`
- NEW - migracja modulu `ShopProduct` (factory) — pelna migracja ~40 metod do `ProductRepository` + ~30 akcji w `ShopProductController`
- NEW - migracja modulu `Dashboard` do Domain + DI (`DashboardRepository`, `DashboardController`)
- NEW - migracja modulu `Update` do Domain + DI (`UpdateRepository`, `UpdateController`)
- UPDATE - klasa `admin\Site` przemianowana na `admin\App` (plik `App.php`)
- UPDATE - refaktoring routingu — usunieto fallback na stare kontrolery, uproszczony routing
- UPDATE - template `update/main-view.php` — panele zamiast `gridEdit`, `$.confirm()` zamiast `$.prompt()`
- UPDATE - refaktoring routingu — usunieto fallback na stare kontrolery, uproszczony routing
- UPDATE - template `update/main-view.php` — panele zamiast `gridEdit`, `$.confirm()` zamiast `$.prompt()`
- CLEANUP - usuniete stare foldery: `autoload/admin/controls/`, `autoload/admin/factory/`, `autoload/admin/view/`
- CLEANUP - usuniete legacy: `class.Dashboard.php` (controls/shop), `class.Update.php` (controls/factory/view), `class.Articles.php` (factory), `class.Page.php` (view), `class.ShopProduct.php` (controls/factory/view)
- UPDATE - `front\factory\Newsletter` przepieta na `ArticleRepository::articlesByDateAdd()`
@@ -336,12 +342,12 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
- UPDATE - pliki aktualizacji: `updates/0.20/ver_0.268.zip`, `ver_0.268_files.txt`
<hr>
<b>ver. 0.267 - 13.02.2026</b><br />
- FIX - front: poprawione dobieranie layoutu dla kategorii/produktu/koszyka i innych stron moduÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡owych (fallback do layoutu domyÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşlnego)
- FIX - produkt/koszyk: poprawiona obsÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡uga iloÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşci dla kombinacji (stan 0 po dodaniu do koszyka, limit max, odczyt `stock_0_buy`)
- FIX - produkt: usuniÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â‚¬ĹľÄ‹Ă˜ty bÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æd JS `TypeError: $(...).visible is not a function` (zamiana na `:visible`)
- FIX - SEO redirecty produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw: blokada konfliktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw po kopiowaniu URL oraz utwardzone wykrywanie pÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â‚¬ĹľÄ‹Ă˜tli redirectÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw (`lang_id` + graf przejÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚˘â‚¬Ë‡)
- UPDATE - admin: `input-switch` zapisuje wartoÄ‚ââ¬ĹľÄ„…›Ä‡ `on` (spÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šjnie z obsÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡ugÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æ pÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šl checkbox w formularzach)
- CLEANUP - usuniÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â‚¬ĹľĂ‹Ă˜te pliki: `apilo-bck`, `geocode-cache.php`
- FIX - front: poprawione dobieranie layoutu dla kategorii/produktu/koszyka i innych stron moduÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€Çowych (fallback do layoutu domyÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźlnego)
- FIX - produkt/koszyk: poprawiona obsÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€Çuga iloÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźci dla kombinacji (stan 0 po dodaniu do koszyka, limit max, odczyt `stock_0_buy`)
- FIX - produkt: usuniÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…Ä‚ââ¬ĹˇÄ‚Ă˜ty bÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€ÇĄââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĄââ¬ĹˇÄ˘â‚¬ĹˇÄ‚ââ¬ĹˇÄ‚æd JS `TypeError: $(...).visible is not a function` (zamiana na `:visible`)
- FIX - SEO redirecty produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w: blokada konfliktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w po kopiowaniu URL oraz utwardzone wykrywanie pÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…Ä‚ââ¬ĹˇÄ‚Ă˜tli redirectÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w (`lang_id` + graf przejÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĄââ¬ĹˇÄ˘â‚¬Ä…‡)
- UPDATE - admin: `input-switch` zapisuje wartoÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚„…›Ä‡ `on` (spÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡jnie z obsÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€ÇugÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĄââ¬ĹˇÄ˘â‚¬ĹˇÄ‚ââ¬ĹˇÄ‚æ pÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡l checkbox w formularzach)
- CLEANUP - usuniÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â€šÂ¬ÄąË‡Ă„‚˘â‚¬ĹľÄ‚˘â€žËÂÂĂ˜te pliki: `apilo-bck`, `geocode-cache.php`
- UPDATE - testy: `OK (235 tests, 682 assertions)`
- UPDATE - pliki aktualizacji: `updates/0.20/ver_0.267.zip`, `ver_0.267_files.txt`, `ver_0.267_sql.txt`
<hr>
@@ -423,7 +429,7 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
<b>ver. 0.257 - 12.02.2026</b><br />
- NEW - migracja modulu `Newsletter` do architektury Domain + DI (`Domain\Newsletter\NewsletterRepository`, `Domain\Newsletter\NewsletterPreviewRenderer`, `admin\Controllers\NewsletterController`)
- UPDATE - widoki `/admin/newsletter/*` przepiete z legacy `grid/gridEdit` na nowe komponenty (`components/table-list`, `components/form-edit`) + nowy endpoint `/admin/newsletter/preview/`
- UPDATE - routing DI (`admin\Site`) rozszerzony o moduÄ‚ââ¬ĹľÄ„…‚ `Newsletter`
- UPDATE - routing DI (`admin\Site`) rozszerzony o moduÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚„…‚ `Newsletter`
- UPDATE - `admin\factory\Newsletter` dziala jako fasada do nowego repozytorium (backward compatibility)
- UPDATE - `front\factory\Newsletter` nie korzysta juz z `admin\view\Newsletter`
- CLEANUP - usuniete legacy klasy `autoload/admin/controls/class.Newsletter.php`, `autoload/admin/view/class.Newsletter.php`
@@ -447,7 +453,7 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
- UPDATE - migracja widokow languages (`languages-list`, `language-edit`, `translations-list`, `translation-edit`) na `components/table-list` i `components/form-edit`
- UPDATE - routing DI dla `Languages` w `admin\Site` oraz kompatybilna fasada `admin\factory\Languages` delegujaca do repozytorium
- UPDATE - naprawiono zapis edycji jezyka (ID jezyka pobierane z URL przy edycji)
- UPDATE - globalne poprawki UX filtrÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw w `components/table-list` (kompaktowe kolumny `Aktywny`/`Domyslny`, spacing i pelna szerokosc selecta)
- UPDATE - globalne poprawki UX filtrÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw w `components/table-list` (kompaktowe kolumny `Aktywny`/`Domyslny`, spacing i pelna szerokosc selecta)
- CLEANUP - usuniete legacy klasy: `autoload/admin/controls/class.Languages.php`, `autoload/admin/view/class.Languages.php`
<hr>
<b>ver. 0.253 - 12.02.2026</b><br />
@@ -516,78 +522,78 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
- UPDATE - refaktoryzacja: article_save przeniesiony do Domain\Article\ArticleRepository::save() z prywatnymi helperami
- UPDATE - refaktoryzacja: article_delete przeniesiony do Domain\Article\ArticleRepository::archive()
- UPDATE - ArticlesController: nowe akcje save() i delete() z DI
- UPDATE - admin\factory\Articles::article_save() i articles_set_archive() delegujÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ă‚¦ do repozytorium (kompatybilnoÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚˘â‚¬Ë‡)
- UPDATE - admin\factory\Articles::article_save() i articles_set_archive() delegujÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąË‡Ă„‚˘â‚¬ĹľÄ‚˘â‚¬Â¦ do repozytorium (kompatybilnoÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĄââ¬ĹˇÄ˘â‚¬Ä…‡)
<hr>
<b>ver. 0.243</b><br />
- UPDATE - refaktoryzacja: cleanup nieprzypisanych plikÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw/zdjÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â‚¬ĹľÄ‹Ă˜Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‹ââ¬Ë‡ artykuÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw przeniesiony do Domain\Article\ArticleRepository
- UPDATE - ArticlesController::edit() uÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬ĹľÄ‹ĹĄywa repozytorium do cleanupu, a admin\factory\Articles zachowuje delegowanie (kompatybilnoÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚˘â‚¬Ë‡)
- UPDATE - refaktoryzacja: cleanup nieprzypisanych plikÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w/zdjÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…Ä‚ââ¬ĹˇÄ‚Ă˜Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĄââ¬ĹˇÄ˘â‚¬Ä…Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‹ââ¬Ë‡ artykuÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€ÇĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w przeniesiony do Domain\Article\ArticleRepository
- UPDATE - ArticlesController::edit() uÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…ĄąĄââ¬Ĺľywa repozytorium do cleanupu, a admin\factory\Articles zachowuje delegowanie (kompatybilnoÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĄââ¬ĹˇÄ˘â‚¬Ä…‡)
<hr>
<b>ver. 0.242</b><br />
- NEW - refaktoryzacja: Domain\Article\ArticleRepository + migracja article_edit do admin\Controllers\ArticlesController (DI)
- UPDATE - admin\factory\Articles::article_details() deleguje do nowego repozytorium (kompatybilnoÄ‚ââ¬ĹľÄ„…›Ä‡ zachowana)
- UPDATE - metody przejÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â‚¬ĹľĂ‹Ă˜te przez nowe kontrolery oznaczone jako @deprecated w legacy kontrolerach admin\controls
- UPDATE - admin\factory\Articles::article_details() deleguje do nowego repozytorium (kompatybilnoÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚„…›Ä‡ zachowana)
- UPDATE - metody przejÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â€šÂ¬ÄąË‡Ă„‚˘â‚¬ĹľÄ‚˘â€žËÂÂĂ˜te przez nowe kontrolery oznaczone jako @deprecated w legacy kontrolerach admin\controls
<hr>
<b>ver. 0.241</b><br />
- NEW - refaktoryzacja: admin\Controllers\ProductArchiveController - archiwum produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw z DI
- NEW - refaktoryzacja: admin\Controllers\ProductArchiveController - archiwum produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw z DI
- NEW - ProductRepository::archive(), unarchive() - operacje archiwizacji w repozytorium
- FIX - naprawiono SQL w liÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşcie archiwum (puste wyszukiwanie filtrowaÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡o wszystkie wyniki)
- FIX - naprawiono brakujÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æcy filtr archive = 1 w zapytaniu bez wyszukiwania
- UPDATE - wyczyszczono szablony archiwum (usuniÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â‚¬ĹľÄ‹Ă˜to zbÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â‚¬ĹľÄ‹Ă˜dne funkcje: apilo, baselinker, duplikowanie)
- FIX - naprawiono SQL w liÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźcie archiwum (puste wyszukiwanie filtrowaÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€Ço wszystkie wyniki)
- FIX - naprawiono brakujÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąË‡Ă„‚˘â‚¬ĹľÄ‚˘â‚¬ÂÂĂæcy filtr archive = 1 w zapytaniu bez wyszukiwania
- UPDATE - wyczyszczono szablony archiwum (usuniÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…Ä‚ââ¬ĹˇÄ‚Ă˜to zbÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…Ä‚ââ¬ĹˇÄ‚Ă˜dne funkcje: apilo, baselinker, duplikowanie)
<hr>
<b>ver. 0.240</b><br />
- NEW - refaktoryzacja: Domain\Settings\SettingsRepository + admin\Controllers\SettingsController (architektura Domain-Driven)
- NEW - refaktoryzacja: Domain\Cache\CacheRepository - czyszczenie cache z obsÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡ugÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ă‚¦ Redis
- FIX - komunikat potwierdzenia zapisu ustawieÄ‚ââ¬ĹľÄ„…„ w panelu administratora
- NEW - refaktoryzacja: Domain\Cache\CacheRepository - czyszczenie cache z obsÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€ÇugÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĄââ¬ĹˇÄ˘â‚¬ĹˇÄ‚ââ¬ĹˇÄ‚‚¦ Redis
- FIX - komunikat potwierdzenia zapisu ustawieÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚„…„ w panelu administratora
- FIX - naprawiono element #content w layoucie admina (powiadomienia grid.js)
<hr>
<b>ver. 0.239</b><br />
- NEW - refaktoryzacja: Domain\Banner\BannerRepository + admin\Controllers\BannerController (peÄ‚ââ¬ĹľÄ„…â€ĹÇna migracja kontrolera)
- NEW - refaktoryzacja: Domain\Banner\BannerRepository + admin\Controllers\BannerController (peÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚„…â€ĹËâ€Ă‡na migracja kontrolera)
- NEW - refaktoryzacja: Domain\Product\ProductRepository::getPrice(), getName() - migracja kolejnych metod
- NEW - router admin z obsÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡ugÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æ nowych kontrolerÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw (fallback na stare)
- UPDATE - shop\Product::get_product_price(), get_product_name() uÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬ĹľÄ‹ĹĄywajÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æ nowego repozytorium (kompatybilnoÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚˘â‚¬Ë‡ zachowana)
- NEW - router admin z obsÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€ÇugÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĄââ¬ĹˇÄ˘â‚¬ĹˇÄ‚ââ¬ĹˇÄ‚æ nowych kontrolerÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w (fallback na stare)
- UPDATE - shop\Product::get_product_price(), get_product_name() uÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…ĄąĄââ¬ĹľywajÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĄââ¬ĹˇÄ˘â‚¬ĹˇÄ‚ââ¬ĹˇÄ‚æ nowego repozytorium (kompatybilnoÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĄââ¬ĹˇÄ˘â‚¬Ä…‡ zachowana)
<hr>
<b>ver. 0.238</b><br />
- NEW - refaktoryzacja: Domain\Product\ProductRepository - pierwsza klasa w nowej architekturze Domain-Driven
- NEW - Dependency Injection zamiast global variables
- UPDATE - shop\Product::get_product_quantity() uÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬ĹľÄ‹ĹĄywa teraz nowego repozytorium (kompatybilnoÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚˘â‚¬Ë‡ zachowana)
- UPDATE - shop\Product::get_product_quantity() uÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…ĄąĄââ¬Ĺľywa teraz nowego repozytorium (kompatybilnoÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĄââ¬ĹˇÄ˘â‚¬Ä…‡ zachowana)
<hr>
<b>ver. 0.237</b><br />
- NEW - automatyczne czyszczenie cache produktu po aktualizacji przez CRON (Sellasist, Apilo, Baselinker)
- UPDATE - przycisk "WyczyÄ‚ââ¬ĹľÄ„…›Ä‡ cache" w panelu administratora z obsÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡ugÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æ AJAX i komunikatami o postÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â‚¬ĹľÄ‹Ă˜pie
- UPDATE - przycisk "WyczyÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚„…›Ä‡ cache" w panelu administratora z obsÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€ÇugÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĄââ¬ĹˇÄ˘â‚¬ĹˇÄ‚ââ¬ĹˇÄ‚æ AJAX i komunikatami o postÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…Ä‚ââ¬ĹˇÄ‚Ă˜pie
<hr>
<b>ver. 0.236</b><br />
- FIX - zabezpieczenie przed duplikatami zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šwieÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľ w Apilo - automatyczne pobieranie ID zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šwienia przy bÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â‚¬ĹľÄ‹Ă˜dzie "idExternal juÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬ĹľÄ‹ĹĄ wykorzystywany"
- FIX - zabezpieczenie przed duplikatami zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡wieÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬ĹľÄ„Äľ w Apilo - automatyczne pobieranie ID zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡wienia przy bÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€ÇĄââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…Ä‚ââ¬ĹˇÄ‚Ă˜dzie "idExternal juÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…ĄąĄââ¬Ĺľ wykorzystywany"
<hr>
<b>ver. 0.235</b><br />
- FIX - poprawka funkcji aktualizacji
<hr>
<b>ver. 0.234</b><br />
- NEW - przycisk zaznaczania zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šwienia jako wysÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡ane do trustmate.io
- NEW - przycisk zaznaczania zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡wienia jako wysÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€Çane do trustmate.io
<hr>
<b>ver. 0.232</b><br />
- NEW - opcje GPSR
<hr>
<b>ver. 0.231</b><br />
- FIX - poprawki bezpieczeÄ‚ââ¬ĹľÄ„…„stwa + dwuetapowa weryfikacja logowania
- FIX - poprawki bezpieczeÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚„…„stwa + dwuetapowa weryfikacja logowania
<hr>
<b>ver. 0.230</b><br />
- FIX - poprawki bezpieczeÄ‚ââ¬ĹľÄ„…„stwa
- FIX - poprawki bezpieczeÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚„…„stwa
<hr>
<b>ver. 0.229</b><br />
- NEW - pola dodatkowe z opcjÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æ wymagane/niewymagane
- NEW - pola dodatkowe z opcjÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąË‡Ă„‚˘â‚¬ĹľÄ‚˘â‚¬Â¦ wymagane/niewymagane
<hr>
<b>ver. 0.228</b><br />
- NEW - cron do wysyÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡ania zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šwieÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľ do trustmate.io
- NEW - cron do wysyÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€Çania zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡wieÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬ĹľÄ„Äľ do trustmate.io
<hr>
<b>ver. 0.227</b><br />
- NEW - historia kodÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw rabatowych
- NEW - historia kodÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw rabatowych
<hr>
<b>ver. 0.226</b><br />
- NEW - dodanie opcji faktury do zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šwienia
- NEW - dodanie opcji faktury do zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šwienia
<hr>
<b>ver. 0.225</b><br />
- NEW - przycisk czyszczenia cache
- NEW - ponowne wysyÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡anie zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šwienia do apilo
- NEW - ponowne wysyÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€Çanie zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡wienia do apilo
<hr>
<b>ver. 0.224</b><br />
- NEW - sortowanie form dostawy
@@ -599,20 +605,20 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
- NEW - integracja z Orlen Paczka
<hr>
<b>ver. 0.221</b><br />
- NEW - Automatyczne przekierowania adresÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw URL produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw, zmiany w pliku htaccess
- NEW - Automatyczne przekierowania adresÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w URL produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w, zmiany w pliku htaccess
<hr>
<b>ver. 0.220</b><br />
- NEW - Dodanie moÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬ĹľÄ‹ĹĄliwoÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşci wyÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşwietlenia na strone ostatnio dodane produkty [PRODUKTY_NEW] lub [PRODUKTY_NEW:10].
- NEW - Dodanie moÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬ĹľÄ‹ĹĄliwoÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşci wyÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşwietlenia na strone popularnych produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw [PRODUKTY_TOP] lub [PRODUKTY_TOP:10].
- NEW - Dodanie moÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…ĄąĄââ¬ĹľliwoÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźci wyÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźwietlenia na strone ostatnio dodane produkty [PRODUKTY_NEW] lub [PRODUKTY_NEW:10].
- NEW - Dodanie moÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…ĄąĄââ¬ĹľliwoÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźci wyÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźwietlenia na strone popularnych produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w [PRODUKTY_TOP] lub [PRODUKTY_TOP:10].
<hr>
<b>ver. 0.219</b><br />
- NEW - Dodanie moÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬ĹľÄ‹ĹĄliwoÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşci zmiany daty w artykuÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡ach
- NEW - Dodanie moÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…ĄąĄââ¬ĹľliwoÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźci zmiany daty w artykuÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€Çach
<hr>
<b>ver. 0.218</b><br />
- NEW - indywidualny kod GTM
<hr>
<b>ver. 0.217</b><br />
- NEW - zwiÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â‚¬ĹľÄ‹Ă˜kszenie obsÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡ugi REDIS
- NEW - zwiÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…Ä‚ââ¬ĹˇÄ‚Ă˜kszenie obsÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€Çugi REDIS
<hr>
<b>ver. 0.216</b><br />
- NEW - aktualizacja api i cron (apilo)
@@ -627,43 +633,43 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
- FIX - wyliczenie darmowej dostawy
<hr>
<b>ver. 0.212</b><br />
- NEW - zmiany w zapisywaniu zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šwienia do apilo
- NEW - zmiany w zapisywaniu zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šwienia do apilo
<hr>
<b>ver. 0.211</b><br />
- NEW - Debugowanie apilo + wyÄ‚ââ¬ĹľÄ„…›wietlanie podkategorii
- NEW - Debugowanie apilo + wyÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚„…›wietlanie podkategorii
<hr>
<b>ver. 0.210</b><br />
- NEW - dodatkowe pola w widoku produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw
- NEW - dodatkowe pola w widoku produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw
<hr>
<b>ver. 0.209</b><br />
- NEW - zmiany w widoku produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw (panel administratora)
- NEW - zmiany w widoku produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw (panel administratora)
<hr>
<b>ver. 0.208</b><br />
- NEW - zmiany w wyszukiwarce produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw
- NEW - zmiany w wyszukiwarce produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw
<hr>
<b>ver. 0.204-0.207</b><br />
- NEW - htaccess update
<hr>
<b>ver. 0.204-0.206</b><br />
- NEW - wysyÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡anie produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw do apilo
- NEW - wysyÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€Çanie produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w do apilo
<hr>
<b>ver. 0.203</b><br />
- NEW - zmiana sposobu wyliczania cen produkty z dodatkami
<hr>
<b>ver. 0.202</b><br />
- NEW - dodano "gÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šwne zdjÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â‚¬ĹľÄ‹Ă˜cie" w edycji artykuÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡u
- NEW - dodano "gÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€ÇĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡wne zdjÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…Ä‚ââ¬ĹˇÄ‚Ă˜cie" w edycji artykuÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€Çu
<hr>
<b>ver. 0.201</b><br />
- FIX - aktualizacja statusÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw na podstawie baselinkera
- FIX - aktualizacja statusÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw na podstawie baselinkera
<hr>
<b>ver. 0.200</b><br />
- NEW - wysyÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡anie produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw do baselinker
- NEW - wysyÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€Çanie produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w do baselinker
<hr>
<b>ver. 0.199</b><br />
- NEW - usprawnienie edycji danych do XML
<hr>
<b>ver. 0.198</b><br />
- NEW - automatyczne generowanie kodÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw SKU
- NEW - automatyczne generowanie kodÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw SKU
<hr>
<b>ver. 0.197</b><br />
- FIX - poprawki w Dashboard
@@ -672,7 +678,7 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
- FIX - integracja z apilo.com
<hr>
<b>ver. 0.195</b><br />
- FIX - aktualizacja statusÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw
- FIX - aktualizacja statusÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw
<hr>
<b>ver. 0.194</b><br />
- UPDATE - integracja apilo
@@ -681,46 +687,46 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
- UPDATE - aktualizacja synchronizacji z baselinker
<hr>
<b>ver. 0.192</b><br />
- NEW - pobieranie statusÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw z sellasist
- NEW - pobieranie statusÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw z sellasist
<hr>
<b>ver. 0.191</b><br />
- NEW - integracja z selasist
<hr>
<b>ver. 0.190</b><br />
- FIX - produkty powiÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æzane
- FIX - produkty powiÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąË‡Ă„‚˘â‚¬ĹľÄ‚˘â‚¬ÂÂĂæzane
<hr>
<b>ver. 0.189</b><br />
- FIX - ceny promocyjne produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw z dodatkiem
- FIX - ceny promocyjne produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw z dodatkiem
<hr>
<b>ver. 0.188</b><br />
- NEW - widok listy produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw
- NEW - widok listy produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw
<hr>
<b>ver. 0.187</b><br />
- FIX - pobieranie cen z APILO
<hr>
<b>ver. 0.186</b><br />
- FIX - dodawanie do koszyka tych samych produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw ale z rÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬ĹľÄ‹ĹĄnÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æ personalizacjÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ă‚¦
- FIX - dodawanie do koszyka tych samych produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w ale z rÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ă„‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…ĄąĄââ¬ĹľnÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĄââ¬ĹˇÄ˘â‚¬ĹˇÄ‚ââ¬ĹˇÄ‚æ personalizacjÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĄââ¬ĹˇÄ˘â‚¬ĹˇÄ‚ââ¬ĹˇÄ‚‚¦
<hr>
<b>ver. 0.185</b><br />
- FIX - masowa edycja produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw
- FIX - masowa edycja produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw
<hr>
<b>ver. 0.184</b><br />
- NEW - druga czÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â‚¬ĹľĂ‹Â˜Ä‚„ąâ€şĂ„‡ integracji z apilo, masowa edycja produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw
- NEW - druga czÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â€šÂ¬ÄąË‡Ă„‚˘â‚¬ĹľÄ‚˘â€žË˜Ă„ąâ€şĂ„‡ integracji z apilo, masowa edycja produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w
<hr>
<b>ver. 0.183</b><br />
- NEW - pierwsza czÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â‚¬ĹľĂ‹Â˜Ä‚„ąâ€şĂ„‡ integracji z apilo
- NEW - pierwsza czÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â€šÂ¬ÄąË‡Ă„‚˘â‚¬ĹľÄ‚˘â€žË˜Ă„ąâ€şĂ„‡ integracji z apilo
<hr>
<b>ver. 0.182</b><br />
- FIX - layout
<hr>
<b>ver. 0.181</b><br />
- NEW - infinitescroll - opcja wÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æczy/wyÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æcz
- NEW - infinitescroll - opcja wÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€ÇĄââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĄââ¬ĹˇÄ˘â‚¬ĹˇÄ‚ââ¬ĹˇÄ‚æczy/wyÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€ÇĄââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĄââ¬ĹˇÄ˘â‚¬ĹˇÄ‚ââ¬ĹˇÄ‚æcz
<hr>
<b>ver. 0.180</b><br />
- NEW - aktualizacja dashboard
<hr>
<b>ver. 0.179</b><br />
- NEW - obsÄ‚ââ¬ĹľÄ„…â€ĹÇuga EAN
- NEW - obsÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚„…â€ĹËâ€Ă‡uga EAN
<hr>
<b>ver. 0.177, 0.178</b><br />
- FIX - custom_label
@@ -736,7 +742,7 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
<hr>
<b>ver. 0.173</b><br />
- NEW - duplikowanie produktu wraz z kombinacjami
- NEW - dodanie przechodzenia pomiÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â‚¬ĹľÄ‹Ă˜dzy zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šwienia (poprzednie/nastÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â‚¬ĹľÄ‹Ă˜pne zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šwienie)
- NEW - dodanie przechodzenia pomiÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…Ä‚ââ¬ĹˇÄ‚Ă˜dzy zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡wienia (poprzednie/nastÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ľĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä„ÄľÄ„ââ¬ĹˇÄ˘â‚¬Ä…Ä‚ââ¬ĹˇÄ‚Ă˜pne zamÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡wienie)
<hr>
<b>ver. 0.172</b><br />
- FIX - poprawki w Cache
@@ -748,22 +754,22 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
- NEW - usuwanie cache produktu przy zapisie
<hr>
<b>ver. 0.169</b><br />
- FIX - poprawki w liÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşcie produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw
- FIX - poprawki w liÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźcie produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w
<hr>
<b>ver. 0.168</b><br />
- NEW - archiwum produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw
- NEW - archiwum produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw
<hr>
<b>ver. 0.167</b><br />
- NEW - dodanie obsÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡ugi cen i stanÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw magazynowych kombinacji produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw
- NEW - dodanie obsÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ă„‚ââ¬Ä…Ģ€Çugi cen i stanÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w magazynowych kombinacji produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w
<hr>
<b>ver. 0.166</b><br />
- NEW - wspÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šĂ„Ä…ĂĂ˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡praca z GTM
- NEW - wspÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľĂ„‚˘â‚¬ĹˇĂ„ąâ€šĂ„ąâ€ĹËâ€Ă‡praca z GTM
<hr>
<b>ver. 0.164/5</b><br />
- FIX - ukrywanie produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw nieaktywnych
- FIX - ukrywanie produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw nieaktywnych
<hr>
<b>ver. 0.163</b><br />
- NEW - automatyczne podpowiadanie produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw do zestawu na podstawie wczeÄ‚ââ¬ĹľÄ„ââ¬Â¦Ă„‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĹşniejszych zakupÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw klientÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ„ąĢ€šw
- NEW - automatyczne podpowiadanie produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w do zestawu na podstawie wczeÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬Ä‚æĂââ¬ĹľÄ˘â‚¬ĹˇÄ‚ââ¬Ä…Ä‚Ă˜Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąĂ‡Ä‚ââ¬ĹˇÄ‚ìĂââ¬ĹľÄ„ââ¬Â¦Ä„ąĹźniejszych zakupÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w klientÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚Ă˜Ä˘ââ¬ĹˇĂ¬ÄąÄľÄ„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡Ä„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚ââ¬ĹľÄ˘â‚¬Ă¦Ä„ââ¬ĹˇÄ‹Ă˜Ä‚Ă˜Ä˘â‚¬ĹˇÄ‚Ă¬Ä„Ä…Ä‹ââ¬Ë‡w
<hr>
<b>ver. 0.162</b><br />
- NEW - GA4
@@ -779,7 +785,7 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
- FIX - cron Baselinker
<hr>
<b>ver. 0.158</b><br />
- UPDATE - poprawa kolorystyki przyciskÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw
- UPDATE - poprawa kolorystyki przyciskÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw
<hr>
<b>ver. 0.157</b><br />
- NEW - szybka zmiana statusu produktu
@@ -791,10 +797,10 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
- NEW - infinite scroll w widoku kategorii
<hr>
<b>ver. 0.154</b><br />
- FIX - atrybuty produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw
- FIX - atrybuty produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw
<hr>
<b>ver. 0.153</b><br />
- FIX - atrybuty produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw
- FIX - atrybuty produktÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw
<hr>
<b>ver. 0.152</b><br />
- FIX - tematy maili
@@ -803,7 +809,7 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
- FIX - tematy maili
<hr>
<b>ver. 0.150</b><br />
- NEW - domyÄ‚ââ¬ĹľÄ„…›lna forma transportu
- NEW - domyÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚„…›lna forma transportu
<hr>
<b>ver. 0.149</b><br />
- NEW - tematy maili
@@ -821,11 +827,11 @@ NEW - Ukrywalne filtry tabel, mobilna wersja szczegÄ‚ââ¬ĹľÄ
- NEW - omnibus ready
<hr>
<b>ver. 0.144</b><br />
- FIX - usuniÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â‚¬ĹľĂ‹Ă˜cie adresu marianek.pl z kodu
- FIX - usuniÄ„ââ¬ĹˇÄ˘â‚¬ĹľÄ‚Ă˜Ä˘â€šÂ¬ÄąË‡Ă„‚˘â‚¬ĹľÄ‚˘â€žËÂÂĂ˜cie adresu marianek.pl z kodu
<hr>
<b>ver. 0.143</b><br />
- FIX - poprawa generowania plikÄ‚ââ¬ĹľÄ˘â‚¬ĹˇĂ„ąâ€šw WEBP
- FIX - poprawa generowania plikÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚˘â‚¬ĹˇĂ„ąâ€šw WEBP
<hr>
<b>ver. 0.142</b><br />
- FIX - poprawa adresu strony gÄ‚ââ¬ĹľÄ„…‚Ăłwnej
- FIX - poprawa adresu strony gÄ‚ââ¬ĹľÄ˘â‚¬ĹˇÄ‚˘â‚¬ĹľÄ‚„…‚Ăłwnej
<hr>

View File

@@ -1,5 +1,5 @@
<?
$current_ver = 327;
$current_ver = 329;
for ($i = 1; $i <= $current_ver; $i++)
{