Completed
Push — master ( 30e1bf...007fe5 )
by Marcus
16s queued 11s
created

code/forms/FrontendWorkflowForm.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
class FrontendWorkflowForm extends Form{
4
5
	function httpSubmission($request) {
6
		$vars = $request->requestVars();
7
		if(isset($funcName)) {
8
			Form::set_current_action($funcName);
9
		}
10
	
11
		// Populate the form
12
		$this->loadDataFrom($vars, true);
13
	
14
		// Protection against CSRF attacks
15
		$token = $this->getSecurityToken();
16
		if(!$token->checkRequest($request)) {
17
			$this->httpError(400, _t('AdvancedWorkflowFrontendForm.SECURITYTOKENCHECK', "Security token doesn't match, possible CSRF attack."));
18
		}
19
	
20
		// Determine the action button clicked
21
		$funcName = null;
22
		foreach($vars as $paramName => $paramVal) {
23
			if(substr($paramName,0,7) == 'action_') {
24
				
25
				// Added for frontend workflow form - get / set transitionID on controller, 
26
				// unset action and replace with doFrontEndAction action
27
				if(substr($paramName,0,18) == 'action_transition_') {
28
					$this->controller->transitionID = substr($paramName,strrpos($paramName,'_') +1);
29
					unset($vars['action_transition_' . $this->controller->transitionID]);
30
					$vars['action_doFrontEndAction'] = 'doFrontEndAction';
31
					$paramName = 'action_doFrontEndAction';
32
					$paramVal = 'doFrontEndAction';
33
				}
34
			
35
				// Break off querystring arguments included in the action
36
				if(strpos($paramName,'?') !== false) {
37
					list($paramName, $paramVars) = explode('?', $paramName, 2);
38
					$newRequestParams = array();
39
					parse_str($paramVars, $newRequestParams);
40
					$vars = array_merge((array)$vars, (array)$newRequestParams);
41
				}
42
			
43
				// Cleanup action_, _x and _y from image fields
44
				$funcName = preg_replace(array('/^action_/','/_x$|_y$/'),'',$paramName);
45
				break;
46
			}
47
		}
48
49
		// If the action wasnt' set, choose the default on the form.
50
		if(!isset($funcName) && $defaultAction = $this->defaultAction()){
51
			$funcName = $defaultAction->actionName();
52
		}
53
		
54
		if(isset($funcName)) {
55
			$this->setButtonClicked($funcName);
56
		}
57
	
58
		// Permission checks (first on controller, then falling back to form)
59
		if(
60
			// Ensure that the action is actually a button or method on the form,
61
			// and not just a method on the controller.
62
			$this->controller->hasMethod($funcName)
63
			&& !$this->controller->checkAccessAction($funcName)
64
			// If a button exists, allow it on the controller
65
			&& !$this->Actions()->fieldByName('action_' . $funcName)
66
		) {
67
			return $this->httpError(
68
				403, 
69
				sprintf(_t('AdvancedWorkflowFrontendForm.ACTIONCONTROLLERCHECK', 'Action "%s" not allowed on controller (Class: %s)'), $funcName, get_class($this->controller))
70
			);
71
		} elseif(
72
			$this->hasMethod($funcName)
73
			&& !$this->checkAccessAction($funcName)
74
			// No checks for button existence or $allowed_actions is performed -
75
			// all form methods are callable (e.g. the legacy "callfieldmethod()")
76
		) {
77
			return $this->httpError(
78
				403, 
79
				sprintf(_t('AdvancedWorkflowFrontendForm.ACTIONFORMCHECK','Action "%s" not allowed on form (Name: "%s")'), $funcName, $this->Name())
0 ignored issues
show
Documentation Bug introduced by
The method Name does not exist on object<FrontendWorkflowForm>? 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...
80
			);
81
		}
82
	
83
		if ($wfTransition = $this->controller->getCurrentTransition()) {
84
			$wfTransType = $wfTransition->Type;
85
		} else {
86
			$wfTransType = null; //ie. when a custom Form Action is defined in WorkflowAction
87
		}
88
		
89
		// Validate the form
90
		if(!$this->validate() && $wfTransType == 'Active') {
91
			if(Director::is_ajax()) {
92
				// Special case for legacy Validator.js implementation (assumes eval'ed javascript collected through FormResponse)
93
				if($this->validator->getJavascriptValidationHandler() == 'prototype') {
94
					return FormResponse::respond();
95
				} else {
96
					$acceptType = $request->getHeader('Accept');
97
					if(strpos($acceptType, 'application/json') !== FALSE) {
98
						// Send validation errors back as JSON with a flag at the start
99
						$response = new SS_HTTPResponse(Convert::array2json($this->validator->getErrors()));
100
						$response->addHeader('Content-Type', 'application/json');
101
					} else {
102
						$this->setupFormErrors();
103
						// Send the newly rendered form tag as HTML
104
						$response = new SS_HTTPResponse($this->forTemplate());
105
						$response->addHeader('Content-Type', 'text/html');
106
					}
107
				
108
					return $response;
109
				}
110
			} else {
111
				if($this->getRedirectToFormOnValidationError()) {
112
					if($pageURL = $request->getHeader('Referer')) {
113
						if(Director::is_site_url($pageURL)) {
114
							// Remove existing pragmas
115
							$pageURL = preg_replace('/(#.*)/', '', $pageURL);
116
							return Director::redirect($pageURL . '#' . $this->FormName());
117
						}
118
					}
119
				}
120
				return Director::redirectBack();
121
			}
122
		}
123
	
124
		// First, try a handler method on the controller (has been checked for allowed_actions above already)
125
		if($this->controller->hasMethod($funcName)) {
126
			return $this->controller->$funcName($vars, $this, $request);
127
		// Otherwise, try a handler method on the form object.
128
		} elseif($this->hasMethod($funcName)) {
129
			return $this->$funcName($vars, $this, $request);
130
		}
131
	
132
		return $this->httpError(404);
133
	}
134
}