Completed
Push — master ( 254925...5d79ce )
by Lhalaa
14s queued 10s
created

PartialUserFormController::validateToken()   B

Complexity

Conditions 8
Paths 4

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 8

Importance

Changes 0
Metric Value
dl 0
loc 29
ccs 16
cts 16
cp 1
rs 8.2114
c 0
b 0
f 0
cc 8
nc 4
nop 1
crap 8
1
<?php
2
3
namespace Firesphere\PartialUserforms\Controllers;
4
5
use Exception;
6
use Firesphere\PartialUserforms\Models\PartialFormSubmission;
7
use Page;
8
use SilverStripe\Control\HTTPRequest;
9
use Firesphere\PartialUserforms\Forms\PasswordForm;
10
use SilverStripe\Control\HTTPResponse;
11
use SilverStripe\Control\HTTPResponse_Exception;
12
use SilverStripe\Control\Middleware\HTTPCacheControlMiddleware;
13
use SilverStripe\Forms\Form;
14
use SilverStripe\ORM\DataObject;
15
use SilverStripe\ORM\FieldType\DBField;
16
use SilverStripe\ORM\FieldType\DBHTMLText;
17
use SilverStripe\UserForms\Control\UserDefinedFormController;
18
use SilverStripe\UserForms\Model\UserDefinedForm;
19
20
/**
21
 * Class PartialUserFormController
22
 *
23
 * @package Firesphere\PartialUserforms\Controllers
24
 */
25
class PartialUserFormController extends UserDefinedFormController
26
{
27
    /**
28
     * @var array
29
     */
30
    private static $url_handlers = [
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
31
        '$Key/$Token' => 'partial',
32
    ];
33
    /**
34
     * @var array
35
     */
36
    private static $allowed_actions = [
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
37
        'partial',
38
    ];
39
    /**
40
     * @var PartialFormSubmission
41
     */
42
    protected $partialFormSubmission;
43
44
    /**
45
     * Partial form
46
     *
47
     * @param HTTPRequest $request
48
     * @return HTTPResponse|DBHTMLText|void
49
     * @throws HTTPResponse_Exception
50
     * @throws Exception
51
     */
52 4
    public function partial(HTTPRequest $request)
53
    {
54
        /** @var PartialFormSubmission $partial */
55 4
        $partial = $this->validateToken($request);
56 1
        $record = DataObject::get_by_id($partial->UserDefinedFormClass, $partial->UserDefinedFormID);
0 ignored issues
show
Documentation introduced by
The property UserDefinedFormClass does not exist on object<Firesphere\Partia...\PartialFormSubmission>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
57
        /** @var self $controller */
58 1
        $controller = self::create($record);
59 1
        $controller->doInit();
60 1
        $controller->dataRecord = $record;
0 ignored issues
show
Documentation Bug introduced by
It seems like $record can also be of type object<SilverStripe\ORM\DataObject>. However, the property $dataRecord is declared as type object<SilverStripe\CMS\Model\SiteTree>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
61 1
        if ($controller->data()->PasswordProtected &&
62 1
            $request->getSession()->get(PasswordForm::PASSWORD_SESSION_KEY) !== $partial->ID
63
        ) {
64 1
            return $this->redirect('verify');
65
        }
66
67
        /** @var Form $form */
68
        $form = $controller->Form();
69
        $fields = $partial->PartialFields()->map('Name', 'Value')->toArray();
70
        $form->loadDataFrom($fields);
71
72
        // Copied from {@link UserDefinedFormController}
73
        if ($controller->Content && $form && !$controller->config()->disable_form_content_shortcode) {
0 ignored issues
show
Documentation introduced by
The property Content does not exist on object<Firesphere\Partia...tialUserFormController>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
74
            $hasLocation = stristr($controller->Content, '$UserDefinedForm');
0 ignored issues
show
Documentation introduced by
The property Content does not exist on object<Firesphere\Partia...tialUserFormController>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
75
            if ($hasLocation) {
76
                /** @see Requirements_Backend::escapeReplacement */
77
                $formEscapedForRegex = addcslashes($form->forTemplate(), '\\$');
78
                $content = preg_replace(
79
                    '/(<p[^>]*>)?\\$UserDefinedForm(<\\/p>)?/i',
80
                    $formEscapedForRegex,
81
                    $controller->Content
0 ignored issues
show
Documentation introduced by
The property Content does not exist on object<Firesphere\Partia...tialUserFormController>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
82
                );
83
84
                return $controller->customise([
85
                    'Content'     => DBField::create_field('HTMLText', $content),
86
                    'Form'        => '',
87
                    'PartialLink' => $partial->getPartialLink()
88
                ])->renderWith([static::class, Page::class]);
89
            }
90
        }
91
92
        return $controller->customise([
93
            'Content'     => DBField::create_field('HTMLText', $controller->Content),
0 ignored issues
show
Documentation introduced by
The property Content does not exist on object<Firesphere\Partia...tialUserFormController>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
94
            'Form'        => $form,
95
            'PartialLink' => $partial->getPartialLink()
96
        ])->renderWith([static::class, Page::class]);
97
    }
98
99
    /**
100
     * A little abstraction to be more readable
101
     *
102
     * @param HTTPRequest $request
103
     * @return PartialFormSubmission|void
104
     * @throws HTTPResponse_Exception
105
     */
106 4
    public function validateToken($request)
107
    {
108
        // Ensure this URL doesn't get picked up by HTTP caches
109 4
        HTTPCacheControlMiddleware::singleton()->disableCache();
110
111 4
        $key = $request->param('Key');
112 4
        $token = $request->param('Token');
113 4
        if (!$key || !$token) {
114 1
            return $this->httpError(404);
115
        }
116
117
        /** @var PartialFormSubmission $partial */
118 3
        $partial = PartialFormSubmission::get()->find('Token', $token);
119 3
        if (!$token ||
120 3
            !$partial ||
121 1
            !$partial->UserDefinedFormID ||
122 3
            !hash_equals($partial->generateKey($token), $key)
123
        ) {
124 2
            return $this->httpError(404);
125
        }
126
127 1
        $sessionKey = PartialSubmissionController::SESSION_KEY;
128
        // Set the session if the last session has expired
129 1
        if (!$request->getSession()->get($sessionKey)) {
130 1
            $request->getSession()->set($sessionKey, $partial->ID);
131
        }
132
133 1
        return $partial;
134
    }
135
136
    /**
137
     * @return PartialFormSubmission
138
     */
139
    public function getPartialFormSubmission(): PartialFormSubmission
140
    {
141
        return $this->partialFormSubmission;
142
    }
143
144
    /**
145
     * @param PartialFormSubmission $partialFormSubmission
146
     */
147
    public function setPartialFormSubmission(PartialFormSubmission $partialFormSubmission): void
148
    {
149
        $this->partialFormSubmission = $partialFormSubmission;
150
    }
151
}
152