AdvertPresenter
extends BasePresenter
in package
uses
AdvertListTrait, AdvertFavListTrait, AdvertDetailTrait, PermissionTrait, CategoryTrait, RegionTrait, ParameterTrait, AddAdvertFormTrait, EditAdvertFormTrait, AdvertAuthorizationFormTrait, AdvertPasswordResetFormTrait, EditStatisticsTrait, EditResponsesTrait, EditRenewTrait, EditExtendTrait, EditDeleteTrait, ArraysInitTrait, UserInitTrait, FavouriteHandlerTrait, ReportTrait, FollowTrait
Table of Contents
Constants
- DEFAULT_URL_PARAMS : mixed = [ 'page' => null, 'view' => null, 'order' => nu...
- URL state reset for a link that starts a new flow (e.g. "Add advert" from a list).
- DEFUALT_URL_PARAMS : mixed = self::DEFAULT_URL_PARAMS
- IDENTITY_LOCALIZED_KEYS : mixed = ['site.name', 'site.tagline']
- Text identity keys that have language variants `<key>.<alias>`.
- SESSION_NAMESPACE : mixed = 'front'
- advertSessionExpiration : mixed = 7200
- extendWindowDays : mixed = 2
- Number of days before expiration when extending is offered.
- FALLBACK_LAYOUT : mixed = '@layout_one.latte'
- Layout used when the theme lacks the requested one.
- IDENTITY_ASSET_KEYS : mixed = ['site.logo.assetId' => 'setLogo', 'site.logo.d...
- Setting key to DTO setter; the order matches the form fields.
- IDENTITY_MODULE : mixed = 1
- Identity settings live in the System module.
- LIST_INCLUDES : mixed = ['parameterRels.parameter.translations', 'asset...
- Includes of the list; identical for the DB path and the search endpoint.
- LOCALE_MAP : mixed = ['cs' => 'cs_CZ', 'en' => 'en_US', 'sk' => 'sk_...
- Maps the short language code to the full locale of the registered NEON sources.
- manageLinkKeyPrefix : string = 'front.bazaar.presenters.advert.manageLink.'
- passwordResetKeyPrefix : string = 'front.bazaar.presenters.advert.passwordReset.'
- responseDetailModalTarget : mixed = 'responseDetailModal'
- Unique key of the response detail modal in `ModalRegistry`.
- sessionSection : mixed = 'front.bazaar.advert.edit'
- SPECIFICATION_SKIP_KEYS : array<string|int, string> = ['name', 'keywords', 'text', 'type', 'state', '...
- tabConfirm : mixed = 'confirm'
- tabDelete : mixed = 'delete'
- tabExtend : mixed = 'extend'
- tabForm : mixed = 'form'
- Tab keys of the edit page; they match the files in `Templates/Advert/Sections/Edit/`.
- tabRenew : mixed = 'renew'
- tabResponses : mixed = 'responses'
- tabStatistics : mixed = 'statistics'
Properties
- $accessTokenValidator : AccessTokenValidator
- Validates access tokens beyond signature and expiry.
- $accountDeletionSessionManager : AccountDeletionSessionManager
- Account deletion — cancel ticket of a sign-in refused while the account awaits deletion.
- $advertFollowerManager : AdvertFollowerManager
- $advertLinksConfig : AdvertLinksConfig
- $advertParameterListFactory : AdvertParameterListFactory
- $advertPasswordResetManager : AdvertPasswordResetManager
- $advertReportManager : AdvertReportManager
- $advertStatisticsManager : AdvertStatisticsManager
- $authManager : AuthManager
- $authStorageManager : AuthStorageManager
- $blacklistedWordManager : BlacklistedWordManager
- $capabilityTokenIssuer : CapabilityTokenIssuer
- Issuer of the capability token for the Api layer (see {@see self::checkAutorization()}).
- $categoryId : string|null
- $categorySlugTranslator : CategoryNameTranslator
- Router translator: the same one that builds the slug from the id in links (see init below).
- $catId : array<string|int, int>|null
- $consentGateFactory : ConsentGateFactory
- $container : Container
- $count : int|null
- $currencyContext : CurrencyContext
- $currencyManager : CurrencyManager
- $deviceDetector : DeviceDetector
- $displayPaymentRegionManager : PaymentRegionManager
- IMPORTANT: a custom name, not `$paymentRegionManager`. Several presenters (Discussion/Bazaar Payment) have the region manager in the constructor, and a same-named property would break the container ("Cannot redeclare").
- $eventDispatcher : EventDispatcher
- $forgotPasswordFormFactory : ForgotPasswordFormFactory
- $frontFormLimiter : FrontFormLimiter
- $googleIntegrations : GoogleIntegrations
- Google services from the third-party connections, used in the page head (`analytics.latte` templates).
- $id : int
- $identityAssetManager : AssetManager
- $jwtManager : JwtManager
- $languageContext : LanguageContext
- $languageManager : LanguageManager
- $linksPaymentItemManager : PaymentItemManager
- $localizationContext : LocalizationContext
- $localizationManager : LocalizationManager
- $loginDeviceCookie : LoginDeviceCookie
- "Known device" cookie for the password login throttle ({@see self::rememberLoginDevice()}).
- $modalRegistry : ModalRegistry
- $modalWindowsFactory : ModalWindowsFactory
- $name : string|null
- $pageManager : PageManager
- $presenterContext : PresenterContext
- $reCaptchaRuntime : ReCaptchaRuntime
- Decides at runtime whether forms use reCAPTCHA (configuration plus the connection set up in the admin).
- $recommendFormFactory : RecommendFormFactory
- $regionSlugTranslator : RegionNameTranslator
- Router translator: the same one that builds the slug from the id in links (see init below).
- $responseFormFactory : ResponseFormFactory
- $responseManager : ResponseManager
- $routerDispatcher : RouterDispatcher
- $securityConfig : SecurityConfig
- reCAPTCHA switch for templates (`$reCaptchaEnabled` in the `scripts.latte` templates).
- $settingContext : SettingContext
- $settingManager : SettingManager
- $siteBaseUrl : SiteBaseUrl
- Website address for links outside the request; public because components use it (`MessageInfoLine`).
- $slug : string|int|null
- $socialsShareFactory : SocialsShareFactory
- $tab : string|null
- Active section (tab) of the edit page; see `Templates/Advert/Sections/Edit/`.
- $tariffManager : TariffManager
- $themeContext : ThemeContext
- $themeManager : ThemeManager
- $themeResolver : DefaultThemeResolver
- $translator : ITranslator
- $translatorSessionResolver : Session
- $userManager : UserManager
- $debugMode : bool
- $metaData : MetaDataDTO|null
- $ogData : OgDataDTO|null
- $pageEntity : Page|null
- $productionMode : bool
- $siteIdentity : SiteIdentityDto|null
- $translatorDomain : string
- $advert : Advert|null
- $advertFormFactory : AdvertFormFactory
- $advertManager : AdvertManager
- $blacklistedWords : array<string|int, string>
- $categoryManager : CategoryManager
- $categoryNodesCache : array<int, array<string, mixed>>|null
- $currentCategory : Category|null
- $currentRegion : Region|null
- $esSearcher : EsSearcher
- $favouriteSessionSection : string
- $favouriteSnippets : array<int, string>
- $frontUserManager : UserManager
- $hasPaidAccess : bool
- $isLoggingIn : bool
- $parameterManager : ParameterManager
- $parameterValues : array<string|int, object>
- $regionManager : RegionManager
- $selectedCategoryList : array<string|int, Category>
- $theme : Theme|null
Methods
- __construct() : mixed
- actionAdd() : void
- actionDetail() : void
- actionEdit() : void
- actionFavouriteList() : void
- actionList() : void
- addFavouriteSnippets() : void
- authFormSucceeded() : void
- beforeRender() : void
- checkAccessPermission() : bool
- completeExternalLogin() : bool
- Completes an OAuth login (`LoginExternalComponent`) with the same storage as a password login.
- createComponent() : IComponent|null
- createComponentAdvertParameterList() : AdvertParameterList
- createComponentAuthForm() : Form
- createComponentConsentGate() : ConsentGate
- createComponentForgotPasswordForm() : ForgotPasswordForm
- createComponentPasswordResetForm() : Form
- createComponentRecommendForm() : RecommendForm
- createComponentResponseForm() : ResponseForm
- createComponentSocialsShare() : SocialsShare
- formatLayoutTemplateFiles() : array<string|int, mixed>
- Returns candidate layout files; Nette takes the first existing one.
- getAdvert() : Advert|null
- getContainer() : Container
- getCurrentCategory() : Category|null
- getCurrentRegion() : Region|null
- getDefaultUrlParams() : array<string, null>
- getFavouriteSnippets() : array<int, string>
- getPageEntity() : Page|null
- getRouterDispatcher() : RouterDispatcher
- getTranslator() : ITranslator
- handleAddToFavourites() : void
- handleChangeLocale() : void
- handleDeleteAdvert() : void
- Handles the advert deletion signal.
- handleDelFromFavourites() : void
- handleExtendAdvert() : void
- Handles the advert extension signal before expiration.
- handleFollow() : void
- handleLogout() : void
- handleRenewAdvert() : void
- Handles the renewal signal of an expired advert.
- handleReport() : void
- Writes to the DB: AJAX from the page only; a bare GET (crawler, link prefetch) ends with 403.
- handleShowPhone() : void
- Handles the "show phone" action of an advert.
- handleShowResponseDetailModal() : void
- Handles the signal that shows the response detail in a modal window.
- handleSignOut() : void
- Sign-out from an ordinary link (account menu), also without JavaScript.
- handleUnfollow() : void
- hasServiceByType() : bool
- Returns whether the container has a service of the given type.
- initCurrentCategory() : void
- initCurrentRegion() : void
- initFavourites() : void
- initializeTranslator() : void
- initParameterValues() : self
- initUser() : void
- loadModalWindowComponent() : void
- loginWithCredentials() : void
- Logs in by username and password; called only by the login form (after validation and CSRF).
- passwordResetFormSucceeded() : void
- prepareFilters() : array<int, Filter>
- redirectToPendingAccountDeletion() : void
- Account deletion: a sign-in (password or OAuth) was refused because the account awaits deletion: keep the cancel ticket in the session and go to the "Account deletion" page, which offers "Cancel the deletion". Without a ticket (should not happen) the visitor gets the plain refusal flash instead.
- refreshAdvertSession() : void
- Updates the session token after editing: rewrites the hash and extends the expiration.
- renderAdd() : void
- renderAuthorizationForm() : void
- renderDetail() : void
- renderEdit() : void
- renderFavouriteList() : void
- renderList() : void
- renderPasswordReset() : void
- renderPermissionDenied() : void
- setAdvert() : self
- setConfigParameters() : void
- setFavouritesForTemplate() : void
- setFavouriteSnippets() : void
- setTranslator() : $this
- startup() : void
- typedComponent() : T
- Returns a subcomponent with a verified type.
- buildSiteIdentity() : SiteIdentityDto
- checkAuthentication() : void
- createComponentAddAdvertForm() : AdvertForm
- createComponentCategorySelectForm() : Form
- createComponentEditAdvertForm() : AdvertForm
- createComponentFrontSystemModalWindows() : ModalWindows
- currentAbsoluteUrl() : string
- Returns `link('//this')`, or the request address without query when it cannot be built.
- fallbackToMainLocalization() : bool
- Whether the presenter may fall back to the main localization for an unknown locale; a regular page may not (404).
- findExpressPaymentTariffs() : iterable<string|int, ExpressTariffInterface>
- Express payment offers whatever the advert can still be boosted with, so the quick prices have to come with the tariff — see {@see ExpressPaymentTrait}.
- getExpressPaymentModuleCode() : string
- getExpressPaymentReference() : string|null
- getFavouriteIds() : array<int, int>
- getFavouriteSessionStorage() : Session
- getSessionKey() : string
- Returns a session key string, e.g. 'front.auth.step1'.
- getSessionSection() : SessionSection
- Returns a Nette\SessionSection instance using a dynamically built session key.
- initFollower() : void
- initializeMetaData() : void
- initializeOgData() : void
- initializePresenterContext() : void
- initSiteIdentity() : void
- isAdvertExpired() : bool
- Returns whether the advert is expired, so the "Renew" tab is offered.
- isAdvertNearExpiration() : bool
- Returns whether the advert is within `extendWindowDays` before expiration (and not yet expired), so the "Extend" tab is offered.
- isSameSiteRequest() : bool
- Tells whether the request comes from the own site (Nette SameSite cookie); protects GET actions with a side effect.
- loadPageEntity() : Page|null
- Returns the page of the request by `slug` (empty is the home page, a number is the ID, otherwise `href`).
- logout() : void
- metaData() : MetaDataDTO
- Returns the page meta data; filled by startup, an empty DTO before that.
- ogData() : OgDataDTO
- Returns the page OG data; filled by `initializeOgData()` in startup, an empty DTO before that.
- prepareBlacklistedWords() : void
- prepareEditResponses() : void
- Prepares the data of the responses tab; `renderEdit()` calls it only when the tab is active.
- prepareEditStatistics() : void
- Prepares the data of the statistics tab; `renderEdit()` calls it only when the tab is active.
- prepareMetaData() : MetaDataDTO
- prepareOgData() : OgDataDTO
- prepareSpecifications() : void
- Builds the advert specifications array for rendering (name, value, type).
- setTranslatorDomain() : void
- buildCategoryHierarchy() : array<int, array<string, mixed>>
- Builds the recursive category tree by `parentId`.
- buildCategoryNodes() : array<int, array<string, mixed>>
- buildDefaultOgImage() : OgImageDTO|null
- Builds the default OG image from the site identity (admin, settings, site identity).
- buildEditTabs() : array<int, string>
- Builds the list of available tabs. Renew and Extend appear by the expiration state.
- buildRegionSubtreeFilters() : array<string|int, BaseFilter>
- Builds the "in region" filter from the suggest (`REGION_PICKER`, `p[<id>]=<regionId>`): adverts whose region lies in the subtree of the selected node, so a county also finds the adverts of its municipalities. Same shape as the list by the region in the path ({@see RegionTrait::prepareRegionFilter()}). A nonexistent region means no filter (an invalid id from the URL must not hide the whole list).
- buildResponseDetailContent() : string
- Builds the response detail HTML (a partial rendered to a string) for the modal content.
- buildResponseDetailError() : string
- categoryLabel() : string
- checkAutorization() : bool
- Checks whether the current user may edit the advert.
- checkUserPaymentValidity() : bool
- collectAdvertVisibilityIssues() : array<int, string>
- Returns the reasons why the advert is not publicly visible; an empty array means it is fine.
- collectLeafItems() : array<int, string>
- Builds the flat list `{leafId => label}` for `addCheckboxList`; only leaf categories (without children) get a checkbox.
- createIdentity() : SimpleIdentity|null
- createMultiplierComponent() : Multiplier<string|int, IComponent>
- Creates a multiplier for the component.
- createNewComponentInstance() : IComponent|null
- Creates a new component instance without adding it to the presenter; used by the multiplier.
- createStandardComponent() : IComponent|null
- Creates a standard component (not a multiplier).
- expireIdleLogin() : bool
- Checks whether the login expired from inactivity.
- extractBaseParameterIds() : array<string|int, int>
- Extracts the unique base `parameterId` from the URL keys (strips the suffixes `_from`, `_to`, `_d`, `_r`).
- formatLayoutCandidates() : array<int, string>
- getCategoryNodes() : array<int, array<string, mixed>>
- getClientIp() : string
- getFavouriteSection() : SessionSection
- getPasswordResetKey() : string
- grantAdvertEditCapability() : void
- Passes the fact that this visitor just proved the advert password to the Api layer. The token is minted again on every request from the current session state (already verified against the DB by the caller) and is never stored.
- grantAdvertEditCapabilityFromSession() : void
- Issues the capability from the session before the advert is loaded. The Api verifies it itself (password digest from the DB in `ownsByCapability()`), so a stale session record opens nothing. Without it `get` for editing would give an anonymous editor a masked e-mail and the form would fail validation. {@see self::checkAutorization()} then issues the capability again after the check against the fresh hash, which stays decisive for access.
- grantAdvertSessionAfterReset() : void
- Same session token as `AdvertAuthorizationFormTrait::authFormSucceeded()` writes after the password form. The hash is read back fresh from the Api — `checkAutorization()` compares it with the DB value on every request.
- hasPaidLinks() : bool
- True when the advert has an active, valid item of the "Show links" tariff (`AdvertLinksConfig`, default 4): the description then shows its web addresses as links.
- hasPasswordResetKey() : bool
- Does the request carry the reset key from the e-mailed link (query) or the form (POST)?
- identitySetting() : string
- Returns the module 1 key value as a string (empty when the key is missing or not a scalar).
- identitySettingOrNull() : string|null
- Works like {@see identitySetting()}, but an empty value is null (the template omits the field).
- initializeDisplayRegion() : void
- Initializes the currency and VAT display of prices.
- initializeExternalFiles() : void
- initializeMetaTags() : void
- initializePage() : void
- isAdvertOwner() : bool
- isCategoryBranchActive() : bool
- Whether the category and all its ancestors are active (nested set: an ancestor encloses lft/rgt).
- isCategoryStepCompleted() : bool
- isDevelopment() : bool
- isEntityInFavourites() : bool
- isRegionBranchActive() : bool
- Whether the region and all its ancestors are active (nested set: an ancestor encloses lft/rgt).
- layoutFileExists() : bool
- loadCategoryTree() : array<string|int, Category>
- loadIdentityAssets() : array<int, Asset>
- Loads the identity assets by id, keyed by id.
- loadLocalization() : Localization|null
- Returns the localization by `loc` from the URL, or `null` when there is no such locale.
- loadSelectedCategories() : array<string|int, Category>
- localizationCurrencyKey() : string|null
- Front needs no currency key from the localization; the currency and the display region are filled by {@see CurrencyInitTrait::initializeDisplayRegion()}.
- localizedIdentitySetting() : string
- Returns the language-dependent identity value: `<key>.<page language alias>`; an empty or missing value falls back to the base key (default language). An empty string means neither is set.
- logoutNetteUser() : void
- parseStatDate() : DateTimeImmutable|null
- Parses a date in the Y-m-d format; returns null otherwise.
- prepareAdvertSearchFilter() : Filter
- Builds the fulltext filter through ES (ids become `SearchIdFilter`; visibility and paging stay in DB phase 1). When ES is off, down or the query is short, it transparently falls back to MySQL `MATCH_AGAINST` over `parameterRels.value`.
- prepareCategoryFilter() : void
- prepareOrderBy() : array<string, bool>
- prepareOtherAdverts() : void
- Loads the other adverts of the owner and the count of their published adverts for the seller card.
- prepareParameterFilter() : void
- preparePriceFilter() : void
- Adds the upper price bound from the URL (`?priceTo=...`) sent by `SearchBox`.
- prepareRegionFilter() : void
- prepareSearchFilters() : array<int, Filter>
- Builds the filters for the search endpoint: everything except fulltext (the Api side does it, ES or `MATCH_AGAINST`). That is visibility + category/region + parameter filters from `$_GET['p']`, which are DB phase 1.
- prepareView() : void
- processFailedLogin() : void
- processInvalidToken() : void
- processLogin() : void
- processLoginException() : void
- processMissingToken() : void
- processSuccessfulLogin() : void
- processValidToken() : void
- readLoginDeviceToken() : string|null
- Returns the raw known-device cookie for the Api login (the Api verifies its signature).
- redeemManageKeyFromLink() : void
- Handles the "advert management" link from the insertion e-mail (`edit?id=...&manageKey=...`), which replaces the readable password the e-mail carried before.
- redirectAfterLoginAction() : void
- Ends a sign-in attempt. A classic (non-AJAX) successful sign-in lands on "My account" ({@see PageId::SYSTEM_USER_ACCOUNT}); a failed one on the home page. An AJAX sign-in stays on the current page and only redraws the flash messages.
- refreshNetteIdentity() : bool
- Refreshes the token for the same logged-in user.
- rememberLoginDevice() : void
- Issues or renews the "known device" cookie after a successful login (password or OAuth).
- resolveLoginErrorMessage() : string
- Resolves the translated login error text.
- resolveStatGranularity() : string
- Validates the granularity from the request against the allowed values.
- resolveStatRange() : DateTimeImmutable}
- Returns the date range from the request. When a bound is missing or invalid, the default range of the granularity is used.
- revokeTokensOnLogout() : void
- Calls the Api logout (revokes the refresh family and deny-lists the access `jti`) for the tokens of the current session.
-
searchViaApi()
: Advert>, 1: int, 2: bool, 3: array
>} |null - Searches adverts through the Api endpoint `api/bazaar/advert/search` instead of building the filter in the presenter. Three states:
- setDefaultAvatar() : array{rel: string}
- setNetteUser() : void
- showResponseDetailModal() : void
- Registers the response detail modal and tells the container to show it.
- tryRefresh() : bool
- Tries an automatic refresh when the access token has expired.
Constants
DEFAULT_URL_PARAMS
URL state reset for a link that starts a new flow (e.g. "Add advert" from a list).
public
mixed
DEFAULT_URL_PARAMS
= [
'page' => null,
'view' => null,
'order' => null,
'count' => null,
'cat' => null,
'catId' => null,
'categoryId' => null,
'search' => null,
'slug' => null,
'id' => null,
'tab' => null,
'c' => null,
'filter' => null,
'pr' => null,
// Private messages (`MessagePresenter`): without the reset the mailbox and the
// unread filter would leak into links outside messages.
'box' => null,
'unread' => null,
]
Nette adds the #[Persistent] parameters of the current request to a link when the target
presenter inherits them from the same class, so /inzeraty/automobily would produce
/pridat-inzerat/?count=0&categoryId=automobily. An explicit null cancels that:
ComponentReflection::saveState() skips a key already present in the parameters, so the
global state is not filled in and null drops out of the URL. null is safe even for
untyped or non-nullable parameters (public int $id) because the skipped value is never
cast.
The list covers all own persistent parameters of front presenters. Parameters declared on
this BasePresenter (slug, lang, loc) are carried on purpose and do not belong in
the reset, except slug, which the caller always overrides with the page ID.
IMPORTANT: a new #[Persistent] parameter must be added here too; otherwise it leaks into
links. Checked by tests/Unit/Core/DefaultUrlParamsCoverageTest.php.
DEFUALT_URL_PARAMS
misspelled name kept for existing callers, use DEFAULT_URL_PARAMS
public
mixed
DEFUALT_URL_PARAMS
= self::DEFAULT_URL_PARAMS
IDENTITY_LOCALIZED_KEYS
Text identity keys that have language variants `<key>.<alias>`.
public
mixed
IDENTITY_LOCALIZED_KEYS
= ['site.name', 'site.tagline']
SESSION_NAMESPACE
protected
mixed
SESSION_NAMESPACE
= 'front'
advertSessionExpiration
private
mixed
advertSessionExpiration
= 7200
extendWindowDays
Number of days before expiration when extending is offered.
private
mixed
extendWindowDays
= 2
FALLBACK_LAYOUT
Layout used when the theme lacks the requested one.
private
mixed
FALLBACK_LAYOUT
= '@layout_one.latte'
@layout_one.latte (one column, shared header and footer) exists in every theme and is
the plainest page the system can render, so anything fits in it.
IMPORTANT: not @layout.latte; that is a bare Nette skeleton titled "Nette Web" without
header, footer or styles, hardly better than a missing layout.
IDENTITY_ASSET_KEYS
Setting key to DTO setter; the order matches the form fields.
private
mixed
IDENTITY_ASSET_KEYS
= ['site.logo.assetId' => 'setLogo', 'site.logo.dark.assetId' => 'setLogoDark', 'site.favicon.assetId' => 'setFavicon', 'site.og.assetId' => 'setOgImage']
IDENTITY_MODULE
Identity settings live in the System module.
private
mixed
IDENTITY_MODULE
= 1
LIST_INCLUDES
Includes of the list; identical for the DB path and the search endpoint.
private
mixed
LIST_INCLUDES
= ['parameterRels.parameter.translations', 'assetRels.asset.translations', 'categoryRels.category.translations', 'user']
LOCALE_MAP
Maps the short language code to the full locale of the registered NEON sources.
private
mixed
LOCALE_MAP
= ['cs' => 'cs_CZ', 'en' => 'en_US', 'sk' => 'sk_SK']
The short code (cs, en, sk) comes from LanguageContext, derived from the URL parameter
loc/lang; the full locales are cs_CZ, en_US, sk_SK. translator.neon configures one
shared fallback chain [cs_CZ, cs, en_US, en, sk_SK, sk] for all languages, so a short code
would always map to cs_CZ first, whatever language is active. A direct match on the full
locale bypasses that.
The Contributte LocaleResolvers\Router (the only configured resolver) looks for the route
parameter locale, but this application routes under loc, so it always returns null and the
translator falls back to default: cs. An explicit setLocale() from here bypasses the
resolver, which Translator::getLocale() asks only while no locale has been set explicitly.
manageLinkKeyPrefix
private
string
manageLinkKeyPrefix
= 'front.bazaar.presenters.advert.manageLink.'
passwordResetKeyPrefix
private
string
passwordResetKeyPrefix
= 'front.bazaar.presenters.advert.passwordReset.'
responseDetailModalTarget
Unique key of the response detail modal in `ModalRegistry`.
private
mixed
responseDetailModalTarget
= 'responseDetailModal'
sessionSection
private
mixed
sessionSection
= 'front.bazaar.advert.edit'
SPECIFICATION_SKIP_KEYS
private
array<string|int, string>
SPECIFICATION_SKIP_KEYS
= ['name', 'keywords', 'text', 'type', 'state', 'street', 'city', 'zip', 'country', 'regionId', 'latitude', 'longitude', 'currency', 'is_vehicle', 'priceType', 'price', 'allow_price_suggestion', 'email', 'phone', 'url', 'datetime', 'date', 'time']
parameter keys that are not rendered in the specifications section
tabConfirm
private
mixed
tabConfirm
= 'confirm'
tabDelete
private
mixed
tabDelete
= 'delete'
tabExtend
private
mixed
tabExtend
= 'extend'
tabForm
Tab keys of the edit page; they match the files in `Templates/Advert/Sections/Edit/`.
private
mixed
tabForm
= 'form'
tabRenew
private
mixed
tabRenew
= 'renew'
tabResponses
private
mixed
tabResponses
= 'responses'
tabStatistics
private
mixed
tabStatistics
= 'statistics'
Properties
$accessTokenValidator
Validates access tokens beyond signature and expiry.
public
AccessTokenValidator
$accessTokenValidator
A revoked token (jti on the deny-list) that has not expired yet would otherwise keep the
session logged in although the Api guard rejects the same token. Same contract as
JwtAuthTrait::checkJwtAuth(), one implementation.
Attributes
- #[Inject]
$accountDeletionSessionManager
Account deletion — cancel ticket of a sign-in refused while the account awaits deletion.
public
AccountDeletionSessionManager
$accountDeletionSessionManager
Attributes
- #[Inject]
$advertFollowerManager
public
AdvertFollowerManager
$advertFollowerManager
Attributes
- #[Inject]
$advertLinksConfig
public
AdvertLinksConfig
$advertLinksConfig
Attributes
- #[Inject]
$advertParameterListFactory
public
AdvertParameterListFactory
$advertParameterListFactory
Attributes
- #[Inject]
$advertPasswordResetManager
public
AdvertPasswordResetManager
$advertPasswordResetManager
Attributes
- #[Inject]
$advertReportManager
public
AdvertReportManager
$advertReportManager
Attributes
- #[Inject]
$advertStatisticsManager
public
AdvertStatisticsManager
$advertStatisticsManager
Attributes
- #[Inject]
$authManager
public
AuthManager
$authManager
Attributes
- #[Inject]
$authStorageManager
public
AuthStorageManager
$authStorageManager
Attributes
- #[Inject]
$blacklistedWordManager
public
BlacklistedWordManager
$blacklistedWordManager
Attributes
- #[Inject]
$capabilityTokenIssuer
Issuer of the capability token for the Api layer (see {@see self::checkAutorization()}).
public
CapabilityTokenIssuer
$capabilityTokenIssuer
Attributes
- #[Inject]
$categoryId
public
string|null
$categoryId
= null
Attributes
- #[Persistent]
$categorySlugTranslator
Router translator: the same one that builds the slug from the id in links (see init below).
public
CategoryNameTranslator
$categorySlugTranslator
Attributes
- #[Inject]
$catId
public
array<string|int, int>|null
$catId
= null
ids of the categories chosen in step 1 (null = nothing chosen yet)
Attributes
- #[Persistent]
$consentGateFactory
public
ConsentGateFactory
$consentGateFactory
Attributes
- #[Inject]
$container
public
Container
$container
Attributes
- #[Inject]
$count
public
int|null
$count
= null
Attributes
- #[Persistent]
$currencyContext
public
CurrencyContext
$currencyContext
Attributes
- #[Inject]
$currencyManager
public
CurrencyManager
$currencyManager
Attributes
- #[Inject]
$deviceDetector
public
DeviceDetector
$deviceDetector
Attributes
- #[Inject]
$displayPaymentRegionManager
IMPORTANT: a custom name, not `$paymentRegionManager`. Several presenters (Discussion/Bazaar Payment) have the region manager in the constructor, and a same-named property would break the container ("Cannot redeclare").
public
PaymentRegionManager
$displayPaymentRegionManager
Attributes
- #[Inject]
$eventDispatcher
public
EventDispatcher
$eventDispatcher
Attributes
- #[Inject]
$forgotPasswordFormFactory
public
ForgotPasswordFormFactory
$forgotPasswordFormFactory
Attributes
- #[Inject]
$frontFormLimiter
public
FrontFormLimiter
$frontFormLimiter
Attributes
- #[Inject]
$googleIntegrations
Google services from the third-party connections, used in the page head (`analytics.latte` templates).
public
GoogleIntegrations
$googleIntegrations
Attributes
- #[Inject]
$id
public
int
$id
Attributes
- #[Persistent]
$identityAssetManager
public
AssetManager
$identityAssetManager
Attributes
- #[Inject]
$jwtManager
public
JwtManager
$jwtManager
Attributes
- #[Inject]
$languageContext
public
LanguageContext
$languageContext
Attributes
- #[Inject]
$languageManager
public
LanguageManager
$languageManager
Attributes
- #[Inject]
$linksPaymentItemManager
public
PaymentItemManager
$linksPaymentItemManager
Attributes
- #[Inject]
$localizationContext
public
LocalizationContext
$localizationContext
Attributes
- #[Inject]
$localizationManager
public
LocalizationManager
$localizationManager
Attributes
- #[Inject]
$loginDeviceCookie
"Known device" cookie for the password login throttle ({@see self::rememberLoginDevice()}).
public
LoginDeviceCookie
$loginDeviceCookie
Attributes
- #[Inject]
$modalRegistry
public
ModalRegistry
$modalRegistry
Attributes
- #[Inject]
$modalWindowsFactory
public
ModalWindowsFactory
$modalWindowsFactory
Attributes
- #[Inject]
$name
public
string|null
$name
= null
$pageManager
public
PageManager
$pageManager
Attributes
- #[Inject]
$presenterContext
public
PresenterContext
$presenterContext
Attributes
- #[Inject]
$reCaptchaRuntime
Decides at runtime whether forms use reCAPTCHA (configuration plus the connection set up in the admin).
public
ReCaptchaRuntime
$reCaptchaRuntime
Attributes
- #[Inject]
$recommendFormFactory
public
RecommendFormFactory
$recommendFormFactory
Attributes
- #[Inject]
$regionSlugTranslator
Router translator: the same one that builds the slug from the id in links (see init below).
public
RegionNameTranslator
$regionSlugTranslator
Attributes
- #[Inject]
$responseFormFactory
public
ResponseFormFactory
$responseFormFactory
Attributes
- #[Inject]
$responseManager
public
ResponseManager
$responseManager
Attributes
- #[Inject]
$routerDispatcher
public
RouterDispatcher
$routerDispatcher
Tags
$securityConfig
reCAPTCHA switch for templates (`$reCaptchaEnabled` in the `scripts.latte` templates).
public
SecurityConfig
$securityConfig
Attributes
- #[Inject]
$settingContext
public
SettingContext
$settingContext
Attributes
- #[Inject]
$settingManager
public
SettingManager
$settingManager
Attributes
- #[Inject]
$siteBaseUrl
Website address for links outside the request; public because components use it (`MessageInfoLine`).
public
SiteBaseUrl
$siteBaseUrl
Attributes
- #[Inject]
$slug
public
string|int|null
$slug
= NULL
Attributes
- #[Persistent]
$socialsShareFactory
public
SocialsShareFactory
$socialsShareFactory
Attributes
- #[Inject]
$tab
Active section (tab) of the edit page; see `Templates/Advert/Sections/Edit/`.
public
string|null
$tab
= null
Attributes
- #[Persistent]
$tariffManager
public
TariffManager
$tariffManager
Attributes
- #[Inject]
$themeContext
public
ThemeContext
$themeContext
Attributes
- #[Inject]
$themeManager
public
ThemeManager
$themeManager
Attributes
- #[Inject]
$themeResolver
public
DefaultThemeResolver
$themeResolver
Attributes
- #[Inject]
$translator
public
ITranslator
$translator
Tags
$translatorSessionResolver
public
Session
$translatorSessionResolver
Tags
$userManager
public
UserManager
$userManager
Attributes
- #[Inject]
$debugMode
protected
bool
$debugMode
= false
$metaData
protected
MetaDataDTO|null
$metaData
= null
$ogData
protected
OgDataDTO|null
$ogData
= null
$pageEntity
protected
Page|null
$pageEntity
= null
$productionMode
protected
bool
$productionMode
= false
$siteIdentity
protected
SiteIdentityDto|null
$siteIdentity
= null
$translatorDomain
protected
string
$translatorDomain
= ''
$advert
private
Advert|null
$advert
= null
$advertFormFactory read-only
private
AdvertFormFactory
$advertFormFactory
$advertManager read-only
private
AdvertManager
$advertManager
$blacklistedWords
private
array<string|int, string>
$blacklistedWords
= []
forbidden words in the target language, for the render-time replacement
$categoryManager read-only
private
CategoryManager
$categoryManager
$categoryNodesCache
private
array<int, array<string, mixed>>|null
$categoryNodesCache
= null
lazily cached tree for the select step
$currentCategory
private
Category|null
$currentCategory
= null
$currentRegion
private
Region|null
$currentRegion
= null
$esSearcher read-only
private
EsSearcher
$esSearcher
$favouriteSessionSection
private
string
$favouriteSessionSection
$favouriteSnippets
private
array<int, string>
$favouriteSnippets
= ['favouriteLinksSnippet', 'flashMessagesSnippet']
$frontUserManager read-only
private
UserManager
$frontUserManager
$hasPaidAccess
private
bool
$hasPaidAccess
= false
$isLoggingIn
private
bool
$isLoggingIn
= false
$parameterManager read-only
private
ParameterManager
$parameterManager
$parameterValues
private
array<string|int, object>
$parameterValues
= []
parameter options by id
$regionManager read-only
private
RegionManager
$regionManager
$selectedCategoryList
private
array<string|int, Category>
$selectedCategoryList
= []
categories loaded in step 2 by $catId
$theme
private
Theme|null
$theme
= null
Methods
__construct()
public
__construct(AdvertManager $advertManager, CategoryManager $categoryManager, RegionManager $regionManager, ParameterManager $parameterManager, AdvertFormFactory $advertFormFactory, EsSearcher $esSearcher, UserManager $frontUserManager) : mixed
Parameters
- $advertManager : AdvertManager
- $categoryManager : CategoryManager
- $regionManager : RegionManager
- $parameterManager : ParameterManager
- $advertFormFactory : AdvertFormFactory
- $esSearcher : EsSearcher
- $frontUserManager : UserManager
actionAdd()
public
actionAdd() : void
actionDetail()
public
actionDetail(string|int|null $slug, int $id, string $loc) : void
Parameters
- $slug : string|int|null
- $id : int
- $loc : string
actionEdit()
public
actionEdit(int $id) : void
Parameters
- $id : int
actionFavouriteList()
public
actionFavouriteList() : void
actionList()
public
actionList(int|null $page, string|int|null $category, string|int|null $loc, int|null $order) : void
Parameters
- $page : int|null
- $category : string|int|null
- $loc : string|int|null
- $order : int|null
addFavouriteSnippets()
public
addFavouriteSnippets(array<int, string> $snippets) : void
Parameters
- $snippets : array<int, string>
authFormSucceeded()
public
authFormSucceeded(Form $form, ArrayHash $values) : void
Parameters
- $form : Form
- $values : ArrayHash
beforeRender()
public
beforeRender() : void
checkAccessPermission()
public
checkAccessPermission(array<string|int, mixed> $categoryList) : bool
Parameters
- $categoryList : array<string|int, mixed>
Return values
boolcompleteExternalLogin()
Completes an OAuth login (`LoginExternalComponent`) with the same storage as a password login.
public
completeExternalLogin(array<string, mixed> $resultData) : bool
IMPORTANT: the whole session section is cleared first and the refresh token from the Api
must be stored. Otherwise the user drops out after 15 minutes, and the refresh token of the
previous account stays in the section, so tryRefresh() would log account A back in after
expiry (shared computer).
Parameters
- $resultData : array<string, mixed>
-
datafrom the ApiloginExternal(token, refreshToken, payload)
Return values
boolcreateComponent()
public
createComponent(string $name) : IComponent|null
Parameters
- $name : string
Return values
IComponent|nullcreateComponentAdvertParameterList()
public
createComponentAdvertParameterList() : AdvertParameterList
Return values
AdvertParameterListcreateComponentAuthForm()
public
createComponentAuthForm() : Form
Return values
FormcreateComponentConsentGate()
public
createComponentConsentGate() : ConsentGate
Return values
ConsentGatecreateComponentForgotPasswordForm()
public
createComponentForgotPasswordForm() : ForgotPasswordForm
Return values
ForgotPasswordFormcreateComponentPasswordResetForm()
public
createComponentPasswordResetForm() : Form
Return values
FormcreateComponentRecommendForm()
public
createComponentRecommendForm() : RecommendForm
Return values
RecommendFormcreateComponentResponseForm()
public
createComponentResponseForm() : ResponseForm
Return values
ResponseFormcreateComponentSocialsShare()
public
createComponentSocialsShare() : SocialsShare
Return values
SocialsShareformatLayoutTemplateFiles()
Returns candidate layout files; Nette takes the first existing one.
public
formatLayoutTemplateFiles() : array<string|int, mixed>
IMPORTANT: when the theme lacks the layout, a fallback is added. The layout name is stored
in cms_system_pages.layout, one column shared by all themes, so a page set to
@text_layout_two.latte wants that file even in a theme that never got it. Without a
fallback Nette finds nothing and renders the presenter without a layout: the page has no
header, footer or styles but returns HTTP 200.
The fallback is logged, because a silent fallback would hide the problem entirely; when the page asks for the fallback layout itself and the theme lacks it, there is nowhere to fall back to, so it is logged as an error and the page renders without a layout.
Return values
array<string|int, mixed>getAdvert()
public
getAdvert() : Advert|null
Return values
Advert|nullgetContainer()
public
getContainer() : Container
Return values
ContainergetCurrentCategory()
public
getCurrentCategory() : Category|null
Return values
Category|nullgetCurrentRegion()
public
getCurrentRegion() : Region|null
Return values
Region|nullgetDefaultUrlParams()
public
getDefaultUrlParams() : array<string, null>
Return values
array<string, null>getFavouriteSnippets()
public
getFavouriteSnippets() : array<int, string>
Return values
array<int, string>getPageEntity()
public
getPageEntity() : Page|null
Return values
Page|nullgetRouterDispatcher()
public
getRouterDispatcher() : RouterDispatcher
Return values
RouterDispatchergetTranslator()
public
getTranslator() : ITranslator
Return values
ITranslatorhandleAddToFavourites()
public
handleAddToFavourites(int $entityId[, string $style = 'Style_1' ]) : void
Parameters
- $entityId : int
- $style : string = 'Style_1'
handleChangeLocale()
public
handleChangeLocale(string $locale) : void
Parameters
- $locale : string
handleDeleteAdvert()
Handles the advert deletion signal.
public
handleDeleteAdvert() : void
Soft delete: sets the column deleted = 1 (same as the cron deleteLongExpired).
Editing cannot continue after deletion, so it redirects to the homepage.
handleDelFromFavourites()
public
handleDelFromFavourites(int $entityId[, string $style = 'Style_1' ]) : void
Parameters
- $entityId : int
- $style : string = 'Style_1'
handleExtendAdvert()
Handles the advert extension signal before expiration.
public
handleExtendAdvert() : void
The Api layer computes the new expiration from the intervals of the advert categories.
handleFollow()
public
handleFollow(int $advertId) : void
Parameters
- $advertId : int
handleLogout()
public
handleLogout() : void
handleRenewAdvert()
Handles the renewal signal of an expired advert.
public
handleRenewAdvert() : void
Shares the computation with extending: extendExpiration() counts the new expiration from
today for an expired advert (see the Api AdvertExpirationTrait).
handleReport()
Writes to the DB: AJAX from the page only; a bare GET (crawler, link prefetch) ends with 403.
public
handleReport(int $advertId) : void
Parameters
- $advertId : int
Attributes
- #[Requires]
- $ajax: true
handleShowPhone()
Handles the "show phone" action of an advert.
public
handleShowPhone() : void
IMPORTANT: the signal goes through three protections, otherwise the template would print a number that is already in the data without any check:
#[Requires(sameOrigin: true, ajax: true)]: a foreign page cannot trigger it and a non-AJAX call ends with 403 instead of a silent no-op,- the guard
:Api:System:User:showPhoneon the Api layer, - a rate limit of 20 per hour per IP (
ratelimit.showPhone); without it the numbers could be harvested by walking through the adverts.
UserManager::revealPhone() provides the guard and
the limit. An empty answer (denied, limit exhausted, seller without a number) does not switch
showPhone; the template keeps the masked value without a visible error.
An advert without an account keeps the phone on the advert ($advert->get('phone')), not on
a user, so revealPhone() cannot serve it; the per-IP limit for that branch is held by
FrontFormLimiter::isAdvertPhoneRevealAllowed().
Attributes
- #[Requires]
- $sameOrigin: true
- $ajax: true
handleShowResponseDetailModal()
Handles the signal that shows the response detail in a modal window.
public
handleShowResponseDetailModal(int $responseId) : void
Loads the response, verifies that it belongs to the edited advert, marks it as read and
sends the rendered detail to ModalWindow.
Parameters
- $responseId : int
handleSignOut()
Sign-out from an ordinary link (account menu), also without JavaScript.
public
handleSignOut() : void
Nette refuses every signal whose request is not same-origin (Sec-Fetch-Site) and redirects
to the same URL without do, so a typed or bookmarked ?do=signOut (Sec-Fetch-Site: none)
never ran. A user-initiated navigation cannot be forged by another site, so it is allowed
here as well; a cross-site request still ends in detectedCsrf().
Attributes
- #[Requires]
- $sameOrigin: false
handleUnfollow()
public
handleUnfollow(int $advertId) : void
Parameters
- $advertId : int
hasServiceByType()
Returns whether the container has a service of the given type.
public
hasServiceByType(string $className) : bool
The name is composed dynamically (module plus component), so class_exists() runs first, and
a true result guarantees a valid type.
Parameters
- $className : string
Tags
Return values
boolinitCurrentCategory()
public
initCurrentCategory() : void
initCurrentRegion()
public
initCurrentRegion() : void
initFavourites()
public
initFavourites(string $sessionSection) : void
Parameters
- $sessionSection : string
initializeTranslator()
public
initializeTranslator(string|null $alias) : void
Parameters
- $alias : string|null
initParameterValues()
public
initParameterValues() : self
Return values
selfinitUser()
public
initUser([Advert|null $advert = null ]) : void
Parameters
- $advert : Advert|null = null
loadModalWindowComponent()
public
loadModalWindowComponent() : void
loginWithCredentials()
Logs in by username and password; called only by the login form (after validation and CSRF).
public
loginWithCredentials(string $username, string $password[, bool $remember = false ]) : void
IMPORTANT: this must not be a handle* method. Nette finds signals by that prefix, so a
public handleLogin() would be a signal on every presenter (?do=login&username=…&password=…):
the password could end up in the URL and the server log, and the form token would be bypassed.
Parameters
- $username : string
- $password : string
- $remember : bool = false
passwordResetFormSucceeded()
public
passwordResetFormSucceeded(Form $form) : void
Parameters
- $form : Form
prepareFilters()
public
prepareFilters([bool $useParameterFilters = true ]) : array<int, Filter>
Parameters
- $useParameterFilters : bool = true
Return values
array<int, Filter>redirectToPendingAccountDeletion()
Account deletion: a sign-in (password or OAuth) was refused because the account awaits deletion: keep the cancel ticket in the session and go to the "Account deletion" page, which offers "Cancel the deletion". Without a ticket (should not happen) the visitor gets the plain refusal flash instead.
public
redirectToPendingAccountDeletion(mixed $resultData) : void
Parameters
- $resultData : mixed
refreshAdvertSession()
Updates the session token after editing: rewrites the hash and extends the expiration.
public
refreshAdvertSession(Advert $advert) : void
Call it after a successful save, when $advert->getPassword() holds the new hash.
Parameters
- $advert : Advert
renderAdd()
public
renderAdd() : void
renderAuthorizationForm()
public
renderAuthorizationForm() : void
renderDetail()
public
renderDetail(string|int|null $slug, int $id, string $loc) : void
Parameters
- $slug : string|int|null
- $id : int
- $loc : string
renderEdit()
public
renderEdit() : void
renderFavouriteList()
public
renderFavouriteList() : void
renderList()
public
renderList(int $page, string|int|null $category, string|int $loc, int $order[, int $count = 20 ]) : void
Parameters
- $page : int
- $category : string|int|null
- $loc : string|int
- $order : int
- $count : int = 20
renderPasswordReset()
public
renderPasswordReset() : void
renderPermissionDenied()
public
renderPermissionDenied() : void
setAdvert()
public
setAdvert(Advert|null $advert) : self
Parameters
- $advert : Advert|null
Return values
selfsetConfigParameters()
public
setConfigParameters([bool $debugMode = false ][, bool $productionMode = false ]) : void
Parameters
- $debugMode : bool = false
- $productionMode : bool = false
setFavouritesForTemplate()
public
setFavouritesForTemplate(int $id) : void
Parameters
- $id : int
setFavouriteSnippets()
public
setFavouriteSnippets(array<int, string> $snippets) : void
Parameters
- $snippets : array<int, string>
setTranslator()
public
setTranslator(ITranslator $translator) : $this
Parameters
- $translator : ITranslator
Return values
$thisstartup()
public
startup() : void
typedComponent()
Returns a subcomponent with a verified type.
public
typedComponent(string $name, T> $type) : T
Use it instead of an inline @var above $this['x'] (which does not narrow the type) and
instead of the generic IComponent that $this['x'] returns. See
Form::typedComponent().
Parameters
- $name : string
- $type : T>
Tags
Return values
TbuildSiteIdentity()
protected
buildSiteIdentity() : SiteIdentityDto
Return values
SiteIdentityDtocheckAuthentication()
protected
checkAuthentication() : void
createComponentAddAdvertForm()
protected
createComponentAddAdvertForm() : AdvertForm
Return values
AdvertFormcreateComponentCategorySelectForm()
protected
createComponentCategorySelectForm() : Form
Return values
FormcreateComponentEditAdvertForm()
protected
createComponentEditAdvertForm() : AdvertForm
Return values
AdvertFormcreateComponentFrontSystemModalWindows()
protected
createComponentFrontSystemModalWindows() : ModalWindows
Return values
ModalWindowscurrentAbsoluteUrl()
Returns `link('//this')`, or the request address without query when it cannot be built.
protected
currentAbsoluteUrl() : string
IMPORTANT: it is called from startup() of every front page (MetaDataInitTrait,
OgDataInitTrait), before Nette verifies the required action parameters. A request
without them (/editace-firmy without id for actionEdit(int $id)) should end as a 404,
but link('//this') reports an invalid link there; in debug mode that is an E_USER_WARNING
which Tracy (strict mode) turns into a 500 that catch cannot catch. So InvalidLinkException
is forced for the duration of the call and the mode is restored in finally (same principle
as SafeLinkExtension::generateSafeLink(), which cannot
handle the //this target because it verifies that the target presenter exists).
Return values
stringfallbackToMainLocalization()
Whether the presenter may fall back to the main localization for an unknown locale; a regular page may not (404).
protected
fallbackToMainLocalization() : bool
Return values
boolfindExpressPaymentTariffs()
Express payment offers whatever the advert can still be boosted with, so the quick prices have to come with the tariff — see {@see ExpressPaymentTrait}.
protected
findExpressPaymentTariffs() : iterable<string|int, ExpressTariffInterface>
Return values
iterable<string|int, ExpressTariffInterface>getExpressPaymentModuleCode()
protected
getExpressPaymentModuleCode() : string
Return values
stringgetExpressPaymentReference()
protected
getExpressPaymentReference() : string|null
Return values
string|nullgetFavouriteIds()
protected
getFavouriteIds() : array<int, int>
Return values
array<int, int>getFavouriteSessionStorage()
protected
getFavouriteSessionStorage() : Session
Return values
SessiongetSessionKey()
Returns a session key string, e.g. 'front.auth.step1'.
protected
getSessionKey([string|null $namespace = null ][, string|null $subsection = null ], string ...$extra) : string
Parameters
- $namespace : string|null = null
-
Base namespace (module prefix). Uses SESSION_NAMESPACE if null.
- $subsection : string|null = null
-
Subsection under the namespace. Uses SESSION_SUBSECTION constant if null.
- $extra : string
-
Additional parts to append (e.g. 'step1', 'wizard', etc.).
Return values
stringgetSessionSection()
Returns a Nette\SessionSection instance using a dynamically built session key.
protected
getSessionSection([string|null $namespace = null ][, string|null $subsection = null ], string ...$extra) : SessionSection
Parameters
- $namespace : string|null = null
- $subsection : string|null = null
- $extra : string
Tags
Return values
SessionSectioninitFollower()
protected
initFollower() : void
initializeMetaData()
protected
initializeMetaData() : void
initializeOgData()
protected
initializeOgData() : void
initializePresenterContext()
protected
initializePresenterContext() : void
initSiteIdentity()
protected
initSiteIdentity() : void
isAdvertExpired()
Returns whether the advert is expired, so the "Renew" tab is offered.
protected
isAdvertExpired() : bool
Return values
boolisAdvertNearExpiration()
Returns whether the advert is within `extendWindowDays` before expiration (and not yet expired), so the "Extend" tab is offered.
protected
isAdvertNearExpiration() : bool
Return values
boolisSameSiteRequest()
Tells whether the request comes from the own site (Nette SameSite cookie); protects GET actions with a side effect.
protected
isSameSiteRequest() : bool
getHttpRequest() returns the IRequest interface, while isSameSite() exists only on
Nette\Http\Request.
Return values
boolloadPageEntity()
Returns the page of the request by `slug` (empty is the home page, a number is the ID, otherwise `href`).
protected
loadPageEntity() : Page|null
Returns null when the page does not exist; the 404 is decided by
BasePresenter::startup(). The error page
(ErrorPresenter) overrides the method
because it has no page in the DB and the layout needs an entity.
Return values
Page|nulllogout()
protected
logout() : void
metaData()
Returns the page meta data; filled by startup, an empty DTO before that.
protected
metaData() : MetaDataDTO
Return values
MetaDataDTOogData()
Returns the page OG data; filled by `initializeOgData()` in startup, an empty DTO before that.
protected
ogData() : OgDataDTO
Return values
OgDataDTOprepareBlacklistedWords()
protected
prepareBlacklistedWords() : void
prepareEditResponses()
Prepares the data of the responses tab; `renderEdit()` calls it only when the tab is active.
protected
prepareEditResponses() : void
prepareEditStatistics()
Prepares the data of the statistics tab; `renderEdit()` calls it only when the tab is active.
protected
prepareEditStatistics() : void
prepareMetaData()
protected
prepareMetaData() : MetaDataDTO
Return values
MetaDataDTOprepareOgData()
protected
prepareOgData() : OgDataDTO
Return values
OgDataDTOprepareSpecifications()
Builds the advert specifications array for rendering (name, value, type).
protected
prepareSpecifications(Advert $advert) : void
Skips the skipped keys, child option parameters and empty values, so an empty array directly means "nothing to show".
Parameters
- $advert : Advert
setTranslatorDomain()
protected
setTranslatorDomain() : void
buildCategoryHierarchy()
Builds the recursive category tree by `parentId`.
private
buildCategoryHierarchy(array<string|int, Category> $flat) : array<int, array<string, mixed>>
Each node: ['id', 'category', 'depth', 'isLeaf', 'label', 'priceLabel', 'children'].
Parameters
- $flat : array<string|int, Category>
Return values
array<int, array<string, mixed>>buildCategoryNodes()
private
buildCategoryNodes(array<string|int, Category> $categories, array<int, array<string|int, Category>> $childrenByParent, int $depth, int|null $langId) : array<int, array<string, mixed>>
Parameters
- $categories : array<string|int, Category>
- $childrenByParent : array<int, array<string|int, Category>>
- $depth : int
- $langId : int|null
Return values
array<int, array<string, mixed>>buildDefaultOgImage()
Builds the default OG image from the site identity (admin, settings, site identity).
private
buildDefaultOgImage(string $alt) : OgImageDTO|null
Default only: detail pages override the image with their own
(OgDataTrait::prepareOgDataForDetail()),
after this call. Without a configured image og:image is not rendered at all.
Parameters
- $alt : string
Return values
OgImageDTO|nullbuildEditTabs()
Builds the list of available tabs. Renew and Extend appear by the expiration state.
private
buildEditTabs() : array<int, string>
Return values
array<int, string>buildRegionSubtreeFilters()
Builds the "in region" filter from the suggest (`REGION_PICKER`, `p[<id>]=<regionId>`): adverts whose region lies in the subtree of the selected node, so a county also finds the adverts of its municipalities. Same shape as the list by the region in the path ({@see RegionTrait::prepareRegionFilter()}). A nonexistent region means no filter (an invalid id from the URL must not hide the whole list).
private
buildRegionSubtreeFilters(int|null $parameterId, array<int|string, mixed> $urlParams) : array<string|int, BaseFilter>
Parameters
- $parameterId : int|null
- $urlParams : array<int|string, mixed>
Return values
array<string|int, BaseFilter>buildResponseDetailContent()
Builds the response detail HTML (a partial rendered to a string) for the modal content.
private
buildResponseDetailContent(Response $response, object|null $currency) : string
Parameters
- $response : Response
- $currency : object|null
Return values
stringbuildResponseDetailError()
private
buildResponseDetailError() : string
Return values
stringcategoryLabel()
private
categoryLabel(Category $category, int|null $langId) : string
Parameters
- $category : Category
- $langId : int|null
Return values
stringcheckAutorization()
Checks whether the current user may edit the advert.
private
checkAutorization() : bool
A logged-in owner passes without a session. A guest needs a valid session token (id + hash + expiration) stored after typing the password.
When the session check passes, a capability token for the Api layer is issued as well
(self::grantAdvertEditCapability()). Without it an anonymous editor is a plain guest
for the Api guard, which rejects save, extend and delete in internalMode: enforce.
IMPORTANT: the order is binding. The capability is issued only after the comparison
$hash !== $advertHash, that is, after the check against the fresh hash from the DB.
Issued earlier, it would lose the property this mechanism exists for: an owner password
change must immediately invalidate every session that is being edited.
Return values
boolcheckUserPaymentValidity()
private
checkUserPaymentValidity() : bool
Return values
boolcollectAdvertVisibilityIssues()
Returns the reasons why the advert is not publicly visible; an empty array means it is fine.
private
collectAdvertVisibilityIssues(Advert $advert) : array<int, string>
Parameters
- $advert : Advert
Return values
array<int, string>collectLeafItems()
Builds the flat list `{leafId => label}` for `addCheckboxList`; only leaf categories (without children) get a checkbox.
private
collectLeafItems(array<string|int, mixed> $nodes) : array<int, string>
Parameters
- $nodes : array<string|int, mixed>
-
nodes
{id, label, isLeaf, children}(children have the same shape)
Return values
array<int, string>createIdentity()
private
createIdentity(array<string, mixed> $payload, string $token) : SimpleIdentity|null
Parameters
- $payload : array<string, mixed>
- $token : string
Return values
SimpleIdentity|nullcreateMultiplierComponent()
Creates a multiplier for the component.
private
createMultiplierComponent(string $name) : Multiplier<string|int, IComponent>
Parameters
- $name : string
Return values
Multiplier<string|int, IComponent>createNewComponentInstance()
Creates a new component instance without adding it to the presenter; used by the multiplier.
private
createNewComponentInstance(string $baseName[, int|string|null $uniqueKey = null ]) : IComponent|null
Parameters
- $baseName : string
- $uniqueKey : int|string|null = null
Return values
IComponent|nullcreateStandardComponent()
Creates a standard component (not a multiplier).
private
createStandardComponent(string $name) : IComponent|null
Parameters
- $name : string
Return values
IComponent|nullexpireIdleLogin()
Checks whether the login expired from inactivity.
private
expireIdleLogin(AuthSessionStorage $authStorage) : bool
If so, it revokes the tokens (like a logout), clears the auth section, logs out the Nette
identity and returns true; otherwise it moves the activity stamp. The limit is 30 minutes
without "remember me", 31 days with it (AuthSessionStorage::isIdleExpired()).
Parameters
- $authStorage : AuthSessionStorage
Return values
boolextractBaseParameterIds()
Extracts the unique base `parameterId` from the URL keys (strips the suffixes `_from`, `_to`, `_d`, `_r`).
private
extractBaseParameterIds(array<string|int, mixed> $urlParams) : array<string|int, int>
Parameters
- $urlParams : array<string|int, mixed>
Return values
array<string|int, int>formatLayoutCandidates()
private
formatLayoutCandidates(Theme $theme, string $layout) : array<int, string>
Parameters
- $theme : Theme
- $layout : string
Return values
array<int, string>getCategoryNodes()
private
getCategoryNodes() : array<int, array<string, mixed>>
Return values
array<int, array<string, mixed>>getClientIp()
private
getClientIp() : string
Return values
stringgetFavouriteSection()
private
getFavouriteSection() : SessionSection
Return values
SessionSectiongetPasswordResetKey()
private
getPasswordResetKey() : string
Return values
stringgrantAdvertEditCapability()
Passes the fact that this visitor just proved the advert password to the Api layer. The token is minted again on every request from the current session state (already verified against the DB by the caller) and is never stored.
private
grantAdvertEditCapability(int $advertId, string $passwordHash, int $expiration) : void
NOTE: userId in the token stays empty for a guest and unchanged for a logged-in user;
the capability is not an identity. See CapabilityTokenIssuer.
Parameters
- $advertId : int
- $passwordHash : string
- $expiration : int
grantAdvertEditCapabilityFromSession()
Issues the capability from the session before the advert is loaded. The Api verifies it itself (password digest from the DB in `ownsByCapability()`), so a stale session record opens nothing. Without it `get` for editing would give an anonymous editor a masked e-mail and the form would fail validation. {@see self::checkAutorization()} then issues the capability again after the check against the fresh hash, which stays decisive for access.
private
grantAdvertEditCapabilityFromSession(int $advertId) : void
Parameters
- $advertId : int
grantAdvertSessionAfterReset()
Same session token as `AdvertAuthorizationFormTrait::authFormSucceeded()` writes after the password form. The hash is read back fresh from the Api — `checkAutorization()` compares it with the DB value on every request.
private
grantAdvertSessionAfterReset(int $advertId) : void
Parameters
- $advertId : int
hasPaidLinks()
True when the advert has an active, valid item of the "Show links" tariff (`AdvertLinksConfig`, default 4): the description then shows its web addresses as links.
private
hasPaidLinks(Advert $advert) : bool
Parameters
- $advert : Advert
Return values
boolhasPasswordResetKey()
Does the request carry the reset key from the e-mailed link (query) or the form (POST)?
private
hasPasswordResetKey() : bool
Return values
boolidentitySetting()
Returns the module 1 key value as a string (empty when the key is missing or not a scalar).
private
identitySetting(string $key) : string
Parameters
- $key : string
Return values
stringidentitySettingOrNull()
Works like {@see identitySetting()}, but an empty value is null (the template omits the field).
private
identitySettingOrNull(string $key) : string|null
Parameters
- $key : string
Return values
string|nullinitializeDisplayRegion()
Initializes the currency and VAT display of prices.
private
initializeDisplayRegion() : void
IMPORTANT: the display region is the payment region of the localization. The currency
column of the localization is not read and ?curr= from the URL is ignored on the front
end; the only source is DisplayRegionResolver. The cart and checkout may switch the
region by the customer's choice (CheckoutRegionTrait), the catalog always shows the
localization region.
Call it after initializeCurrencyList() (the resolver needs the currencies).
initializeExternalFiles()
private
initializeExternalFiles(Page|null $pageEntity) : void
Parameters
- $pageEntity : Page|null
initializeMetaTags()
private
initializeMetaTags(Page|null $pageEntity) : void
Parameters
- $pageEntity : Page|null
initializePage()
private
initializePage() : void
isAdvertOwner()
private
isAdvertOwner(Advert $advert) : bool
Parameters
- $advert : Advert
Return values
boolisCategoryBranchActive()
Whether the category and all its ancestors are active (nested set: an ancestor encloses lft/rgt).
private
isCategoryBranchActive(Category $category) : bool
Parameters
- $category : Category
Return values
boolisCategoryStepCompleted()
private
isCategoryStepCompleted() : bool
Return values
boolisDevelopment()
private
isDevelopment() : bool
Return values
boolisEntityInFavourites()
private
isEntityInFavourites(int $entityId) : bool
Parameters
- $entityId : int
Return values
boolisRegionBranchActive()
Whether the region and all its ancestors are active (nested set: an ancestor encloses lft/rgt).
private
isRegionBranchActive(Region $region) : bool
Parameters
- $region : Region
Return values
boollayoutFileExists()
private
layoutFileExists(array<int, string> $files) : bool
Parameters
- $files : array<int, string>
Return values
boolloadCategoryTree()
private
loadCategoryTree() : array<string|int, Category>
Return values
array<string|int, Category>loadIdentityAssets()
Loads the identity assets by id, keyed by id.
private
loadIdentityAssets(array<int, int> $ids) : array<int, Asset>
Fail-soft: a deleted asset (its id remains in settings) is simply not loaded and the template falls back; a missing logo must not take down the whole front end.
Parameters
- $ids : array<int, int>
Return values
array<int, Asset>loadLocalization()
Returns the localization by `loc` from the URL, or `null` when there is no such locale.
private
loadLocalization() : Localization|null
IMPORTANT: an unknown locale must return null (a non-null return type would turn a forged
prefix such as /xx/ into a TypeError, HTTP 500). BasePresenter::startup()
turns null into a 404; the error page takes the main website localization via
fallbackToMainLocalization().
Return values
Localization|nullloadSelectedCategories()
private
loadSelectedCategories(array<string|int, int> $ids) : array<string|int, Category>
Parameters
- $ids : array<string|int, int>
Return values
array<string|int, Category>localizationCurrencyKey()
Front needs no currency key from the localization; the currency and the display region are filled by {@see CurrencyInitTrait::initializeDisplayRegion()}.
private
localizationCurrencyKey(object $localization) : string|null
Parameters
- $localization : object
Return values
string|nulllocalizedIdentitySetting()
Returns the language-dependent identity value: `<key>.<page language alias>`; an empty or missing value falls back to the base key (default language). An empty string means neither is set.
private
localizedIdentitySetting(string $baseKey) : string
Parameters
- $baseKey : string
Return values
stringlogoutNetteUser()
private
logoutNetteUser() : void
parseStatDate()
Parses a date in the Y-m-d format; returns null otherwise.
private
parseStatDate(string $value) : DateTimeImmutable|null
Parameters
- $value : string
Return values
DateTimeImmutable|nullprepareAdvertSearchFilter()
Builds the fulltext filter through ES (ids become `SearchIdFilter`; visibility and paging stay in DB phase 1). When ES is off, down or the query is short, it transparently falls back to MySQL `MATCH_AGAINST` over `parameterRels.value`.
private
prepareAdvertSearchFilter(string $search, object $language) : Filter
Parameters
- $search : string
- $language : object
-
LanguageContextreturns a real entity (never a proxy)
Return values
FilterprepareCategoryFilter()
private
prepareCategoryFilter(array<int, Filter> &$filters) : void
Parameters
- $filters : array<int, Filter>
prepareOrderBy()
private
prepareOrderBy() : array<string, bool>
Return values
array<string, bool>prepareOtherAdverts()
Loads the other adverts of the owner and the count of their published adverts for the seller card.
private
prepareOtherAdverts(Advert $advert) : void
IMPORTANT: the owner is looked up by insertUserId, not by e-mail. The Api masks the e-mail
on output (PersonalDataPolicy), so a filter by the masked e-mail never matches and the list
would always be empty. An anonymous advert (no owner account) has nothing to search by: the
list stays empty and the count card is not shown.
One query loads all published adverts of the owner: the count is their number (what the visitor really sees) and the list is the same without the one being displayed.
Parameters
- $advert : Advert
prepareParameterFilter()
private
prepareParameterFilter(array<int, Filter> &$filters[, bool $withSearch = true ]) : void
Parameters
- $filters : array<int, Filter>
- $withSearch : bool = true
-
false= do not add the fulltext filter, only the parameter filters ($_GET['p']). The search endpoint uses it: the Api side does the search there (ES relevance,MATCH_AGAINSTfallback), so a second DB fulltext would be a pointless extra query and would narrow the result differently than ES.
preparePriceFilter()
Adds the upper price bound from the URL (`?priceTo=...`) sent by `SearchBox`.
private
preparePriceFilter(array<int, Filter> &$filters) : void
It filters the denormalized indexed column advert.price (decimal), not the parameter
price: a parameter value is text and can be neither compared nor indexed. The column exists
for sorting but fits a range just as well.
IMPORTANT: adverts without a price (price IS NULL, typically "by agreement") are not shown
when a bound is chosen. This is intended: the user set a ceiling and an offer without a
price cannot meet it.
Without the parameter in the URL nothing is added.
Parameters
- $filters : array<int, Filter>
prepareRegionFilter()
private
prepareRegionFilter(array<int, Filter> &$filters) : void
Parameters
- $filters : array<int, Filter>
prepareSearchFilters()
Builds the filters for the search endpoint: everything except fulltext (the Api side does it, ES or `MATCH_AGAINST`). That is visibility + category/region + parameter filters from `$_GET['p']`, which are DB phase 1.
private
prepareSearchFilters() : array<int, Filter>
Return values
array<int, Filter>prepareView()
private
prepareView() : void
processFailedLogin()
private
processFailedLogin(AuthSessionStorage $authStorage, Result $result, string $username) : void
Parameters
- $authStorage : AuthSessionStorage
- $result : Result
- $username : string
processInvalidToken()
private
processInvalidToken(AuthStorageInterface $authStorage) : void
Parameters
- $authStorage : AuthStorageInterface
processLogin()
private
processLogin(string $username, string $password[, bool $remember = false ]) : void
Parameters
- $username : string
- $password : string
- $remember : bool = false
processLoginException()
private
processLoginException(Exception $e) : void
Parameters
- $e : Exception
processMissingToken()
private
processMissingToken() : void
processSuccessfulLogin()
private
processSuccessfulLogin(AuthSessionStorage $authStorage, Result $result, string $username[, bool $remember = false ]) : void
Parameters
- $authStorage : AuthSessionStorage
- $result : Result
- $username : string
- $remember : bool = false
processValidToken()
private
processValidToken(AuthSessionStorage $authStorage, string $token) : void
Parameters
- $authStorage : AuthSessionStorage
- $token : string
readLoginDeviceToken()
Returns the raw known-device cookie for the Api login (the Api verifies its signature).
private
readLoginDeviceToken() : string|null
Return values
string|nullredeemManageKeyFromLink()
Handles the "advert management" link from the insertion e-mail (`edit?id=...&manageKey=...`), which replaces the readable password the e-mail carried before.
private
redeemManageKeyFromLink(int $advertId) : void
The Api verifies the key (:Api:Bazaar:Advert:redeemManageKey: digest, 7 days, bound to the
current password). A valid key creates the same session as typing the password
(self::grantAdvertSessionAfterReset()); an invalid or expired one gives a message and the
password form. Both cases redirect to the edit page without the key, so it stays out of the
browser history and the Referer header. The key is not consumed; it is valid until it expires.
Parameters
- $advertId : int
redirectAfterLoginAction()
Ends a sign-in attempt. A classic (non-AJAX) successful sign-in lands on "My account" ({@see PageId::SYSTEM_USER_ACCOUNT}); a failed one on the home page. An AJAX sign-in stays on the current page and only redraws the flash messages.
private
redirectAfterLoginAction([bool $succeeded = false ]) : void
Parameters
- $succeeded : bool = false
refreshNetteIdentity()
Refreshes the token for the same logged-in user.
private
refreshNetteIdentity(array<string, mixed> $payload, string $token) : bool
The identity data (token, name, email) are overwritten in the stored object without login(),
so neither the session ID nor the form CSRF tokens change. The identity lives in the session
section as an object and the change is written at the end of the request.
Parameters
- $payload : array<string, mixed>
- $token : string
Return values
bool —false when not possible (nobody logged in or another user), the caller then uses login
rememberLoginDevice()
Issues or renews the "known device" cookie after a successful login (password or OAuth).
private
rememberLoginDevice(mixed $payload) : void
The cookie (LoginDeviceCookie) is a signed proof that this browser has already logged
in to the account. The next login sends it to the Api (self::processLogin()), so above
the account limit the password from this browser is still verified and foreign attempts do not
lock the owner out. HttpOnly, SameSite=Lax, Secure on HTTPS; lifetime ratelimit.loginDevice.cookieLifetime.
Parameters
- $payload : mixed
resolveLoginErrorMessage()
Resolves the translated login error text.
private
resolveLoginErrorMessage(Result $result) : string
IMPORTANT: a throttle by the brute-force gate must not be shown as "wrong password";
the limit would then look like an inexplicably failing form. The generic
results.rateLimitExceeded carries no seconds and does not belong to login, so the login
flow has its own key login.rateLimit.message (same family as front.general.login.error.message),
with the seconds passed as %count% (Contributte: numeric second argument).
The Api sends retryAfter in data (AuthPresenter::rateLimitedResult());
the internal bridge call does not see the Retry-After header.
Parameters
- $result : Result
Return values
stringresolveStatGranularity()
Validates the granularity from the request against the allowed values.
private
resolveStatGranularity() : string
Return values
stringresolveStatRange()
Returns the date range from the request. When a bound is missing or invalid, the default range of the granularity is used.
private
resolveStatRange(string $granularity) : DateTimeImmutable}
Parameters
- $granularity : string
Return values
DateTimeImmutable} —[from, to]
revokeTokensOnLogout()
Calls the Api logout (revokes the refresh family and deny-lists the access `jti`) for the tokens of the current session.
private
revokeTokensOnLogout(AuthSessionStorage $authStorage, mixed $userId) : void
Deliberately fail-open: any failure is only logged, because the local logout must not stay unfinished.
Parameters
- $authStorage : AuthSessionStorage
- $userId : mixed
searchViaApi()
Searches adverts through the Api endpoint `api/bazaar/advert/search` instead of building the filter in the presenter. Three states:
private
searchViaApi(string $search, bool $orderChosen, Paginator|null $paginator) : Advert>, 1: int, 2: bool, 3: array>} |null
(a) search without a manual sort choice: orderBys = null, ES sorts and pages by score
(fromEs: true); visibility and parameter filters stay in the DB,
(b) search with a manual choice (/o-N in the URL): orderBys from prepareOrderBy(),
the DB sorts, pages and counts over the ES id set and relevance is not used,
(c) without a search this path is not taken at all and nothing changes.
NOTE: in state (a) the precedence of topped adverts does not apply. prepareOrderBy()
normally puts topedUntil > NOW() first, but on the relevance path ES sorts by score and the
DB does not take part in the order. Without a search, and with a manual sort choice, topping
works unchanged.
All filters are sent, including the $_GET['p'] parameter filters: they are DB phase 1 just
like visibility, and the ES ids are only candidates.
null = use the DB path: the endpoint returned no list (deny or bridge outage), or ES is not
running and without a manual choice the DB branch of the endpoint would return unsorted rows.
Parameters
- $search : string
- $orderChosen : bool
- $paginator : Paginator|null
Return values
Advert>, 1: int, 2: bool, 3: array[entities, totalCount, fromEs, highlights]
setDefaultAvatar()
private
setDefaultAvatar() : array{rel: string}
Return values
array{rel: string}setNetteUser()
private
setNetteUser(array<string, mixed>|null $payload, string $token) : void
Parameters
- $payload : array<string, mixed>|null
- $token : string
showResponseDetailModal()
Registers the response detail modal and tells the container to show it.
private
showResponseDetailModal(string $content[, int|null $responseId = null ]) : void
Parameters
- $content : string
- $responseId : int|null = null
tryRefresh()
Tries an automatic refresh when the access token has expired.
private
tryRefresh(AuthSessionStorage $authStorage) : bool
If the session holds a refresh token and the Api accepts it, the new pair is stored in the session and true is returned; otherwise false, and the caller drops the session.
Parameters
- $authStorage : AuthSessionStorage