This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
0 ignored issues
–
show
Coding Style
introduced
by
![]() |
|||
2 | /* |
||
3 | *@author: nicolaas [at] sunnysideup.co.nz |
||
4 | * |
||
5 | * |
||
6 | **/ |
||
7 | |||
8 | class SearchPlusPage extends Page |
||
0 ignored issues
–
show
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.
You can fix this by adding a namespace to your class: namespace YourVendor;
class YourClass { }
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries. ![]() |
|||
9 | { |
||
10 | private static $add_action = 'Search Plus Page'; |
||
11 | |||
12 | private static $can_be_root = true; |
||
13 | |||
14 | private static $icon = 'searchplus/images/treeicons/SearchPlusPage'; |
||
15 | |||
16 | private static $db = array(); |
||
17 | |||
18 | private static $has_many = array( |
||
19 | "RecommendedSearchPlusSections" => "RecommendedSearchPlusSection" |
||
20 | ); |
||
21 | |||
22 | public function canCreate($member = null) |
||
23 | { |
||
24 | return SearchPlusPage::get()->count ? false : true; |
||
25 | } |
||
26 | |||
27 | public function canDelete($member = null) |
||
28 | { |
||
29 | return false; |
||
30 | } |
||
31 | |||
32 | private static $result_length = 10; |
||
33 | |||
34 | public function getCMSFields($params = null) |
||
35 | { |
||
36 | $fields = parent::getCMSFields($params); |
||
37 | $fields->addFieldToTab( |
||
38 | "Root.RecommendedSections", |
||
39 | new GridField( |
||
40 | $name = "RecommendedSearchPlusSections", |
||
41 | $sourceClass = "Recommended Extras", |
||
42 | RecommendedSearchPlusSection::get() |
||
43 | ) |
||
44 | ); |
||
45 | $fields->addFieldToTab( |
||
46 | "Root.PopularSearchPhrases", |
||
47 | new LiteralField( |
||
48 | "PopularSearchPhrasesLink", |
||
49 | '<p>Please make sure to regular <a href="'.$this->Link().'popularsearchwords/100/10">review the most popular search phrases</a> and to add recommendations for each</a>.</p>' |
||
50 | ) |
||
51 | ); |
||
52 | return $fields; |
||
53 | } |
||
54 | } |
||
55 | |||
56 | class SearchPlusPage_Controller extends Page_Controller |
||
0 ignored issues
–
show
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.
You can fix this by adding a namespace to your class: namespace YourVendor;
class YourClass { }
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries. ![]() |
|||
57 | { |
||
58 | public function init() |
||
59 | { |
||
60 | parent::init(); |
||
61 | Requirements::javascript("searchplus/javascript/searchpluspage.js"); |
||
62 | } |
||
63 | |||
64 | private static $search_history_object = null; |
||
65 | |||
66 | public function Form() |
||
67 | { |
||
68 | return $this->SearchPlusForm("MainSearchForm", "MainSearch", ""); |
||
69 | } |
||
70 | |||
71 | public function results($data) |
||
0 ignored issues
–
show
results uses the super-global variable $_GET which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() results uses the super-global variable $_REQUEST which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
72 | { |
||
73 | if (isset($data["Search"]) || isset($data["MainSearch"])) { |
||
74 | // there is a search |
||
75 | Requirements::themedCSS("searchpluspage_searchresults", "searchplus"); |
||
76 | if (isset($data["MainSearch"]) || !isset($data["Search"])) { |
||
77 | $data["Search"] = $data["MainSearch"]; |
||
78 | } |
||
79 | //redirect if needed |
||
80 | $data["Search"] = urldecode($data["Search"]); |
||
81 | $form = $this->SearchPlusForm(); |
||
82 | if (!isset($_GET["redirect"])) { |
||
83 | self::$search_history_object = SearchHistory::add_entry($data["Search"]); |
||
84 | if (self::$search_history_object) { |
||
85 | if (self::$search_history_object->RedirectTo && self::$search_history_object->RedirectTo != self::$search_history_object->Title) { |
||
86 | $this->redirect( |
||
87 | str_replace( |
||
88 | "Search=".urlencode(self::$search_history_object->Title), |
||
89 | "Search=".urlencode(self::$search_history_object->RedirectTo), |
||
90 | HTTP::RAW_setGetVar('redirect', 1, null) |
||
91 | ) |
||
92 | ); |
||
93 | } |
||
94 | } |
||
95 | } else { |
||
96 | self::$search_history_object = SearchHistory::find_entry($data["Search"]); |
||
97 | } |
||
98 | //load data for recommended pages |
||
99 | $recommendationsSet = $this->Recommendations(); |
||
100 | $matchArrayRecommended = array(); |
||
101 | $matchArrayResults = array(); |
||
102 | if ($recommendationsSet) { |
||
103 | foreach ($recommendationsSet as $rec) { |
||
104 | $matchArrayRecommended[$rec->ClassName.$rec->ID] = $rec->ClassName.$rec->ID; |
||
105 | } |
||
106 | } |
||
107 | //work out positions |
||
108 | $results = $form->getResults(); |
||
109 | $query = $form->getSearchQuery(); |
||
110 | $startingPosition = isset($_REQUEST["start"]) ? $_REQUEST["start"] : 0; |
||
111 | $endingPosition = $startingPosition + Config::inst()->get("SearchPlusPage", "result_length"); |
||
112 | $startingPosition++; |
||
113 | if ($results) { |
||
114 | $total = $results->TotalItems(); |
||
115 | } else { |
||
116 | $total = 0; |
||
117 | } |
||
118 | if ($endingPosition > $total) { |
||
119 | $endingPosition = $total; |
||
120 | } |
||
121 | //highlight search text and check which ones are recommended |
||
122 | if ($total) { |
||
123 | foreach ($results as $result) { |
||
124 | $title = $result->getTitle(); |
||
125 | $dbField = DBField::create_field($className = "Text", $title); |
||
126 | $result->HighlightedTitle = $dbField->ContextSummary(); |
||
127 | $result->IsRecommended = false; |
||
128 | $matchArrayResults[$result->ClassName.$result->ID] = $result->ClassName.$result->ID; |
||
129 | if (isset($matchArrayRecommended[$result->ClassName.$result->ID])) { |
||
130 | $result->IsRecommended = true; |
||
131 | } |
||
132 | } |
||
133 | } |
||
134 | $data = array( |
||
135 | 'Results' => $results, |
||
136 | 'Query' => $query, |
||
137 | 'From' => $startingPosition, |
||
138 | 'To' => $endingPosition, |
||
139 | 'Total' => $total, |
||
140 | 'HasResults' => $total ? true : false, |
||
141 | 'Recommendations' => $this->Recommendations(), |
||
142 | 'RecommendedSearchPlusSection' => $this->dataRecord->RecommendedSearchPlusSections(), |
||
143 | ); |
||
144 | $this->Title = 'Search Results'; |
||
145 | $this->MenuTitle = 'Search Results'; |
||
146 | return $this->customise($data)->renderWith(array('SearchPlusPage_results', 'Page')); |
||
147 | } |
||
148 | return array(); |
||
149 | } |
||
150 | |||
151 | public function Recommendations() |
||
152 | { |
||
153 | if (self::$search_history_object) { |
||
154 | return self::$search_history_object->Recommendations(); |
||
155 | } |
||
156 | } |
||
157 | |||
158 | public function HasPopularSearchWords() |
||
159 | { |
||
160 | return Permission::check("ADMIN"); |
||
161 | } |
||
162 | |||
163 | public function PopularSearchWordsForAllUsers($days = 100, $limit = 7) |
||
164 | { |
||
165 | $do = $this->getPopularSearchWords($days, $limit, $mergeRedirects = true); |
||
166 | return $do->DataByCount; |
||
167 | } |
||
168 | |||
169 | public function popularsearchwords(HTTPRequest $HTTPRequest) |
||
170 | { |
||
171 | if (!$this->HasPopularSearchWords()) { |
||
172 | Security::permissionFailure($this, _t('Security.PERMFAILURE', ' This page is secured and you need administrator rights to access it. Enter your credentials below and we will send you right along.')); |
||
173 | return; |
||
174 | } |
||
175 | Requirements::themedCSS("popularsearches", "searchplus"); |
||
176 | $days = intval($HTTPRequest->param("ID")); |
||
177 | if (!$days) { |
||
178 | $days = 100; |
||
179 | } |
||
180 | $limit = intval($HTTPRequest->param("OtherID")+0); |
||
181 | if (!$limit) { |
||
182 | $limit++; |
||
183 | } |
||
184 | $do = $this->getPopularSearchWords($days, $limit); |
||
185 | $page->MenuTitle = $do->Title; |
||
186 | $do->Title = $do->Title; |
||
187 | return $this->customise($do)->renderWith(array('SearchPlusPage_popularsearches', 'Page')); |
||
188 | } |
||
189 | |||
190 | protected function getPopularSearchWords($days, $limit, $mergeRedirects = false) |
||
191 | { |
||
192 | $extraWhere = ''; |
||
193 | if ($mergeRedirects) { |
||
194 | $extraWhere = " AND {$bt}RedirectTo{$bt} = '' OR {$bt}RedirectTo{$bt} IS NULL"; |
||
195 | } |
||
196 | $data = DB::query(" |
||
197 | SELECT COUNT(\"SearchHistoryLog\".\"ID\") count, \"SearchHistory\".\"RedirectTo\" RedirectTo, \"SearchHistory\".\"Title\" title, \"SearchHistory\".\"ID\" id |
||
198 | FROM \"SearchHistoryLog\" |
||
199 | INNER JOIN \"SearchHistory\" ON \"SearchHistory\".\"ID\" = \"SearchHistoryLog\".\"SearchedForID\" |
||
200 | WHERE \"SearchHistoryLog\".\"Created\" > ( NOW() - INTERVAL $days DAY ) ".$extraWhere." |
||
201 | GROUP BY \"SearchHistory\".\"ID\" |
||
202 | ORDER BY count DESC |
||
203 | LIMIT 0, $limit |
||
204 | "); |
||
205 | $do = new DataObject(); |
||
206 | $do->Title = "Search phrase popularity, $days days $limit entries"; |
||
207 | $do->DataByCount = new ArrayList(); |
||
208 | $do->DataByTitle = new ArrayList(); |
||
209 | $do->Limit = $limit; |
||
210 | $do->Days = $days; |
||
211 | $list = array(); |
||
212 | foreach ($data as $key => $row) { |
||
213 | if (!$key) { |
||
214 | $max = $row["count"]; |
||
215 | } |
||
216 | if ($mergeRedirects) { |
||
217 | $data = DB::query(" |
||
218 | SELECT COUNT(\"SearchHistoryLog\".\"ID\") count |
||
219 | FROM \"SearchHistoryLog\" |
||
220 | INNER JOIN \"SearchHistory\" |
||
221 | ON \"SearchHistory\".\"ID\" = \"SearchHistoryLog\".\"SearchedForID\" |
||
222 | WHERE \"SearchHistoryLog\".\"Created\" > ( NOW() - INTERVAL $days DAY ) |
||
223 | AND \"SearchHistory\".\"RedirectTo\" = '".$row["title"]."' |
||
224 | GROUP BY \"SearchHistory\".\"RedirectTo\" |
||
225 | ORDER BY count |
||
226 | DESC LIMIT 1 |
||
227 | "); |
||
228 | if ($data) { |
||
229 | $extraCounts = $data->value(); |
||
230 | } |
||
231 | $row["count"] += $extraCounts; |
||
232 | } |
||
233 | $percentage = floor(($row["count"]/$max)*100); |
||
234 | $subDataSet = new ArrayData( |
||
235 | array( |
||
236 | "ParentID" => $row["id"], |
||
237 | "Title" => $row["title"], |
||
238 | "Width" => $percentage, |
||
239 | "Count" => $row["count"], |
||
240 | "Link" => $this->Link()."results/?Search=".urldecode($row["title"])."&action_results=Search" |
||
241 | ) |
||
242 | ); |
||
243 | $list[$row["title"]] = $subDataSet; |
||
244 | $do->DataByCount->push($subDataSet); |
||
245 | } |
||
246 | ksort($list); |
||
247 | foreach ($list as $subDataSet) { |
||
248 | $do->DataByTitle->push($subDataSet); |
||
249 | } |
||
250 | return $do; |
||
251 | } |
||
252 | } |
||
253 |