Completed
Push — master ( 7229c3...6e7f58 )
by Stanislav
02:20
created

StatsGet::execute()   B

Complexity

Conditions 6
Paths 31

Size

Total Lines 67
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 8
Bugs 2 Features 2
Metric Value
c 8
b 2
f 2
dl 0
loc 67
rs 8.5896
cc 6
eloc 44
nc 31
nop 2

How to fix   Long Method   

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
namespace Popstas\Transmission\Console\Command;
4
5
use InfluxDB;
6
use Martial\Transmission\API\Argument\Torrent;
7
use Popstas\Transmission\Console\Helpers\TableUtils;
8
use Popstas\Transmission\Console\Helpers\TorrentListUtils;
9
use Popstas\Transmission\Console\Helpers\TorrentUtils;
10
use Symfony\Component\Console\Input\ArrayInput;
11
use Symfony\Component\Console\Input\InputInterface;
12
use Symfony\Component\Console\Input\InputOption;
13
use Symfony\Component\Console\Output\OutputInterface;
14
15
class StatsGet extends Command
16
{
17
    protected function configure()
18
    {
19
        parent::configure();
20
        $this
21
            ->setName('stats-get')
22
            ->setAliases(['sg'])
23
            ->setDescription('Get metrics from InfluxDB')
24
            ->addOption('name', null, InputOption::VALUE_OPTIONAL, 'Sort by torrent name (regexp)')
25
            ->addOption('age', null, InputOption::VALUE_OPTIONAL, 'Sort by torrent age, ex. \'>1 <5\'')
26
            ->addOption('profit', null, InputOption::VALUE_OPTIONAL, 'Filter by profit')
27
            ->addOption('days', null, InputOption::VALUE_OPTIONAL, 'Show stats for last days', 7)
28
            ->addOption('sort', null, InputOption::VALUE_OPTIONAL, 'Sort by column number', 4)
29
            ->addOption('limit', null, InputOption::VALUE_OPTIONAL, 'Limit torrent list')
30
            ->addOption('rm', null, InputOption::VALUE_NONE, 'Remove filtered torrents')
31
            ->addOption('soft', null, InputOption::VALUE_NONE, 'Remove only from Transmission, not delete data')
32
            ->addOption('yes', 'y', InputOption::VALUE_NONE, 'Don\'t ask confirmation')
33
            ->addOption('transmission-host', null, InputOption::VALUE_OPTIONAL, 'Transmission host')
34
            ->setHelp(<<<EOT
35
## Get torrents stats from InfluxDB
36
37
Command `stats-get` almost same as `torrent-list`, but it use InfluxDB:
38
```
39
transmission-cli stats-get [--name='name'] [--age='age'] [profit='>0'] [--days=7] [--sort=1] [--limit=10] [--rm]
40
```
41
42
You can also use `--name`, `--age`, `--sort`, `--limit`, plus `--profit` and `--days` options.
43
44
Profit = uploaded for period / torrent size. Profit metric more precise than uploaded ever value.
45
46
Show 10 worst torrents for last week:
47
```
48
transmission-cli stats-get --days 7 --profit '=0' --limit 10
49
```
50
51
Show stats of last added torrents sorted by profit:
52
```
53
transmission-cli stats-get --days 1 --age '<2' --sort='-7'
54
```
55
56
57
## Remove torrents
58
59
You can use command `stats-get` with `--rm` option to remove filtered unpopular torrents:
60
```
61
transmission-cli stats-get --days 7 --profit '=0' --rm
62
```
63
64
With `--rm` option you can use all options of `torrent-remove` command: `--soft`, `--dry-run`, `-y`.  
65
66
Without `-y` option command ask your confirmation for remove torrents.  
67
68
If you don't want to remove all filtered torrents, you can save ids of torrents and call `torrent-remove` manually.
69
EOT
70
            );
71
    }
72
73
    protected function execute(InputInterface $input, OutputInterface $output)
74
    {
75
        $config = $this->getApplication()->getConfig();
76
        $logger = $this->getApplication()->getLogger();
77
        $client = $this->getApplication()->getClient();
78
79
        try {
80
            $influxDbClient = $this->getApplication()->getInfluxDbClient(
81
                $config->get('influxdb-host'),
82
                $config->get('influxdb-port'),
83
                $config->get('influxdb-user'),
84
                $config->get('influxdb-password'),
85
                $config->get('influxdb-database')
86
            );
87
88
            $lastDays = (int)$input->getOption('days') ? (int)$input->getOption('days') : 0;
89
            $limit = (int)$input->getOption('limit') ? (int)$input->getOption('limit') : 0;
90
91
            $torrentList = $client->getTorrentData();
92
93
            $torrentList = array_map(function ($torrent) {
94
                $torrent['age'] = TorrentUtils::getTorrentAgeInDays($torrent);
95
                return $torrent;
96
            }, $torrentList);
97
98
            $torrentList = TorrentListUtils::filterTorrents($torrentList, [
99
                'age' => $input->getOption('age'),
100
                'name' => $input->getOption('name'),
101
            ]);
102
103
            $transmissionHost = $config->get('transmission-host');
104
105
            $torrentList = array_map(function ($torrent) use ($influxDbClient, $transmissionHost, $lastDays) {
106
                $torrent['uploaded'] = $influxDbClient->getTorrentSum(
107
                    $torrent,
108
                    'uploaded_last',
109
                    $transmissionHost,
110
                    $lastDays
111
                );
112
113
                $days = max(1, min($torrent['age'], $lastDays));
114
                $torrent['per_day'] = $days ?
115
                    TorrentUtils::getSizeInGb($torrent['uploaded'] / $days) : 0;
116
117
                $torrent['profit'] = round($torrent['uploaded'] / $torrent[Torrent\Get::TOTAL_SIZE] / $days * 100, 2);
118
119
                return $torrent;
120
            }, $torrentList);
121
        } catch (\Exception $e) {
122
            $logger->critical($e->getMessage());
123
            return 1;
124
        }
125
126
        $torrentList = TorrentListUtils::filterTorrents($torrentList, [
127
            'profit' => ['type' => 'numeric', 'value' => $input->getOption('profit')]
128
        ]);
129
130
        $tableData = $this->buildTableData($torrentList, $input->getOption('sort'), $limit);
131
132
        TableUtils::printTable($tableData, $output);
133
134
        if ($input->getOption('rm')) {
135
            return $this->removeTorrents($input, $output, $tableData['rows']);
136
        }
137
138
        return 0;
139
    }
140
141
    private function removeTorrents(InputInterface $input, OutputInterface $output, array $rows)
142
    {
143
        $limit = (int)$input->getOption('limit') ? (int)$input->getOption('limit') : 0;
144
145
        $rows = TableUtils::sortRowsByColumnNumber($rows, $input->getOption('sort'));
146
147
        if ($limit && $limit < count($rows)) {
148
            $rows = array_slice($rows, 0, $limit);
149
        }
150
151
        $torrentIds = TorrentListUtils::getArrayField($rows, 1);
152
        $command = $this->getApplication()->find('torrent-remove');
153
        $arguments = array(
154
            'command'     => 'torrent-remove',
155
            'torrent-ids' => $torrentIds,
156
            '--dry-run'   => $input->getOption('dry-run'),
157
            '--yes'       => $input->getOption('yes'),
158
            '--soft'      => $input->getOption('soft'),
159
        );
160
161
        $removeInput = new ArrayInput($arguments);
162
        return $command->run($removeInput, $output);
163
    }
164
165
    private function buildTableData(array $torrentList, $sort, $limit)
166
    {
167
        $rows = [];
168
169
        foreach ($torrentList as $torrent) {
170
            $rows[] = [
171
                $torrent[Torrent\Get::NAME],
172
                $torrent[Torrent\Get::ID],
173
                $torrent['age'],
174
                TorrentUtils::getSizeInGb($torrent[Torrent\Get::TOTAL_SIZE]),
175
                TorrentUtils::getSizeInGb($torrent['uploaded']),
176
                $torrent['per_day'],
177
                $torrent['profit']
178
            ];
179
        }
180
181
        $rows = TableUtils::sortRowsByColumnNumber($rows, $sort);
182
        $rows = TableUtils::limitRows($rows, $limit);
0 ignored issues
show
Bug introduced by
The method limitRows() does not seem to exist on object<Popstas\Transmiss...ole\Helpers\TableUtils>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
183
184
        return [
185
            'headers' => ['Name', 'Id', 'Age, days', 'Size, GB', 'Uploaded, GB', 'Per day, GB', 'Profit, %'],
186
            'rows' => $rows,
187
            'totals' => [
188
                '',
189
                '',
190
                '',
191
                TorrentListUtils::sumArrayField($rows, 3),
192
                TorrentListUtils::sumArrayField($rows, 4),
193
                TorrentListUtils::sumArrayField($rows, 5),
194
                TorrentListUtils::sumArrayField($rows, 6),
195
            ]
196
        ];
197
    }
198
}
199