# 画面設計書 48-拡張機能管理

## 概要

本ドキュメントは、Shopware 6 Administration（管理画面）における「拡張機能管理」画面の設計書です。この画面はプラグイン・アプリのインストール、更新、有効化を行う拡張機能管理機能を提供します。

### 本画面の処理概要

**業務上の目的・背景**：Shopware 6はプラグインとアプリによる拡張機能を通じて機能を追加できます。プラグインはPHPで記述されサーバー側で動作し、アプリは外部サービスとの連携やiframe内での機能提供が可能です。本画面は、インストール済みの拡張機能の管理（有効化/無効化、更新、アンインストール）を行う機能を提供します。また、Shopware Storeから新しい拡張機能を探してインストールすることもできます。

**画面へのアクセス方法**：管理画面にログイン後、左側メニューの「拡張機能」→「マイ拡張機能」をクリックすることでアクセスできます。URLパスは `/admin#/sw/extension/my-extensions/listing/app` となります。`system.plugin_maintain` 権限を持つユーザーのみがアクセス可能です。

**主要な操作・処理内容**：
1. 拡張機能一覧の表示 - インストール済みのアプリ/プラグインを一覧表示
2. 拡張機能の検索 - キーワードによる絞り込み
3. 有効化/無効化 - 拡張機能の有効/無効を切り替え
4. アンインストール - 拡張機能を削除
5. 更新 - 新バージョンへの更新
6. 設定 - 拡張機能固有の設定画面へ遷移
7. テーマ管理 - テーマ型拡張機能の管理

**画面遷移**：
- 遷移元: ダッシュボード、メインメニュー
- 遷移先: 拡張機能設定画面（sw.extension.config）、ストア画面（sw.extension.store）

**権限による表示制御**：
- `system.plugin_maintain`: プラグイン管理権限 - 拡張機能の管理が可能
- `system.extension_store`: ストアアクセス権限 - 拡張機能ストアへのアクセスが可能

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 66 | 拡張機能設定 | 主機能 | プラグイン・アプリの管理 |

## 画面種別

一覧（タブ切替: アプリ / テーマ）

## URL/ルーティング

- **パス**: `/admin#/sw/extension/my-extensions/listing/app` または `/admin#/sw/extension/my-extensions/listing/theme`
- **コンポーネント**: `sw-extension-my-extensions-listing`
- **ルート名**: `sw.extension.my-extensions.listing.app` または `sw.extension.my-extensions.listing.theme`
- **必要権限**: `system.plugin_maintain`

## 入出力項目

| 項目名 | 種別 | 型 | 必須 | 説明 |
|--------|------|-----|------|------|
| term | 入力 | string | - | 検索キーワード |
| page | 入力 | number | - | ページ番号（デフォルト: 1） |
| limit | 入力 | number | - | 1ページあたりの表示件数（デフォルト: 25） |
| sortingOption | 入力 | string | - | ソート方法（updated-at, name-asc, name-desc） |
| filterByActiveState | 入力 | boolean | - | 有効な拡張機能のみ表示 |

## 表示項目

| 項目名 | 説明 | 編集可否 |
|--------|------|----------|
| アイコン | 拡張機能のアイコン画像 | - |
| 名前 | 拡張機能の名称 | - |
| バージョン | インストールされているバージョン | - |
| 有効状態 | 有効/無効の状態 | 可 |
| 更新日時 | 最終更新日時 | - |
| アクション | 有効化/無効化、アンインストール、設定 | - |

## イベント仕様

### 1-ページ読み込み（mountedComponent）

画面初期表示時に拡張機能一覧を取得する。

**処理フロー**:
1. `shopwareExtensionService.updateExtensionData()` を呼び出し
2. `shopwareExtensions` ストアから `myExtensions` データを取得
3. ルートに応じてアプリまたはテーマをフィルタリング
4. ソート条件に従って並び替え
5. ページネーションを適用して表示

### 2-検索実行

検索ボックスにキーワードを入力し検索を実行。

