Completed
Pull Request — master (#80)
by Damian
04:08
created

ShareDraftController::getIsDraftSecured()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\ShareDraftContent\Controllers;
4
5
use BadMethodCallException;
6
use PageController;
0 ignored issues
show
Bug introduced by
The type PageController 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\CMS\Controllers\ContentController;
8
use SilverStripe\CMS\Controllers\ModelAsController;
9
use SilverStripe\CMS\Model\SiteTree;
10
use SilverStripe\Control\Controller;
11
use SilverStripe\Control\HTTPRequest;
12
use SilverStripe\Control\Session;
13
use SilverStripe\Core\Injector\Injector;
14
use SilverStripe\ORM\FieldType\DBHTMLText;
15
use SilverStripe\ShareDraftContent\Extensions\ShareDraftContentSiteTreeExtension;
16
use SilverStripe\ShareDraftContent\Models\ShareToken;
17
use SilverStripe\Versioned\Versioned;
18
use SilverStripe\View\ArrayData;
19
use SilverStripe\View\Requirements;
20
21
class ShareDraftController extends Controller
22
{
23
    /**
24
     * Controller for rendering draft pages.
25
     *
26
     * @config
27
     *
28
     * @var string
29
     */
30
    private static $controller = PageController::class;
0 ignored issues
show
introduced by
The private property $controller is not used, and could be removed.
Loading history...
31
32
    /**
33
     * @var array
34
     */
35
    private static $allowed_actions = array(
0 ignored issues
show
introduced by
The private property $allowed_actions is not used, and could be removed.
Loading history...
36
        'preview'
37
    );
38
39
    /**
40
     * @var array
41
     */
42
    private static $url_handlers = array(
0 ignored issues
show
introduced by
The private property $url_handlers is not used, and could be removed.
Loading history...
43
        '$Key/$Token' => 'preview'
44
    );
45
46
    /**
47
     * @param HTTPRequest $request
48
     *
49
     * @return string|DBHTMLText
50
     */
51
    public function preview(HTTPRequest $request)
52
    {
53
        $key = $request->param('Key');
54
        $token = $request->param('Token');
55
        try {
56
            $session = $this->getRequest()->getSession();
57
        } catch (BadMethodCallException $e) {
58
            // Create a new session
59
            $session = $this->getRequest()
60
                ->setSession(Injector::inst()->create(Session::class, []))
61
                ->getSession();
62
        }
63
        /** @var ShareToken $shareToken */
64
        $shareToken = ShareToken::get()->filter('Token', $token)->first();
65
66
        if (!$shareToken) {
67
            return $this->errorPage();
68
        }
69
70
        /** @var SiteTree|ShareDraftContentSiteTreeExtension $page */
71
        $page = Versioned::get_by_stage(SiteTree::class, Versioned::DRAFT)
72
            ->byID($shareToken->PageID);
73
74
        $latest = Versioned::get_latest_version(SiteTree::class, $shareToken->PageID);
75
76
        $controller = $this->getControllerFor($page);
0 ignored issues
show
Bug introduced by
It seems like $page can also be of type SilverStripe\ShareDraftC...ontentSiteTreeExtension; however, parameter $page of SilverStripe\ShareDraftC...ler::getControllerFor() does only seem to accept SilverStripe\CMS\Model\SiteTree, maybe add an additional type check? ( Ignorable by Annotation )

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

76
        $controller = $this->getControllerFor(/** @scrutinizer ignore-type */ $page);
Loading history...
77
78
        if (!$shareToken->isExpired() && $page->generateKey($shareToken->Token) === $key) {
79
            Requirements::css('silverstripe/sharedraftcontent: client/dist/styles/top-bar.css');
80
81
            // Temporarily un-secure the draft site and switch to draft
82
            $oldSecured = $this->getIsDraftSecured($session);
83
            $oldMode = Versioned::get_reading_mode();
84
85
            // Process page inside an unsecured draft container
86
            try {
87
                $this->setIsDraftSecured($session, false);
88
                Versioned::set_stage('Stage');
89
90
                // Hack to get around ContentController::init() redirecting on home page
91
                $_FILES = array(array());
92
93
                // Create mock request; Simplify request to single top level request
94
                $pageRequest = new HTTPRequest('GET', $page->URLSegment);
0 ignored issues
show
Bug introduced by
The property URLSegment does not seem to exist on SilverStripe\ShareDraftC...ontentSiteTreeExtension.
Loading history...
95
                $pageRequest->match('$URLSegment//$Action/$ID/$OtherID', true);
96
                $pageRequest->setSession($session);
97
                $rendered = $controller->handleRequest($pageRequest);
98
99
                // Render draft heading
100
                $data = new ArrayData(array(
101
                    'Page' => $page,
102
                    'Latest' => $latest,
103
                ));
104
                $include = (string) $data->renderWith('Includes/TopBar');
105
            } finally {
106
                $this->setIsDraftSecured($session, $oldSecured);
107
                Versioned::set_reading_mode($oldMode);
108
            }
109
110
            return str_replace('</body>', $include . '</body>', (string) $rendered->getBody());
111
        } else {
112
            return $this->errorPage();
113
        }
114
    }
115
116
    /**
117
     * @return DBHTMLText
118
     */
119
    protected function errorPage()
120
    {
121
        Requirements::css('silverstripe/sharedraftcontent: client/dist/styles/error-page.css');
122
        return $this->renderWith('ShareDraftContentError');
123
    }
124
125
    /**
126
     * @param SiteTree $page
127
     * @return ContentController
128
     */
129
    protected function getControllerFor($page)
130
    {
131
        return ModelAsController::controller_for($page);
132
    }
133
134
    /**
135
     * Check if the draft site is secured
136
     *
137
     * @param Session $session
138
     * @return bool True if the draft site is secured
139
     */
140
    protected function getIsDraftSecured(Session $session)
141
    {
142
        // Versioned >=1.2
143
        if (method_exists(Versioned::class, 'get_draft_site_secured')) {
144
            return Versioned::get_draft_site_secured();
0 ignored issues
show
Bug introduced by
The method get_draft_site_secured() does not exist on SilverStripe\Versioned\Versioned. ( Ignorable by Annotation )

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

144
            return Versioned::/** @scrutinizer ignore-call */ get_draft_site_secured();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
145
        }
146
147
        // Fall back to session
148
        return !$session->get('unsecuredDraftSite');
149
    }
150
151
    /**
152
     * Set draft site security
153
     *
154
     * @param Session $session
155
     * @param bool $secured True if draft site should be secured
156
     */
157
    protected function setIsDraftSecured(Session $session, $secured)
158
    {
159
        // Versioned >=1.2
160
        if (method_exists(Versioned::class, 'set_draft_site_secured')) {
161
            Versioned::set_draft_site_secured($secured);
0 ignored issues
show
Bug introduced by
The method set_draft_site_secured() does not exist on SilverStripe\Versioned\Versioned. ( Ignorable by Annotation )

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

161
            Versioned::/** @scrutinizer ignore-call */ 
162
                       set_draft_site_secured($secured);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
162
        }
163
164
        // Set session variable anyway
165
        $session->set('unsecuredDraftSite', !$secured);
166
    }
167
}
168