Cancelled
Push — master ( e1e02b...1e7a78 )
by Mantas
02:19
created

Subtitles::convertTo()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 0
cts 4
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 1
crap 2
1
<?php namespace Done\Subtitles;
2
3
interface SubtitleContract {
4
5
    public static function convert($from_file_path, $to_file_path);
6
7
    public static function load($file_name, $extension = null); // load file
8
    public function save($file_name); // save file
9
    public function content($format); // output file content (instead of saving to file)
10
11
    public function add($start, $end, $text); // add one line // @TODO ability to add multilines
12
    public function remove($from, $till); // delete test from subtitles
13
    public function time($seconds); // shift time
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    // input
35
    public static function loadString($string, $extension);
36
37
    // chose format
38
    public function convertTo($format);
39
40
    // only text from file (without timestamps)
41
    public function getOnlyTextFromInput();
42
43
    // output
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
44
//    public function download($filename);
45
}
46
47
48
class Subtitles implements SubtitleContract {
0 ignored issues
show
Coding Style Compatibility introduced by
Each interface must be in a file by itself

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Bug introduced by
There is at least one abstract method in this class. Maybe declare it as abstract, or implement the remaining methods: convertTo, getOnlyTextFromInput
Loading history...
49
50
    protected $input;
51
    protected $input_format;
52
53
    protected $internal_format; // data in internal format (when file is converted)
54
55
    protected $converter;
56
    protected $output;
57
58 3
    public static function convert($from_file_path, $to_file_path)
59
    {
60 3
        self::load($from_file_path)->save($to_file_path);
61 3
    }
62
63 11
    public static function load($file_name, $extension = null)
64
    {
65 11
        if (strstr($file_name, "\n") === false) {
66 7
            return self::loadFile($file_name);
67
        } else {
68 4
            if (!$extension) {
69
                throw new \Exception('Specify extension');
70
            }
71 4
            return self::loadString($file_name, $extension);
72
        }
73
    }
74
75 3
    public function save($path)
76
    {
77 3
        $file_extension = self::fileExtension($path);
78 3
        $content = $this->content($file_extension);
79
80 3
        file_put_contents($path, $content);
81
82 3
        return $this;
83
    }
84
85 11
    public function add($start, $end, $text)
86
    {
87
        // @TODO validation
88
        // @TODO check subtitles to not overlap
89 11
        $this->internal_format[] = [
90 11
            'start' => $start,
91 11
            'end' => $end,
92 11
            'lines' => is_array($text) ? $text : [$text],
93
        ];
94 11
        usort($this->internal_format, function ($item1, $item2) {
95
            // return $item2['start'] <=> $item1['start']; // from  PHP 7
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
96 4
            if ($item2['start'] == $item1['start']) {
97
                return 0;
98 4
            } elseif ($item2['start'] < $item1['start']) {
99
                return 1;
100
            } else {
101 4
                return -1;
102
            }
103 11
        });
104
105 11
        return $this;
106
    }
107
108 3
    public function remove($from, $till)
109
    {
110 3
        foreach ($this->internal_format as $k => $block) {
111 3
            if (($from < $block['start'] && $block['start'] < $till) || ($from < $block['end'] && $block['end'] < $till)) {
112 3
                unset($this->internal_format[$k]);
113
            }
114
        }
115
116 3
        $this->internal_format = array_values($this->internal_format); // reorder keys
117
118 3
        return $this;
119
    }
120
121 2
    public function time($seconds)
122
    {
123 2
        foreach ($this->internal_format as &$block) {
124 2
            $block['start'] += $seconds;
125 2
            $block['end'] += $seconds;
126
        }
127 2
        unset($block);
128
129 2
        return $this;
130
    }
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145 7
    private static function loadFile($path, $extension = null)
146
    {
147 7
        $string = file_get_contents($path);
148 7
        if (!$extension) {
149 7
            $extension = self::fileExtension($path);
150
        }
151
152 7
        return self::loadString($string, $extension);
153
    }
154
155 11
    public static function loadString($text, $extension)
156
    {
157 11
        $converter = new self;
158 11
        $converter->input = self::normalizeNewLines(self::removeUtf8Bom($text));
159
160 11
        $converter->input_format = $extension;
161
162 11
        $input_converter = self::getConverter($extension);
163 11
        $converter->internal_format = $input_converter->fileContentToInternalFormat($converter->input);
164
165 11
        return $converter;
166
    }
167
168
//    public function convertTo($extension)
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
169
//    {
170
//        $converter = self::getConverter($extension);
171
//
172
//        $this->output = $converter->internalFormatToFileContent($this->internal_format);
173
//
174
//        return $this;
175
//    }
176
177
//    public function download($filename)
0 ignored issues
show
Unused Code Comprehensibility introduced by
49% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
178
//    {
179
//        return Response::make($this->output, '200', array(
180
//            'Content-Type' => 'text/plain',
181
//            'Content-Disposition' => 'attachment; filename="' . $filename . '"',
182
//        ));
183
//    }
184
185 8
    public function content($format)
186
    {
187 8
        $format = strtolower(trim($format, '.'));
188
189 8
        $converter = self::getConverter($format);
190 8
        $content = $converter->internalFormatToFileContent($this->internal_format);
191
192 8
        return $content;
193
    }
194
195
//    public function getOnlyTextFromInput()
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
196
//    {
197
//        $text = '';
198
//        $data = $this->internal_format;
199
//        foreach ($data as $row) {
200
//            foreach ($row['lines'] as $line) {
201
//                $text .= $line . "\n";
202
//            }
203
//        }
204
//
205
//        return $text;
206
//    }
207
208
    // for testing only
209 14
    public function getInternalFormat()
210
    {
211 14
        return $this->internal_format;
212
    }
213
214
    // for testing only
215 2
    public function setInternalFormat(array $internal_format)
216
    {
217 2
        $this->internal_format = $internal_format;
218
219 2
        return $this;
220
    }
221
222
    // -------------------------------------- private ------------------------------------------------------------------
223
224 11
    public static function removeUtf8Bom($text)
225
    {
226 11
        $bom = pack('H*','EFBBBF');
227 11
        $text = preg_replace("/^$bom/", '', $text);
228
229 11
        return $text;
230
    }
231
232 15
    private static function getConverter($extension)
233
    {
234 15
        if ($extension == 'stl') {
235 2
            return new StlConverter();
236 15
        } elseif ($extension == 'vtt') {
237 2
            return new VttConverter();
238 13
        } elseif ($extension == 'srt') {
239 9
            return new SrtConverter();
240 4
        } elseif ($extension == 'sbv') {
241 2
            return new SbvConverter();
242 2
        } elseif ($extension == 'sub') {
243 2
            return new SubConverter();
244
        }
245
246
        throw new \Exception('unknown format');
247
    }
248
249 7
    private static function fileExtension($filename) {
250 7
        $parts = explode('.', $filename);
251 7
        $extension = end($parts);
252 7
        $extension = strtolower($extension);
253
254 7
        return $extension;
255
    }
256
257 11
    private static function normalizeNewLines($file_content)
258
    {
259 11
        $file_content = str_replace("\r\n", "\n", $file_content);
260 11
        $file_content = str_replace("\r", "\n", $file_content);
261
262 11
        return $file_content;
263
    }
264
}
265
266
// https://github.com/captioning/captioning has potential, but :(
267
// https://github.com/snikch/captions-php too small
268
269
/*
270
**Other popular formats that are not implemented**
271
Feel free to implement one if you can, or choose some other format if you need
272
```
273
.sub, .sbv - similar to .srt
274
.vtt - very similar to .srt
275
[.scc](https://en.wikipedia.org/wiki/EIA-608)
276
```
277
 */