cfg = Config::get(); $this->sectionTree = $sectionTree; } public function generate($params): string { $domainContext = ServiceContainer::getService(DomainContext::class); unset($params['name']); if (empty($params['absolute'])) { $SERVER_URL = $this->cfg['Addr']['rel']; } else { $SERVER_URL = "https://{$domainContext->getActiveId()}/"; } unset($params['absolute']); if (!array_key_exists('URL', $params)) { $params['URL'] = 'launch.php'; } $SEO_URL = ''; $SEO_TITLE = ''; if (!empty($params['TITLE'])) { $SEO_TITLE = createScriptURL_Text($params['TITLE']); } $SEO_URL = $this->processAll($params, $SERVER_URL, $SEO_URL, $SEO_TITLE); unset($params['s']); if (array_key_exists('search', $params) && !$params['search']) { unset($params['search']); } $SEO_URL = createScriptURL_Next_Params($SEO_URL, $params); if ($SEO_URL[0] == '/') { $SEO_URL = $SERVER_URL.substr($SEO_URL, 1); } elseif (!StringUtil::isAbsoluteUrl($SEO_URL)) { $SEO_URL = $SERVER_URL.$SEO_URL; } return $SEO_URL; } protected function processAll(&$params, &$SERVER_URL, $SEO_URL, $SEO_TITLE): string { switch (@$params['s']) { case 'category': $SEO_URL = '/'; $IDcat = intval(getVal('IDcat', $params, 0)); $IDp = intval(getVal('IDpd', $params, 0)); $label = ''; $urlFlags = $this->cfg['Products']['UrlFlags'] ?? null; if (preg_match("/^[[:digit:]]+({$urlFlags})$/i", getVal('IDcat', $params), $arr)) { $label = strtoupper($arr[1]); } if (isset($params['campaign'])) { $label = $params['campaign']; } if ($IDp) { if (!empty($params['producerTitle'])) { $SEO_URL .= createScriptURL_Text($params['producerTitle']); } else { if ($producerName = $this->getProducerName($IDp)) { $SEO_URL .= createScriptURL_Text($producerName); } else { $SEO_URL .= translate_shop('producer', 'SEO_URL'); } } $SEO_URL .= "_v{$IDp}/"; } $IDpv = intval(getVal('IDpv', $params, 0)); if ($IDpv) { if (!empty($params['parameterValueTitle'])) { $SEO_URL .= createScriptURL_Text($params['parameterValueTitle']); } else { $paramValue = sqlQueryBuilder()->select('value')->from('parameters_list') ->where('id=:id')->setParameter('id', $IDpv)->setMaxResults(1)->execute()->fetch(); if ($paramValue) { $SEO_URL .= createScriptURL_Text($paramValue['value']); } } $SEO_URL .= "_pv{$IDpv}/"; } if ($IDcat > 0) { if ($section = $this->sectionTree->getSectionById($IDcat)) { if (!$IDp) { if (($redirectUrl = $section->getRedirectUrl()) && StringUtil::isAbsoluteUrl($redirectUrl)) { $SEO_URL = $redirectUrl; } else { $SEO_URL .= $section->getUrl(); } } else { $SEO_URL .= $section->getAutogeneratedUrl(); } } else { if (!empty($SEO_TITLE)) { $SEO_URL .= $SEO_TITLE; } else { $SEO_URL .= translate_shop('category', 'SEO_URL'); } $SEO_URL .= '_k'.$IDcat.'/'; } } if (!empty($label)) { switch ($label) { case 'F': $SEO_URL .= translate_shop('favourite', 'SEO_URL'); break; case 'W': $SEO_URL .= translate_shop('watchdog-list', 'SEO_URL'); break; default: $SEO_URL .= getCampaigns()[$label]['url']; } $SEO_URL .= '/'; } elseif (!$IDp && !$IDcat) { $SEO_URL .= translate_shop('category', 'SEO_URL').'/'; } unset($params['IDcat'], $params['IDpd'], $params['producerTitle'], $params['parents'], $params['TM'], $params['campaign'],$params['IDpv'], $params['parameterValueTitle']); break; case 'product': if (!empty($params['currency'])) { $SERVER_URL .= "mena/{$params['currency']}/"; unset($params['currency']); } if (isset($params['category']) && isset($params['IDcat'])) { unset($params['category']); unset($params['IDcat']); } $params['IDproduct'] = intval(getVal('IDproduct', $params, 0)); if (empty($SEO_TITLE) && $params['IDproduct']) { $SEO_TITLE = createScriptURL_Text(returnSQLResult("SELECT title FROM products WHERE id='{$params['IDproduct']}' LIMIT 1")); } $SEO_URL .= '/'.$SEO_TITLE; $SEO_URL .= '_z'.$params['IDproduct']; $SEO_URL .= '/'; unset($params['IDproduct']); break; case 'articles': $SEO_URL = '/'.translate_shop($params['s'], 'SEO_URL').'/'; if (!empty($params['IDb'])) { $SEO_URL .= $params['IDb']; if (!empty($SEO_TITLE)) { $SEO_URL .= '/'.$SEO_TITLE; } $SEO_URL .= '/'; } unset($params['IDb']); break; case 'articles_tags': $SEO_URL = '/'.translate_shop('articles', 'SEO_URL').'/'.translate_shop('tag', 'SEO_URL').'/'; if (!empty($params['ID'])) { $SEO_URL .= $params['ID']; if (empty($SEO_TITLE) && $params['ID']) { $tag = sqlQueryBuilder() ->from('articles_tags', 'at') ->where(Operator::equals(['at.id' => $params['ID']])) ->andWhere(Translation::coalesceTranslatedFields(ArticlesTagsTranslation::class, ['tag'])) ->execute()->fetch(); $SEO_TITLE = createScriptURL_Text($tag['tag'] ?? ''); } $SEO_URL .= '/'.$SEO_TITLE.'/'; } unset($params['ID']); break; case 'article': $SEO_URL = '/'.translate_shop($params['s'], 'SEO_URL').'/'; $SEO_URL .= $params['IDa']; if (!empty($SEO_TITLE)) { $SEO_URL .= '/'.$SEO_TITLE; } $SEO_URL .= '/'; unset($params['IDa']); break; case 'author': $SEO_URL = '/'.translate_shop('articles', 'SEO_URL').'/'.translate_shop($params['s'], 'SEO_URL').'/'; $SEO_URL .= $params['IDa']; if (!empty($SEO_TITLE)) { $SEO_URL .= '/'.$SEO_TITLE; } $SEO_URL .= '/'; unset($params['IDa']); break; case 'image': $SEO_URL = '/'.translate_shop($params['s'], 'SEO_URL').'/'; $SEO_URL .= $params['IDph']; if (!empty($SEO_TITLE)) { $SEO_URL .= '/'.$SEO_TITLE; } $SEO_URL .= '/'; unset($params['IDph']); break; case 'watchdog': $acn = $params['acn'] ?? 'add'; $route = $acn == 'add' ? 'kupshop_watchdog_watchdog_add' : 'kupshop_watchdog_watchdog_remove'; unset($params['acn'], $params['URL'], $params['s']); $SEO_URL .= path($route, $params); break; case 'page': if (empty($SEO_TITLE)) { $page = $this->getPageData($params); if (!$page && isDevelopment() && !translate_shop($params['label'] ?? '', 'SEO_URL', true)) { throw new \Exception('Neexistuje stranka s label:'.($params['label'] ?? '').' nebo ID:'.($params['ID'] ?? '')); } $SEO_TITLE = createScriptURL_Text($page['name'] ?? ''); if (!empty($params['label'])) { $params['ID'] = $page['id'] ?? null; } if ($page['url'] ?? false) { $SEO_URL = '/'.$page['url']; } } if (empty($SEO_URL) && !empty($params['label']) && translate_shop($params['label'], 'SEO_URL', true)) { // Translated url - use fixed string $SEO_URL = '/'.translate_shop($params['label'], 'SEO_URL', true).'/'; } if (!$SEO_URL) { $SEO_URL = "/{$SEO_TITLE}_p{$params['ID']}.html"; } unset($params['label']); unset($params['ID']); break; case 'menuitem': $menuLinkId = $params['ID']; $menuLink = sqlQueryBuilder() ->from('menu_links', 'ml') ->andWhere(Operator::equals(['ml.id' => $menuLinkId])) ->andWhere(Translation::coalesceTranslatedFields(MenuLinksTranslation::class, ['url'])) ->execute()->fetch(); if (isDevelopment() && (!$menuLink || !$menuLink['url'])) { throw new \Exception("Neexistuje stranka s ID {$params['ID']} nebo nemá URL"); } $SEO_URL = $menuLink['url'] ?? '/'; unset($params['ID']); break; case 'index': $SEO_URL = '/'; break; case 'user': $SEO_URL = (getVal('act', $params) == 'new') ? '/'.translate_shop('user_new', 'SEO_URL').'/' : '/'.translate_shop('user_edit', 'SEO_URL').'/'; unset($params['act']); break; case 'login': if (@$params['act'] == 'passw') { $SEO_URL = '/'.translate_shop('login-passw', 'SEO_URL').'/'; unset($params['act']); } else { $SEO_URL = '/'.translate_shop('login', 'SEO_URL').'/'; if (!empty($params['redir'])) { $SEO_URL .= '?'.$params['redir']; } unset($params['redir']); } break; case 'orderView': $SEO_URL = '/'.translate_shop($params['s'], 'SEO_URL').'/'; $SEO_URL .= $params['IDo'].'/'; if (empty($params['cf'])) { unset($params['cf']); } if (!empty($params['edit'])) { $SEO_URL .= translate_shop('orderEdit', 'SEO_URL').'/'; } unset($params['edit']); unset($params['IDo']); break; /*case "orderHistory": $SEO_URL = "/".translate_shop($params['s'], 'SEO_URL')."/"; $SEO_URL .= $params['IDo'] . "/"; if(empty($params['cf'])) unset($params['cf']); unset($params['IDo']); break;*/ case 'compare': $SEO_URL = '/'.translate_shop($params['s'], 'SEO_URL').'/'; if (!empty($params['linkProducts'])) { $SEO_URL .= '?'.$params['linkProducts']; } unset($params['s'], $params['linkProducts']); break; case 'newsletter': $SEO_URL = '/'.$params['s'].'/'; if (!empty($params['ID']) && !empty($params['date'])) { $SEO_URL .= $params['date'].'/'.$params['ID'].'/'; unset($params['date'], $params['ID']); } break; case 'ordering': $cart = ServiceContainer::getService(CartFactory::class)->create(); if (isset($cart->steps[$params['step']])) { $step = $cart->steps[$params['step']]; } else { // fallback, kdyz chybi step, aby to nespadlo na tom, ze return type neni string $step = reset($cart->steps); } $SEO_URL = $step['url']; unset($params['step']); break; case 'currency': $SEO_URL = '/'; if (!empty($params['change'])) { $SERVER_URL .= "mena/{$params['change']}/"; unset($params['change']); } break; case 'captcha': default: if (isset($params['s']) && translate_shop($params['s'], 'SEO_URL', true)) { $SEO_URL .= '/'.translate_shop($params['s'], 'SEO_URL').'/'; } else { $SEO_URL = '/'.ltrim($params['URL'], '/'); if (!empty($params['s'])) { $SEO_URL .= '?s='.$params['s']; } } break; } unset($params['s']); return $SEO_URL; } private function getPageData(array $params): ?array { $language = Contexts::get(LanguageContext::class)->getActiveId(); if (!($this->pageDataCache[$language] ?? false)) { $qb = sqlQueryBuilder() ->select('ml.id, ml.name, ml.url, ml.code, ml.old_id_page') ->from('menu_links', 'ml') ->andWhere(Translation::coalesceTranslatedFields(MenuLinksTranslation::class, ['id', 'name', 'url'])) ->andWhere('ml.code IS NOT NULL OR ml.old_id_page IS NOT NULL'); $this->pageDataCache[$language]['byCode'] = []; $this->pageDataCache[$language]['byOldIdPage'] = []; foreach ($qb->execute() as $item) { if (!empty($item['old_id_page'])) { $this->pageDataCache[$language]['byOldIdPage'][$item['old_id_page']] = $item; } if (!empty($item['code'])) { $this->pageDataCache[$language]['byCode'][$item['code']] = $item; } } } if (!empty($params['label'])) { $data = $this->pageDataCache[$language]['byCode'][$params['label']] ?? null; } else { $data = $this->pageDataCache[$language]['byOldIdPage'][$params['ID']] ?? null; } return $data; } private function getProducerName(int $producerId): ?string { if (!isset($this->producersCache[$producerId])) { $query = sqlQueryBuilder() ->select('name') ->from('producers') ->andWhere(Operator::equals(['id' => $producerId])) ->setMaxResults(1); $this->producersCache[$producerId] = $query->execute()->fetchOne() ?: null; } return $this->producersCache[$producerId]; } }