Completed
Pull Request — master (#30)
by Lhalaa
07:31
created

PartialUserFormController   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 114
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Test Coverage

Coverage 88.24%

Importance

Changes 0
Metric Value
wmc 15
lcom 1
cbo 11
dl 0
loc 114
ccs 45
cts 51
cp 0.8824
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
C partial() 0 61 12
A populateFileData() 0 21 3
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 SilverStripe\Control\HTTPResponse_Exception;
10
use SilverStripe\Control\Middleware\HTTPCacheControlMiddleware;
11
use SilverStripe\Forms\Form;
12
use SilverStripe\ORM\DataObject;
13
use SilverStripe\ORM\FieldType\DBField;
14
use SilverStripe\ORM\FieldType\DBHTMLText;
15
use SilverStripe\UserForms\Control\UserDefinedFormController;
16
17
/**
18
 * Class PartialUserFormController
19
 *
20
 * @package Firesphere\PartialUserforms\Controllers
21
 */
22
class PartialUserFormController extends UserDefinedFormController
23
{
24
    /**
25
     * @var array
26
     */
27
    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...
28
        '$Key/$Token' => 'partial',
29
    ];
30
31
    /**
32
     * @var array
33
     */
34
    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...
35
        'partial',
36
    ];
37
38
    /**
39
     * Partial form
40
     *
41
     * @param HTTPRequest $request
42
     * @return DBHTMLText|void
43
     * @throws HTTPResponse_Exception
44
     * @throws Exception
45
     */
46 5
    public function partial(HTTPRequest $request)
47
    {
48
        // Ensure this URL doesn't get picked up by HTTP caches
49 5
        HTTPCacheControlMiddleware::singleton()->disableCache();
50
51 5
        $key = $request->param('Key');
52 5
        $token = $request->param('Token');
53 5
        if (!$key || !$token) {
54 1
            return $this->httpError(404);
55
        }
56
57
        /** @var PartialFormSubmission $partial */
58 4
        $partial = PartialFormSubmission::get()->find('Token', $token);
59 4
        if (!$partial ||
60 2
            !$partial->UserDefinedFormID ||
61 4
            !hash_equals($partial->generateKey($token), $key)
62
        ) {
63 3
            return $this->httpError(404);
64
        }
65
66
        // Set the session if the last session has expired or from another submission
67 2
        $session = $request->getSession()->get(PartialSubmissionController::SESSION_KEY);
68 2
        if (!$session || $session !==  $partial->ID) {
69 2
            $request->getSession()->set(PartialSubmissionController::SESSION_KEY, $partial->ID);
70
        }
71
72
        // Set data record and load the form
73 2
        $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...
74 2
        $controller = parent::create($record);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (create() instead of partial()). Are you sure this is correct? If so, you might want to change this to $this->create().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
75 2
        $controller->doInit();
76
77 2
        $form = $controller->Form();
78 2
        $form->loadDataFrom($partial->getFields());
0 ignored issues
show
Documentation Bug introduced by
The method loadDataFrom does not exist on object<Firesphere\Partia...tialUserFormController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
79 2
        $this->populateFileData($form, $partial);
0 ignored issues
show
Documentation introduced by
$form is of type object<Firesphere\Partia...tialUserFormController>, but the function expects a object<SilverStripe\Forms\Form>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
80
81
        // Copied from {@link UserDefinedFormController}
82 2
        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...
83 2
            $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...
84 2
            if ($hasLocation) {
85
                /** @see Requirements_Backend::escapeReplacement */
86 2
                $formEscapedForRegex = addcslashes($form->forTemplate(), '\\$');
0 ignored issues
show
Documentation Bug introduced by
The method forTemplate does not exist on object<Firesphere\Partia...tialUserFormController>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
87 2
                $content = preg_replace(
88 2
                    '/(<p[^>]*>)?\\$UserDefinedForm(<\\/p>)?/i',
89 2
                    $formEscapedForRegex,
90 2
                    $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...
91
                );
92
93 2
                return $controller->customise([
94 2
                    'Content'     => DBField::create_field('HTMLText', $content),
95 2
                    'Form'        => '',
96 2
                    'PartialLink' => $partial->getPartialLink()
97 2
                ])->renderWith([static::class, Page::class]);
98
            }
99
        }
100
101
        return $controller->customise([
102
            '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...
103
            'Form'        => $form,
104
            'PartialLink' => $partial->getPartialLink()
105
        ])->renderWith([static::class, Page::class]);
106
    }
107
108
    /**
109
     * Set the uploaded filenames as right title of the file fields
110
     *
111
     * @param Form $form
112
     * @param PartialFormSubmission $partialSubmission
113
     */
114 2
    protected function populateFileData($form, $partialSubmission)
115
    {
116 2
        $uploads = $partialSubmission->PartialUploads()->filter([
117 2
            'UploadedFileID:not'=> null
118
        ]);
119
120 2
        if (!$uploads->exists()) {
121
            return;
122
        }
123
124 2
        $fields = $form->Fields();
125 2
        foreach ($uploads as $upload) {
126 2
            $fields->dataFieldByName($upload->Name)
127 2
                ->setRightTitle(
128 2
                    sprintf(
129 2
                        'Uploaded: %s (Attach a new file to replace the uploaded file)',
130 2
                        $upload->UploadedFile()->Name
131
                    )
132
                );
133
        }
134 2
    }
135
}
136