Completed
Push — master ( 933a29...3be0f3 )
by Damian
02:31
created

ModelAsController::beforeHandleRequest()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 13
Ratio 100 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 13
loc 13
rs 9.2
cc 4
eloc 8
nc 2
nop 2
1
<?php
2
/**
3
 * ModelAsController deals with mapping the initial request to the first {@link SiteTree}/{@link ContentController}
4
 * pair, which are then used to handle the request.
5
 *
6
 * @package cms
7
 * @subpackage control
8
 */
9
class ModelAsController extends Controller implements NestedController {
10
	private static $extensions = array('OldPageRedirector');
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...
11
12
	/**
13
	 * Get the appropriate {@link ContentController} for handling a {@link SiteTree} object, link it to the object and
14
	 * return it.
15
	 *
16
	 * @param SiteTree $sitetree
17
	 * @param string $action
18
	 * @return ContentController
19
	 */
20
	public static function controller_for(SiteTree $sitetree, $action = null) {
21
		if ($sitetree->class == 'SiteTree') {
22
			$controller = "ContentController";
23
		} else {
24
			$ancestry = ClassInfo::ancestry($sitetree->class);
25
			while ($class = array_pop($ancestry)) {
26
				if (class_exists($class . "_Controller")) break;
27
			}
28
			$controller = ($class !== null) ? "{$class}_Controller" : "ContentController";
29
		}
30
31
		if($action && class_exists($controller . '_' . ucfirst($action))) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $action of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
32
			$controller = $controller . '_' . ucfirst($action);
33
		}
34
35
		return class_exists($controller) ? Injector::inst()->create($controller, $sitetree) : $sitetree;
36
	}
37
38
	public function init() {
39
		singleton('SiteTree')->extend('modelascontrollerInit', $this);
40
		parent::init();
41
	}
42
43 View Code Duplication
	protected function beforeHandleRequest(SS_HTTPRequest $request, DataModel $model) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
44
		parent::beforeHandleRequest($request, $model);
0 ignored issues
show
Bug introduced by
The method beforeHandleRequest() does not exist on Controller. Did you maybe mean handleRequest()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
45
		// If the database has not yet been created, redirect to the build page.
46
		if(!DB::is_active() || !ClassInfo::hasTable('SiteTree')) {
47
			$this->getResponse()->redirect(Controller::join_links(
48
				Director::absoluteBaseURL(),
49
				'dev/build',
50
				'?' . array(
51
					'returnURL' => isset($_GET['url']) ? $_GET['url'] : null,
52
				)
53
			));
54
		}
55
	}
56
57
	/**
58
	 * @uses ModelAsController::getNestedController()
59
	 * @param SS_HTTPRequest $request
60
	 * @param DataModel $model
61
	 * @return SS_HTTPResponse
62
	 */
63
	public function handleRequest(SS_HTTPRequest $request, DataModel $model) {
64
		$this->beforeHandleRequest($request, $model);
65
66
		// If we had a redirection or something, halt processing.
67
		if($this->getResponse()->isFinished()) {
68
			$this->popCurrent();
69
			return $this->getResponse();
70
		}
71
72
		// If the database has not yet been created, redirect to the build page.
73 View Code Duplication
		if(!DB::is_active() || !ClassInfo::hasTable('SiteTree')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
74
			$this->getResponse()->redirect(Director::absoluteBaseURL() . 'dev/build?returnURL=' . (isset($_GET['url']) ? urlencode($_GET['url']) : null));
75
			$this->popCurrent();
76
77
			return $this->getResponse();
78
		}
79
80
		try {
81
			$result = $this->getNestedController();
82
83
			if($result instanceof RequestHandler) {
84
				$result = $result->handleRequest($this->getRequest(), $model);
85
			} else if(!($result instanceof SS_HTTPResponse)) {
86
				user_error("ModelAsController::getNestedController() returned bad object type '" .
87
					get_class($result)."'", E_USER_WARNING);
88
			}
89
		} catch(SS_HTTPResponse_Exception $responseException) {
90
			$result = $responseException->getResponse();
91
		}
92
93
		$this->popCurrent();
94
		return $result;
95
	}
96
97
	/**
98
	 * @return ContentController
99
	 * @throws Exception If URLSegment not passed in as a request parameter.
100
	 */
101
	public function getNestedController() {
102
		$request = $this->getRequest();
103
104
		if(!$URLSegment = $request->param('URLSegment')) {
105
			throw new Exception('ModelAsController->getNestedController(): was not passed a URLSegment value.');
106
		}
107
108
		// Find page by link, regardless of current locale settings
109
		if(class_exists('Translatable')) Translatable::disable_locale_filter();
110
111
		// Select child page
112
		$conditions = array('"SiteTree"."URLSegment"' => rawurlencode($URLSegment));
113
		if(SiteTree::config()->nested_urls) {
114
			$conditions[] = array('"SiteTree"."ParentID"' => 0);
115
		}
116
		$sitetree = DataObject::get_one('SiteTree', $conditions);
117
118
		// Check translation module
119
		// @todo Refactor out module specific code
120
		if(class_exists('Translatable')) Translatable::enable_locale_filter();
121
122
		if(!$sitetree) {
123
			$this->httpError(404, 'The requested page could not be found.');
124
		}
125
126
		// Enforce current locale setting to the loaded SiteTree object
127
		if(class_exists('Translatable') && $sitetree->Locale) Translatable::set_current_locale($sitetree->Locale);
128
129
		if(isset($_REQUEST['debug'])) {
130
			Debug::message("Using record #$sitetree->ID of type $sitetree->class with link {$sitetree->Link()}");
131
		}
132
133
		return self::controller_for($sitetree, $this->getRequest()->param('Action'));
0 ignored issues
show
Compatibility introduced by
$sitetree of type object<DataObject> is not a sub-type of object<SiteTree>. It seems like you assume a child class of the class DataObject to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
134
	}
135
136
	/**
137
	 * @deprecated 4.0 Use OldPageRedirector::find_old_page instead
138
	 *
139
	 * @param string $URLSegment A subset of the url. i.e in /home/contact/ home and contact are URLSegment.
140
	 * @param int $parent The ID of the parent of the page the URLSegment belongs to.
141
	 * @param bool $ignoreNestedURLs
142
	 * @return SiteTree
143
	 */
144
	static public function find_old_page($URLSegment, $parent = null, $ignoreNestedURLs = false) {
0 ignored issues
show
Unused Code introduced by
The parameter $ignoreNestedURLs is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
145
		Deprecation::notice('4.0', 'Use OldPageRedirector::find_old_page instead');
146
		if ($parent) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $parent of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
147
			$parent = SiteTree::get()->byId($parent);
148
		}
149
		$url = OldPageRedirector::find_old_page(array($URLSegment), $parent);
0 ignored issues
show
Bug introduced by
It seems like $parent can also be of type integer or object<DataObject>; however, OldPageRedirector::find_old_page() does only seem to accept object<SiteTree>|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
150
		return SiteTree::get_by_link($url);
0 ignored issues
show
Bug introduced by
It seems like $url defined by \OldPageRedirector::find...($URLSegment), $parent) on line 149 can also be of type boolean; however, SiteTree::get_by_link() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
151
	}
152
}
153