| @@ -109,6 +109,6 @@ | ||
| 109 | 109 | */ | 
| 110 | 110 | protected static function internalTimeToFormat($internal_time) | 
| 111 | 111 |      { | 
| 112 | - return round($internal_time * 1000); | |
| 112 | + return round($internal_time * 1000); | |
| 113 | 113 | } | 
| 114 | 114 | } | 
| @@ -108,7 +108,7 @@ | ||
| 108 | 108 | $file_content .= '<SYNC Start=' . self::internalTimeToFormat($last_time) . '><P Class=ENUSCC> ' . "</P></SYNC>\r\n"; | 
| 109 | 109 | } | 
| 110 | 110 | |
| 111 | -            $file_content .= '<SYNC Start=' . self::internalTimeToFormat($block['start']) . '><P Class=ENUSCC>' . implode('<br>', $block['lines']) .  "</P></SYNC>\r\n"; | |
| 111 | +            $file_content .= '<SYNC Start=' . self::internalTimeToFormat($block['start']) . '><P Class=ENUSCC>' . implode('<br>', $block['lines']) . "</P></SYNC>\r\n"; | |
| 112 | 112 | $last_time = $block['end']; | 
| 113 | 113 | } | 
| 114 | 114 | $file_content .= '<SYNC Start=' . self::internalTimeToFormat($last_time) . '><P Class=ENUSCC> ' . "</P></SYNC>\r\n"; | 
| @@ -913,7 +913,7 @@ | ||
| 913 | 913 | '91bf' => 'û', | 
| 914 | 914 | ]; | 
| 915 | 915 | |
| 916 | - private static $extended_chars = [ | |
| 916 | + private static $extended_chars = [ | |
| 917 | 917 | '9220' => 'Á', | 
| 918 | 918 | '92a1' => 'É', | 
| 919 | 919 | '92a2' => 'Ó', | 
| @@ -145,7 +145,7 @@ | ||
| 145 | 145 |      { | 
| 146 | 146 | $time = $internal_time - ($text_bytes / 2) / self::$fps; | 
| 147 | 147 |          $parts = explode('.', $time); | 
| 148 | - $whole = (int) $parts[0]; | |
| 148 | + $whole = (int)$parts[0]; | |
| 149 | 149 |          $decimal = isset($parts[1]) ? (float)('0.' . $parts[1]) : 0.0; | 
| 150 | 150 | $frame = round($decimal * self::$fps); | 
| 151 | 151 | $frame = min($frame, floor(self::$fps)); // max 29 | 
| @@ -97,7 +97,10 @@ | ||
| 97 | 97 |          foreach ($lines as $line) { | 
| 98 | 98 |              foreach (self::$allowedSeparators as $delimiter) { | 
| 99 | 99 | $count = count(explode($delimiter, $line)); | 
| 100 | - if ($count < 2) continue; // delimiter not found in line, minimum 2 cols (timestamp + text) | |
| 100 | +                if ($count < 2) { | |
| 101 | + continue; | |
| 102 | + } | |
| 103 | + // delimiter not found in line, minimum 2 cols (timestamp + text) | |
| 101 | 104 | |
| 102 | 105 |                  if (empty($results[$delimiter])) { | 
| 103 | 106 | $results[$delimiter] = []; | 
| @@ -40,17 +40,17 @@ discard block | ||
| 40 | 40 | public function fileContentToInternalFormat($file_content) | 
| 41 | 41 |      { | 
| 42 | 42 | $data = self::csvToArray(trim($file_content)); | 
| 43 | - $data_string = ''; | |
| 43 | + $data_string = ''; | |
| 44 | 44 | |
| 45 | - $is_start_time = (bool) preg_match(TxtConverter::$time_regexp, $data[1][0]); | |
| 46 | - $is_end_time = (bool) preg_match(TxtConverter::$time_regexp, $data[1][1]); | |
| 45 | + $is_start_time = (bool)preg_match(TxtConverter::$time_regexp, $data[1][0]); | |
| 46 | + $is_end_time = (bool)preg_match(TxtConverter::$time_regexp, $data[1][1]); | |
| 47 | 47 |          if ($is_end_time && !isset($data[1][2])) { | 
| 48 | 48 |              throw new UserException('No text (TxtConverter)'); | 
| 49 | 49 | } | 
| 50 | 50 | |
| 51 | 51 |          foreach ($data as $k => $row) { | 
| 52 | - $timestamp_found = (bool) preg_match(TxtConverter::$time_regexp, $row[0]); | |
| 53 | -            if ($k === 0  && $timestamp_found === false) { // heading | |
| 52 | + $timestamp_found = (bool)preg_match(TxtConverter::$time_regexp, $row[0]); | |
| 53 | +            if ($k === 0 && $timestamp_found === false) { // heading | |
| 54 | 54 | continue; | 
| 55 | 55 | } | 
| 56 | 56 | |
| @@ -105,7 +105,7 @@ discard block | ||
| 105 | 105 | |
| 106 | 106 | $separator = self::detectSeparator($content); | 
| 107 | 107 | $csv = []; | 
| 108 | -        while ( ($data = fgetcsv($fp, 0, $separator) ) !== false ) { | |
| 108 | +        while (($data = fgetcsv($fp, 0, $separator)) !== false) { | |
| 109 | 109 | $csv[] = $data; | 
| 110 | 110 | } | 
| 111 | 111 | fclose($fp); | 
| @@ -12,7 +12,7 @@ | ||
| 12 | 12 | |
| 13 | 13 |          foreach ($expected as $k => $block) { | 
| 14 | 14 | $this->assertTrue(abs(round($expected[$k]['start'], 2) - round($actual[$k]['start'], 2)) < $allowable_error, round($expected[$k]['start'], 3) . ' vs ' . round($actual[$k]['start'], 3)); | 
| 15 | - $this->assertTrue(abs(round($expected[$k]['end'], 2) - round($actual[$k]['end'], 2)) < $allowable_error, round($expected[$k]['end'], 3) . ' vs ' . round($actual[$k]['end'], 3)); | |
| 15 | + $this->assertTrue(abs(round($expected[$k]['end'], 2) - round($actual[$k]['end'], 2)) < $allowable_error, round($expected[$k]['end'], 3) . ' vs ' . round($actual[$k]['end'], 3)); | |
| 16 | 16 | |
| 17 | 17 | $this->assertEquals(count($expected[$k]['lines']), count($actual[$k]['lines']), 'Line count is different'); | 
| 18 | 18 |              foreach ($expected[$k]['lines'] as $line_k => $line) { | 
| @@ -36,7 +36,7 @@ discard block | ||
| 36 | 36 | } | 
| 37 | 37 | } | 
| 38 | 38 | |
| 39 | -        usort($internal_format, function ($a, $b) { | |
| 39 | +        usort($internal_format, function($a, $b) { | |
| 40 | 40 | return $a['start'] <=> $b['start']; | 
| 41 | 41 | }); | 
| 42 | 42 | |
| @@ -74,18 +74,18 @@ discard block | ||
| 74 | 74 |      { | 
| 75 | 75 |          $parts = explode(':', $lrc_time); | 
| 76 | 76 |          if (count($parts) === 3) { | 
| 77 | - $minutes = (int) $parts[0]; | |
| 78 | - $seconds = (float) $parts[1]; | |
| 77 | + $minutes = (int)$parts[0]; | |
| 78 | + $seconds = (float)$parts[1]; | |
| 79 | 79 | $milliseconds = str_pad($parts[2], 3, '0', STR_PAD_RIGHT); | 
| 80 | 80 |          } else if (count($parts) === 2) { | 
| 81 | - $minutes = (int) $parts[0]; | |
| 82 | - $seconds = (float) $parts[1]; | |
| 81 | + $minutes = (int)$parts[0]; | |
| 82 | + $seconds = (float)$parts[1]; | |
| 83 | 83 | $milliseconds = 0; | 
| 84 | 84 |          } else { | 
| 85 | 85 |              throw new UserException("$lrc_time timestamp is not valid in .lrc file"); | 
| 86 | 86 | } | 
| 87 | 87 | |
| 88 | -        return $minutes * 60 + $seconds + (float) ('.' . $milliseconds) - $timestamp_offset; | |
| 88 | +        return $minutes * 60 + $seconds + (float)('.' . $milliseconds) - $timestamp_offset; | |
| 89 | 89 | } | 
| 90 | 90 | |
| 91 | 91 | protected static function internalTimeToLrc($internal_time) : string | 
| @@ -107,9 +107,9 @@ discard block | ||
| 107 | 107 |      { | 
| 108 | 108 | $timestamp_offset = 0; | 
| 109 | 109 |          if (preg_match(self::$time_offset_regexp, $content, $match)) { | 
| 110 | - $factor = (int) $match[1] < 0 ? -1 : 1; | |
| 111 | - $offset = abs((int) $match[1]); | |
| 112 | -            $timestamp_offset = ((int) ($offset / 1000) + (float) ('.' . $offset % 1000)) * $factor; | |
| 110 | + $factor = (int)$match[1] < 0 ? -1 : 1; | |
| 111 | + $offset = abs((int)$match[1]); | |
| 112 | +            $timestamp_offset = ((int)($offset / 1000) + (float)('.' . $offset % 1000)) * $factor; | |
| 113 | 113 | } | 
| 114 | 114 | |
| 115 | 115 | return $timestamp_offset; | 
| @@ -109,7 +109,7 @@ discard block | ||
| 109 | 109 | } | 
| 110 | 110 | } | 
| 111 | 111 | |
| 112 | - $internal_format[$j] = [ | |
| 112 | + $internal_format[$j] = [ | |
| 113 | 113 | 'start' => $row['start'], | 
| 114 | 114 | 'end' => $row['end'], | 
| 115 | 115 | 'lines' => [$row['text']], | 
| @@ -212,7 +212,7 @@ discard block | ||
| 212 | 212 | } | 
| 213 | 213 | |
| 214 | 214 | // sort times | 
| 215 | -        usort($internal_format, function ($a, $b) { | |
| 215 | +        usort($internal_format, function($a, $b) { | |
| 216 | 216 |              if ($a['start'] === $b['start']) { | 
| 217 | 217 | return $a['end'] <=> $b['end']; | 
| 218 | 218 | } | 
| @@ -288,23 +288,23 @@ discard block | ||
| 288 | 288 | return $matches; | 
| 289 | 289 | } | 
| 290 | 290 | |
| 291 | - public static function timeToInternal(string $time, int|null $fps) | |
| 291 | + public static function timeToInternal(string $time, int | null $fps) | |
| 292 | 292 |      { | 
| 293 | 293 | $time = trim($time); | 
| 294 | 294 |          $time_parts = explode(':', $time); | 
| 295 | 295 | $total_parts = count($time_parts); | 
| 296 | 296 | |
| 297 | 297 |          if ($total_parts === 1) { | 
| 298 | -            $tmp = (float) str_replace(',', '.', $time_parts[0]); | |
| 298 | +            $tmp = (float)str_replace(',', '.', $time_parts[0]); | |
| 299 | 299 | return $tmp; | 
| 300 | 300 |          } elseif ($total_parts === 2) { // minutes:seconds format | 
| 301 | 301 |              list($minutes, $seconds) = array_map('intval', $time_parts); | 
| 302 | -            $tmp = (float) str_replace(',', '.', $time_parts[1]); | |
| 302 | +            $tmp = (float)str_replace(',', '.', $time_parts[1]); | |
| 303 | 303 | $milliseconds = $tmp - floor($tmp); | 
| 304 | 304 | return ($minutes * 60) + $seconds + $milliseconds; | 
| 305 | 305 |          } elseif ($total_parts === 3) { // hours:minutes:seconds,milliseconds format | 
| 306 | 306 |              list($hours, $minutes, $seconds) = array_map('intval', $time_parts); | 
| 307 | -            $tmp = (float) str_replace(',', '.', $time_parts[2]); | |
| 307 | +            $tmp = (float)str_replace(',', '.', $time_parts[2]); | |
| 308 | 308 | $milliseconds = $tmp - floor($tmp); | 
| 309 | 309 | return ($hours * 3600) + ($minutes * 60) + $seconds + $milliseconds; | 
| 310 | 310 |          } elseif ($total_parts === 4) { // hours:minutes:seconds:frames format | 
| @@ -341,7 +341,7 @@ discard block | ||
| 341 | 341 | return $subject; | 
| 342 | 342 | } | 
| 343 | 343 | |
| 344 | - $result = strstr($subject, (string) $search, true); | |
| 344 | + $result = strstr($subject, (string)$search, true); | |
| 345 | 345 | |
| 346 | 346 | return $result === false ? $subject : $result; | 
| 347 | 347 | } | 
| @@ -215,7 +215,7 @@ | ||
| 215 | 215 | $internal_format = []; | 
| 216 | 216 | |
| 217 | 217 |          foreach ($xml->Paragraph as $paragraph) { | 
| 218 | - $subtitle = [ | |
| 218 | + $subtitle = [ | |
| 219 | 219 | 'start' => (int)$paragraph->StartMilliseconds / 1000, | 
| 220 | 220 | 'end' => (int)$paragraph->EndMilliseconds / 1000, | 
| 221 | 221 | 'lines' => self::getLinesFromTextWithBr($paragraph->Text->asXML()), | 
| @@ -164,7 +164,7 @@ discard block | ||
| 164 | 164 |              $time_parts = explode('.', $ttml_time); | 
| 165 | 165 | $milliseconds = 0; | 
| 166 | 166 |              if (isset($time_parts[1])) { | 
| 167 | -                $milliseconds = (float) ('0.' . $time_parts[1]); | |
| 167 | +                $milliseconds = (float)('0.' . $time_parts[1]); | |
| 168 | 168 | } | 
| 169 | 169 | |
| 170 | 170 |              list($hours, $minutes, $seconds) = array_map('intval', explode(':', $time_parts[0])); | 
| @@ -191,16 +191,16 @@ discard block | ||
| 191 | 191 | |
| 192 | 192 | protected static function internalTimeToTtml($internal_time) | 
| 193 | 193 |      { | 
| 194 | - $formatted_output = round($internal_time, 3); | |
| 194 | + $formatted_output = round($internal_time, 3); | |
| 195 | 195 | |
| 196 | 196 |          if (strpos($formatted_output, '.') === false) { | 
| 197 | - $formatted_output .= ".0"; // Add at least one digit after decimal if there are no digits | |
| 197 | + $formatted_output .= ".0"; // Add at least one digit after decimal if there are no digits | |
| 198 | 198 | } | 
| 199 | 199 | |
| 200 | 200 | return $formatted_output; | 
| 201 | 201 | } | 
| 202 | 202 | |
| 203 | - protected static function framesPerSecond(string $file_content) : float|null | |
| 203 | + protected static function framesPerSecond(string $file_content) : float | null | |
| 204 | 204 |      { | 
| 205 | 205 | $frameRate = null; | 
| 206 | 206 |          preg_match('/ttp:frameRate="(\d+)"/', $file_content, $matches); | 
| @@ -280,8 +280,8 @@ discard block | ||
| 280 | 280 |          foreach ($xml->text as $text) { | 
| 281 | 281 | $attributes = $text->attributes(); | 
| 282 | 282 | $internal_format[] = array( | 
| 283 | - 'start' => (string) $attributes['start'], | |
| 284 | - 'end' => (float)((string) $attributes['start'] + (string) $attributes['dur']), | |
| 283 | + 'start' => (string)$attributes['start'], | |
| 284 | + 'end' => (float)((string)$attributes['start'] + (string)$attributes['dur']), | |
| 285 | 285 |                  'lines' => self::getLinesFromTextWithBr(str_replace("\n", "<br>", $text->asXML())) | 
| 286 | 286 | ); | 
| 287 | 287 | } | 
| @@ -30,23 +30,23 @@ discard block | ||
| 30 | 30 | protected $output; | 
| 31 | 31 | |
| 32 | 32 | public static $formats = [ | 
| 33 | - ['extension' => 'ass', 'format' => 'ass', 'name' => 'Advanced Sub Station Alpha', 'class' => AssConverter::class], | |
| 34 | - ['extension' => 'ssa', 'format' => 'ass', 'name' => 'Advanced Sub Station Alpha', 'class' => AssConverter::class], | |
| 35 | - ['extension' => 'dfxp', 'format' => 'dfxp', 'name' => 'Netflix Timed Text', 'class' => DfxpConverter::class], | |
| 36 | - ['extension' => 'sbv', 'format' => 'sbv', 'name' => 'YouTube', 'class' => SbvConverter::class], | |
| 37 | - ['extension' => 'vtt', 'format' => 'vtt', 'name' => 'WebVTT', 'class' => VttConverter::class], | |
| 38 | - ['extension' => 'srt', 'format' => 'srt', 'name' => 'SubRip', 'class' => SrtConverter::class], | |
| 39 | - ['extension' => 'stl', 'format' => 'stl', 'name' => 'Spruce Subtitle File', 'class' => StlConverter::class], | |
| 40 | - ['extension' => 'sub', 'format' => 'sub_microdvd', 'name' => 'MicroDVD', 'class' => SubMicroDvdConverter::class], | |
| 41 | - ['extension' => 'sub', 'format' => 'sub_subviewer', 'name' => 'SubViewer2.0', 'class' => SubViewerConverter::class], | |
| 42 | - ['extension' => 'ttml', 'format' => 'ttml', 'name' => 'TimedText 1.0', 'class' => TtmlConverter::class], | |
| 43 | - ['extension' => 'xml', 'format' => 'ttml', 'name' => 'TimedText 1.0', 'class' => TtmlConverter::class], | |
| 44 | - ['extension' => 'smi', 'format' => 'smi', 'name' => 'SAMI', 'class' => SmiConverter::class], | |
| 45 | - ['extension' => 'txt', 'format' => 'txt_quicktime', 'name' => 'Quick Time Text', 'class' => TxtQuickTimeConverter::class], | |
| 46 | - ['extension' => 'scc', 'format' => 'scc', 'name' => 'Scenarist', 'class' => SccConverter::class], | |
| 47 | - ['extension' => 'lrc', 'format' => 'lrc', 'name' => 'LyRiCs', 'class' => LrcConverter::class], | |
| 48 | - ['extension' => 'csv', 'format' => 'csv', 'name' => 'Coma Separated Values', 'class' => CsvConverter::class], // must be last from bottom | |
| 49 | - ['extension' => 'txt', 'format' => 'txt', 'name' => 'Plaintext', 'class' => TxtConverter::class], // must be the last one | |
| 33 | + ['extension' => 'ass', 'format' => 'ass', 'name' => 'Advanced Sub Station Alpha', 'class' => AssConverter::class], | |
| 34 | + ['extension' => 'ssa', 'format' => 'ass', 'name' => 'Advanced Sub Station Alpha', 'class' => AssConverter::class], | |
| 35 | + ['extension' => 'dfxp', 'format' => 'dfxp', 'name' => 'Netflix Timed Text', 'class' => DfxpConverter::class], | |
| 36 | + ['extension' => 'sbv', 'format' => 'sbv', 'name' => 'YouTube', 'class' => SbvConverter::class], | |
| 37 | + ['extension' => 'vtt', 'format' => 'vtt', 'name' => 'WebVTT', 'class' => VttConverter::class], | |
| 38 | + ['extension' => 'srt', 'format' => 'srt', 'name' => 'SubRip', 'class' => SrtConverter::class], | |
| 39 | + ['extension' => 'stl', 'format' => 'stl', 'name' => 'Spruce Subtitle File', 'class' => StlConverter::class], | |
| 40 | + ['extension' => 'sub', 'format' => 'sub_microdvd', 'name' => 'MicroDVD', 'class' => SubMicroDvdConverter::class], | |
| 41 | + ['extension' => 'sub', 'format' => 'sub_subviewer', 'name' => 'SubViewer2.0', 'class' => SubViewerConverter::class], | |
| 42 | + ['extension' => 'ttml', 'format' => 'ttml', 'name' => 'TimedText 1.0', 'class' => TtmlConverter::class], | |
| 43 | + ['extension' => 'xml', 'format' => 'ttml', 'name' => 'TimedText 1.0', 'class' => TtmlConverter::class], | |
| 44 | + ['extension' => 'smi', 'format' => 'smi', 'name' => 'SAMI', 'class' => SmiConverter::class], | |
| 45 | + ['extension' => 'txt', 'format' => 'txt_quicktime', 'name' => 'Quick Time Text', 'class' => TxtQuickTimeConverter::class], | |
| 46 | + ['extension' => 'scc', 'format' => 'scc', 'name' => 'Scenarist', 'class' => SccConverter::class], | |
| 47 | + ['extension' => 'lrc', 'format' => 'lrc', 'name' => 'LyRiCs', 'class' => LrcConverter::class], | |
| 48 | + ['extension' => 'csv', 'format' => 'csv', 'name' => 'Coma Separated Values', 'class' => CsvConverter::class], // must be last from bottom | |
| 49 | + ['extension' => 'txt', 'format' => 'txt', 'name' => 'Plaintext', 'class' => TxtConverter::class], // must be the last one | |
| 50 | 50 | ]; | 
| 51 | 51 | |
| 52 | 52 | public static function convert($from_file_path, $to_file_path, $to_format = null) | 
| @@ -167,7 +167,7 @@ discard block | ||
| 167 | 167 | |
| 168 | 168 | protected function sortInternalFormat() | 
| 169 | 169 |      { | 
| 170 | -        usort($this->internal_format, function ($item1, $item2) { | |
| 170 | +        usort($this->internal_format, function($item1, $item2) { | |
| 171 | 171 | return $item1['start'] <=> $item2['start']; | 
| 172 | 172 | }); | 
| 173 | 173 | } | 
| @@ -258,7 +258,7 @@ discard block | ||
| 258 | 258 | } | 
| 259 | 259 | |
| 260 | 260 | // reorder by time | 
| 261 | -        usort($internal_format, function ($a, $b) { | |
| 261 | +        usort($internal_format, function($a, $b) { | |
| 262 | 262 |              if ($a['start'] === $b['start']) { | 
| 263 | 263 | return $a['end'] <=> $b['end']; | 
| 264 | 264 | } | 
| @@ -302,7 +302,7 @@ discard block | ||
| 302 | 302 | $last_end_time = 0; | 
| 303 | 303 |          foreach ($internal_format as $k => $row) { | 
| 304 | 304 |              if ($row['start'] < $last_end_time) { | 
| 305 | -                throw new UserException("Timestamps are overlapping over 60 seconds: \nxx:xx:xx,xxx --> " . SrtConverter::internalTimeToSrt($internal_format[$k - 1]['end']) . ' ' .  $internal_format[$k - 1]['lines'][0] . "\n" . SrtConverter::internalTimeToSrt($row['start']) . ' --> xx:xx:xx,xxx ' . $row['lines'][0]); | |
| 305 | +                throw new UserException("Timestamps are overlapping over 60 seconds: \nxx:xx:xx,xxx --> " . SrtConverter::internalTimeToSrt($internal_format[$k - 1]['end']) . ' ' . $internal_format[$k - 1]['lines'][0] . "\n" . SrtConverter::internalTimeToSrt($row['start']) . ' --> xx:xx:xx,xxx ' . $row['lines'][0]); | |
| 306 | 306 | } | 
| 307 | 307 | $last_end_time = $row['end']; | 
| 308 | 308 |              if ($row['start'] > $row['end']) { | 
| @@ -94,7 +94,7 @@ | ||
| 94 | 94 |          $parts = explode('.', $corrected_time); | 
| 95 | 95 | |
| 96 | 96 | // parts[0] could be mm:ss or hh:mm:ss format -> always use hh:mm:ss | 
| 97 | - $parts[0] = substr_count($parts[0], ':') == 2 ? $parts[0] : '00:'.$parts[0]; | |
| 97 | + $parts[0] = substr_count($parts[0], ':') == 2 ? $parts[0] : '00:' . $parts[0]; | |
| 98 | 98 | |
| 99 | 99 |          if (!isset($parts[1])) { | 
| 100 | 100 |              throw new UserException("Time doesn't have milliseconds: " . $vtt_time); |