Completed
Pull Request — master (#30)
by Robbie
02:19
created

BasePageController::results()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 40
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 27
nc 16
nop 3
dl 0
loc 40
rs 8.439
c 0
b 0
f 0
1
<?php
2
3
namespace CWP\CWP\PageTypes;
4
5
use SilverStripe\Assets\Filesystem;
6
use SilverStripe\CMS\Controllers\ContentController;
7
use SilverStripe\Control\Director;
8
use SilverStripe\Control\HTTPRequest;
9
use SilverStripe\Core\Config\Config;
10
use SilverStripe\Core\Environment;
11
use SilverStripe\ORM\FieldType\DBDatetime;
12
use SilverStripe\Versioned\Versioned;
13
14
class BasePageController extends ContentController
15
{
16
    private static $allowed_actions = [
0 ignored issues
show
introduced by
The private property $allowed_actions is not used, and could be removed.
Loading history...
17
        'downloadpdf',
18
    ];
19
20
    /**
21
     * Serve the page rendered as PDF.
22
     */
23
    public function downloadpdf()
24
    {
25
        if (!Config::inst()->get(BasePage::class, 'pdf_export')) {
26
            return false;
27
        }
28
29
        // We only allow producing live pdf. There is no way to secure the draft files.
30
        Versioned::set_stage(Versioned::LIVE);
31
32
        $path = $this->dataRecord->getPdfFilename();
33
        if (!file_exists($path)) {
34
            $this->generatePDF();
35
        }
36
37
        return HTTPRequest::send_file(file_get_contents($path), basename($path), 'application/pdf');
38
    }
39
40
    /*
41
    * This will return either pdf_base_url from YML, CWP_SECURE_DOMAIN
42
    * from _ss_environment, or blank. In that order of importance.
43
    */
44
    public function getPDFBaseURL()
45
    {
46
        //if base url YML is defined in YML, use that
47
        if (Config::inst()->get(BasePage::class, 'pdf_base_url')) {
48
            $pdfBaseUrl = Config::inst()->get(BasePage::class, 'pdf_base_url').'/';
49
            //otherwise, if we are CWP use the secure domain
50
        } elseif (Environment::getEnv('CWP_SECURE_DOMAIN')) {
51
            $pdfBaseUrl = Environment::getEnv('CWP_SECURE_DOMAIN') . '/';
52
            //or if neither, leave blank
53
        } else {
54
            $pdfBaseUrl = '';
55
        }
56
        return $pdfBaseUrl;
57
    }
58
59
    /*
60
    * Don't use the proxy if the pdf domain is the CWP secure domain
61
    * Or if we aren't on a CWP server
62
    */
63
    public function getPDFProxy($pdfBaseUrl)
64
    {
65
        if (!Environment::getEnv('CWP_SECURE_DOMAIN')
66
            || $pdfBaseUrl == Environment::getEnv('CWP_SECURE_DOMAIN') . '/'
67
        ) {
68
            $proxy = '';
69
        } else {
70
            $proxy = ' --proxy ' . Environment::getEnv('SS_OUTBOUND_PROXY')
71
                . ':' . Environment::getEnv('SS_OUTBOUND_PROXY_PORT');
72
        }
73
        return $proxy;
74
    }
75
76
    /**
77
     * Render the page as PDF using wkhtmltopdf.
78
     */
79
    public function generatePDF()
80
    {
81
        if (!Config::inst()->get(BasePage::class, 'pdf_export')) {
82
            return false;
83
        }
84
85
        $binaryPath = Config::inst()->get(BasePage::class, 'wkhtmltopdf_binary');
86
        if (!$binaryPath || !is_executable($binaryPath)) {
87
            if (Environment::getEnv('WKHTMLTOPDF_BINARY')
88
                && is_executable(Environment::getEnv('WKHTMLTOPDF_BINARY'))
89
            ) {
90
                $binaryPath = Environment::getEnv('WKHTMLTOPDF_BINARY');
91
            }
92
        }
93
94
        if (!$binaryPath) {
95
            user_error('Neither WKHTMLTOPDF_BINARY nor BasePage.wkhtmltopdf_binary are defined', E_USER_ERROR);
96
        }
97
98
        if (Versioned::get_reading_mode() == 'Stage.Stage') {
99
            user_error('Generating PDFs on draft is not supported', E_USER_ERROR);
100
        }
101
102
        set_time_limit(60);
103
104
        // prepare the paths
105
        $pdfFile = $this->dataRecord->getPdfFilename();
106
        $bodyFile = str_replace('.pdf', '_pdf.html', $pdfFile);
107
        $footerFile = str_replace('.pdf', '_pdffooter.html', $pdfFile);
108
109
        // make sure the work directory exists
110
        if (!file_exists(dirname($pdfFile))) {
111
            Filesystem::makeFolder(dirname($pdfFile));
112
        }
113
114
        //decide the domain to use in generation
115
        $pdfBaseUrl = $this->getPDFBaseURL();
116
117
        // Force http protocol on CWP - fetching from localhost without using the proxy, SSL terminates on gateway.
118
        if (Environment::getEnv('CWP_ENVIRONMENT')) {
119
            Config::modify()->set(Director::class, 'alternate_protocol', 'http');
120
            //only set alternate protocol if CWP_SECURE_DOMAIN is defined OR pdf_base_url is
121
            if ($pdfBaseUrl) {
122
                Config::modify()->set(Director::class, 'alternate_base_url', 'http://' . $pdfBaseUrl);
123
            }
124
        }
125
126
        $bodyViewer = $this->getViewer('pdf');
127
128
        // write the output of this page to HTML, ready for conversion to PDF
129
        file_put_contents($bodyFile, $bodyViewer->process($this));
130
131
        // get the viewer for the current template with _pdffooter
132
        $footerViewer = $this->getViewer('pdffooter');
133
134
        // write the output of the footer template to HTML, ready for conversion to PDF
135
        file_put_contents($footerFile, $footerViewer->process($this));
136
137
        //decide what the proxy should look like
138
        $proxy = $this->getPDFProxy($pdfBaseUrl);
139
140
        // finally, generate the PDF
141
        $command = $binaryPath . $proxy . ' --outline -B 40pt -L 20pt -R 20pt -T 20pt --encoding utf-8 '
142
            . '--orientation Portrait --disable-javascript --quiet --print-media-type ';
143
        $retVal = 0;
144
        $output = array();
145
        exec(
146
            $command . " --footer-html \"$footerFile\" \"$bodyFile\" \"$pdfFile\" &> /dev/stdout",
147
            $output,
148
            $retVal
149
        );
150
151
        // remove temporary file
152
        unlink($bodyFile);
153
        unlink($footerFile);
154
155
        // output any errors
156
        if ($retVal != 0) {
157
            user_error('wkhtmltopdf failed: ' . implode("\n", $output), E_USER_ERROR);
158
        }
159
160
        // serve the generated file
161
        return HTTPRequest::send_file(file_get_contents($pdfFile), basename($pdfFile), 'application/pdf');
162
    }
163
164
    /**
165
     * Provide current year.
166
     */
167
    public function CurrentDatetime()
168
    {
169
        return DBDatetime::now();
170
    }
171
172
    public function getRSSLink()
173
    {
174
    }
175
}
176