# 機能設計書 56-Filesystem

## 概要

本ドキュメントは、Symfony Filesystemコンポーネントの機能設計を記述する。Filesystemコンポーネントはファイルシステムの基本ユーティリティを提供し、ファイルコピー、ディレクトリ作成、シンボリックリンク、パス操作等の機能を統合する。

### 本機能の処理概要

Filesystemコンポーネントは、PHP標準のファイル操作関数を統一されたエラーハンドリングとクロスプラットフォーム対応で包み込むラッパーを提供する。加えてPathクラスによるパス文字列の正規化・操作ユーティリティを含む。

**業務上の目的・背景**：PHP標準のファイル操作関数はエラー時にwarningを発生させるが、例外ベースのエラーハンドリングが困難である。Filesystemコンポーネントは全てのファイル操作エラーをIOException等の例外として統一し、信頼性の高いファイル操作を可能にする。また、Windows/Unix間のパス差異をPathクラスで吸収する。

**機能の利用シーン**：キャッシュファイルの書き込み・削除、アップロードファイルの移動、テンポラリファイル/ディレクトリの作成、シンボリックリンクの管理、アセットファイルのデプロイ、パス文字列の正規化・相対化。

**主要な処理内容**：
1. ファイルコピー(copy) - 新旧比較、パーミッション/日時保持
2. ディレクトリ再帰作成(mkdir) - 権限設定付き
3. ファイル・ディレクトリ存在確認(exists)
4. ファイル・ディレクトリ削除(remove) - 再帰的削除対応
5. ファイルのchmod、chown、chgrp
6. シンボリックリンク・ハードリンクの作成
7. テンポラリファイル/ディレクトリの作成(tempnam)
8. ファイル内容の書き込み(dumpFile) - アトミック書き込み対応
9. ファイル内容の追記(appendToFile)
10. パスの正規化、相対化、結合(Pathクラス)

**関連システム・外部連携**：OS のファイルシステム、FTPストリームラッパー。

**権限による制御**：OSレベルのファイルパーミッションに依存。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 7 | ソースファイル表示 | 補助機能 | SplFileInfoによるファイル情報の取得と読み込み可否の判定 |

## 機能種別

ファイル操作 / ユーティリティ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| originFile | string | Yes(copy) | コピー元ファイルパス | ファイルが存在すること |
| targetFile | string | Yes(copy) | コピー先ファイルパス | 書き込み可能であること |
| dirs | string\|iterable | Yes(mkdir) | 作成するディレクトリパス(複数可) | 文字列またはイテラブル |
| mode | int | No(mkdir) | ディレクトリ権限(デフォルト: 0o777) | 有効な権限値 |
| path | string | Yes(Path操作) | 操作対象のパス文字列 | 任意の文字列 |

### 入力データソース

ファイルシステム上のファイル・ディレクトリ。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| void | void | ほとんどのメソッドは戻り値なし(失敗時は例外) |
| exists | bool | 存在確認結果 |
| canonicalPath | string | 正規化されたパス文字列 |
| relativePath | string | 相対パス文字列 |
| tempFile | string | 作成されたテンポラリファイルのパス |

### 出力先

ファイルシステム上のファイル・ディレクトリ。

## 処理フロー

### 処理シーケンス

```
1. ファイル操作メソッド呼び出し(例: copy, mkdir, remove)
   └─ 引数のバリデーション
2. PHP標準関数の呼び出し(box()メソッド経由)
   └─ set_error_handler()でwarningをキャプチャ
3. エラー判定
   └─ 標準関数の返り値がfalseの場合、キャプチャしたエラーメッセージを使用
4. 例外またはvoid返却
   └─ 失敗時はIOException/FileNotFoundException等をスロー
```

### フローチャート

