feat: 店舗設定に構造化データ拡張項目を追加 (sameAs/foundingDate 等) (#6147) - #6957
feat: 店舗設定に構造化データ拡張項目を追加 (sameAs/foundingDate 等) (#6147)#6957ttokoro20240902 wants to merge 9 commits into
Conversation
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>
📝 WalkthroughWalkthrough店舗基本情報に構造化データ項目と営業時間を追加しました。管理画面で入力・検証・保存し、 Changesサイト構造化データと営業時間
Estimated code review effort: 4 (Complex) | ~60 minutes Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 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.75% 77.85% +0.09%
==========================================
Files 597 600 +3
Lines 29339 29553 +214
==========================================
+ Hits 22814 23009 +195
- Misses 6525 6544 +19
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:
|
validators.{ja,en}.yaml のコンフリクトを解消。
双方とも末尾へのキー追記のみだったため、4.4 側の
form_error.refund_request.* と本ブランチの
admin.setting.shop.* を両方残した。
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
tests/Eccube/Tests/Service/SiteStructuredDataServiceTest.php (1)
202-208: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win空の営業時間エンティティも検証してください。
このテストはコレクションを空にします。
buildOpeningHours()の「空のOpeningHoursエンティティを除外する」分岐は実行しません。値を設定しないOpeningHoursを追加して、openingHoursSpecificationが出力されないことを検証してください。🤖 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 `@tests/Eccube/Tests/Service/SiteStructuredDataServiceTest.php` around lines 202 - 208, Update testEmptyOpeningHoursIsOmitted to add an OpeningHours entity with no values after clearing the collection, so buildOpeningHours() exercises its empty-entity exclusion branch. Keep the assertion that openingHoursSpecification is absent from the generated organization JSON-LD.
🤖 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 `@e2e/tests/admin-basicinfo.spec.ts`:
- Around line 1329-1424: Wrap the test body after the initial reset save in a
try/finally so cleanup always runs when persistence or duplicate-validation
assertions fail. Move the existing cleanup logic beginning with the
deleteButtons loop into the finally block, preserving its removal of
opening-hour rows and scalar fields before saving.
In `@src/Eccube/Form/Type/Admin/ShopMasterType.php`:
- Around line 372-399: OpeningHours の元のコレクションキーが失われ、$j
がフォーム上の実際の行を指さなくなっています。array_values() を使わず元キーを保持したリストで比較し、atPath() の
OpeningHours[$j].closes には該当する元キーを使用してください。削除後にキーが飛んだ状態で重複行を検出した場合も、正しい closes
フィールドへ違反が表示されるテストを追加してください。
In `@tests/Eccube/Tests/Form/Type/Admin/ShopMasterTypeTest.php`:
- Around line 173-332: Update each newly added test method in
ShopMasterTypeTest, including testValidOpeningHours and the related
opening-hours, same_as, employee, copyright, founding-date, and site-image
tests, to declare a void return type. Keep their existing test logic unchanged.
---
Nitpick comments:
In `@tests/Eccube/Tests/Service/SiteStructuredDataServiceTest.php`:
- Around line 202-208: Update testEmptyOpeningHoursIsOmitted to add an
OpeningHours entity with no values after clearing the collection, so
buildOpeningHours() exercises its empty-entity exclusion branch. Keep the
assertion that openingHoursSpecification is absent from the generated
organization JSON-LD.
🪄 Autofix
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 Plus
Run ID: e6e2fd26-5e0e-4410-b45e-29fffbc286e5
📒 Files selected for processing (16)
app/DoctrineMigrations/Version20260722010000.phpe2e/tests/admin-basicinfo.spec.tssrc/Eccube/Entity/BaseInfo.phpsrc/Eccube/Entity/OpeningHours.phpsrc/Eccube/Form/Type/Admin/OpeningHoursType.phpsrc/Eccube/Form/Type/Admin/ShopMasterType.phpsrc/Eccube/Repository/OpeningHoursRepository.phpsrc/Eccube/Resource/locale/messages.en.yamlsrc/Eccube/Resource/locale/messages.ja.yamlsrc/Eccube/Resource/locale/validators.en.yamlsrc/Eccube/Resource/locale/validators.ja.yamlsrc/Eccube/Resource/template/admin/Setting/Shop/opening_hours_prototype.twigsrc/Eccube/Resource/template/admin/Setting/Shop/shop_master.twigsrc/Eccube/Service/SiteStructuredDataService.phptests/Eccube/Tests/Form/Type/Admin/ShopMasterTypeTest.phptests/Eccube/Tests/Service/SiteStructuredDataServiceTest.php
|
@nanasess @dotani1111 レビューをお願いした直後に恐縮ですが、本 PR を一旦 draft に戻します。 先に #6139 を進めるべきと判断しました。まだ着手されていなければ、そのままお待ちいただければ幸いです。 理由本 PR と #6139 が、同じファイルをそれぞれ「新規追加」しています。
4.4 にはどちらも存在しない(あるのは とくに、サイト共通の構造化データについてのレビューは #6139 側に蓄積されています。nanasess さんが 8/3 に出力値そのものを精査してくださっており、未解決スレッドが 11 件残っています。本 PR を先に通すと、そのレビューを迂回して同じ実装を取り込むことになります( 進め方
|
#6139 が 4.4 へマージされ、SiteStructuredDataService とそのテストが本体側に 入ったため、本ブランチの「新規追加」を 4.4 版への追記へ組み替える。 - BaseInfo: 4.4 の mcp_enabled と本ブランチの構造化データ項目を両方残す - SiteStructuredDataService: 4.4 版(@graph・publisher 参照・normalizeDescription・ buildLogoUrl・email02)を土台にし、本ブランチ固有の copyrightYear / image / foundingDate / numberOfEmployees / sameAs / openingHours を載せる - WebSite.author に Organization を内包する形は 4.4 の publisher 参照へ寄せた - description は normalizeDescription 経由、email は email01 でなく email02 - テスト: copyrightYear 検証を @graph 構造へ追随させる Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- ShopMasterType: 営業時間の重複検証をクラス制約の Callback から POST_SUBMIT へ移す。
画面で中間行を削除すると送信キーが歯抜け(0, 2 等)になる一方、エンティティ側は
adder で 0 始まりに詰め直されるため、コレクションの添字から組んだ property path が
実在しない子を指し、エラーが該当行に表示されていなかった。フォームの子を走査して
closes へ直接 addError する形にする
- 指摘の「エンティティのキーを保持する」案では直らないことを実測で確認したため、
フォーム側のキーに合わせる形を採用した
- ShopMasterTypeTest: 歯抜けキーでエラー位置を固定するテストを追加。
本 PR で追加した 21 メソッドに : void を付与
- admin-basicinfo.spec.ts: 検証失敗時も後始末が走るよう try/finally で囲む
(BaseInfo と営業時間が後続テストへ引き継がれ、実行順序に依存するため)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
納品書PDFの出力項目トグル (6197) が 4.4 へ入ったため取り込む。 衝突 5 ファイルはいずれも両側が同じ位置へ追記した形なので、双方を残して解消した。 - Entity/BaseInfo: 4.4 の order_pdf_visible_* と本ブランチの構造化データ項目・ OpeningHours コレクションを併存させる - locale (ja/en): tooltip を双方とも残す - ShopMasterTypeTest: 双方のテストメソッドを残す - e2e/admin-basicinfo.spec.ts: 双方の test を残す。テストIDが両側とも EA0701-UC01-T18 で重複したため、本ブランチ側を EA0701-UC01-T19 へ振り直した
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/Eccube/Resource/template/admin/Setting/Shop/shop_master.twig (1)
25-32: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win既存行数ではなく、最大インデックスから新しい行を生成してください。
画面で中間行を削除すると、営業時間の送信キーは
0, 2のように欠番になります。この状態でlengthを使うと、新しい行にもOpeningHours[2]が入力名に割り当てられ、既存の営業時間が上書きまたは欠落します。既存のOpeningHours行から最大インデックスを読み取り、そこに1を加えた値で__name__を置換してください。🤖 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/Resource/template/admin/Setting/Shop/shop_master.twig` around lines 25 - 32, Update the index initialization in the opening-hours add-row handler around $holder and `#add-opening-hour-button`: derive the maximum existing OpeningHours row index from the current input names, then initialize the next index to that maximum plus one instead of using .length. Preserve the existing prototype replacement, append, and increment behavior.
🤖 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.
Outside diff comments:
In `@src/Eccube/Resource/template/admin/Setting/Shop/shop_master.twig`:
- Around line 25-32: Update the index initialization in the opening-hours
add-row handler around $holder and `#add-opening-hour-button`: derive the maximum
existing OpeningHours row index from the current input names, then initialize
the next index to that maximum plus one instead of using .length. Preserve the
existing prototype replacement, append, and increment behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 11c0c4cf-aeef-4f12-bc19-36ad77ea9f29
📒 Files selected for processing (7)
e2e/tests/admin-basicinfo.spec.tssrc/Eccube/Entity/BaseInfo.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.twigtests/Eccube/Tests/Form/Type/Admin/ShopMasterTypeTest.php
🚧 Files skipped from review as they are similar to previous changes (5)
- src/Eccube/Resource/locale/messages.en.yaml
- src/Eccube/Resource/locale/messages.ja.yaml
- e2e/tests/admin-basicinfo.spec.ts
- src/Eccube/Form/Type/Admin/ShopMasterType.php
- src/Eccube/Entity/BaseInfo.php
概要 (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
Summary by CodeRabbit
新機能
改善