MediaSourceImporter
in package
ローカルファイルパスからメディアを取り込み、media_id を返す
CSV インポート(CMS-7715)向け。実際の検証(パストラバーサル対策/mime 検証/ サイズ上限)はここに閉じ、呼び出し側は import() の戻り値(media_id)だけを扱えばよい。 失敗時は例外を投げるだけに留め、「行をどう扱うか」の判断は呼び出し側に委ねる。
Why not: URL(https 経由)からの取得は当初の設計に含めていたが、社内 MTG の判断で 一旦スコープ外となったため削除した(SSRF 対策・PSR-18 クライアント実装を含む一式)。 復活する場合は git 履歴(MediaSourceImporter の URL 経路実装コミット)を参照すること。
Table of Contents
Properties
- $cache : array<string, int>
- $localPathBase : string
- $localStorage : Filesystem
- $maxFileSize : int
- $mediaHelper : Helper
Methods
- __construct() : mixed
- import() : int
- ローカルファイルパスからメディアを取得し登録する
- importDryRun() : MediaImportPreview
- import() のドライラン版(CSV インポートのドライラン機能向け)
- createTempFilePath() : string
- extractFilename() : string
- source からファイル名部分だけを取り出す(拡張子判定・表示名として使う)
- extractUrlPath() : string
- http(s):// URL からパス部分を取り出す
- fetchFromLocalPath() : string
- ローカルファイルパスを取り込みベースディレクトリ配下の実在ファイルとして検証し、 サイズ上限内であることを確認したうえで一時ファイルへコピーしてそのパスを返す
- resolveExistingLocalPath() : string
- ローカルファイルパスを取り込みベースディレクトリ配下の実在ファイルとして検証し、 サイズ上限内であることを確認したうえで、実ファイルの解決済み絶対パスを返す (ファイルのコピーは行わない)。import()/importDryRun() 共通の検証ロジック。
- resolveLocalCandidate() : string
- CSV の値を、取り込みベースディレクトリ配下の候補パスに変換する
Properties
$cache
private
array<string, int>
$cache
= []
参照先文字列 → media_id(同一インスタンス内の重複排除キャッシュ)
$localPathBase
private
string
$localPathBase
$localStorage
private
Filesystem
$localStorage
$maxFileSize
private
int
$maxFileSize
$mediaHelper
private
Helper
$mediaHelper
Methods
__construct()
public
__construct(Filesystem $localStorage, Helper $mediaHelper, string $localPathBase, int $maxFileSize) : mixed
Parameters
- $localStorage : Filesystem
- $mediaHelper : Helper
- $localPathBase : string
- $maxFileSize : int
import()
ローカルファイルパスからメディアを取得し登録する
public
import(string $source) : int
同一インスタンス内で同一の $source が再度渡された場合は、登録済みの media_id を返す (取得・登録処理は再実行しない)。
Parameters
- $source : string
Tags
Return values
intimportDryRun()
import() のドライラン版(CSV インポートのドライラン機能向け)
public
importDryRun(string $source) : MediaImportPreview
ファイルの実在・パストラバーサル・サイズ上限の検証と、内容ハッシュによる重複検知までは import() と同じ経路を通るが、実ファイルのコピー・保存・media テーブルへの登録は 一切行わない。呼び出し側は戻り値の MediaImportPreview から「既存メディアが 再利用される見込みか」「新規登録される見込みか」を判定できる。
Parameters
- $source : string
Tags
Return values
MediaImportPreviewcreateTempFilePath()
private
createTempFilePath(string $source) : string
Parameters
- $source : string
Return values
stringextractFilename()
source からファイル名部分だけを取り出す(拡張子判定・表示名として使う)
private
extractFilename(string $source) : string
http(s):// URL はクエリ文字列を含むため、パス部分だけを取り出してから ファイル名を得る(resolveLocalCandidate() と同じ「URL のパス表記」の扱いに揃える)。
Parameters
- $source : string
Return values
stringextractUrlPath()
http(s):// URL からパス部分を取り出す
private
extractUrlPath(string $source) : string
Why not Rfc3986Uri::getPath() をそのまま使わないか:
- getPath() は
..セグメントを正規化してしまうため、validateDirectoryTraversalPath() に渡す前にトラバーサルの手がかりが失われる。getRawPath() で正規化前の生パスを渡し、 ベース外への脱出判定は後続の validateDirectoryTraversalPath() に委ねる。 - Rfc3986Uri::parse() は生の Unicode 文字(パーセントエンコードされていない日本語
ファイル名等)を含む URL を無効な URI として null を返す。移行元 DB にはそのような
URL がそのまま残っていることが多いため、失敗時は WHATWG 準拠のパーサーへ
フォールバックする(WhatWgUrl::getPath() は正規化済みだが、Unicode を含むケースは
稀に
..を併用するとは考えにくいため許容する)。
getRawPath() はパーセントエンコードもそのまま残すため、正しくエンコードされた日本語
ファイル名(%E7%94%BB...)を含むURLは rawurldecode() しないと実ファイル名と一致しない。
デコードで ..(%2e%2e 等)が現れても、resolveLocalCandidate() で localPathBase と
連結した後に validateDirectoryTraversalPath() 側で Path::makeAbsolute() により
正規化・境界判定されるため、デコード自体がトラバーサル検証を迂回させることはない
(素の .. セグメントを含む URL と同じ経路・同じメッセージで拒否される)。
Parameters
- $source : string
Return values
stringfetchFromLocalPath()
ローカルファイルパスを取り込みベースディレクトリ配下の実在ファイルとして検証し、 サイズ上限内であることを確認したうえで一時ファイルへコピーしてそのパスを返す
private
fetchFromLocalPath(string $source) : string
Parameters
- $source : string
Tags
Return values
stringresolveExistingLocalPath()
ローカルファイルパスを取り込みベースディレクトリ配下の実在ファイルとして検証し、 サイズ上限内であることを確認したうえで、実ファイルの解決済み絶対パスを返す (ファイルのコピーは行わない)。import()/importDryRun() 共通の検証ロジック。
private
resolveExistingLocalPath(string $source) : string
Parameters
- $source : string
Tags
Return values
stringresolveLocalCandidate()
CSV の値を、取り込みベースディレクトリ配下の候補パスに変換する
private
resolveLocalCandidate(string $source) : string
file:// プレフィックスは剥がす。相対パスはベースディレクトリからの相対として解決し、 絶対パスはそのまま validateDirectoryTraversalPath() の判定に委ねる。
http(s):// URL はホストを無視し、パス部分だけを取り込みベースディレクトリからの 相対パスとして解決する(実際に URL へ HTTP アクセスすることはない)。移行元 DB に 残る絶対 URL をそのまま CSV に書き写せるよう、移行元のディレクトリ構造を FTP で ベースディレクトリ配下に再現しておく運用を想定する(URL 取得自体のスコープ外方針 は変えない。あくまで「URL に見えるパス表記」からの解決先の話)。
Parameters
- $source : string