/** * ファイルサイズをチェックします。 * @param int $size * @param string $topLevelType * @param string $filename * @throws SyntaxException */ protected function checkFileSize(int $size, string $topLevelType, string $filename) { $byteFormatter = new \ScriptFUSION\Byte\ByteFormatter(); $message = sprintf(_('「%1$s」の容量は %2$s です。'), $filename, $byteFormatter->format($size)); switch ($topLevelType) { case 'image': if ($size > self::MAX_IMAGE_SIZE) { throw new SyntaxException(sprintf(_('画像ファイルの容量は %s 以下にしてください。'), $byteFormatter->format(self::MAX_IMAGE_SIZE)) . $message); } elseif ($size > self::MAX_RECOMMENDED_IMAGE_SIZE) { $this->logger->warning(sprintf(_('画像ファイルの容量は %s 以下にすべきです。'), $byteFormatter->format(self::MAX_RECOMMENDED_IMAGE_SIZE)) . $message); } break; case 'audio': if ($size > self::MAX_AUDIO_SIZE) { throw new SyntaxException(sprintf(_('音声ファイルの容量は %s 以下にしてください。'), $byteFormatter->format(self::MAX_AUDIO_SIZE)) . $message); } elseif ($size > self::MAX_RECOMMENDED_AUDIO_SIZE) { $this->logger->warning(sprintf(_('音声ファイルの容量は %s 以下にすべきです。'), $byteFormatter->format(self::MAX_RECOMMENDED_AUDIO_SIZE)) . $message); } break; case 'video': if ($size > self::MAX_VIDEO_SIZE) { throw new SyntaxException(sprintf(_('動画ファイルの容量は %s 以下にしてください。'), $byteFormatter->format(self::MAX_VIDEO_SIZE)) . $message); } elseif ($size > self::MAX_RECOMMENDED_VIDEO_SIZE) { $this->logger->warning(sprintf(_('動画ファイルの容量は %s 以下にすべきです。'), $byteFormatter->format(self::MAX_RECOMMENDED_VIDEO_SIZE)) . $message); } break; } }
/** * @param Dictionary $dictionary * @throws \BadMethodCallException $this->csvOnly が偽、かつ「画像・音声・動画ファイルを含む場合のファイル形式」をCSVファイルのみで構文解析していた場合。 * @throws TooLargeOutputException ZIPファイルについて、CSVファイルの追加により、許容される容量を超過したとき。 * @return string[] */ public function serialize(Dictionary $dictionary) : array { $csv = (new \esperecyan\dictionary_php\Parser())->getBinary($this->getAsCSVFile($dictionary)); $files = $dictionary->getFiles(); if (!$files && !$this->csvOnly && $dictionary->getFilenames()) { throw new \BadMethodCallException(); } elseif ($files && !$this->csvOnly) { $archive = $this->generateArchive(); foreach ($files as $file) { $archive->addFile($file, $file->getFilename()); } $archive->addFromString('dictionary.csv', $csv); $archiveFileInfo = new \SplFileInfo($archive->filename); $archive->close(); if ($archiveFileInfo->getSize() > GenericDictionaryParser::MAX_COMPRESSED_ARCHIVE_SIZE) { $byteFormatter = new \ScriptFUSION\Byte\ByteFormatter(); throw new TooLargeOutputException(sprintf(_('出力される圧縮ファイルの容量が %1$s を超えました: 現在 %2$s'), $byteFormatter->format(GenericDictionaryParser::MAX_COMPRESSED_ARCHIVE_SIZE), $byteFormatter->format($archiveFileInfo->getSize()))); } return ['bytes' => (new \esperecyan\dictionary_php\Parser())->getBinary($archiveFileInfo), 'type' => 'application/zip', 'name' => $this->getFilename($dictionary, 'zip')]; } else { return ['bytes' => $csv, 'type' => 'text/csv; charset=UTF-8; header=present', 'name' => $this->getFilename($dictionary, 'csv')]; } }
/** * @param \SplFileInfo $file * @param string|null $filename * @param string|null $title * @throws SyntaxException * @return Dictionary */ public function parse(\SplFileInfo $file, string $filename = null, string $title = null) : Dictionary { if ($file instanceof \SplTempFileObject) { $binary = (new Parser())->getBinary($file); } $byteFormatter = new \ScriptFUSION\Byte\ByteFormatter(); $fileSize = isset($binary) ? strlen(bin2hex($binary)) / 2 : $file->getSize(); if ($fileSize > self::MAX_COMPRESSED_ARCHIVE_SIZE) { throw new SyntaxException(sprintf(_('ファイルサイズは %1$s 以下にしてください: 現在 %2$s'), $byteFormatter->format(self::MAX_COMPRESSED_ARCHIVE_SIZE), $byteFormatter->format($fileSize))); } elseif ($fileSize > self::MAX_RECOMMENDED_COMPRESSED_ARCHIVE_SIZE) { $this->logger->warning(sprintf(_('ファイルサイズは %1$s 以下にすべきです: 現在 %2$s'), $byteFormatter->format(self::MAX_RECOMMENDED_COMPRESSED_ARCHIVE_SIZE), $byteFormatter->format($fileSize))); } $finfo = new Finfo(FILEINFO_MIME_TYPE); $type = isset($binary) ? $finfo->buffer($binary) : $finfo->file($file->getRealPath()); switch ($type) { case 'application/zip': $this->header = true; $csvFile = $this->parseArchive($file); $csv = new \SplFileInfo($this->generateTempFile($csvFile)); $files = new \FilesystemIterator($csvFile->getPath(), \FilesystemIterator::SKIP_DOTS); unlink($csvFile); break; case 'text/csv': case 'text/plain': $csv = $file; break; default: throw new SyntaxException(_('汎用辞書はCSVファイルかZIPファイルでなければなりません。')); } $filesCount = (isset($files) ? iterator_count($files) : count($this->filenames)) + 1; if ($filesCount > self::MAX_FILES) { throw new SyntaxException(sprintf(_('アーカイブ中のファイル数は %1$s 個以下にしてください: 現在 %2$s 個'), self::MAX_FILES, $filesCount)); } elseif ($filesCount > self::MAX_RECOMMENDED_FILES) { $this->logger->warning(sprintf(_('アーカイブ中のファイル数は %1$s 個以下にすべきです: 現在 %2$s 個'), self::MAX_RECOMMENDED_FILES, $filesCount)); } $dictionary = new Dictionary($files ?? $this->filenames); $dictionary->setLogger($this->logger); $this->parseCSVFile($dictionary, $csv, $this->header); if (!$dictionary->getWords()) { throw new SyntaxException(_('CSVファイルが空です。')); } $metadata = $dictionary->getMetadata(); if (!isset($metadata['@title'])) { if (!is_null($title)) { $metadata['@title'] = $title; } elseif (!is_null($filename)) { $titleFromFilename = $this->getTitleFromFilename($filename); if ($titleFromFilename !== '') { $metadata['@title'] = $titleFromFilename; } } $dictionary->setMetadata($metadata); } return $dictionary; }