Skip to content
Draft
73 changes: 73 additions & 0 deletions app/DoctrineMigrations/Version20260722000000.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

declare(strict_types=1);

/*
* This file is part of EC-CUBE
*
* Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
*
* http://www.ec-cube.co.jp/
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace DoctrineMigrations;

use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* 店舗情報の構造化データ(JSON-LD / schema.org)拡張用カラムを dtb_base_info に追加する.
*
* - same_as : SNS 等の公式 URL(改行区切り, Organization.sameAs)
* - founding_date : 稼働開始日(Organization.foundingDate)
* - number_of_employees: 従業員数(Organization.numberOfEmployees)
* - copyright_year : 著作権表示の開始年(WebSite.copyrightYear)
* - site_image : サイト代表画像 URL(Organization.image)
*/
final class Version20260722000000 extends AbstractMigration
{
public const NAME = 'dtb_base_info';

public function up(Schema $schema): void
{
if (!$schema->hasTable(self::NAME)) {
return;
}

$table = $schema->getTable(self::NAME);
if ($table->hasColumn('same_as')) {
return;
}

// TEXT 型は MySQL では LONGTEXT にマップされるため、schema:update との差分を避けて分岐する
$textType = $this->connection->getDatabasePlatform() instanceof AbstractMySQLPlatform ? 'LONGTEXT' : 'TEXT';

$this->addSql('ALTER TABLE dtb_base_info ADD same_as '.$textType.' DEFAULT NULL');
$this->addSql('ALTER TABLE dtb_base_info ADD founding_date DATE DEFAULT NULL');
$this->addSql('ALTER TABLE dtb_base_info ADD number_of_employees INT DEFAULT NULL');
$this->addSql('ALTER TABLE dtb_base_info ADD copyright_year INT DEFAULT NULL');
$this->addSql('ALTER TABLE dtb_base_info ADD site_image VARCHAR(255) DEFAULT NULL');
}

public function down(Schema $schema): void
{
if (!$schema->hasTable(self::NAME)) {
return;
}

$table = $schema->getTable(self::NAME);
if (!$table->hasColumn('same_as')) {
return;
}

$this->addSql('ALTER TABLE dtb_base_info DROP COLUMN same_as');
$this->addSql('ALTER TABLE dtb_base_info DROP COLUMN founding_date');
$this->addSql('ALTER TABLE dtb_base_info DROP COLUMN number_of_employees');
$this->addSql('ALTER TABLE dtb_base_info DROP COLUMN copyright_year');
$this->addSql('ALTER TABLE dtb_base_info DROP COLUMN site_image');
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
107 changes: 107 additions & 0 deletions src/Eccube/Entity/BaseInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,21 @@ class BaseInfo extends AbstractEntity
#[ORM\Column(name: 'ucp_catalog_requires_auth', type: Types::BOOLEAN, options: ['default' => false])]
private bool $ucp_catalog_requires_auth = false;

#[ORM\Column(name: 'same_as', type: Types::TEXT, nullable: true)]
private ?string $same_as = null;

#[ORM\Column(name: 'founding_date', type: Types::DATE_MUTABLE, nullable: true)]
private ?\DateTime $founding_date = null;

#[ORM\Column(name: 'number_of_employees', type: Types::INTEGER, nullable: true)]
private ?int $number_of_employees = null;

#[ORM\Column(name: 'copyright_year', type: Types::INTEGER, nullable: true)]
private ?int $copyright_year = null;

#[ORM\Column(name: 'site_image', type: Types::STRING, length: 255, nullable: true)]
private ?string $site_image = null;

/**
* Get id.
*
Expand Down Expand Up @@ -937,4 +952,96 @@ public function isUcpCatalogRequiresAuth(): bool
{
return $this->ucp_catalog_requires_auth;
}

/**
* Get sameAs.
*
* 構造化データ(Organization.sameAs)に出力する SNS 等の公式 URL を改行区切りで保持する.
*/
public function getSameAs(): ?string
{
return $this->same_as;
}

/**
* Set sameAs.
*/
public function setSameAs(?string $sameAs): BaseInfo
{
$this->same_as = $sameAs;

return $this;
}

/**
* Get foundingDate.
*/
public function getFoundingDate(): ?\DateTime
{
return $this->founding_date;
}

/**
* Set foundingDate.
*/
public function setFoundingDate(?\DateTime $foundingDate): BaseInfo
{
$this->founding_date = $foundingDate;

return $this;
}

/**
* Get numberOfEmployees.
*/
public function getNumberOfEmployees(): ?int
{
return $this->number_of_employees;
}

/**
* Set numberOfEmployees.
*/
public function setNumberOfEmployees(?int $numberOfEmployees): BaseInfo
{
$this->number_of_employees = $numberOfEmployees;

return $this;
}

/**
* Get copyrightYear.
*/
public function getCopyrightYear(): ?int
{
return $this->copyright_year;
}

/**
* Set copyrightYear.
*/
public function setCopyrightYear(?int $copyrightYear): BaseInfo
{
$this->copyright_year = $copyrightYear;

return $this;
}

/**
* Get siteImage.
*/
public function getSiteImage(): ?string
{
return $this->site_image;
}

/**
* Set siteImage.
*/
public function setSiteImage(?string $siteImage): BaseInfo
{
$this->site_image = $siteImage;

return $this;
}
}
4 changes: 3 additions & 1 deletion src/Eccube/EventListener/TwigInitializeListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
use Eccube\Repository\PageLayoutRepository;
use Eccube\Repository\PageRepository;
use Eccube\Request\Context;
use Eccube\Service\SiteStructuredDataService;
use Eccube\Service\SystemService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\ParameterBag;
Expand All @@ -49,7 +50,7 @@ class TwigInitializeListener implements EventSubscriberInterface
/**
* TwigInitializeListener constructor.
*/
public function __construct(protected Environment $twig, protected BaseInfoRepository $baseInfoRepository, protected PageRepository $pageRepository, protected PageLayoutRepository $pageLayoutRepository, protected BlockPositionRepository $blockPositionRepository, protected DeviceTypeRepository $deviceTypeRepository, private readonly AuthorityRoleRepository $authorityRoleRepository, private EccubeConfig $eccubeConfig, protected Context $requestContext, private readonly MobileDetect $mobileDetector, private readonly UrlGeneratorInterface $router, private readonly LayoutRepository $layoutRepository, protected SystemService $systemService)
public function __construct(protected Environment $twig, protected BaseInfoRepository $baseInfoRepository, protected PageRepository $pageRepository, protected PageLayoutRepository $pageLayoutRepository, protected BlockPositionRepository $blockPositionRepository, protected DeviceTypeRepository $deviceTypeRepository, private readonly AuthorityRoleRepository $authorityRoleRepository, private EccubeConfig $eccubeConfig, protected Context $requestContext, private readonly MobileDetect $mobileDetector, private readonly UrlGeneratorInterface $router, private readonly LayoutRepository $layoutRepository, protected SystemService $systemService, private readonly SiteStructuredDataService $siteStructuredDataService)
{
}

Expand Down Expand Up @@ -177,6 +178,7 @@ public function setFrontVariables(RequestEvent $event): void
$this->twig->addGlobal('title', $Page->getName());
$this->twig->addGlobal('isMaintenance', $this->systemService->isMaintenanceMode());
$this->twig->addGlobal('isDebugMode', env('APP_DEBUG'));
$this->twig->addGlobal('site_json_ld', $this->siteStructuredDataService->createWebSiteJsonLd($this->baseInfoRepository->get()));
}

