Completed
Pull Request — master (#89)
by thomas
16:20
created

BackupGenerator::renderTemplate()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

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