\$isLocalAudio ? 'local_audio' : 'video'", 'attachLocalCallAudio($attachmentParams)', "'local_audio_urls'", "'local_audio_status' => 2", "'local_audio_urls_list'", "'local_audio_status_text'", "'uploads/audio/'", 'FileEnum::FILE_TYPE', ] as $needle ) { LocalAudioUploadContractExpect::contains( $logic, $needle, 'Local audio upload and DTO contract must remain complete' ); } foreach ( [ "'uploads/video/'", 'FileEnum::VIDEO_TYPE', 'attachLocalCallRecording($attachmentParams)', "'recording_status' => \$isLocalAudio ? 0 : 2", ] as $needle ) { LocalAudioUploadContractExpect::contains( $logic, $needle, 'Manual video uploads must remain separate from local audio' ); } LocalAudioUploadContractExpect::isTrue( str_contains($logic, '!$isAmbiguousWebm && $hasAudioMime'), 'Known non-WebM video extensions must not be misclassified when an old client sends audio/webm' ); foreach (['zyt_tcm_call_record', 'local_audio_urls', 'local_audio_status'] as $needle) { LocalAudioUploadContractExpect::contains( $migration, $needle, 'The database migration must include every local audio field' ); } // Exercise the real internal-file path used after all recording chunks are // merged. A source-code assertion alone did not catch the missing realPath key // (or the missing File object required by the local storage engine). $sourceBase = tempnam(sys_get_temp_dir(), 'zyt-audio-source-'); LocalAudioUploadContractExpect::isTrue( is_string($sourceBase), 'A temporary local-audio source file must be creatable' ); $sourcePath = $sourceBase . '.webm'; LocalAudioUploadContractExpect::isTrue( rename($sourceBase, $sourcePath), 'The temporary local-audio source must keep its WebM extension' ); $payload = "\x1A\x45\xDF\xA3local-audio-regression"; LocalAudioUploadContractExpect::isTrue( file_put_contents($sourcePath, $payload) === strlen($payload), 'The local-audio fixture must be written completely' ); $targetDir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'zyt-local-audio-target-' . bin2hex(random_bytes(6)); try { $localStorage = new \app\common\service\storage\engine\Local(); $localStorage->setUploadFileByReal($sourcePath); $fileInfo = $localStorage->getFileInfo(); LocalAudioUploadContractExpect::isTrue( isset($fileInfo['realPath']) && $fileInfo['realPath'] === realpath($sourcePath), 'Internal storage metadata must include the merged recording realPath' ); LocalAudioUploadContractExpect::isTrue( ($fileInfo['tmp_name'] ?? '') === realpath($sourcePath), 'Internal storage metadata must preserve a compatible temporary path' ); LocalAudioUploadContractExpect::isTrue( str_ends_with($localStorage->getFileName(), '.webm'), 'The generated storage name must preserve the recording extension' ); LocalAudioUploadContractExpect::isTrue( $localStorage->upload($targetDir), 'The local storage driver must accept a merged internal recording' ); $storedPath = $targetDir . DIRECTORY_SEPARATOR . $localStorage->getFileName(); LocalAudioUploadContractExpect::isTrue( is_file($storedPath) && file_get_contents($storedPath) === $payload, 'The internally uploaded local recording must remain byte-identical' ); } finally { if (isset($storedPath) && is_file($storedPath)) { unlink($storedPath); } if (is_file($sourcePath)) { unlink($sourcePath); } if (is_dir($targetDir)) { rmdir($targetDir); } } $missingPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'zyt-missing-local-audio-' . bin2hex(random_bytes(8)) . '.webm'; $missingRejected = false; try { $localStorage = new \app\common\service\storage\engine\Local(); $localStorage->setUploadFileByReal($missingPath); } catch (Throwable $exception) { $missingRejected = !str_contains($exception->getMessage(), 'realPath') && str_contains($exception->getMessage(), 'does not exist'); } LocalAudioUploadContractExpect::isTrue( $missingRejected, 'A missing merged recording must fail clearly before storage-name generation' ); echo "Local audio upload contract: OK\n";