Commit Graph

13 Commits

Author SHA1 Message Date
Jakub Zych
a10ce2d9de feat: Google News sitemap
- sitemap-news.xml lists the articles (content kind article) first
  published in the last two days, newest first, at most 1000, with the
  publication name (news_publication, else app.name), the language of the
  locale, the publication date and the title
- news_sources narrows it to type:<key> and category:<key>:<id> values;
  the Images and News tab lists the values to use in a partial
- the index lists the file while news_enabled is on; otherwise it is 404
2026-11-04 12:22:40 +01:00
Jakub Zych
5bf56fde57 feat: image sitemap files (tracer)
- migration 202610280004: image_file_no, kind, published_at and parent_refs
  on the slot table; the image, News, IndexNow and HTML sitemap settings
- the rebuild stores each page's featured and body images (absolute on the
  site, deduplicated, at most 1000) and numbers the rows with images into
  sitemap-images-<n>.xml with the per-type files' stable rules
- the index lists the image files while images_enabled is on; the files
  route serves them with image:image and image:loc only
2026-11-04 12:19:05 +01:00
Jakub Zych
ded1095c39 feat: hreflang alternates and the sitemap filter contract
- every listed address of a record with more than one listed locale
  carries xhtml:link alternates for each locale plus x-default on the
  default locale (D-55 to D-57); no alternate for a missing translation
- each page of records and the additional addresses go to the published
  contract.Filter in one batch: Exclude leaves the files with its reason,
  Group moves the address, LastMod seeds a new row (D-95, D-24)
- classes.Listing implements contract.Listing and is published in Register
2026-11-04 11:20:38 +01:00
Jakub Zych
653627b8c4 feat: real lastmod from record events and debounced rebuilds
- RecordSaved with a change outside golem15.sitemap.lastmod_ignore moves
  the lastmod of the record's rows (only the changed locale's for a
  translated change); a no-op save, an ignored change or a rebuild does not
- RecordDeleted takes the record's rows out of the files at once
- record events queue one rebuild per golem15.sitemap.rebuild_delay_seconds
  (rebuild_pending_until, P33-12); the job clears it when it starts
- sitemap:rebuild [--queue], scheduled nightly at 03:00 (pact.HasSchedule)
2026-11-04 11:17:28 +01:00
Jakub Zych
84cb27a810 feat!: remove the PHP-parity sitemap, tiers, definitions screen and XSL
BREAKING CHANGE: /sitemap.xsl is gone (404), the definitions screen and
the Phase 17 settings tile are replaced by the settings singleton, and
priority, change frequency, priority tiers and the update manifest are
no longer written or read. The config keys golem15.sitemap.cache_seconds
and golem15.sitemap.priority_tiers are removed; site_url, lastmod_ignore
and rebuild_delay_seconds are new.

- sitemap:import and sitemap:import-winter write the additional addresses
  (and site_url, default_locale) instead of the definition
- the golem15_sitemap_definitions table stays in the database, unread
2026-11-04 11:12:51 +01:00
Jakub Zych
3ba70bb69f feat: sitemap settings singleton with content types and additional addresses
- one settings tile opening the golem15.sitemap.settings singleton
- Files tab (site address, file size, S1 files partial), Additional
  addresses repeater, Content types tab built from signpost at boot
- golem15_sitemap_types; a type switched off leaves the files (reason type)
- a save validates (errors.*) and dispatches a rebuild after commit
2026-11-04 11:06:29 +01:00
Jakub Zych
3359f1a196 feat: sitemap index and per-type files from a slot table (tracer)
- contract package: Filter, Listing and their types (D-95)
- golem15_sitemap_urls slot table and the new settings columns
- Rebuild over signpost Records, stable slot assignment, rebuild job
- GET /sitemap.xml index and GET /_sitemap/files/{file} from the table
2026-11-04 10:58:05 +01:00
Jakub Zych
96c790df39 feat: console help, examples and named loggers (SummerCMS v0.4.0)
Every command gets long help and examples, descriptions in imperative
sentence case, and a warn-only TestCommandsDocumented over bonfire.CheckDocs.
The plugin logs through a diary component logger instead of the process
default logger. Requires SummerCMS v0.4.0; command names and flags unchanged.
2026-10-21 17:35:43 +02:00
Jakub Zych
b9804ddf17 fix(17): T-17-15 apply the frontend_url rewrite only for a safe http(s) URL
- models.AllowedFrontendURL: empty, or an absolute http(s) URL with a host
  and without whitespace, control characters, a double quote, <, > or &