**処理フロー**:
1. `term` がクエリパラメータとして設定される
2. `extensionListSearched` computed プロパティでフィルタリング
3. `label` または `name` に検索キーワードが含まれるものを抽出
4. ページを1にリセット

### 3-ソート変更（changeSortingOption）

ソート条件を変更。

**処理フロー**:
1. `sortingOption` を更新（updated-at, name-asc, name-desc）
2. `sortExtensions()` メソッドで並び替え
3. 一覧を再描画

### 4-有効/無効切り替え

拡張機能の有効状態を切り替え。

**処理フロー**:
1. カードコンポーネントの有効化/無効化ボタンをクリック
2. `shopwareExtensionService.activateExtension()` または `deactivateExtension()` を実行
3. 成功/失敗の通知を表示
4. 一覧を更新

### 5-アンインストール

拡張機能をアンインストール。

**処理フロー**:
1. アンインストールモーダルを表示
2. データ削除オプションの選択（オプション）
3. 確定時、`shopwareExtensionService.uninstallExtension()` を実行
4. 成功/失敗の通知を表示
5. 一覧を更新

### 6-設定画面遷移

拡張機能の設定画面へ遷移。

**処理フロー**:
1. 設定ボタンをクリック
2. `$router.push({ name: 'sw.extension.config', params: { namespace } })` で設定画面へ遷移

### 7-フィルター切り替え（changeActiveState）

有効な拡張機能のみ表示するフィルターを切り替え。

**処理フロー**:
1. `filterByActiveState` を更新
2. `filterExtensionsByActiveState()` でフィルタリング
3. 一覧を再描画

## データベース更新仕様

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 拡張機能取得 | plugin, app | SELECT | 拡張機能データの取得 |
| 有効化 | plugin, app | UPDATE | activeフラグを更新 |
| 無効化 | plugin, app | UPDATE | activeフラグを更新 |
| アンインストール | plugin, app | DELETE | 拡張機能データの削除 |
| 更新 | plugin, app | UPDATE | バージョン情報等の更新 |

### テーブル別更新項目詳細

#### plugin

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | type, active等の条件 | |
| UPDATE | active | true/false | 有効化/無効化 |
| DELETE | - | id指定 | アンインストール |

#### app

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | type, active等の条件 | |
| UPDATE | active | true/false | 有効化/無効化 |
| DELETE | - | id指定 | アンインストール |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|----------|
| sw-extension.notification.activateSuccess | 成功 | 拡張機能を有効化しました | 有効化成功時 |
| sw-extension.notification.activateError | エラー | 有効化に失敗しました | 有効化失敗時 |
| sw-extension.notification.deactivateSuccess | 成功 | 拡張機能を無効化しました | 無効化成功時 |
| sw-extension.notification.deactivateError | エラー | 無効化に失敗しました | 無効化失敗時 |
| sw-extension.notification.uninstallSuccess | 成功 | アンインストールしました | アンインストール成功時 |
| sw-extension.notification.uninstallError | エラー | アンインストールに失敗しました | アンインストール失敗時 |

## 例外処理

| 例外ケース | 処理内容 |
|-----------|---------|
| 検索結果0件 | 空状態の画面を表示 |
| App URL到達不可 | 警告メッセージを表示（isAppUrlReachable） |
| 拡張機能管理無効 | 管理機能を非表示（extensionManagementDisabled） |
| 有効化失敗 | エラー通知を表示 |
| アンインストール失敗 | エラー通知を表示 |
| 権限不足 | 該当機能のボタンを非表示/無効化 |

## 備考

- 拡張機能はプラグイン（PHPベース）とアプリ（外部サービス連携）の2種類がある
- テーマはisThemeフラグで区別され、別タブで表示される
- ストアからの購入・ダウンロードは別画面（sw.extension.store）で行う
- 拡張機能設定は各拡張機能のconfigルートで個別に表示
- ソートはupdated-at（デフォルト）、name-asc、name-descの3種類

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

拡張機能の状態管理構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | store/index.js | `src/Administration/Resources/app/administration/src/module/sw-extension/store/index.js` | ストア初期化 |
| 1-2 | extensions.store.js | `src/Administration/Resources/app/administration/src/module/sw-extension/store/extensions.store.js` | 拡張機能ストア |

