Completed
Push — master ( f89ae2...a732df )
by Carlos
10s
created

Downloader::_haveOptions()   D

Complexity

Conditions 10
Paths 26

Size

Total Lines 45
Code Lines 35

Duplication

Lines 21
Ratio 46.67 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 21
loc 45
rs 4.8196
cc 10
eloc 35
nc 26
nop 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Main cycle of the app
4
 */
5
namespace App;
6
7
use App\Exceptions\LoginException;
8
use App\Exceptions\SubscriptionNotActiveException;
9
use App\Http\Resolver;
10
use App\System\Controller;
11
use App\Utils\Utils;
12
use Cocur\Slugify\Slugify;
13
use GuzzleHttp\Client;
14
use League\Flysystem\Filesystem;
15
use Ubench;
16
17
/**
18
 * Class Downloader
19
 * @package App
20
 */
21
class Downloader
22
{
23
    /**
24
     * Http resolver object
25
     * @var Resolver
26
     */
27
    private $client;
28
29
    /**
30
     * System object
31
     * @var Controller
32
     */
33
    private $system;
34
35
    /**
36
     * Ubench lib
37
     * @var Ubench
38
     */
39
    private $bench;
40
41
    /**
42
     * Number of local lessons
43
     * @var int
44
     */
45
    public static $totalLocalLessons;
46
47
    /**
48
     * Current lesson number
49
     * @var int
50
     */
51
    public static $currentLessonNumber;
52
53
    private $wantSeries = [];
54
    private $wantLessons = [];
55
56
    /**
57
     * Receives dependencies
58
     *
59
     * @param Client $client
60
     * @param Filesystem $system
61
     * @param Ubench $bench
62
     */
63
    public function __construct(Client $client, Filesystem $system, Ubench $bench)
64
    {
65
        $this->client = new Resolver($client, $bench);
66
        $this->system = new Controller($system);
67
        $this->bench = $bench;
68
    }
69
70
    /**
71
     * All the logic
72
     *
73
     * @param $options
74
     */
75
    public function start($options)
76
    {
77
        try {
78
            $counter = [
79
                'series'  => 1,
80
                'lessons' => 1,
81
                'failed_episode' => 0,
82
                'failed_lesson' => 0
83
            ];
84
85
            Utils::box('Authenticating');
86
87
            $this->doAuth($options);
88
89
            Utils::box('Starting Collecting the data');
90
91
            $this->bench->start();
92
93
            $localLessons = $this->system->getAllLessons();
94
            $allLessonsOnline = $this->client->getAllLessons();
95
96
            $this->bench->end();
97
            if($this->_haveOptions()):
98
                $allLessonsOnline = $this->downloadSeriesAndLessons($allLessonsOnline);
99
            endif;
100
            Utils::box('Downloading');
101
            //Magic to get what to download
102
            $diff = Utils::resolveFaultyLessons($allLessonsOnline, $localLessons);
103
104
            $new_lessons = Utils::countLessons($diff);
105
            $new_episodes = Utils::countEpisodes($diff);
106
107
            Utils::write(sprintf("%d new lessons and %d episodes. %s elapsed with %s of memory usage.",
108
                    $new_lessons,
109
                    $new_episodes,
110
                    $this->bench->getTime(),
111
                    $this->bench->getMemoryUsage())
112
            );
113
114
115
            //Download Lessons
116
            if ($new_lessons > 0) {
117
                $this->downloadLessons($diff, $counter, $new_lessons);
118
            }
119
120
            //Donwload Episodes
121
            if ($new_episodes > 0) {
122
                $this->downloadEpisodes($diff, $counter, $new_episodes);
123
            }
124
125
            Utils::writeln(sprintf("Finished! Downloaded %d new lessons and %d new episodes. Failed: %d",
126
                $new_lessons - $counter['failed_lesson'],
127
                $new_episodes - $counter['failed_episode'],
128
                $counter['failed_lesson'] + $counter['failed_episode']
129
            ));
130
        } catch (LoginException $e) {
131
            Utils::write("Your login details are wrong!");
132
        } catch (SubscriptionNotActiveException $e) {
133
            Utils::write('Your subscription is not active!');
134
        }
135
    }
136
137
    /**
138
     * Tries to login.
139
     *
140
     * @param $options
141
     *
142
     * @throws \Exception
143
     */
144
    public function doAuth($options)
145
    {
146
        if (!$this->client->doAuth($options['email'], $options['password'])) {
147
            throw new LoginException("Can't do the login..");
148
        }
149
        Utils::write("Successfull!");
150
    }
151
152
    /**
153
     * Download Lessons
154
     * @param $diff
155
     * @param $counter
156
     * @param $new_lessons
157
     */
158
    public function downloadLessons(&$diff, &$counter, $new_lessons)
159
    {
160
        $this->system->createFolderIfNotExists(LESSONS_FOLDER);
161
        Utils::box('Downloading Lessons');
162 View Code Duplication
        foreach ($diff['lessons'] as $lesson) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
163
164
            if($this->client->downloadLesson($lesson) === false) {
165
                $counter['failed_lesson']++;
166
            }
167
168
            Utils::write(sprintf("Current: %d of %d total. Left: %d",
169
                $counter['lessons']++,
170
                $new_lessons,
171
                $new_lessons - $counter['lessons'] + 1
172
            ));
173
        }
174
    }