```mermaid
flowchart TD
    A[ファイル操作呼び出し] --> B[引数バリデーション]
    B --> C{バリデーションOK?}
    C -->|No| D[例外スロー]
    C -->|Yes| E[box経由でPHP標準関数呼び出し]
    E --> F{操作成功?}
    F -->|Yes| G[void返却]
    F -->|No| H[IOExceptionスロー]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-56-01 | 新旧ファイル比較 | copy()はデフォルトでターゲットが新しい場合はコピーをスキップ | overwriteNewerFiles=false(デフォルト)の場合 |
| BR-56-02 | パーミッション保持 | copy()はコピー元の実行権限ビットをコピー先に保持する | ローカルファイルの場合 |
| BR-56-03 | アトミック書き込み | dumpFile()はテンポラリファイルへの書き込み後にrenameする | dumpFile()呼び出し時 |
| BR-56-04 | パス正規化 | Path::canonicalize()はスラッシュを統一し、"."と".."セグメントを解決する | 全Path操作 |

### 計算ロジック

特になし。

## データベース操作仕様

本コンポーネントはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | FileNotFoundException | コピー元ファイルが存在しない場合 | ファイルパスを確認 |
| - | IOException | ファイル操作が失敗した場合(権限不足、ディスクフル等) | ファイルシステムの状態を確認 |
| - | InvalidArgumentException | Path操作で不正なパスが渡された場合 | 有効なパス文字列を指定 |

### リトライ仕様

リトライ機構は実装されていない。

## トランザクション仕様

ファイルシステム操作はトランザクション管理対象外。dumpFile()のアトミック書き込みにより部分的な整合性を確保。

## パフォーマンス要件

- Path::canonicalize()はバッファ(CLEANUP_THRESHOLD=1250)で結果をキャッシュし、同一パスの繰り返し正規化を高速化(Path.php 33-47行目)

## セキュリティ考慮事項

- symlink()はシンボリックリンクの作成であり、ディレクトリトラバーサルに注意
- tempnam()で作成されたファイルは適切な権限で保護すること
- dumpFile()はアトミック書き込みにより部分的なファイル書き込みを防止

## 備考

Filesystemクラスのbox()メソッドはPHP標準関数のwarningをキャプチャするための内部ヘルパーであり、set_error_handler()を利用してエラーメッセージを$lastErrorに格納する。

---

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

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

### 推奨読解順序

#### Step 1: メインクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Filesystem.php | `src/Symfony/Component/Filesystem/Filesystem.php` | 全ファイル操作メソッド、box()によるエラーハンドリング |

**主要処理フロー**:
- **37-83行目**: copy() - ファイル存在確認、新旧比較、ストリームコピー、パーミッション保持
- **90-100行目**: mkdir() - 再帰的ディレクトリ作成
- box()メソッド: set_error_handler()でPHP warningをキャプチャし、$lastErrorに格納

#### Step 2: パスユーティリティを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Path.php | `src/Symfony/Component/Filesystem/Path.php` | canonicalize()のバッファリング、UNIX/Windowsパス対応 |

**主要処理フロー**:
- **66-80行目**: canonicalize() - バッファ確認、"~"の展開、スラッシュ統一、".."解決

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

```
Filesystem::copy($originFile, $targetFile)
    |
    +-- is_file($originFile) [存在確認]
    +-- mkdir(dirname($targetFile)) [親ディレクトリ作成]
    +-- box('fopen', $originFile, 'r') [ソース開く]
    +-- box('fopen', $targetFile, 'w') [ターゲット開く]
    +-- stream_copy_to_stream() [コピー実行]
    +-- box('chmod', ...) [パーミッション設定]
    +-- box('touch', ...) [更新日時設定]

Path::canonicalize($path)
    +-- [バッファチェック]
    +-- [スラッシュ正規化: \\ -> /]
    +-- ["."/"." セグメント解決]
    +-- [結果バッファ格納]
```

### データフロー図

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

ファイルパス ─────────────> Filesystem::copy()          コピーされたファイル
                            |
                            +-- box(PHP関数)
                            +-- エラーハンドリング
                            |
                            v
                    IOException (失敗時)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Filesystem.php | `src/Symfony/Component/Filesystem/Filesystem.php` | ソース | ファイルシステム操作の全メソッド |
| Path.php | `src/Symfony/Component/Filesystem/Path.php` | ソース | パス文字列操作ユーティリティ |
| IOException.php | `src/Symfony/Component/Filesystem/Exception/IOException.php` | ソース | IO例外 |
| FileNotFoundException.php | `src/Symfony/Component/Filesystem/Exception/FileNotFoundException.php` | ソース | ファイル未発見例外 |
| InvalidArgumentException.php | `src/Symfony/Component/Filesystem/Exception/InvalidArgumentException.php` | ソース | 引数不正例外 |
