Completed
Branch master (f3f5ef)
by
unknown
02:33
created

BackupGenerator::__construct()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 21
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
cc 5
eloc 9
nc 6
nop 4
dl 0
loc 21
ccs 0
cts 11
cp 0
crap 30
rs 8.7624
c 0
b 0
f 0
1
<?php
2
3
namespace Blocktrail\SDK;
4
5
use BitWasp\Bitcoin\Key\Deterministic\HierarchicalKeyFactory;
6
use Blocktrail\SDK\Bitcoin\BIP32Key;
7
use Endroid\QrCode\QrCode;
8
9
/**
10
 * Class BackupGenerator
11
 */
12
class BackupGenerator {
13
14
    const QR_CODE_SIZE = 195;
15
16
    /**
17
     * path to fonts used for pdf generation
18
     *
19
     * @var string
20
     */
21
    protected $fontsPath;
22
23
    /**
24
     * array of data and QR codes for the blocktrail public keys
25
     *
26
     * @var null
27
     */
28
    protected $blocktrailPubKeyQRs = [];
29
30
    protected $identifier;
31
32
    protected $backupInfo;
33
34
    protected $extra;
35
36
    protected $options = [
37
        'page1' => true,
38
        'page2' => true,
39
        'page3' => true,
40
    ];
41
42
    /**
43
     * @param string $identifier
44
     * @param array  $backupInfo
45
     * @param array  $extra
46
     * @param null   $options
47
     */
48
    public function __construct($identifier, $backupInfo, $extra = null, $options = null) {
49
        /*
50
         * if DOMPDF is not already loaded we have to do it
51
         * they require a config file to be loaded, no autoloading :/
52
         */
53
        if (!defined('DOMPDF_ENABLE_AUTOLOAD')) {
54
            // disable DOMPDF's internal autoloader if you are using Composer
55
            define('DOMPDF_ENABLE_AUTOLOAD', false);
56
57
            //try the different possible locations for the config file, depending on if the sdk is included as a dependency or is the main project itself
58
            (@include_once __DIR__ . '/../../../dompdf/dompdf/dompdf_config.inc.php') || @include_once __DIR__ . '/../vendor/dompdf/dompdf/dompdf_config.inc.php';
59
        }
60
61
        //set the fonts path
62
        $this->fontsPath = dirname(__FILE__) . '/../resources/fonts';
63
64
        $this->identifier = $identifier;
65
        $this->backupInfo = $backupInfo;
66
        $this->extra = $extra ?: [];
67
        $this->options = array_merge($this->options, $options ?: []);
68
    }
69
70
    /**
71
     * process the blocktrail public keys and create qr codes for each one
72
     */
73
    protected function processBlocktrailPubKeys() {
74
        if (!isset($this->backupInfo['blocktrail_public_keys'])) {
75
            return;
76
        }
77
78
        //create QR codes for each blocktrail pub key
79
        foreach ($this->backupInfo['blocktrail_public_keys'] as $keyIndex => $key) {
80
            $key = $key instanceof BIP32Key ? $key : BIP32Key::create(HierarchicalKeyFactory::fromExtended($key[0]), $key[1]);
81
82
            $qrCode = new QrCode();
83
            $qrCode
84
                ->setText($key->key()->toExtendedKey())
85
                ->setSize(self::QR_CODE_SIZE-20)
86
                ->setPadding(10)
87
                ->setErrorCorrection('high')
88
                ->setForegroundColor(array('r' => 0, 'g' => 0, 'b' => 0, 'a' => 0))
89
                ->setBackgroundColor(array('r' => 255, 'g' => 255, 'b' => 255, 'a' => 0))
90
                ->setLabel("KeyIndex: ".$keyIndex."    Path: ".$key->path())
91
                ->setLabelFontSize(10)
92
            ;
93
            $this->blocktrailPubKeyQRs[] = array(
94
                'keyIndex'  => $keyIndex,
95
                'path'      => $key->path(),
96
                'qr'        => $qrCode->getDataUri(),
97
                'qrImg'     => $qrCode->getImage(),
98
            );
99
        }
100
    }
101
102
    /**
103
     * generate html document of backup details
104
     *
105
     * @return string
106
     */
107
    public function generateHTML() {
108
        //create blocktrail pub key QR codes if not already done
109
        if (!$this->blocktrailPubKeyQRs) {
110
            $this->processBlocktrailPubKeys();
111
        }
112
        $pubKeysHtml = "";
113
        foreach ($this->blocktrailPubKeyQRs as $pubKey) {
0 ignored issues
show
Bug introduced by
The expression $this->blocktrailPubKeyQRs of type null is not traversable.
Loading history...
114
            $pubKeysHtml .= "<img src='{$pubKey['qr']}' />";
115
        }
116
        $totalPubKeys = count($this->blocktrailPubKeyQRs);
117
118
        $backupInfo = $this->prepareBackupInfo();
119
        $extraInfo = $this->prepareExtraInfo();
120
121
        $passwordEncryptedSecret = null;
122
        if (isset($this->backupInfo['encrypted_secret'])) {
123
            $passwordEncryptedSecret = $this->backupInfo['encrypted_secret'];
124
        }
125
126
        $html = self::renderTemplate(__DIR__ . "/../resources/templates/recovery_sheet.html.php", [
127
            'identifier' => $this->identifier,
128
            'totalPubKeys' => $totalPubKeys,
129
            'pubKeysHtml' => $pubKeysHtml,
130
            'backupInfo' => $backupInfo,
131
            'extraInfo' => $extraInfo,
132
            'passwordEncryptedSecret' => $passwordEncryptedSecret,
133
            'options' => $this->options,
134
        ]);
135
136
        return $html;
137
    }
138
139
    protected function prepareBackupInfo() {
140
        $backupInfo = [];
141
142
        if (isset($this->backupInfo['primary_mnemonic'])) {
143
            $backupInfo[] = [
144
                'title' => 'Primary Mnemonic',
145
                'mnemonic' => $this->backupInfo['primary_mnemonic'],
146
            ];
147
        }
148
        if (isset($this->backupInfo['backup_mnemonic'])) {
149
            $backupInfo[] = [
150
                'title' => 'Primary Mnemonic',
151
                'mnemonic' => $this->backupInfo['backup_mnemonic'],
152
            ];
153
        }
154
        if (isset($this->backupInfo['encrypted_primary_seed'])) {
155
            $backupInfo[] = [
156
                'title' => 'Encrypted Primary Seed',
157
                'mnemonic' => $this->backupInfo['encrypted_primary_seed'],
158
            ];
159
        }
160
        if (isset($this->backupInfo['backup_seed'])) {
161
            $backupInfo[] = [
162
                'title' => 'Backup Seed',
163
                'mnemonic' => $this->backupInfo['backup_seed'],
164
            ];
165
        }
166
        if (isset($this->backupInfo['recovery_encrypted_secret'])) {
167
            $backupInfo[] = [
168
                'title' => 'Encrypted Recovery Secret',
169
                'mnemonic' => $this->backupInfo['recovery_encrypted_secret'],
170
            ];
171
        }
172
173
        return $backupInfo;
174
    }
175
176
    protected function prepareExtraInfo() {
177
        $extraInfo = [];
178
179
        foreach ($this->extra as $k => $v) {
180
            if (is_array($v)) {
181
                $extraInfo[] = $v;
182
            } else {
183
                $extraInfo[] = ['title' => $k, 'value' => $v];
184
            }
185
        }
186
187
        return $extraInfo;
188
    }
189
190
    public static function renderTemplate($file, $vars) {
191
        if (is_array($vars) && !empty($vars)) {
192
            extract($vars);
193
        }
194
195
        ob_start();
196
197
        include $file;
198
199
        return ob_get_clean();
200
    }
201
202
    /**
203
     * generate PDF document of backup details
204
     * @return string       pdf data, ready to be saved to file or streamed to browser
205
     */
206
    public function generatePDF() {
207
        $dompdf = new \DOMPDF();
208
        $html = $this->generateHTML();
209
        $dompdf->load_html($html);
210
211
        $dompdf->render();
212
        $pdfStream = $dompdf->output();
213
        return $pdfStream;
214
    }
215
216
    /**
217
     * generate text document of backup details (not implemented yet)
218
     *
219
     */
220
    public function generateTxt() {
221
        //...
222
    }
223
}
224