Skip to content

Commit cb941d0

Browse files
committed
feat: 受注一覧ステータス色分けプラグインの初回実装
EC-CUBE 4.2/4.3対応のプラグイン。受注一覧画面の各行の背景色を 注文ステータスに応じて自動的に色分けし、視認性を向上させます。 主な機能: - 受注一覧の行背景色をステータスごとに自動色分け - mtb_order_status_colorテーブルから色を取得 - Shipping.id → OrderStatus.id のマッピングを使用 - Bootstrap 5のCSS変数(--bs-table-accent-bg)を使用 - 設定不要でインストールするだけで動作 実装内容: - Event.php: テンプレートイベント購読とJavaScript注入 - order_index_script.twig: クライアント側の色分けロジック - PHPUnitテスト実装 - GitHub Actions CI設定(PHP 8.1/8.3, MySQL/PostgreSQL) - ドキュメント(仕様書、設計書、README) 技術仕様: - 固定透明度0.1でパステルカラー調のハイライト - 既存スタイルを保持しつつ背景色を追加(競合回避) - IIFEでスコープを分離(グローバル変数不使用) - エラーハンドリング実装(PHP側でログ記録)
0 parents  commit cb941d0

12 files changed

Lines changed: 1598 additions & 0 deletions

File tree

.gitattributes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/.gitattributes export-ignore
2+
/.github export-ignore
3+
/.gitignore export-ignore

.github/workflows/ci.yml

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches:
6+
- '*'
7+
tags:
8+
- '*'
9+
paths:
10+
- '**'
11+
- '!*.md'
12+
pull_request:
13+
paths:
14+
- '**'
15+
- '!*.md'
16+
17+
jobs:
18+
test:
19+
name: PHPUnit Tests (PHP ${{ matrix.php-version }}, ${{ matrix.database }})
20+
runs-on: ubuntu-latest
21+
22+
strategy:
23+
matrix:
24+
php-version: ['8.1', '8.3']
25+
ec-cube-version: ['4.3']
26+
database: ['mysql', 'postgresql']
27+
28+
steps:
29+
- name: Checkout plugin repository
30+
uses: actions/checkout@v6
31+
with:
32+
path: plugin
33+
34+
- name: Checkout EC-CUBE
35+
uses: actions/checkout@v6
36+
with:
37+
repository: EC-CUBE/ec-cube
38+
ref: ${{ matrix.ec-cube-version }}
39+
path: eccube
40+
41+
- name: Setup PHP
42+
uses: shivammathur/setup-php@v2
43+
with:
44+
php-version: ${{ matrix.php-version }}
45+
extensions: mbstring, intl, pdo_mysql, pdo_pgsql, curl, zip, opcache
46+
coverage: none
47+
48+
- name: Setup MySQL
49+
if: matrix.database == 'mysql'
50+
uses: shogo82148/actions-setup-mysql@v1
51+
with:
52+
mysql-version: '8.0'
53+
root-password: 'root'
54+
database: 'eccube_test'
55+
56+
- name: Setup PostgreSQL
57+
if: matrix.database == 'postgresql'
58+
uses: shogo82148/actions-setup-postgres@v1
59+
with:
60+
postgres-version: '15'
61+
postgres-user: 'postgres'
62+
postgres-password: 'postgres'
63+
postgres-db: 'eccube_test'
64+
65+
- name: Install EC-CUBE dependencies
66+
working-directory: eccube
67+
run: |
68+
composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader --no-interaction
69+
70+
- name: Install plugin
71+
run: |
72+
mkdir -p eccube/app/Plugin/OrderStatusColor42
73+
# プラグインリポジトリのルートがそのままプラグインディレクトリの場合
74+
# .githubディレクトリと.gitディレクトリは除外
75+
find plugin -mindepth 1 -maxdepth 1 ! -name '.github' ! -name '.git' -exec cp -r {} eccube/app/Plugin/OrderStatusColor42/ \;
76+
77+
- name: Run PHPUnit tests
78+
working-directory: eccube
79+
env:
80+
APP_ENV: 'test'
81+
DATABASE_URL: ${{ matrix.database == 'mysql' && 'mysql://root:root@127.0.0.1:3306/eccube_test' || 'postgresql://postgres:postgres@127.0.0.1:5432/eccube_test' }}
82+
DATABASE_SERVER_VERSION: ${{ matrix.database == 'mysql' && '8.0' || '15' }}
83+
DATABASE_CHARSET: ${{ matrix.database == 'mysql' && 'utf8mb4' || 'UTF8' }}
84+
MAILER_URL: 'smtp://127.0.0.1:1025'
85+
run: |
86+
vendor/bin/phpunit app/Plugin/OrderStatusColor42/tests/
87+
88+
- name: Upload logs
89+
if: failure()
90+
uses: actions/upload-artifact@v4
91+
with:
92+
name: plugin-test-php${{ matrix.php-version }}-${{ matrix.database }}-logs
93+
path: eccube/var/log/
94+
retention-days: 7
95+
if-no-files-found: ignore
96+

