Files
shopPRO/autoload/Shared/Helpers/Helpers.php
Jacek Pyziak 8162df7356 ver. 0.286: Layouts, Menu, Pages frontend migration to Domain
- Add 6 frontend methods to LayoutsRepository (Redis cache, 3-level fallback)
- Add 6 frontend methods to PagesRepository (Redis cache, recursive pages)
- Create front\Views\Menu (clean VIEW replacing front\view\Menu)
- Delete front\factory\Layouts, Menu, Pages + front\view\Menu + dead submenu.php
- Fix null $lang_id TypeError in check_url_params() (remove string type hint + ?? '')
- Optimize Helpers::htacces() from 3 layout calls to 1
- Tests: 470 OK, 1484 assertions (+16 new)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 08:21:53 +01:00

961 lines
40 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace Shared\Helpers;
class Helpers
{
static function canAddRedirect( $from, $to, $lang_id = null )
{
global $mdb;
if ( !$from or !$to or $from === $to )
return false;
$where = [];
if ( null !== $lang_id )
$where['lang_id'] = $lang_id;
$redirects = $mdb -> select( 'pp_redirects', [ 'from', 'to' ], $where );
$redirectMap = [];
foreach ( $redirects as $redirect )
{
if ( !isset( $redirectMap[$redirect['from']] ) )
$redirectMap[$redirect['from']] = [];
if ( !in_array( $redirect['to'], $redirectMap[$redirect['from']], true ) )
$redirectMap[$redirect['from']][] = $redirect['to'];
}
if ( !isset( $redirectMap[$from] ) )
$redirectMap[$from] = [];
if ( !in_array( $to, $redirectMap[$from], true ) )
$redirectMap[$from][] = $to;
$visited = [];
$stack = [ $to ];
while ( !empty( $stack ) )
{
$current = array_pop( $stack );
if ( $current === $from )
return false;
if ( isset( $visited[$current] ) )
continue;
$visited[$current] = true;
if ( isset( $redirectMap[$current] ) )
{
foreach ( $redirectMap[$current] as $next )
if ( !isset( $visited[$next] ) )
$stack[] = $next;
}
}
return true;
}
static public function clear_product_cache( int $product_id )
{
if ( class_exists('Redis') )
{
try
{
$cacheHandler = new \Shared\Cache\CacheHandler();
// Wyczyść cache produktu dla wszystkich języków i permutacji
$cacheHandler -> deletePattern( "shop\\product:$product_id:*" );
// Wyczyść cache związane z opcjami ilościowymi
$cacheHandler -> deletePattern( "\\shop\\Product::get_product_permutation_quantity_options:$product_id:*" );
// Wyczyść cache zestawów produktów
$cacheHandler -> deletePattern( "\\shop\\Product::product_sets_when_add_to_basket:$product_id" );
}
catch (\Exception $e)
{
error_log("Błąd podczas czyszczenia cache produktu: " . $e->getMessage());
}
}
}
static public function remove_special_chars( $string ) {
return str_ireplace( array( '\'', '"', ',' , ';', '<', '>' ), ' ', $string );
}
static public function removeDuplicates( $array, $param ) {
$result = [];
foreach ($array as $key => $subArray) {
$idsSeen = [];
foreach ($subArray as $subKey => $item) {
if (!in_array($item[ $param ], $idsSeen)) {
$idsSeen[] = $item[ $param ];
$result[$key][] = $item;
}
}
}
return $result;
}
static public function generate_webp_image($file, $compression_quality = 85)
{
if ( strpos( $file, 'thumb/' ) !== false )
{
$file_tmp = explode( '/', $file );
$width = $file_tmp[1];
if ( empty( $width ) and $width !== '0' )
$width = 500;
$height = $file_tmp[2];
if ( empty( $height ) and $height !== '0' )
$height = 500;
for ( $i = 0; $i <= 2; $i++ )
unset( $file_tmp[$i] );
$img_src = implode( '/', $file_tmp );
$crop_w = $_GET['c_w'];
$crop_h = $_GET['c_h'];
$img_md5 = md5( $img_src . $height . $width . $crop_h . $crop_w );
$file = 'thumbs/' . $img_md5[0] . '/' . $img_md5[1] . '/' . $img_md5[2] . '/' . $img_md5;
}
if ( !file_exists( $file ) )
return false;
$output_file = 'cache/' . $file . '.webp';
if ( file_exists( $output_file ) )
return $output_file;
$file_type = mime_content_type( $file );
if ( function_exists( 'imagewebp' ) )
{
switch ( $file_type )
{
case 'image/jpeg':
$image = imagecreatefromjpeg($file);
break;
case 'image/png':
$image = imagecreatefrompng($file);
imagepalettetotruecolor($image);
imagealphablending($image, true);
imagesavealpha($image, true);
break;
case 'image/gif':
$image = imagecreatefromgif($file);
break;
default:
return false;
}
$dir = dirname($output_file);
if (!is_dir($dir))
mkdir($dir, 0755, true);
$result = imagewebp($image, $output_file, $compression_quality);
if (false === $result)
return false;
imagedestroy($image);
return $output_file;
}
elseif (class_exists('Imagick'))
{
$dir = dirname($output_file);
if (!is_dir($dir))
mkdir($dir, 0755, true);
$image = new \Imagick();
$image->readImage($file);
if ($file_type === 'png')
{
$image->setImageFormat('webp');
$image->setImageCompressionQuality($compression_quality);
$image->setOption('webp:lossless', 'true');
}
$image->writeImage($output_file);
return $output_file;
}
return false;
}
public static function is_array_fix( $value )
{
if ( is_array( $value ) and count( $value ) )
return true;
return false;
}
public static function delete_cache()
{
self::delete_dir( '../cache/' );
self::delete_dir( '../temp/' );
self::delete_dir( '../cron/temp/' );
self::delete_dir( 'temp/' );
}
public static function pretty_date( $format, $timestamp = null )
{
$to_convert = array(
'l' => array( 'dat' => 'N', 'str' => array( 'Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota', 'Niedziela' ) ),
'F' => array( 'dat' => 'n', 'str' => array( 'styczeń', 'luty', 'marzec', 'kwiecień', 'maj', 'czerwiec', 'lipiec', 'sierpień', 'wrzesień', 'październik', 'listopad', 'grudzień' ) ),
'f' => array( 'dat' => 'n', 'str' => array( 'stycznia', 'lutego', 'marca', 'kwietnia', 'maja', 'czerwca', 'lipca', 'sierpnia', 'września', 'października', 'listopada', 'grudnia' ) )
);
if ( $pieces = preg_split( '#[:/.\-, ]#', $format ) )
{
if ( $timestamp === null )
$timestamp = time();
foreach ( $pieces as $datepart )
{
if ( array_key_exists( $datepart, $to_convert ) )
$replace[] = $to_convert[$datepart]['str'][( date( $to_convert[$datepart]['dat'], $timestamp ) - 1)];
else
$replace[] = date( $datepart, $timestamp );
}
$result = strtr( $format, array_combine( $pieces, $replace ) );
return $result;
}
}
public static function lang( $text )
{
global $lang;
return $lang[$text] ? $lang[$text] : 'LANG-' . $text;
}
public static function array_cartesian_product( $input )
{
$result = array();
foreach ($input as $key => $values)
{
if ( empty( $values ) )
continue;
if ( empty( $result ) )
{
foreach ( $values as $value )
{
$result[] = array( $key => $value );
}
}
else
{
$append = array();
foreach ( $result as &$product )
{
$product[$key] = array_shift( $values );
$copy = $product;
foreach ( $values as $item )
{
$copy[$key] = $item;
$append[] = $copy;
}
array_unshift( $values, $product[$key] );
}
$result = array_merge( $result, $append );
}
}
return $result;
}
static public function normalize_decimal($val, int $precision = 2)
{
if ($val === null || $val === '') {
return number_format(0, $precision, '.', '');
}
// 1) wstępne czyszczenie
$s = (string)$val;
$s = str_replace(["\xC2\xA0", ' ', '', "'"], '', $s); // spacje (w tym NBSP) i apostrofy
$s = preg_replace('/[^0-9.,\-]/', '', $s); // zostaw tylko cyfry, . , i -
// 2) ustalenie separatora dziesiętnego
$lastDot = strrpos($s, '.');
$lastComma = strrpos($s, ',');
if ($lastDot !== false && $lastComma !== false) {
// oba występują prawy znak traktujemy jako dziesiętny
if ($lastDot > $lastComma) {
$s = str_replace(',', '', $s); // , = tysiące
} else {
$s = str_replace('.', '', $s); // . = tysiące
$s = str_replace(',', '.', $s); // , = dziesiętny
}
} elseif ($lastComma !== false) {
// tylko przecinek traktuj jako dziesiętny
$s = str_replace(',', '.', $s);
} elseif (substr_count($s, '.') > 1) {
// wiele kropek ostatnia dziesiętna, pozostałe tysiące
$pos = strrpos($s, '.');
$s = str_replace('.', '', substr($s, 0, $pos)) . '.' . substr($s, $pos + 1);
}
// na tym etapie mamy opcjonalny '-' i co najwyżej jedną kropkę dziesiętną
// 3) zaokrąglenie i normalizacja
$rounded = round((float)$s, $precision);
return number_format($rounded, $precision, '.', '');
}
public static function decimal( $val, $precision = 2, $dec_point = ',', $thousands_sep = ' ' )
{
return number_format( $val, $precision, $dec_point, $thousands_sep );
}
public static function get_new_version()
{
global $settings;
if ( $version = self::get_session( 'new-version' ) )
return $version;
$version = 0;
$versions = file_get_contents( 'https://shoppro.project-dc.pl/updates/versions.php?key=' . $settings['update_key'] );
$versions = explode( PHP_EOL, $versions );
foreach ( $versions as $key => $version_tmp )
{
$version_tmp = floatval( $version_tmp );
if ( $version_tmp > $version and $version_tmp )
$version = $version_tmp;
}
self::set_session( 'new-version', $version );
return $version;
}
public static function get_version()
{
return (float) @file_get_contents( '../libraries/version.ini' );
}
public static function set_session( $var, $val )
{
$_SESSION[$var] = $val;
}
public static function get_session( $var )
{
return $_SESSION[$var];
}
public static function delete_session( $var )
{
unset( $_SESSION[$var] );
}
public static function get( $var, $clear = false )
{
if ( isset( $_POST[$var] ) )
{
if ( is_string( $_POST[$var] ) )
{
$value = $_POST[$var];
if ( $clear )
{
$value = strip_tags( $value );
$value = preg_replace( '/[\'\"\\\\]/i', '', $value );
}
return trim( $value );
}
else
return $_POST[$var];
}
else
{
if ( isset( $_GET[$var] ) )
{
if ( is_string( $_GET[$var] ) )
return trim( $_GET[$var] );
else
return $_GET[$var];
}
}
}
public static function set_message( $text )
{
self::set_session( 'message', $text );
}
public static function alert( $text )
{
self::set_session( 'alert', $text );
}
public static function error( $text )
{
self::set_session( 'error', $text );
}
public static function htacces( $dir = '../' )
{
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;
$htaccess_data = file_get_contents( $dir . 'libraries/htaccess.conf' );
$htaccess_data = str_replace( '{PAGE}', $url, $htaccess_data );
$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]';
}
//
// 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
//
$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 ] );
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;
}
$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;
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]';
}
}
}
}
$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'] )
{
$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 ] );
}
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 ] );
}
}
}
}
}
}
$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]';
}
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]';
}
}
}
$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;
}
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]';
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]';
}
}
$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>';
/* 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' );
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 );
}
public static function seo( $val, $delete_rhombs = false )
{
$array_rep1 = array('*', '_', ' ', '+', '"', "'", '?', '-', ',', '!', '~', '<', '>', '@', '#', '$', '%', '^', '&', '*' . '(', ')' . '-', '=', '\\', '|', '[', ']', ':', '(', ')');
$array_rep2 = array('-', '-', '-', '-', '', '', '', '-', '-', '', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '', '-', '-', '-', '-', '-', '-', '-', '-');
$val = self::noPl($val);
$val = str_replace($array_rep1, $array_rep2, $val);
if ($delete_rhombs)
$val = str_replace('/', '', $val);
$val = strtolower($val);
$val = preg_replace('/(-){2,}/', '-', $val);
$val = ltrim($val, '-');
$val = rtrim($val, '-');
return $val;
}
public static function noPL($string)
{
$chars = array( // Decompositions for Latin-1 Supplement chr(195).chr(128)=> 'A', chr(195).chr(129) => 'A',
chr(195) . chr(130) => 'A', chr(195) . chr(131) => 'A',
chr(195) . chr(132) => 'A', chr(195) . chr(133) => 'A',
chr(195) . chr(135) => 'C', chr(195) . chr(136) => 'E',
chr(195) . chr(137) => 'E', chr(195) . chr(138) => 'E',
chr(195) . chr(139) => 'E', chr(195) . chr(140) => 'I',
chr(195) . chr(141) => 'I', chr(195) . chr(142) => 'I',
chr(195) . chr(143) => 'I', chr(195) . chr(145) => 'N',
chr(195) . chr(146) => 'O', chr(195) . chr(147) => 'O',
chr(195) . chr(148) => 'O', chr(195) . chr(149) => 'O',
chr(195) . chr(150) => 'O', chr(195) . chr(153) => 'U',
chr(195) . chr(154) => 'U', chr(195) . chr(155) => 'U',
chr(195) . chr(156) => 'U', chr(195) . chr(157) => 'Y',
chr(195) . chr(159) => 's', chr(195) . chr(160) => 'a',
chr(195) . chr(161) => 'a', chr(195) . chr(162) => 'a',
chr(195) . chr(163) => 'a', chr(195) . chr(164) => 'a',
chr(195) . chr(165) => 'a', chr(195) . chr(167) => 'c',
chr(195) . chr(168) => 'e', chr(195) . chr(169) => 'e',
chr(195) . chr(170) => 'e', chr(195) . chr(171) => 'e',
chr(195) . chr(172) => 'i', chr(195) . chr(173) => 'i',
chr(195) . chr(174) => 'i', chr(195) . chr(175) => 'i',
chr(195) . chr(177) => 'n', chr(195) . chr(178) => 'o',
chr(195) . chr(179) => 'o', chr(195) . chr(180) => 'o',
chr(195) . chr(181) => 'o', chr(195) . chr(182) => 'o',
chr(195) . chr(182) => 'o', chr(195) . chr(185) => 'u',
chr(195) . chr(186) => 'u', chr(195) . chr(187) => 'u',
chr(195) . chr(188) => 'u', chr(195) . chr(189) => 'y',
chr(195) . chr(191) => 'y',
// Decompositions for Latin Extended-A
chr(196) . chr(128) => 'A', chr(196) . chr(129) => 'a',
chr(196) . chr(130) => 'A', chr(196) . chr(131) => 'a',
chr(196) . chr(132) => 'A', chr(196) . chr(133) => 'a',
chr(196) . chr(134) => 'C', chr(196) . chr(135) => 'c',
chr(196) . chr(136) => 'C', chr(196) . chr(137) => 'c',
chr(196) . chr(138) => 'C', chr(196) . chr(139) => 'c',
chr(196) . chr(140) => 'C', chr(196) . chr(141) => 'c',
chr(196) . chr(142) => 'D', chr(196) . chr(143) => 'd',
chr(196) . chr(144) => 'D', chr(196) . chr(145) => 'd',
chr(196) . chr(146) => 'E', chr(196) . chr(147) => 'e',
chr(196) . chr(148) => 'E', chr(196) . chr(149) => 'e',
chr(196) . chr(150) => 'E', chr(196) . chr(151) => 'e',
chr(196) . chr(152) => 'E', chr(196) . chr(153) => 'e',
chr(196) . chr(154) => 'E', chr(196) . chr(155) => 'e',
chr(196) . chr(156) => 'G', chr(196) . chr(157) => 'g',
chr(196) . chr(158) => 'G', chr(196) . chr(159) => 'g',
chr(196) . chr(160) => 'G', chr(196) . chr(161) => 'g',
chr(196) . chr(162) => 'G', chr(196) . chr(163) => 'g',
chr(196) . chr(164) => 'H', chr(196) . chr(165) => 'h',
chr(196) . chr(166) => 'H', chr(196) . chr(167) => 'h',
chr(196) . chr(168) => 'I', chr(196) . chr(169) => 'i',
chr(196) . chr(170) => 'I', chr(196) . chr(171) => 'i',
chr(196) . chr(172) => 'I', chr(196) . chr(173) => 'i',
chr(196) . chr(174) => 'I', chr(196) . chr(175) => 'i',
chr(196) . chr(176) => 'I', chr(196) . chr(177) => 'i',
chr(196) . chr(178) => 'IJ', chr(196) . chr(179) => 'ij',
chr(196) . chr(180) => 'J', chr(196) . chr(181) => 'j',
chr(196) . chr(182) => 'K', chr(196) . chr(183) => 'k',
chr(196) . chr(184) => 'k', chr(196) . chr(185) => 'L',
chr(196) . chr(186) => 'l', chr(196) . chr(187) => 'L',
chr(196) . chr(188) => 'l', chr(196) . chr(189) => 'L',
chr(196) . chr(190) => 'l', chr(196) . chr(191) => 'L',
chr(197) . chr(128) => 'l', chr(197) . chr(129) => 'L',
chr(197) . chr(130) => 'l', chr(197) . chr(131) => 'N',
chr(197) . chr(132) => 'n', chr(197) . chr(133) => 'N',
chr(197) . chr(134) => 'n', chr(197) . chr(135) => 'N',
chr(197) . chr(136) => 'n', chr(197) . chr(137) => 'N',
chr(197) . chr(138) => 'n', chr(197) . chr(139) => 'N',
chr(197) . chr(140) => 'O', chr(197) . chr(141) => 'o',
chr(197) . chr(142) => 'O', chr(197) . chr(143) => 'o',
chr(197) . chr(144) => 'O', chr(197) . chr(145) => 'o',
chr(197) . chr(146) => 'OE', chr(197) . chr(147) => 'oe',
chr(197) . chr(148) => 'R', chr(197) . chr(149) => 'r',
chr(197) . chr(150) => 'R', chr(197) . chr(151) => 'r',
chr(197) . chr(152) => 'R', chr(197) . chr(153) => 'r',
chr(197) . chr(154) => 'S', chr(197) . chr(155) => 's',
chr(197) . chr(156) => 'S', chr(197) . chr(157) => 's',
chr(197) . chr(158) => 'S', chr(197) . chr(159) => 's',
chr(197) . chr(160) => 'S', chr(197) . chr(161) => 's',
chr(197) . chr(162) => 'T', chr(197) . chr(163) => 't',
chr(197) . chr(164) => 'T', chr(197) . chr(165) => 't',
chr(197) . chr(166) => 'T', chr(197) . chr(167) => 't',
chr(197) . chr(168) => 'U', chr(197) . chr(169) => 'u',
chr(197) . chr(170) => 'U', chr(197) . chr(171) => 'u',
chr(197) . chr(172) => 'U', chr(197) . chr(173) => 'u',
chr(197) . chr(174) => 'U', chr(197) . chr(175) => 'u',
chr(197) . chr(176) => 'U', chr(197) . chr(177) => 'u',
chr(197) . chr(178) => 'U', chr(197) . chr(179) => 'u',
chr(197) . chr(180) => 'W', chr(197) . chr(181) => 'w',
chr(197) . chr(182) => 'Y', chr(197) . chr(183) => 'y',
chr(197) . chr(184) => 'Y', chr(197) . chr(185) => 'Z',
chr(197) . chr(186) => 'z', chr(197) . chr(187) => 'Z',
chr(197) . chr(188) => 'z', chr(197) . chr(189) => 'Z',
chr(197) . chr(190) => 'z', chr(197) . chr(191) => 's'
);
$string = strtr($string, $chars);
$table = array(
"А" => "a", "Б" => "b", "В" => "v", "Г" => "g", "Д" => "d",
"Е" => "e", "Ё" => "yo", "Ж" => "zh", "З" => "z", "И" => "i",
"Й" => "j", "К" => "k", "Л" => "l", "М" => "m", "Н" => "n",
"О" => "o", "П" => "p", "Р" => "r", "С" => "s", "Т" => "t",
"У" => "u", "Ф" => "f", "Х" => "kh", "Ц" => "ts", "Ч" => "ch",
"Ш" => "sh", "Щ" => "sch", "Ъ" => "", "Ы" => "y", "Ь" => "",
"Э" => "e", "Ю" => "yu", "Я" => "ya", "а" => "a", "б" => "b",
"в" => "v", "г" => "g", "д" => "d", "е" => "e", "ё" => "yo",
"ж" => "zh", "з" => "z", "и" => "i", "й" => "j", "к" => "k",
"л" => "l", "м" => "m", "н" => "n", "о" => "o", "п" => "p",
"р" => "r", "с" => "s", "т" => "t", "у" => "u", "ф" => "f",
"х" => "kh", "ц" => "ts", "ч" => "ch", "ш" => "sh", "щ" => "sch",
"ъ" => "", "ы" => "y", "ь" => "", "э" => "e", "ю" => "yu",
"я" => "ya", " " => "-", "." => "", "," => "",
":" => "", ";" => "", "" => "", "" => "-"
);
$string = strtr($string, $table);
return $string;
}
public static function delete_dir( $dir )
{
if ( is_file( $dir ) )
return @unlink( $dir );
else if ( is_dir( $dir ) )
{
$scan = glob( rtrim( $dir, '/' ) . '/*' );
if ( is_array( $scan ) )
foreach ( $scan as $index => $path )
self::delete_dir( $path );
if ( is_dir( $dir ) && ( ( $files = @scandir( $dir ) ) && count( $files ) <= 2 ) )
return @rmdir( $dir );
}
}
public static function email_check( $email )
{
return filter_var( $email, FILTER_VALIDATE_EMAIL );
}
public static function send_email( $email, $subject, $text, $replay = '', $file = '' )
{
global $settings;
if ( self::email_check( $email ) and $subject )
{
$mail = new \PHPMailer();
$mail -> IsSMTP();
$mail -> SMTPAuth = true;
$mail -> Host = $settings['email_host'];
$mail -> Port = $settings['email_port'];
$mail -> Username = $settings['email_login'];
$mail -> Password = $settings['email_password'];
$mail -> CharSet = "UTF-8";
$mail -> SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
if ( self::email_check( $replay ) )
{
$mail -> AddReplyTo( $replay, $replay );
$mail -> SetFrom( $replay, $replay );
}
else
{
$mail -> AddReplyTo( $settings['contact_email'], $settings['firm_name'] );
$mail -> SetFrom( $settings['contact_email'], $settings['firm_name'] );
}
$mail -> AddAddress( $email, '' );
$mail -> Subject = $subject;
$mail -> Body = $text;
if ( is_array( $file ) )
{
foreach ( $file as $file_tmp )
{
if ( file_exists( $file_tmp ) )
$mail -> AddAttachment( $file_tmp );
}
}
else
{
if ( file_exists( $file ) )
$mail -> AddAttachment( $file );
}
$mail -> IsHTML( true );
return $mail -> Send();
}
return false;
}
}