public function setAdminGlobals(RequestEvent $event): void
Expand Down
42 changes: 42 additions & 0 deletions src/Eccube/Form/Type/Admin/ShopMasterType.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use Eccube\Form\Type\ToggleSwitchType;
use Eccube\Form\Validator\Email;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
Expand Down Expand Up @@ -142,6 +143,47 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
]),
],
])
// 構造化データ(JSON-LD / schema.org)
->add('same_as', TextareaType::class, [
'required' => false,
'constraints' => [
new Assert\Length([
'max' => $this->eccubeConfig['eccube_ltext_len'],
]),
],
])
->add('founding_date', DateType::class, [
'required' => false,
'input' => 'datetime',
'widget' => 'single_text',
])
->add('number_of_employees', IntegerType::class, [
'required' => false,
'constraints' => [
new Assert\Regex([
'pattern' => "/^\d+$/u",
'message' => 'form_error.numeric_only',
]),
],
])
->add('copyright_year', IntegerType::class, [
'required' => false,
'constraints' => [
new Assert\Range([
'min' => 1900,
'max' => 9999,
]),
],
])
->add('site_image', TextType::class, [
'required' => false,
'constraints' => [
new Assert\Length([
'max' => $this->eccubeConfig['eccube_stext_len'],
]),
new Assert\Url(),
],
])
// 送料設定
->add('delivery_free_amount', PriceType::class, [
'required' => false,
Expand Down
10 changes: 10 additions & 0 deletions src/Eccube/Resource/locale/messages.en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1201,6 +1201,11 @@ admin.setting.shop.shop.email_reply_to: Emails for Replies (ReplyTo)
admin.setting.shop.shop.email_return_path: Email for Errors (ReturnPath)
admin.setting.shop.shop.good_traded: Product Descriptions
admin.setting.shop.shop.message: Message from Owner
admin.setting.shop.shop.same_as: Official URLs (SNS, etc.)
admin.setting.shop.shop.founding_date: Founding Date
admin.setting.shop.shop.number_of_employees: Number of Employees
admin.setting.shop.shop.copyright_year: Copyright Start Year
admin.setting.shop.shop.site_image: Site Image URL
admin.setting.shop.shop.option_delivery_fee: Shipping Charge
admin.setting.shop.shop.option_delivery_fee_free_amount: Free Shipping (Amount)
admin.setting.shop.shop.option_delivery_fee_free_quantity: Free Shipping (Qty)
Expand Down Expand Up @@ -1791,6 +1796,11 @@ tooltip.setting.shop.shop.email_reply_to: This is the email address by which you
tooltip.setting.shop.shop.email_return_path: This is the email address by which you will receive a notice when a transmission error occurs in sending emails from your store.
tooltip.setting.shop.shop.good_traded: Brief descriptions of your products.
tooltip.setting.shop.shop.message: This will be displayed on storefront. The placement varies according to the design templates.
tooltip.setting.shop.shop.same_as: Official account URLs (SNS, etc.) output to structured data (Organization.sameAs). Enter one URL per line to specify multiple URLs.
tooltip.setting.shop.shop.founding_date: The founding date of the shop/company, output to structured data (Organization.foundingDate).
tooltip.setting.shop.shop.number_of_employees: The number of employees, output to structured data (Organization.numberOfEmployees).
tooltip.setting.shop.shop.copyright_year: The starting year of the copyright notice, output to structured data (WebSite.copyrightYear).
tooltip.setting.shop.shop.site_image: The absolute URL of the site image, output to structured data (Organization.image).
tooltip.setting.shop.shop.option_delivery_fee_free_amount: Shipping charge will be waived if a customer purchases more than this amount.
tooltip.setting.shop.shop.option_delivery_fee_free_quantity: Shipping charge will be waived if a customer purchases more than this quantity.
tooltip.setting.shop.shop.option_delivery_fee_by_product: If turned on, you can set shipping charge per product.
Expand Down
10 changes: 10 additions & 0 deletions src/Eccube/Resource/locale/messages.ja.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1200,6 +1200,11 @@ admin.setting.shop.shop.email_reply_to: 返信先メールアドレス(ReplyTo)
admin.setting.shop.shop.email_return_path: 送信エラー通知メールアドレス(ReturnPath)
admin.setting.shop.shop.good_traded: 取り扱い商品説明文
admin.setting.shop.shop.message: 店舗からのメッセージ
admin.setting.shop.shop.same_as: SNS等の公式URL
admin.setting.shop.shop.founding_date: 稼働開始日
admin.setting.shop.shop.number_of_employees: 従業員数
admin.setting.shop.shop.copyright_year: 著作権表示の開始年
admin.setting.shop.shop.site_image: サイト代表画像URL
admin.setting.shop.shop.option_delivery_fee: 送料設定
admin.setting.shop.shop.option_delivery_fee_free_amount: 送料無料条件(金額)
admin.setting.shop.shop.option_delivery_fee_free_quantity: 送料無料条件(数量)
Expand Down Expand Up @@ -1791,6 +1796,11 @@ tooltip.setting.shop.shop.email_reply_to: 返信メールを受け付けるメ
tooltip.setting.shop.shop.email_return_path: 店舗からメールを送信しエラーが生じた場合に、その通知を受信するメールアドレスです。
tooltip.setting.shop.shop.good_traded: 店舗が取り扱う商品についての簡単な説明文です。
tooltip.setting.shop.shop.message: フロント側に表示されます。表示位置はデザインテンプレートによって異なります。
tooltip.setting.shop.shop.same_as: 構造化データ(Organization.sameAs)に出力する、SNS等の公式アカウントURLです。1行に1URLで複数指定できます。
tooltip.setting.shop.shop.founding_date: 構造化データ(Organization.foundingDate)に出力する、店舗・法人の稼働開始日です。
tooltip.setting.shop.shop.number_of_employees: 構造化データ(Organization.numberOfEmployees)に出力する従業員数です。
tooltip.setting.shop.shop.copyright_year: 構造化データ(WebSite.copyrightYear)に出力する著作権表示の開始年です。
tooltip.setting.shop.shop.site_image: 構造化データ(Organization.image)に出力するサイト代表画像の絶対URLです。
tooltip.setting.shop.shop.option_delivery_fee_free_amount: この金額を超える購入があった場合、送料を無料とします。
tooltip.setting.shop.shop.option_delivery_fee_free_quantity: この個数を超える購入があった場合、送料を無料とします。
tooltip.setting.shop.shop.option_delivery_fee_by_product: ここをオンにすると、商品ごとに送料を指定できるようになります。
Expand Down
45 changes: 45 additions & 0 deletions src/Eccube/Resource/template/admin/Setting/Shop/shop_master.twig
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,51 @@ file that was distributed with this source code.
{{ form_errors(form.message) }}
</div>
</div>
<div class="row">
<div class="col-3">
<div class="d-inline-block" data-bs-toggle="tooltip" data-bs-placement="top" title="{{ 'tooltip.setting.shop.shop.same_as'|trans }}"><span>{{ 'admin.setting.shop.shop.same_as'|trans }}</span><i class="fa fa-question-circle fa-lg ms-1"></i></div>
</div>
<div class="col mb-2">
{{ form_widget(form.same_as) }}
{{ form_errors(form.same_as) }}
</div>
</div>
<div class="row">
<div class="col-3">
<div class="d-inline-block" data-bs-toggle="tooltip" data-bs-placement="top" title="{{ 'tooltip.setting.shop.shop.founding_date'|trans }}"><span>{{ 'admin.setting.shop.shop.founding_date'|trans }}</span><i class="fa fa-question-circle fa-lg ms-1"></i></div>
</div>
<div class="col mb-2">
{{ form_widget(form.founding_date) }}
{{ form_errors(form.founding_date) }}
</div>
</div>
<div class="row">
<div class="col-3">
<div class="d-inline-block" data-bs-toggle="tooltip" data-bs-placement="top" title="{{ 'tooltip.setting.shop.shop.number_of_employees'|trans }}"><span>{{ 'admin.setting.shop.shop.number_of_employees'|trans }}</span><i class="fa fa-question-circle fa-lg ms-1"></i></div>
</div>
<div class="col mb-2">
{{ form_widget(form.number_of_employees) }}
{{ form_errors(form.number_of_employees) }}
</div>
</div>
<div class="row">
<div class="col-3">
<div class="d-inline-block" data-bs-toggle="tooltip" data-bs-placement="top" title="{{ 'tooltip.setting.shop.shop.copyright_year'|trans }}"><span>{{ 'admin.setting.shop.shop.copyright_year'|trans }}</span><i class="fa fa-question-circle fa-lg ms-1"></i></div>
</div>
<div class="col mb-2">
{{ form_widget(form.copyright_year) }}
{{ form_errors(form.copyright_year) }}
</div>
</div>
<div class="row">
<div class="col-3">
<div class="d-inline-block" data-bs-toggle="tooltip" data-bs-placement="top" title="{{ 'tooltip.setting.shop.shop.site_image'|trans }}"><span>{{ 'admin.setting.shop.shop.site_image'|trans }}</span><i class="fa fa-question-circle fa-lg ms-1"></i></div>
</div>
<div class="col mb-2">
{{ form_widget(form.site_image) }}
{{ form_errors(form.site_image) }}
</div>
</div>
{# エンティティ拡張の自動出力 #}
{% for f in form|filter(f => f.vars.eccube_form_options.auto_render) %}
{% if f.vars.eccube_form_options.form_theme %}
Expand Down
3 changes: 3 additions & 0 deletions src/Eccube/Resource/template/default/default_frame.twig
Original file line number Diff line number Diff line change
Expand Up @@ -187,5 +187,8 @@ file that was distributed with this source code.
{{ include('snippet.twig', { snippets: plugin_snippets }) }}
{% endif %}
<script src="{{ asset('assets/js/customize.js', 'user_data') }}"></script>
{% if site_json_ld is defined and site_json_ld %}
<script type="application/ld+json">{{ site_json_ld|json_ld }}</script>
{% endif %}
</body>
</html>
Loading
Loading