Passed
Push — 1.0 ( f98e99...d51fd4 )
by Morven
03:56 queued 01:45
created

DisplayController::generate_pdf()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 9
c 1
b 0
f 1
nc 1
nop 1
dl 0
loc 13
rs 9.9666
1
<?php
2
3
namespace SilverCommerce\OrdersAdmin\Control;
4
5
use Dompdf\Dompdf;
6
use Dompdf\Options;
7
use SilverStripe\Core\Path;
8
use SilverStripe\Assets\Image;
9
use SilverStripe\Security\Member;
10
use SilverStripe\Control\Director;
11
use SilverStripe\Security\Security;
12
use SilverStripe\View\Requirements;
13
use SilverStripe\Control\Controller;
14
use SilverStripe\Control\HTTPRequest;
15
use SilverStripe\SiteConfig\SiteConfig;
16
use SilverStripe\Control\HTTPStreamResponse;
17
use SilverCommerce\OrdersAdmin\Model\Invoice;
18
use SilverCommerce\OrdersAdmin\Model\Estimate;
19
use SilverStripe\Core\Manifest\ModuleResourceLoader;
20
21
/**
22
 * Controller responsible for displaying either an rendered order or a
23
 * rendered quote that can be emailed or printed.
24
 *
25
 * @package Orders
26
 */
