bagisto-theme-sections

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Theme Sections

主题Sections

packages/Webkul/Theme
owns the Appearance area: the theme gallery, and the sections a theme's storefront is built from. Sections replaced the old
settings/themes
CRUD — the routes are gone, and a section is now edited beside a live preview rather than on a form of its own.
packages/Webkul/Theme
负责外观区域:主题库,以及构成主题前台的Sections。Sections取代了旧的
settings/themes
CRUD——相关路由已移除,现在Section的编辑是在实时预览旁进行,而非在单独的表单上。

Reference files

参考文件

FileLoad when
drafts.mdThe staging model — what is held, what publishing does, the preview
sections.mdSection types, the field schema, media, and the rules per type
文件加载场景
drafts.md暂存模型——存储内容、发布操作、预览相关说明
sections.mdSection类型、字段 schema、媒体资源及各类型规则

Where things live

目录结构

PathWhat
admin/appearance/themes
The gallery — installed themes and ones on offer
admin/appearance/themes/{code}/sections
The editor for one theme, on one channel
appearance-preview
(shop)
The storefront rendered from drafts, framed in the editor
ThemeCatalog
supplies the gallery;
SectionSchema
supplies the field schema the editor renders per type;
SectionRepository
owns every read and write.
路径说明
admin/appearance/themes
主题库——已安装主题及可供选择的主题
admin/appearance/themes/{code}/sections
单主题单渠道的编辑器
appearance-preview
(shop)
基于草稿渲染的前台,在编辑器中展示
ThemeCatalog
提供主题库;
SectionSchema
提供编辑器根据不同类型渲染的字段 schema;
SectionRepository
负责所有读写操作。

Nothing goes live until it is published

未发布内容不会上线

This is the rule the whole area is built on. Every change is staged — editing content, toggling a section on or off, and dragging it to a new position. Each is held on the row and applied only when the operator publishes:
ChangeHeld in
Content, per locale
theme_section_translations.draft_options
On/off
theme_sections.draft_status
Order
theme_sections.draft_sort_order
A draft column is nulled when it would equal the live value, so toggling a section off and back on leaves nothing staged rather than an empty pending change.
hasDraft()
is true when any of the three is set, and that is what the editor's unsaved-changes count and per-row dot read.
publishDraft()
promotes all three and then purges media the published options no longer reference;
discardDraft()
clears all three and purges the same way.
这是整个区域的核心规则。所有更改都会被暂存——编辑内容、切换Section的启用/禁用状态、拖动调整位置。这些更改都会被存储,仅当操作人员执行发布操作时才会生效:
更改类型存储位置
多语言内容
theme_section_translations.draft_options
启用/禁用状态
theme_sections.draft_status
排序顺序
theme_sections.draft_sort_order
当草稿字段与线上值相同时,该字段会被置空,因此切换Section禁用后再启用不会留下待处理的空更改。当上述三个字段中的任意一个被设置时,
hasDraft()
返回true,这也是编辑器中未保存更改计数及每行标记的判断依据。
publishDraft()
会将三个字段的草稿值同步到线上,然后清理已发布内容不再引用的媒体资源;
discardDraft()
会清空三个字段的草稿值,并以相同方式清理媒体资源。

Non-negotiables

不可协商规则

  • The storefront reads live values, the preview reads drafts. The switch is
    SectionRepository::PREVIEWING
    , set in the request's internal attribute bag — never from a query parameter, or a visitor could ask a storefront page for unpublished content. Use
    getRenderable()
    for the storefront and
    getDraftedForPreview()
    for the preview; do not branch on the flag yourself.
  • The preview is admin-only.
    appearance-preview
    aborts unless
    bouncer()->hasPermission('appearance.sections')
    — an authenticated admin without that permission is not enough.
  • Sanitise on the way in.
    static_content
    HTML and CSS pass through Purify and
    sanitizeStaticCss()
    in the repository, on both the draft and the publish path. A new write path must go through
    sanitizeOptions()
    .
  • One footer per channel.
    footer_links
    is a singleton, guarded server-side in the controller — not only by hiding the type in the UI.
  • Clear the page cache on every change. FPC listens to
    section.create.after
    ,
    section.update.after
    and
    section.delete.before
    ;
    footer_links
    and
    services_content
    are drawn by the layout on every page, so those clear the whole cache rather than just the home page.
  • Fire before and after events. Every action dispatches a pair —
    section.create.*
    ,
    section.update.*
    ,
    section.delete.*
    ,
    section.draft.save.*
    ,
    section.draft.discard.*
    ,
    section.media.upload.*
    ,
    section.reorder.*
    . A new action needs both, or FPC and third-party listeners miss it.
  • Guard against a section deleted in another tab. Every action resolves through
    sectionOrFail()
    and answers with a plain "no longer exists" rather than a 500.
  • A section's media directory is removed by
    SectionObserver
    on delete, not by the controller.
REQUIRED SUB-SKILL: Use bagisto-change-verification before calling any change done.
  • 前台读取线上值,预览读取草稿值。切换标识为
    SectionRepository::PREVIEWING
    ,通过请求的内部属性包设置——绝不能通过查询参数设置,否则访客可能获取到未发布内容。前台使用
    getRenderable()
    ,预览使用
    getDraftedForPreview()
    ;请勿自行根据标识进行分支判断。
  • 预览仅对管理员开放
    appearance-preview
    会在
    bouncer()->hasPermission('appearance.sections')
    不满足时终止——仅登录但无该权限的管理员无法访问。
  • 输入时进行内容清理
    static_content
    中的HTML和CSS会在仓储层通过Purify和
    sanitizeStaticCss()
    进行清理,草稿和发布流程均会执行。新的写入流程必须经过
    sanitizeOptions()
  • 每个渠道仅一个页脚
    footer_links
    是单例,在控制器端进行服务端防护——而非仅在UI中隐藏该类型。
  • 每次更改都清除页面缓存。FPC会监听
    section.create.after
    section.update.after
    section.delete.before
    事件;
    footer_links
    services_content
    会在每个页面的布局中加载,因此这些更改会清除整个缓存而非仅首页缓存。
  • 触发前后事件。每个操作都会触发一对事件——
    section.create.*
    section.update.*
    section.delete.*
    section.draft.save.*
    section.draft.discard.*
    section.media.upload.*
    section.reorder.*
    。新操作必须触发这两类事件,否则FPC和第三方监听器会遗漏相关变更。
  • 防范在其他标签页中删除Section的情况。每个操作都会通过
    sectionOrFail()
    进行解析,若Section不存在则返回“已不存在”的提示而非500错误。
  • Section的媒体目录会在删除时由
    SectionObserver
    移除
    ,而非由控制器处理。
必备子技能: 在执行任何更改前,请使用bagisto-change-verification。