LoadGearSets::handle()   C
last analyzed

Complexity

Conditions 9
Paths 42

Size

Total Lines 50
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 0
Metric Value
dl 0
loc 50
ccs 0
cts 50
cp 0
rs 6
c 0
b 0
f 0
cc 9
eloc 38
nc 42
nop 0
crap 90
1
<?php namespace FreedomCore\TrinityCore\Character\Commands;
2
3
use FreedomCore\TrinityCore\Character\Classes\Boost\GearSets;
4
use Illuminate\Console\Command;
5
use Symfony\Component\Console\Helper\ProgressBar;
6
use Symfony\Component\Console\Output\ConsoleOutput;
7
8
/**
9
 * Class LoadGearSets
10
 * @package FreedomCore\TrinityCore\Character\Commands
11
 */
12
class LoadGearSets extends Command
13
{
14
15
    /**
16
     * The name and signature of the console command.
17
     * @var string
18
     */
19
    protected $signature = 'character:gearsets';
20
21
    /**
22
     * The console command description.
23
     * @var string
24
     */
25
    protected $description = 'Load gear sets data for character boost';
26
27
    /**
28
     * Create a new command instance.
29
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
30
     */
31
    public function __construct()
32
    {
33
        parent::__construct();
34
    }
35
36
    /**
37
     * Execute the console command.
38
     * @return mixed
39
     */
40
    public function handle()
41
    {
42
        $saveFolder = str_replace('Commands', 'Data', __DIR__) . DIRECTORY_SEPARATOR;
43
        $fileName = 'gearingStrategy.json';
44
        $gearSets = new GearSets();
45
        $links = [];
46
        foreach ($gearSets->getLevelsRelation() as $levelID => $level) {
47
            foreach ($gearSets->getClasses() as $classID => $className) {
48
                $links[$className][$levelID] = $this->getWoWDBClassLink($gearSets, $classID, $levelID);
49
            }
50
        }
51
        $totalItems = count($links, COUNT_RECURSIVE);
52
        $progress = new ProgressBar(new ConsoleOutput(), $totalItems);
53
        $data = [];
54
        $unexpected = false;
55
        foreach ($links as $class => $levelData) {
56
            foreach ($levelData as $level => $specData) {
57
                foreach ($specData as $spec => $slotData) {
58
                    foreach ($slotData as $slot => $link) {
59
                        try {
60
                            $data[$class][$level][$spec][$slot] = $this->crawlGearPiece($link);
61
                            $progress->advance();
62
                        } catch (\Exception $exception) {
63
                            $unexpected = [
64
                                'message'       =>  'Error occurred during the processing!',
65
                                'link'          =>  $link,
66
                                'parameters'    =>  [
67
                                    'class'     =>  $class,
68
                                    'level'     =>  $level,
69
                                    'slot'      =>  $slot
70
                                ]
71
                            ];
72
                            break 4;
73
                        }
74
                    }
75
                }
76
            }
77
        }
78
        $progress->finish();
79
        $fp = fopen($saveFolder . $fileName, 'w');
80
        fwrite($fp, json_encode($data));
81
        fclose($fp);
82
        if ($unexpected !== false) {
83
            $this->info(PHP_EOL . 'There was an error during the processing. Here is the last error:');
84
            dd($unexpected);
85
        } else {
86
            $this->info(PHP_EOL . 'Successfully fetched all required data!');
87
        }
88
        return true;
89
    }
90
91
    /**
92
     * Get links to wowdb items finder to manually add items
93
     * to the gear set for each class
94
     * @param GearSets $gearSets
95
     * @param int $classID
96
     * @param int $levelID
97
     * @return array
98
     */
99
    public function getWoWDBClassLink(GearSets $gearSets, int $classID, int $levelID)
100
    {
101
        $wowDBGearLinks = [];
102
        $dataForLevel = $gearSets->getClassDataByLevel($classID, $levelID);
103
        $gearLevel = $gearSets->gearLevels($levelID);
104
        foreach ($dataForLevel as $specID => $slots) {
105
            foreach ($slots as $slotID => $itemID) {
106
                $wowDBGearLinks[$specID][$slotID] = sprintf($gearSets->getWebsiteSearchLink(), $gearLevel, $gearLevel, $levelID, $levelID, $classID, $specID, $gearSets->getWebsiteSlots($slotID));
107
            }
108
        }
109
        return $wowDBGearLinks;
110
    }
111
112
    /**
113
     * Crawl single gear piece
114
     * @param string $link
115
     * @return int
116
     */
117
    public function crawlGearPiece(string $link) : int
118
    {
119
        $content = file_get_contents($link);
120
        $crawler = new \Symfony\Component\DomCrawler\Crawler();
121
        $crawler->addHtmlContent($content);
122
        $links = $crawler->filter('a.listing-icon')->each(function (\Symfony\Component\DomCrawler\Crawler $node, $index) {
0 ignored issues
show
Unused Code introduced by
The parameter $index is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
123
            $icon = $this->getTextBetween($node->html(), '<img class="icon-36 " src="', '" width="36" height="36"');
124
            $link = $this->getTextBetween($node->parents()->html(), '<a class="listing-icon" href="', '">');
125
            $valid = strstr($icon, 'panda') ? true : false;
126
            return [
127
                'icon'  =>  $icon,
128
                'link'  =>  $link,
129
                'valid' =>  $valid
130
            ];
131
        });
132
        $itemID = 0;
133
        foreach ($links as $data) {
134
            if ($data['valid']) {
135
                $itemID = intval($this->getTextBetween($data['link'], 'http://www.wowdb.com/items/', '-'));
136
                break;
137
            }
138
        }
139
        if ($itemID === 0) {
140
            try {
141
                $itemID = intval($this->getTextBetween($links[0]['link'], 'http://www.wowdb.com/items/', '-'));
142
            } catch (\Exception $exception) {
143
                dd(['link' => $link, 'data' => $links]);
144
            }
145
        }
146
        if ($itemID === 0) {
147
            throw new \RuntimeException('Item ID should not be equal to 0.' . PHP_EOL . 'Error occurred on link: ' . $link);
148
        }
149
        return $itemID;
150
    }
151
152
    /**
153
     * Get text between two substrings
154
     * @param $string
155
     * @param $start
156
     * @param $end
157
     * @see https://stackoverflow.com/a/9826656/2057806
158
     * @author Alejandro Iglesias
159
     * @return bool|string
160
     */
161
    private function getTextBetween($string, $start, $end)
162
    {
163
        $string = ' ' . $string;
164
        $ini = strpos($string, $start);
165
        if ($ini == 0) {
166
            return '';
167
        }
168
        $ini += strlen($start);
169
        $len = strpos($string, $end, $ini) - $ini;
170
        return substr($string, $ini, $len);
171
    }
172
}
173