27
class DisplayController extends Controller
28
{
29
    /**
30
     * ClassName of Order object
31
     *
32
     * @var string
33
     * @config
34
     */
35
    private static $url_segment = "ordersadmin/display";
36
    
37
    
38
    private static $allowed_actions = [
39
        "invoice",
40
        "invoicepdf",
41
        "estimate",
42
        "estimatepdf"
43
    ];
44
45
    /**
46
     * directory for pdf css file (in requirements format)
47
     *
48
     * @var string
49
     * @config
50
     */
51
    private static $pdf_css = 'silvercommerce/orders-admin: client/dist/css/pdf.css';
52
53
    /**
54
     * Ther object associated with this controller
55
     *
56
     * @var Estimate
57
     */
58
    protected $object;
59
60
    protected function init()
61
    {
62
        parent::init();
63
64
        $member = Security::getCurrentUser();
65
        $object = Estimate::get()
66
            ->byID($this->getrequest()->param("ID"));
67
68
        if ($object && (
69
            ($member && $object->canView($member)) ||
70
            ($object->AccessKey && $object->AccessKey == $this->request->param("OtherID"))
71
        )) {
72
            $this->object = $object;
73
        } else {
74
            return Security::permissionFailure();
75
        }
76
    }
77
78
    /**
79
     * Generate a Dompdf object from the provided html
80
     *
81
     * @param string $html
82
     * @return Dompdf
83
     */
84
    protected function generate_pdf($html)
85
    {
86
        $options = new Options([
87
            "compressed" => true,
88
            'defaultFont' => 'sans-serif',
89
            'isHtml5ParserEnabled' => true,
90
            'isRemoteEnabled' => true
91
        ]);
92
        $dompdf = new Dompdf($options);
93
        $dompdf->loadHtml($html);
94
        $dompdf->setPaper('A4', 'portrait');
95
96
        return $dompdf;
97
    }
98
99
    /**
100
     * Undocumented function
101
     *
102
     * @return \SilverStripe\Assets\Image
103
     */
104
    public function Logo()
105
    {
106
        $config = SiteConfig::current_site_config();
107
        $image = $config->EstimateInvoiceLogo();
108
109
        $this->extend("updateLogo", $image);
110
        
111
        return $image;
112
    }
113
114
    /**
115
     * get the current logo as a base 64 encoded string
116
     *
117
     * @return string
118
     */
119
    public function LogoBase64(int $width = 0, int $height = 0)
120
    {
121
        $logo = $this->Logo();
122
123
        if ($width > 0 && $height > 0) {
124
            $logo = $logo->Fit($width, $height);
125
        }
126
        $string = base64_encode($logo->getString());
127
128
        $this->extend("updateLogoBase64", $string);
129
        
130
        return $string;
131
    }
132
    
133
    /**
134
     * Get a relative link to anorder or invoice
135
     *
136
     * NOTE: this controller will always require an ID of an order and
137
     * access key to be passed (as well as an action).
138
     *
139
     * @param $action Action we would like to view.
140
     * @param $id ID or the order we want to view.
141
     * @param $key Access key of the order (for security).
142
     * @return string
143
     */
144
    public function Link($action = "invoice")
145
    {
146
        return Controller::join_links(
147
            $this->config()->url_segment,
148
            $action
149
        );
150
    }
151
    
152
    /**
153
     * Get an absolute link to an order or invoice
154
     *
155
     * NOTE: this controller will always require an ID of an order and
156
     * access key to be passed (as well as an action).
157
     *
158
     * @param $action Action we would like to view.
159
     * @param $id ID or the order we want to view.
160
     * @param $key Access key of the order (for security).
161
     * @return string
162
     */
163
    public function AbsoluteLink($action = "invoice")
164
    {
165
        return Controller::join_links(
166
            Director::absoluteBaseURL(),
167
            $this->Link($action)
168
        );
169
    }
170
171
    /**
172
     * Generate the CSS for the rendered PDF as a string (based on the provided path in config)
173
     *
174
     * @return string
175
     */
176
    protected function getPdfCss()
177
    {
178
        $loader = ModuleResourceLoader::singleton();
179
        $path = $loader->resolvePath($this->config()->pdf_css);
180
181
        // If using a public dir, then apend it's location
182
        if (Director::publicDir() && defined('RESOURCES_DIR')) {
183
            // All resources mapped directly to _resources/
184
            $path = Path::join(RESOURCES_DIR, $path);
185
        }
186
187
        return file_get_contents($path);
188
    }
189
190
    public function invoice(HTTPRequest $request)
191
    {
192
        $config = SiteConfig::current_site_config();
193
        
194
        $this->customise([
195
            "Type" => "Invoice",
196
            "HeaderContent" => $config->dbObject("InvoiceHeaderContent"),
197
            "FooterContent" => $config->dbObject("InvoiceFooterContent"),
198
            "Title" => _t("Orders.InvoiceTitle", "Invoice"),
199
            "MetaTitle" => _t("Orders.InvoiceTitle", "Invoice"),
200
            "Object" => $this->object
201
        ]);
202
203
        $this->extend("updateInvoice");
204
        
205
        return $this->render();
206
    }
207
208
    /**
209
     * Generate a PDF based on the invoice html output.
210
     *
211
     * @todo At the moment this exits all execution after generating
212
     * and streaming PDF. Ideally this should tap into
213
     * @link http://api.silverstripe.org/4/SilverStripe/Control/HTTPStreamResponse.html
214
     *
215
     * @param HTTPRequest $request
216
     * @return void
217
     */
218
    public function invoicepdf(HTTPRequest $request)
219
    {
220
        $style = $this->getPdfCss();
221
        Requirements::clear();
222
        Requirements::customCSS(<<<CSS
223
        $style
224
CSS
225
        );
226
        $result = $this->invoice($request);
227
        $html = $result->getValue();
228
        $pdf = $this->generate_pdf($html);
229
230
        $this->extend("updateInvoicePDF", $pdf);
231
232
        $pdf->render();
233
        $pdf->stream("{$this->object->FullRef}.pdf");
234
        exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
235
    }
236
    
237
    public function estimate(HTTPRequest $request)
238
    {
239
        $config = SiteConfig::current_site_config();
240
        $this->customise([
241
            "Type" => "Estimate",
242
            "HeaderContent" => $config->dbObject("EstimateHeaderContent"),
243
            "FooterContent" => $config->dbObject("EstimateFooterContent"),
244
            "Title" => _t("Orders.EstimateTitle", "Estimate"),
245
            "MetaTitle" => _t("Orders.EstimateTitle", "Estimate"),
246
            "Object" => $this->object
247
        ]);
248
249
        $this->extend("updateEstimate");
250
        
251
        return $this->render();
252
    }
253
254
    public function estimatepdf(HTTPRequest $request)
255
    {
256
        $style = $this->getPdfCss();
257
        Requirements::clear();
258
        Requirements::customCSS(<<<CSS
259
        $style
260
CSS
261
        );
262
        $result = $this->estimate($request);
263
        $html = $result->getValue();
264
265
        $pdf = $this->generate_pdf($html);
266
267
        $this->extend("updateEstimatePDF", $pdf);
268
269
        $pdf->render();
270
        $pdf->stream("{$this->object->FullRef}.pdf");
271
        exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
272
    }
273
}
274