feat: 店舗設定に構造化データ拡張項目を追加 (sameAs/foundingDate 等) (#6147) - #6957
feat: 店舗設定に構造化データ拡張項目を追加 (sameAs/foundingDate 等) (#6147)#6957ttokoro20240902 wants to merge 7 commits into
Conversation
Organization / WebSite の JSON-LD をテンプレートの文字列補間で組み立てていたため、 店名等に " や </script> が含まれると構造化データが壊れる/XSS 経路になりうる問題があった (CodeRabbit 指摘)。#6883 で導入済みの json_ld フィルタ(JSON_HEX_* でエスケープ)に揃える。 - SiteStructuredDataService を新設し WebSite / Organization の連想配列を組み立て - TwigInitializeListener で site_json_ld を front グローバルに注入 - default_frame.twig は {{ site_json_ld|json_ld }} で出力 - 旧 Schema/organization.twig・website.twig を削除 - 値が空の任意プロパティは出力しない(ProductStructuredDataService と同方針) - 都道府県未設定(Pref=null)でもフロントが 500 にならない(元 PR の不具合も解消) - SiteStructuredDataServiceTest を追加 出力される JSON-LD は、値のある項目については従来と同一 (空の任意プロパティが省略される点のみ差分)。 Refs #6136 #6147 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Issue #6147。#6139 で新設した SiteStructuredDataService に、店舗設定 (BaseInfo) から出力する構造化データ項目を拡充する。 - BaseInfo に same_as / founding_date / number_of_employees / copyright_year / site_image を追加 - 店舗設定「基本設定」に入力欄(ShopMasterType / shop_master.twig / 翻訳 ja,en)を追加 - SiteStructuredDataService で Organization の sameAs(配列)/ foundingDate / numberOfEmployees(QuantitativeValue)/ image、WebSite の copyrightYear を出力 - マイグレーション追加(Version20260722000000, TEXT型はMySQL/PostgreSQLで分岐) - SiteStructuredDataServiceTest に各項目のテストを追加 値が空の任意プロパティは出力しない(#6139 の方針を踏襲)。 Refs #6136 #6147 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthrough店舗基本情報に構造化データ用の5項目を追加し、管理画面で編集できるようにしました。 Changesサイト情報の保存と管理画面
JSON-LD生成と出力
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant 管理画面
participant BaseInfo
participant SiteStructuredDataService
participant Twig
管理画面->>BaseInfo: 構造化データ項目を保存
Twig->>SiteStructuredDataService: WebSite JSON-LDを生成
SiteStructuredDataService->>BaseInfo: 店舗基本情報を参照
SiteStructuredDataService-->>Twig: site_json_ldを返却
Twig-->>Twig: JSON-LD scriptをレンダリング
Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/Eccube/Form/Type/Admin/ShopMasterType.php (1)
160-168: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win
number_of_employeesに上限を設ける値域チェックが必要
number_of_employeesは数値のみを許容するAssert\Regexのみで、上限がありません。DBカラムはINT(migration参照)のため、桁数の大きい値を入力すると保存時にDBエラーとなる可能性があります。同ファイル内のcopyright_year/basic_point_rate/point_conversion_rateは Range 制約で値域を制限しているため、同様の対応を推奨します。♻️ 提案する修正
->add('number_of_employees', IntegerType::class, [ 'required' => false, 'constraints' => [ new Assert\Regex([ 'pattern' => "/^\d+$/u", 'message' => 'form_error.numeric_only', ]), + new Assert\Range([ + 'min' => 0, + 'max' => 2147483647, + ]), ], ])🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/Eccube/Form/Type/Admin/ShopMasterType.php` around lines 160 - 168, Update the number_of_employees constraints in ShopMasterType to include an Assert\Range upper bound matching the database INT column, while preserving the existing numeric-only validation. Follow the established Range constraint pattern used by copyright_year, basic_point_rate, and point_conversion_rate, including an appropriate validation message.src/Eccube/EventListener/TwigInitializeListener.php (1)
181-181: 🚀 Performance & Scalability | 🔵 Trivial構造化データの生成はリクエスト毎に行われる点に留意
createWebSiteJsonLdはフロント全ページのリクエストごとに呼び出され、キャッシュされません。現状は軽量な処理(配列構築とルート生成数回)のため大きな懸念はありませんが、将来的に負荷が問題になる場合は、BaseInfoの更新時のみ再計算するキャッシュ戦略(例: タグ付きキャッシュやBaseInfo更新イベントでの無効化)を検討してください。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/Eccube/EventListener/TwigInitializeListener.php` at line 181, Review the site_json_ld initialization in TwigInitializeListener and add a cache for createWebSiteJsonLd keyed to the current BaseInfo state, with invalidation when BaseInfo is updated; ensure subsequent requests reuse the cached structured data until that update occurs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app/DoctrineMigrations/Version20260722000000.php`:
- Around line 35-73: Remove the Version20260722000000 migration because it only
adds nullable columns already represented by BaseInfo entity attributes and
should be applied through schema:update. Delete both up() and down() handling
for same_as, founding_date, number_of_employees, copyright_year, and site_image;
retain the migration only if a documented production-upgrade requirement makes
it necessary, with that exception explicitly recorded.
---
Nitpick comments:
In `@src/Eccube/EventListener/TwigInitializeListener.php`:
- Line 181: Review the site_json_ld initialization in TwigInitializeListener and
add a cache for createWebSiteJsonLd keyed to the current BaseInfo state, with
invalidation when BaseInfo is updated; ensure subsequent requests reuse the
cached structured data until that update occurs.
In `@src/Eccube/Form/Type/Admin/ShopMasterType.php`:
- Around line 160-168: Update the number_of_employees constraints in
ShopMasterType to include an Assert\Range upper bound matching the database INT
column, while preserving the existing numeric-only validation. Follow the
established Range constraint pattern used by copyright_year, basic_point_rate,
and point_conversion_rate, including an appropriate validation message.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6a3143e4-2c95-413a-bc02-0809e40c0501
📒 Files selected for processing (10)
app/DoctrineMigrations/Version20260722000000.phpsrc/Eccube/Entity/BaseInfo.phpsrc/Eccube/EventListener/TwigInitializeListener.phpsrc/Eccube/Form/Type/Admin/ShopMasterType.phpsrc/Eccube/Resource/locale/messages.en.yamlsrc/Eccube/Resource/locale/messages.ja.yamlsrc/Eccube/Resource/template/admin/Setting/Shop/shop_master.twigsrc/Eccube/Resource/template/default/default_frame.twigsrc/Eccube/Service/SiteStructuredDataService.phptests/Eccube/Tests/Service/SiteStructuredDataServiceTest.php
247de17 to
b031ca9
Compare
Issue #6147。営業時間を構造化データ(Organization.openingHoursSpecification) として出力できるようにする。既存 business_hour(自由テキスト・Help表示用)とは 別に、曜日×開店/閉店時刻を構造化して保持する。 - OpeningHours エンティティ(dtb_opening_hours)を新設し BaseInfo に OneToMany を追加 - 店舗設定「基本設定」に CollectionType の営業時間入力欄(動的な行追加/削除UI)を追加 - OpeningHoursType(曜日=複数選択, opens/closes=TimeType)・prototype テンプレート - SiteStructuredDataService で openingHoursSpecification(配列)を出力 (曜日/時刻がいずれも無いエントリは出力しない) - バリデーション: 開店<閉店・曜日必須・開店/閉店ペア必須(OpeningHours)、 同一曜日の時間帯重複禁止(ShopMasterType)。BaseInfo の OneToMany に Assert\Valid でカスケード - 削除ボタンは既存の collection UI に合わせ fa-close アイコン化、時刻欄クリックで showPicker - マイグレーション Version20260722010000(Schema APIで両DB対応) - 翻訳(ja/en, ラベルは messages・エラーは validators)・テスト追加 Refs #6136 #6147 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
b031ca9 to
4e3a5c0
Compare
- same_as: 改行区切り各行を Assert\Url で検証(site_image と対称化)
- founding_date: LessThanOrEqual('today') で未来日を禁止
- number_of_employees: Regex を Assert\PositiveOrZero に置換(非負整数)
- 営業時間の重複エラーを該当行に表示(overlap の atPath を closes に変更)
- ShopMasterTypeTest にスカラー5項目のUT 14件を追加(計32件)
- admin-basicinfo.spec.ts に営業時間の動的行UI・保存往復・JSON-LD反映・重複エラーのE2Eを追加(冪等)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- number_of_employees に Assert\LessThanOrEqual(2147483647) を追加(INT桁あふれ防止) 併せて上限のUT 2件を追加(境界2147483647は有効・2147483648は無効) - Version20260722000000(BaseInfo単純nullableカラム追加のみ)を削除 Entity属性+schema:update で反映されるためガイドライン準拠(dtb_opening_hours 作成の Version20260722010000 はテーブル新設のため維持) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
CodeRabbit のレビュー指摘に対応しました(commit 4e97130 / c4e64cb)。
なお、本 PR には別途、追加項目のバリデーション強化( |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## 4.4 #6957 +/- ##
==========================================
+ Coverage 77.14% 77.27% +0.13%
==========================================
Files 546 550 +4
Lines 27133 27413 +280
==========================================
+ Hits 20932 21184 +252
- Misses 6201 6229 +28
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
概要 (Refs #6147, #6136)
店舗設定(BaseInfo)を拡張し、Organization / WebSite の構造化データに以下を出力できるようにします。
スカラー項目
Organization.sameAs(SNS等の公式URL・複数=改行区切り)Organization.foundingDate(稼働開始日)Organization.numberOfEmployees(従業員数, QuantitativeValue)Organization.image(サイト代表画像URL)WebSite.copyrightYear(著作権表示の開始年)営業時間
Organization.openingHoursSpecification(曜日×開店/閉店時刻・複数行)business_hour(自由テキスト・Help表示用)とは別に、構造化データ用の曜日/時刻を保持依存 / 順序(Stacked PR)
SiteStructuredDataServiceに項目を追加する構成)。変更内容
BaseInfoにスカラー5カラム追加 +OpeningHours(dtb_opening_hours) を OneToMany で追加SiteStructuredDataServiceに各項目を反映(値が空の任意プロパティは出力しない)Version20260722000000(BaseInfo列)/Version20260722010000(dtb_opening_hours, Schema APIで両DB対応)SiteStructuredDataServiceTestに各項目のテストを追加テスト
残作業(別軸, #6147)
🤖 Generated with Claude Code