.github/workflows/release.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
name: Packaging for EC-CUBE Plugin
3+
on:
4+
release:
5+
types: [ published ]
6+
jobs:
7+
deploy:
8+
name: Build
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Checkout
12+
uses: actions/checkout@v2
13+
- name: Packaging
14+
run: |
15+
git archive HEAD --format=tar.gz > ../${{ github.event.repository.name }}-${{ github.event.release.tag_name }}.tar.gz
16+
- name: Upload binaries to release of TGZ
17+
uses: svenstaro/upload-release-action@v1-release
18+
with:
19+
repo_token: ${{ secrets.GITHUB_TOKEN }}
20+
file: ${{ runner.workspace }}/${{ github.event.repository.name }}-${{ github.event.release.tag_name }}.tar.gz
21+
asset_name: ${{ github.event.repository.name }}-${{ github.event.release.tag_name }}.tar.gz
22+
tag: ${{ github.ref }}
23+
overwrite: true

.gitignore

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# ローカル開発用ファイル(コミットしない)
2+
懸念事項.txt
3+
4+
# IDE設定ファイル
5+
.idea/
6+
.vscode/
7+
*.swp
8+
*.swo
9+
*~
10+
11+
# OS設定ファイル
12+
.DS_Store
13+
Thumbs.db
14+
15+
# ログファイル
16+
*.log
17+
18+
# 一時ファイル
19+
*.tmp
20+
*.bak
21+