**読解のコツ**: 拡張機能データはPinia/Vuexストアで管理され、`shopwareExtensions`ストアの`myExtensions`に格納される。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.js | `src/Administration/Resources/app/administration/src/module/sw-extension/index.js` | モジュール登録、ルート定義 |

**主要処理フロー**:
1. **86-242行**: `Module.register('sw-extension', ...)` でモジュールを登録
2. **115-173行**: `routes['my-extensions']` で一覧画面のルート定義（listing, recommendation, account）
3. **217-241行**: `navigation` でメニュー登録

#### Step 3: 一覧画面コンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sw-extension-my-extensions-listing/index.js | `src/Administration/Resources/app/administration/src/module/sw-extension/page/sw-extension-my-extensions-listing/index.js` | Vue.jsコンポーネントの定義 |

**主要処理フロー**:
- **13-17行**: `data()` - コンポーネントの状態定義（filterByActiveState, sortingOption）
- **31-43行**: `extensionList` - 拡張機能リストの生成（フィルター、ソート適用）
- **52-63行**: `extensionListSearched` - 検索フィルター適用
- **188-201行**: `filterExtensionsByType()` - タイプ（app/theme）によるフィルタリング
- **204-244行**: `sortExtensions()` - ソート処理

### プログラム呼び出し階層図

```
sw-extension-my-extensions-listing (Vue Component)
    │
    ├─ mountedComponent()
    │      └─ shopwareExtensionService.updateExtensionData()
    │             └─ Shopware Store (shopwareExtensions)
    │                    └─ API (_action/extension/*)
    │
    ├─ 有効化/無効化
    │      └─ shopwareExtensionService.activateExtension() / deactivateExtension()
    │             └─ API (POST /api/_action/extension/activate|deactivate)
    │
    ├─ アンインストール
    │      └─ shopwareExtensionService.uninstallExtension()
    │             └─ API (POST /api/_action/extension/uninstall)
    │
    └─ 設定画面遷移
           └─ $router.push({ name: 'sw.extension.config', params: { namespace } })
```

### データフロー図

```
[入力]                      [処理]                           [出力]

検索キーワード ─────────┐
                        │
ソート設定 ─────────────┼──▶ sw-extension-my-extensions-listing
                        │         │
フィルター設定 ─────────┘         ├──▶ extensionListSearched (検索)
                                  │         │
                                  │         ▼
                                  │    filterExtensionsByType (タイプフィルター)
                                  │         │
                                  │         ▼
                                  │    sortExtensions (ソート)
                                  │         │
                                  │         ▼
                                  └──▶ extensionListPaginated ──▶ カード一覧表示

shopwareExtensions Store ──▶ myExtensions.data ──▶ 拡張機能データ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.js | `src/Administration/Resources/app/administration/src/module/sw-extension/index.js` | ソース | モジュール定義 |
| sw-extension-my-extensions-listing/index.js | `src/Administration/Resources/app/administration/src/module/sw-extension/page/sw-extension-my-extensions-listing/index.js` | ソース | 一覧画面コンポーネント |
| sw-extension-my-extensions-listing.html.twig | `src/Administration/Resources/app/administration/src/module/sw-extension/page/sw-extension-my-extensions-listing/sw-extension-my-extensions-listing.html.twig` | テンプレート | 画面テンプレート |
| sw-extension-card-base/index.js | `src/Administration/Resources/app/administration/src/module/sw-extension/component/sw-extension-card-base/index.js` | ソース | カードベースコンポーネント |
| sw-extension-card-bought/index.js | `src/Administration/Resources/app/administration/src/module/sw-extension/component/sw-extension-card-bought/index.js` | ソース | 購入済みカード |
| acl/index.js | `src/Administration/Resources/app/administration/src/module/sw-extension/acl/index.js` | ソース | 権限定義 |
| extensions.store.js | `src/Administration/Resources/app/administration/src/module/sw-extension/store/extensions.store.js` | ソース | 状態管理 |
