Passed
Push — master ( ed222d...64e89d )
by
unknown
02:51
created

BasePageController::getRSSLink()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 0
nc 1
nop 0
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace CWP\CWP\PageTypes;
4
5
use CWP\CWP\Search\CwpSearchEngine;
6
use Page;
0 ignored issues
show
Bug introduced by
The type Page was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
use SilverStripe\Assets\Filesystem;
8
use SilverStripe\CMS\Controllers\ContentController;
9
use SilverStripe\CMS\Search\SearchForm;
10
use SilverStripe\Control\Director;
11
use SilverStripe\Control\HTTPRequest;
12
use SilverStripe\Core\Config\Config;
13
use SilverStripe\Core\Environment;
14
use SilverStripe\Core\Injector\Injector;
15
use SilverStripe\Forms\FieldList;
16
use SilverStripe\Forms\FormAction;
17
use SilverStripe\Forms\TextField;
18
use SilverStripe\ORM\FieldType\DBDatetime;
19
use SilverStripe\ORM\FieldType\DBHTMLText;
20
use SilverStripe\Versioned\Versioned;
21
22
class BasePageController extends ContentController
23
{
24
    private static $allowed_actions = [
0 ignored issues
show
introduced by
The private property $allowed_actions is not used, and could be removed.
Loading history...
25
        'downloadpdf',
26
        'SearchForm',
27
        'results',
28
    ];
29
30
    /**
31
     * How many search results should be shown per-page?
32
     *
33
     * @config
34
     * @var int
35
     */
36
    private static $results_per_page = 10;
0 ignored issues
show
introduced by
The private property $results_per_page is not used, and could be removed.
Loading history...
37
38
    /**
39
     * If spelling suggestions for searches are given, enable
40
     * suggested searches to be followed immediately
41
     *
42
     * @config
43
     * @var bool
44
     */
45
    private static $search_follow_suggestions = true;
0 ignored issues
show
introduced by
The private property $search_follow_suggestions is not used, and could be removed.
Loading history...
46
47
    /**
48
     * Which classes should be queried when searching?
49
     *
50
     * @config
51
     * @var array
52
     */
53
    private static $classes_to_search = [
0 ignored issues
show
introduced by
The private property $classes_to_search is not used, and could be removed.
Loading history...
54
        [
55
            'class' => 'Page',
56
            'includeSubclasses' => true,
57
        ]
58
    ];
59
60
    /**
61
     * Serve the page rendered as PDF.
62
     */
63
    public function downloadpdf()
64
    {
65
        if (!Config::inst()->get(BasePage::class, 'pdf_export')) {
66
            return false;
67
        }
68
69
        // We only allow producing live pdf. There is no way to secure the draft files.
70
        Versioned::set_stage(Versioned::LIVE);
71
72
        $path = $this->dataRecord->getPdfFilename();
73
        if (!file_exists($path)) {
74
            $this->generatePDF();
75
        }
76
77
        return HTTPRequest::send_file(file_get_contents($path), basename($path), 'application/pdf');
78
    }
79
80
    /*
81
    * This will return either pdf_base_url from YML, CWP_SECURE_DOMAIN
82
    * from _ss_environment, or blank. In that order of importance.
83
    */
84
    public function getPDFBaseURL()
85
    {
86
        //if base url YML is defined in YML, use that
87
        if (Config::inst()->get(BasePage::class, 'pdf_base_url')) {
88
            $pdfBaseUrl = Config::inst()->get(BasePage::class, 'pdf_base_url').'/';
89
            //otherwise, if we are CWP use the secure domain
90
        } elseif (Environment::getEnv('CWP_SECURE_DOMAIN')) {
91
            $pdfBaseUrl = Environment::getEnv('CWP_SECURE_DOMAIN') . '/';
92
            //or if neither, leave blank
93
        } else {
94
            $pdfBaseUrl = '';
95
        }
96
        return $pdfBaseUrl;
97
    }
98
99
    /*
100
    * Don't use the proxy if the pdf domain is the CWP secure domain
101
    * Or if we aren't on a CWP server
102
    */
103
    public function getPDFProxy($pdfBaseUrl)
104
    {
105
        if (!Environment::getEnv('CWP_SECURE_DOMAIN')
106
            || $pdfBaseUrl == Environment::getEnv('CWP_SECURE_DOMAIN') . '/'
107
        ) {
108
            $proxy = '';
109
        } else {
110
            $proxy = ' --proxy ' . Environment::getEnv('SS_OUTBOUND_PROXY')
111
                . ':' . Environment::getEnv('SS_OUTBOUND_PROXY_PORT');
112
        }
113
        return $proxy;
114
    }
115
116
    /**
117
     * Render the page as PDF using wkhtmltopdf.
118
     */
119
    public function generatePDF()
120
    {
121
        if (!Config::inst()->get(BasePage::class, 'pdf_export')) {
122
            return false;
123
        }
124
125
        $binaryPath = Config::inst()->get(BasePage::class, 'wkhtmltopdf_binary');
126
        if (!$binaryPath || !is_executable($binaryPath)) {
127
            if (Environment::getEnv('WKHTMLTOPDF_BINARY')
128
                && is_executable(Environment::getEnv('WKHTMLTOPDF_BINARY'))
129
            ) {
130
                $binaryPath = Environment::getEnv('WKHTMLTOPDF_BINARY');
131
            }
132
        }
133
134
        if (!$binaryPath) {
135
            user_error('Neither WKHTMLTOPDF_BINARY nor BasePage.wkhtmltopdf_binary are defined', E_USER_ERROR);
136
        }
137
138
        if (Versioned::get_reading_mode() == 'Stage.Stage') {
139
            user_error('Generating PDFs on draft is not supported', E_USER_ERROR);
140
        }
141
142
        set_time_limit(60);
143
144
        // prepare the paths
145
        $pdfFile = $this->dataRecord->getPdfFilename();
146
        $bodyFile = str_replace('.pdf', '_pdf.html', $pdfFile);
147
        $footerFile = str_replace('.pdf', '_pdffooter.html', $pdfFile);
148
149
        // make sure the work directory exists
150
        if (!file_exists(dirname($pdfFile))) {
151
            Filesystem::makeFolder(dirname($pdfFile));
152
        }
153
154
        //decide the domain to use in generation
155
        $pdfBaseUrl = $this->getPDFBaseURL();
156
157
        // Force http protocol on CWP - fetching from localhost without using the proxy, SSL terminates on gateway.
158
        if (Environment::getEnv('CWP_ENVIRONMENT')) {
159
            Config::modify()->set(Director::class, 'alternate_protocol', 'http');
160
            //only set alternate protocol if CWP_SECURE_DOMAIN is defined OR pdf_base_url is
161
            if ($pdfBaseUrl) {
162
                Config::modify()->set(Director::class, 'alternate_base_url', 'http://' . $pdfBaseUrl);
163
            }
164
        }
165
166
        $bodyViewer = $this->getViewer('pdf');
167
168
        // write the output of this page to HTML, ready for conversion to PDF
169
        file_put_contents($bodyFile, $bodyViewer->process($this));
170
171
        // get the viewer for the current template with _pdffooter
172
        $footerViewer = $this->getViewer('pdffooter');
173
174
        // write the output of the footer template to HTML, ready for conversion to PDF
175
        file_put_contents($footerFile, $footerViewer->process($this));
176
177
        //decide what the proxy should look like
178
        $proxy = $this->getPDFProxy($pdfBaseUrl);
179
180
        // finally, generate the PDF
181
        $command = $binaryPath . $proxy . ' --outline -B 40pt -L 20pt -R 20pt -T 20pt --encoding utf-8 '
182
            . '--orientation Portrait --disable-javascript --quiet --print-media-type ';
183
        $retVal = 0;
184
        $output = array();
185
        exec(
186
            $command . " --footer-html \"$footerFile\" \"$bodyFile\" \"$pdfFile\" &> /dev/stdout",
187
            $output,
188
            $retVal
189
        );
190
191
        // remove temporary file
192
        unlink($bodyFile);
193
        unlink($footerFile);
194
195
        // output any errors
196
        if ($retVal != 0) {
197
            user_error('wkhtmltopdf failed: ' . implode("\n", $output), E_USER_ERROR);
198
        }
199
200
        // serve the generated file
201
        return HTTPRequest::send_file(file_get_contents($pdfFile), basename($pdfFile), 'application/pdf');
202
    }
203
204
    /**
205
     * Site search form
206
     */
207
    public function SearchForm()
208
    {
209
        $searchText = $this->getRequest()->getVar('Search');
210
211
        $fields = FieldList::create(
212
            TextField::create('Search', false, $searchText)
0 ignored issues
show
Bug introduced by
'Search' of type string is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

212
            TextField::create(/** @scrutinizer ignore-type */ 'Search', false, $searchText)
Loading history...
Bug introduced by
false of type false is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

212
            TextField::create('Search', /** @scrutinizer ignore-type */ false, $searchText)
Loading history...
213
        );
214
        $actions = FieldList::create(
215
            FormAction::create('results', _t('SilverStripe\\CMS\\Search\\SearchForm.GO', 'Go'))
216
        );
217
218
        $form = SearchForm::create($this, SearchForm::class, $fields, $actions);
0 ignored issues
show
Bug introduced by
$this of type CWP\CWP\PageTypes\BasePageController is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

218
        $form = SearchForm::create(/** @scrutinizer ignore-type */ $this, SearchForm::class, $fields, $actions);
Loading history...
219
        $form->setFormAction('search/SearchForm');
220
221
        return $form;
222
    }
223
224
    /**
225
     * Get search form with _header suffix
226
     *
227
     * @return SearchForm
228
     */
229
    public function HeaderSearchForm()
230
    {
231
        return $this->SearchForm()->setTemplate('SearchForm_header');
232
    }
233
234
    /**
235
     * Process and render search results.
236
     *
237
     * @param array $data The raw request data submitted by user
238
     * @param SearchForm $form The form instance that was submitted
239
     * @param HTTPRequest $request Request generated for this action
240
     * @return DBHTMLText
241
     */
242
    public function results($data, $form, $request)
243
    {
244
        // Check parameters for terms, pagination, and if we should follow suggestions
245
        $keywords = empty($data['Search']) ? '' : $data['Search'];
246
        $start = isset($data['start']) ? $data['start'] : 0;
247
        $suggestions = isset($data['suggestions'])
248
            ? $data['suggestions']
249
            : $this->config()->get('search_follow_suggestions');
250
251
        $results = CwpSearchEngine::create()
252
            ->search(
253
                $keywords,
254
                $this->config()->get('classes_to_search'),
255
                Injector::inst()->get(CwpSearchEngine::class . '.search_index'),
256
                $this->config()->get('results_per_page'),
257
                $start,
258
                $suggestions
259
            );
260
261
        // Customise content with these results
262
        $properties = [
263
            'MetaTitle' => _t(__CLASS__ . '.MetaTitle', 'Search {keywords}', ['keywords' => $keywords]),
264
            'NoSearchResults' => _t(__CLASS__ . '.NoResult', 'Sorry, your search query did not return any results.'),
265
            'EmptySearch' => _t(__CLASS__ . '.EmptySearch', 'Search field empty, please enter your search query.'),
266
            'PdfLink' => '',
267
            'Title' => _t('SilverStripe\\CMS\\Search\\SearchForm.SearchResults', 'Search Results'),
268
        ];
269
        $this->extend('updateSearchResults', $results, $properties);
270
271
        // Customise page
272
        $response = $this->customise($properties);
273
        if ($results) {
274
            $response = $response
275
                ->customise($results)
276
                ->customise(array( 'Results' => $results->getResults() ));
277
        }
278
279
        // Render
280
        $templates = $this->getResultsTemplate($request);
281
        return $response->renderWith($templates);
282
    }
283
284
    /**
285
     * Select the template to render search results with
286
     *
287
     * @param HTTPRequest $request
288
     * @return array
289
     */
290
    protected function getResultsTemplate($request)
291
    {
292
        $templates = [Page::class . '_results', Page::class];
293
        if ($request->getVar('format') == 'rss') {
294
            array_unshift($templates, 'Page_results_rss');
295
        }
296
        if ($request->getVar('format') == 'atom') {
297
            array_unshift($templates, 'Page_results_atom');
298
        }
299
        return $templates;
300
    }
301
302
    /**
303
     * Provide current year.
304
     */
305
    public function CurrentDatetime()
306
    {
307
        return DBDatetime::now();
308
    }
309
310
    public function getRSSLink()
311
    {
312
    }
313
}
314