Event.php

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
<?php
2+
3+
namespace Plugin\OrderStatusColor42;
4+
5+
use Eccube\Event\TemplateEvent;
6+
use Eccube\Repository\Master\OrderStatusRepository;
7+
use Doctrine\ORM\EntityManagerInterface;
8+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
9+
10+
class Event implements EventSubscriberInterface
11+
{
12+
/**
13+
* デフォルト色(グレー)
14+
*/
15+
const DEFAULT_COLOR = '#999999';
16+
17+
/**
18+
* 背景色の透明度(0.0〜1.0)
19+
*/
20+
const OPACITY = 0.1;
21+
22+
/**
23+
* @var OrderStatusRepository
24+
*/
25+
protected $orderStatusRepository;
26+
27+
/**
28+
* @var EntityManagerInterface
29+
*/
30+
protected $entityManager;
31+
32+
/**
33+
* Event constructor.
34+
*
35+
* @param OrderStatusRepository $orderStatusRepository
36+
* @param EntityManagerInterface $entityManager
37+
*/
38+
public function __construct(OrderStatusRepository $orderStatusRepository, EntityManagerInterface $entityManager)
39+
{
40+
$this->orderStatusRepository = $orderStatusRepository;
41+
$this->entityManager = $entityManager;
42+
}
43+
44+
/**
45+
* @return array
46+
*/
47+
public static function getSubscribedEvents()
48+
{
49+
return [
50+
'@admin/Order/index.twig' => 'onAdminOrderIndex',
51+
];
52+
}
53+
54+
/**
55+
* 受注一覧画面にJSを注入
56+
*
57+
* @param TemplateEvent $event
58+
*/
59+
public function onAdminOrderIndex(TemplateEvent $event)
60+
{
61+
// mtb_order_status_colorテーブルからステータス色を取得
62+
$statusColors = [];
63+
64+
// mtb_order_status_colorテーブルから直接データを取得
65+
// 注意: このテーブルでは色の値はnameカラムに格納されている
66+
// 注意: mtb_order_status_colorはEC-CUBE標準テーブルのため、エラーハンドリングは不要
67+
$connection = $this->entityManager->getConnection();
68+
$sql = 'SELECT id, name FROM mtb_order_status_color ORDER BY id';
69+
$results = $connection->fetchAllAssociative($sql);
70+
71+
foreach ($results as $row) {
72+
$statusId = (int)$row['id'];
73+
$color = $row['name'] ?: null; // nameカラムに色の値が格納されている
74+
75+
// 色が設定されている場合
76+
if ($color) {
77+
// HEX形式に変換(念の為、#がなければ追加)
78+
if (strpos($color, '#') !== 0) {
79+
$color = '#' . $color;
80+
}
81+
82+
// カラーコードの形式を検証(#RRGGBB または #RGB 形式)
83+
// 正規表現: #の後に3桁または6桁の16進数(0-9, A-F, a-f)
84+
if (preg_match('/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/', $color)) {
85+
$statusColors[$statusId] = $color;
86+
} else {
87+
// 無効なカラーコードの場合はデフォルト色を使用
88+
$statusColors[$statusId] = self::DEFAULT_COLOR;
89+
}
90+
}
91+
}
92+
93+
// 全ステータスを取得して、色が設定されていないものにデフォルト色(グレー)を設定
94+
// 注意: OrderStatusRepositoryはEC-CUBE標準のため、エラーハンドリングは不要
95+
$OrderStatuses = $this->orderStatusRepository->findAll();
96+
foreach ($OrderStatuses as $OrderStatus) {
97+
$statusId = $OrderStatus->getId();
98+
99+
// mtb_order_status_colorから取得した色がない場合、デフォルト色(グレー)を使用
100+
if (!isset($statusColors[$statusId])) {
101+
$statusColors[$statusId] = self::DEFAULT_COLOR;
102+
}
103+
}
104+
105+
// Shipping.id → OrderStatus.id のマッピングを作成
106+
// テンプレートイベントから受注データを取得
107+
$shippingIdToStatusIdMap = [];
108+
109+
try {
110+
$Orders = $event->getParameter('pagination') ? $event->getParameter('pagination')->getItems() : [];
111+
112+
// paginationがない場合は、直接Ordersパラメータを確認
113+
if (empty($Orders)) {
114+
$Orders = $event->getParameter('Orders') ?: [];
115+
}
116+
117+
// 各OrderからShippingsを取得し、Shipping.id → OrderStatus.id のマッピングを作成
118+
foreach ($Orders as $Order) {
119+
try {
120+
if (method_exists($Order, 'getOrderStatus') && method_exists($Order, 'getShippings')) {
121+
$OrderStatus = $Order->getOrderStatus();
122+
if ($OrderStatus && method_exists($OrderStatus, 'getId')) {
123+
$statusId = $OrderStatus->getId();
124+
125+
// OrderからShippingsを取得
126+
$Shippings = $Order->getShippings();
127+
if ($Shippings) {
128+
foreach ($Shippings as $Shipping) {
129+
if (method_exists($Shipping, 'getId')) {
130+
$shippingId = $Shipping->getId();
131+
$shippingIdToStatusIdMap[$shippingId] = $statusId;
132+
}
133+
}
134+
}
135+
}
136+
}
137+
} catch (\Exception $e) {
138+
// 個別のOrder処理でエラーが発生した場合(ログに記録して続行)
139+
if (function_exists('log_error')) {
140+
$orderId = method_exists($Order, 'getId') ? $Order->getId() : 'unknown';
141+
\log_error('OrderStatusColor42: Orderの処理中にエラーが発生しました', ['order_id' => $orderId, 'error' => $e->getMessage()]);
142+
}
143+
continue;
144+
}
145+
}
146+
} catch (\Exception $e) {
147+
// Orderの取得に失敗した場合
148+
if (function_exists('log_error')) {
149+
\log_error('OrderStatusColor42: Orderの取得に失敗しました', [$e->getMessage()]);
150+
}
151+
}
152+
153+
// テンプレートにパラメータを追加
154+
$event->setParameter('statusColors', $statusColors);
155+
$event->setParameter('shippingIdToStatusIdMap', $shippingIdToStatusIdMap);
156+
$event->setParameter('opacity', self::OPACITY);
157+
158+
// Twigテンプレートをスニペットとして追加
159+
$event->addSnippet('@OrderStatusColor42/admin/order_index_script.twig');
160+
}
161+
}

LICENSE

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
受注一覧ステータス色分けプラグイン(OrderStatusColor42)のライセンスについて
2+
3+
本プラグインのライセンスはデュアルライセンス方式を採用しています。
4+
無償で利用できるオープンソースのライセンス『GPL ライセンス』をそのまま使用するか、
5+
有償の『商用ライセンス』を選択する事ができます。
6+
7+
本プラグインを頒布する場合に、ソースコードを開示したくない場合には
8+
(GPLライセンスに準拠しない場合)、商用ライセンスが必要となります。
9+
10+
ライセンスに関して詳しくはEC-CUBE公式サイトをご確認下さい。
11+
http://www.ec-cube.net/license/business.php
12+
13+
---
14+
15+
[GPL-2.0-only]
16+
本プラグインは、GNU General Public License version 2.0(GPL-2.0)の下で
17+
配布される場合があります。GPL-2.0の全文は以下のURLで確認できます:
18+
https://www.gnu.org/licenses/gpl-2.0.html
19+
20+
[商用ライセンス]
21+
ソースコードを開示せずに配布する場合は、EC-CUBEの商用ライセンスが必要です。
22+
詳細はEC-CUBE公式サイトをご確認ください:
23+
http://www.ec-cube.net/license/business.php
24+
25+
---
26+
27+
Copyright (c) [Your Name/Company]
28+
All Rights Reserved.
29+

0 commit comments

Comments
 (0)