175
176
    /**
177
     * Download Episodes
178
     * @param $diff
179
     * @param $counter
180
     * @param $new_episodes
181
     */
182
    public function downloadEpisodes(&$diff, &$counter, $new_episodes)
183
    {
184
        $this->system->createFolderIfNotExists(SERIES_FOLDER);
185
        Utils::box('Downloading Series');
186
        foreach ($diff['series'] as $serie => $episodes) {
187
            $this->system->createSerieFolderIfNotExists($serie);
188 View Code Duplication
            foreach ($episodes as $episode) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
189
190
                if($this->client->downloadSerieEpisode($serie, $episode) === false) {
191
                    $counter['failed_episode'] = $counter['failed_episode'] +1;
192
                }
193
194
                Utils::write(sprintf("Current: %d of %d total. Left: %d",
195
                    $counter['series']++,
196
                    $new_episodes,
197
                    $new_episodes - $counter['series'] + 1
198
                ));
199
            }
200
        }
201
    }
202
203
    protected function _haveOptions()
204
    {
205
        $found = false;
206
207
        $short_options = "s:";
208
        $short_options .= "l:";
209
210
        $long_options  = array(
211
            "series-name:",
212
            "lesson-name:"
213
        );
214
        $options = getopt($short_options, $long_options);
215
216
        Utils::box(sprintf("Checking for options %s", json_encode($options)));
217
218
        if(count($options) == 0):
219
            Utils::write('No options provided');
220
            return false;
221
        endif;
222
223 View Code Duplication
        if(isset($options['s']) || isset($options['series-name'])):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
224
            $series = isset($options['s']) ? $options['s'] : $options['series-name'];
225
            if(!is_array($series)) $series = [$series];
226
            Utils::write(sprintf("Series names provided: %s", json_encode($series)));
227
            $slugify = new Slugify();
228
            $slugify->addRule("'", '');
229
            $this->wantSeries = $slugify->slugify($series);
0 ignored issues
show
Documentation introduced by
$series is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation Bug introduced by
It seems like $slugify->slugify($series) of type string is incompatible with the declared type array of property $wantSeries.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
230
            $this->wantSeries = array_map(function($serie) use ($slugify) {return $slugify->slugify($serie); },$series);
231
            Utils::write(sprintf("Series names provided: %s", json_encode($this->wantSeries)));
232
            $found = true;
233
        endif;
234
235 View Code Duplication
        if(isset($options['l']) || isset($options['lesson-name'])):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
236
            $lessons = isset($options['l']) ? $options['l'] : $options['lesson-name'];
237
            if(!is_array($lessons)) $lessons = [$lessons];
238
            Utils::write(sprintf("Lesson names provided: %s", json_encode($lessons)));
239
            $slugify = new Slugify();
240
            $slugify->addRule("'", '');
241
            $this->wantLessons = array_map(function($lesson) use ($slugify) {return $slugify->slugify($lesson); },$lessons);
242
            Utils::write(sprintf("Lesson names provided: %s", json_encode($this->wantLessons)));
243
            $found = true;
244
        endif;
245
246
        return $found;
247
    }
248
249
    /**
250
     * Download Series and lessons
251
     * @param $allLessonsOnline
252
     * @return array
253
     */
254
    public function downloadSeriesAndLessons($allLessonsOnline)
255
    {
256
        Utils::box('Checking if series and lessons exists');
257
258
        $selectedLessonsOnline = [
259
            'lessons' => [],
260
            'series' => []
261
        ];
262
263
        foreach($this->wantSeries as $series):
264
            if(isset($allLessonsOnline['series'][$series])):
265
                Utils::write('Series "'.$series.'" found!');
266
                $selectedLessonsOnline['series'][$series] = $allLessonsOnline['series'][$series];
267
            else:
268
                Utils::write("Series '".$series."' not found!");
269
            endif;
270
        endforeach;
271
272
        foreach($this->wantLessons as $lesson):
273
            if(in_array($lesson, $allLessonsOnline['lessons'])):
274
                Utils::write('Lesson "'.$lesson.'" found');
275
                $selectedLessonsOnline['lessons'][] = $allLessonsOnline['lessons'][array_search($lesson, $allLessonsOnline)];
276
            else:
277
                Utils::write("Lesson '".$lesson."' not found!");
278
            endif;
279
        endforeach;
280
281
        return $selectedLessonsOnline;
282
    }
283
}
284