- classes.Rewrite leaves the document unchanged for a refused value,
  inserts through EscapeText/EscapeAttr and keeps a loc or href that would
  not stay an http(s) URL
- TestRewriteUnsafeFrontendURL, TestAllowedFrontendURL and a stored-row
  check in TestSitemapImportSmoke
2026-10-13 00:57:02 +02:00
c42bc265c8 fix(17): CR-01 refuse non-http sitemap URLs on save, import and output
A url item stored as javascript://%0aalert(1)%0a//x passed Url::to and
reached <loc>, which sitemap.xsl renders as a link on the site origin.

- The definitions form refuses, per row, a url that is not a path or an
  http(s) URL (classes.AllowedItemURL) and a urlPattern that is not a
  path (signpost.ValidItemPattern), keyed data.<i>.url / .urlPattern.
- Generator.addItem drops a loc or alternate that is not http(s).
- sitemap:import-winter drops such url items and clears such patterns
  with a report line; sitemap:import refuses such an entry.
2026-10-12 21:28:28 +02:00
4e55939a1f test(17-06): sitemap parity unit tests
- TestURLTo (every Url::to golden case, BackendURL, URLPath),
  TestXMLEscaping (PHP XmlEscapingTest as behaviour), TestTiers (each
  default rule, first match, off, bad pattern fails Boot), TestRewrite,
  TestHooks, TestURLCap, TestManifest (fail-safe reads, key
  normalization, dates), TestFillable (PHP MassAssignmentTest),
  TestDefinitionItemJSON, TestBackendURL (trusted forwarded proto)
- TestImportWinter on Postgres: maps and drops with report, --theme,
  --dry-run, --force, settings upsert, refusals
2026-10-12 19:38:04 +02:00
4a82240429 feat(17-03): full sitemap generation, settings, hooks and import commands
- generator in Definition::addItemToSet order: 50000 URL cap, lastmod from
  the record or the updates manifest (regular file, 5 MiB cap, fail safe),
  BeforeAddItem (skip) and AddItem (extra XML) festival events, tier or item
  priority, per-alternate expansion of list type children
- priority tiers from golem15.sitemap.priority_tiers, compiled at boot,
  defaults equal to the PHP getPriorityForUrl rules
- frontend_url rewrite of loc, xhtml:link href and the stylesheet href;
  GET /sitemap.xsl serves the PHP stylesheet byte for byte
- golem15_sitemap_settings singleton and Settings model
- sitemap:import (PHP ImportCommand) and sitemap:import-winter with the
  read-only Winter export SQL
- urlto and full goldens generated from PHP; TestSitemapImportSmoke
2026-10-12 17:07:39 +02:00
fe39e26ce0 feat(17-03): sitemap plugin tracer, /sitemap.xml byte-identical to PHP
- golem15.sitemap plugin: golem15_sitemap_definitions migration, Definition
  model (Fillable theme and data) with tolerant PHP-shaped item decoding and
  PHP toArray item encoding
- Url::to and buildUrl port, libxml-format serializer, generator for url and
  registry items
- GET /sitemap.xml serves the definition with theme default (404 without one,
  empty body without items)
- tests/php/gen-goldens.php and the tracer golden; TestSitemapGolden and the
  Postgres TestSitemapTracer
2026-10-12 16:53:09 +02:00