Total Complexity | 48 |
Total Lines | 310 |
Duplicated Lines | 6.13 % |
Changes | 0 |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like DatedUpdateHolder_Controller often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use DatedUpdateHolder_Controller, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
223 | class DatedUpdateHolder_Controller extends Page_Controller { |
||
224 | |||
225 | private static $allowed_actions = array( |
||
226 | 'rss', |
||
227 | 'atom', |
||
228 | 'DateRangeForm' |
||
229 | ); |
||
230 | |||
231 | |||
232 | private static $casting = array( |
||
233 | 'MetaTitle' => 'Text', |
||
234 | 'FilterDescription' => 'Text' |
||
235 | ); |
||
236 | |||
237 | /** |
||
238 | * Get the meta title for the current action |
||
239 | * |
||
240 | * @return string |
||
241 | */ |
||
242 | public function getMetaTitle() { |
||
243 | $title = $this->data()->getTitle(); |
||
244 | $filter = $this->FilterDescription(); |
||
245 | if($filter) { |
||
246 | $title = "{$title} - {$filter}"; |
||
247 | } |
||
248 | |||
249 | $this->extend('updateMetaTitle', $title); |
||
250 | return $title; |
||
251 | } |
||
252 | |||
253 | /** |
||
254 | * Returns a description of the current filter |
||
255 | * |
||
256 | * @return string |
||
257 | */ |
||
258 | public function FilterDescription() { |
||
259 | $params = $this->parseParams(); |
||
260 | |||
261 | $filters = array(); |
||
262 | if ($params['tag']) { |
||
263 | $term = TaxonomyTerm::get_by_id('TaxonomyTerm', $params['tag']); |
||
264 | if ($term) { |
||
265 | $filters[] = _t('DatedUpdateHolder.FILTER_WITHIN', 'within') . ' "' . $term->Name . '"'; |
||
266 | } |
||
267 | } |
||
268 | |||
269 | if ($params['from'] || $params['to']) { |
||
270 | if ($params['from']) { |
||
271 | $from = strtotime($params['from']); |
||
272 | if ($params['to']) { |
||
273 | $to = strtotime($params['to']); |
||
274 | $filters[] = _t('DatedUpdateHolder.FILTER_BETWEEN', 'between') . ' ' |
||
275 | . date('j/m/Y', $from) . ' and ' . date('j/m/Y', $to); |
||
276 | } else { |
||
277 | $filters[] = _t('DatedUpdateHolder.FILTER_ON', 'on') . ' ' . date('j/m/Y', $from); |
||
278 | } |
||
279 | } else { |
||
280 | $to = strtotime($params['to']); |
||
281 | $filters[] = _t('DatedUpdateHolder.FILTER_ON', 'on') . ' ' . date('j/m/Y', $to); |
||
282 | } |
||
283 | } |
||
284 | |||
285 | if ($params['year'] && $params['month']) { |
||
286 | $timestamp = mktime(1, 1, 1, $params['month'], 1, $params['year']); |
||
287 | $filters[] = _t('DatedUpdateHolder.FILTER_IN', 'in') . ' ' . date('F', $timestamp) . ' ' . $params['year']; |
||
288 | } |
||
289 | |||
290 | if ($filters) { |
||
291 | return $this->getUpdateName() . ' ' . implode(' ', $filters); |
||
292 | } |
||
293 | } |
||
294 | |||
295 | public function getUpdateName() { |
||
296 | return Config::inst()->get($this->data()->ClassName, 'update_name'); |
||
297 | } |
||
298 | |||
299 | public function init() { |
||
300 | parent::init(); |
||
301 | RSSFeed::linkToFeed($this->Link() . 'rss', $this->getSubscriptionTitle()); |
||
302 | } |
||
303 | |||
304 | /** |
||
305 | * Parse URL parameters. |
||
306 | * |
||
307 | * @param $produceErrorMessages Set to false to omit session messages. |
||
308 | */ |
||
309 | public function parseParams($produceErrorMessages = true) { |
||
310 | $tag = $this->request->getVar('tag'); |
||
311 | $from = $this->request->getVar('from'); |
||
312 | $to = $this->request->getVar('to'); |
||
313 | $year = $this->request->getVar('year'); |
||
314 | $month = $this->request->getVar('month'); |
||
315 | |||
316 | if ($tag=='') $tag = null; |
||
317 | if ($from=='') $from = null; |
||
318 | if ($to=='') $to = null; |
||
319 | if ($year=='') $year = null; |
||
320 | if ($month=='') $month = null; |
||
321 | |||
322 | if (isset($tag)) $tag = (int)$tag; |
||
323 | View Code Duplication | if (isset($from)) { |
|
324 | $from = urldecode($from); |
||
325 | $parser = new SS_Datetime; |
||
326 | $parser->setValue($from); |
||
327 | $from = $parser->Format('Y-m-d'); |
||
328 | } |
||
329 | View Code Duplication | if (isset($to)) { |
|
330 | $to = urldecode($to); |
||
331 | $parser = new SS_Datetime; |
||
332 | $parser->setValue($to); |
||
333 | $to = $parser->Format('Y-m-d'); |
||
334 | } |
||
335 | if (isset($year)) $year = (int)$year; |
||
336 | if (isset($month)) $month = (int)$month; |
||
337 | |||
338 | // If only "To" has been provided filter by single date. Normalise by swapping with "From". |
||
339 | if (isset($to) && !isset($from)) { |
||
340 | list($to, $from) = array($from, $to); |
||
341 | } |
||
342 | |||
343 | // Flip the dates if the order is wrong. |
||
344 | if (isset($to) && isset($from) && strtotime($from)>strtotime($to)) { |
||
345 | list($to, $from) = array($from, $to); |
||
346 | |||
347 | if ($produceErrorMessages) { |
||
348 | Session::setFormMessage( |
||
349 | 'Form_DateRangeForm', |
||
350 | _t('DateUpdateHolder.FilterAppliedMessage','Filter has been applied with the dates reversed.'), |
||
351 | 'warning' |
||
352 | ); |
||
353 | } |
||
354 | } |
||
355 | |||
356 | // Notify the user that filtering by single date is taking place. |
||
357 | if (isset($from) && !isset($to)) { |
||
358 | if ($produceErrorMessages) { |
||
359 | Session::setFormMessage( |
||
360 | 'Form_DateRangeForm', |
||
361 | _t('DateUpdateHolder.DateRangeFilterMessage','Filtered by a single date.'), |
||
362 | 'warning' |
||
363 | ); |
||
364 | } |
||
365 | } |
||
366 | |||
367 | return array( |
||
368 | 'tag' => $tag, |
||
369 | 'from' => $from, |
||
370 | 'to' => $to, |
||
371 | 'year' => $year, |
||
372 | 'month' => $month |
||
373 | ); |
||
374 | } |
||
375 | |||
376 | /** |
||
377 | * Build the link - keep the date range, reset the rest. |
||
378 | */ |
||
379 | public function AllTagsLink() { |
||
380 | $link = HTTP::setGetVar('tag', null, null, '&'); |
||
381 | $link = HTTP::setGetVar('month', null, $link, '&'); |
||
382 | $link = HTTP::setGetVar('year', null, $link, '&'); |
||
383 | $link = HTTP::setGetVar('start', null, $link, '&'); |
||
384 | |||
385 | return $link; |
||
386 | } |
||
387 | |||
388 | /** |
||
389 | * List tags and attach links. |
||
390 | */ |
||
391 | public function UpdateTagsWithLinks() { |
||
392 | $tags = $this->UpdateTags(); |
||
393 | |||
394 | $processed = new ArrayList(); |
||
395 | |||
396 | foreach ($tags as $tag) { |
||
397 | // Build the link - keep the tag, and date range, but reset month, year and pagination. |
||
398 | $link = HTTP::setGetVar('tag', $tag->ID, null, '&'); |
||
399 | $link = HTTP::setGetVar('month', null, $link, '&'); |
||
400 | $link = HTTP::setGetVar('year', null, $link, '&'); |
||
401 | $link = HTTP::setGetVar('start', null, $link, '&'); |
||
402 | |||
403 | $tag->Link = $link; |
||
404 | $processed->push($tag); |
||
405 | } |
||
406 | |||
407 | return $processed; |
||
408 | } |
||
409 | |||
410 | /** |
||
411 | * Get the TaxonomyTerm related to the current tag GET parameter. |
||
412 | */ |
||
413 | public function CurrentTag() { |
||
414 | $tagID = $this->request->getVar('tag'); |
||
415 | |||
416 | if (isset($tagID)) { |
||
417 | return TaxonomyTerm::get_by_id('TaxonomyTerm', (int)$tagID); |
||
418 | } |
||
419 | } |
||
420 | |||
421 | /** |
||
422 | * Extract the available months based on the current query. |
||
423 | * Only tag is respected. Pagination and months are ignored. |
||
424 | */ |
||
425 | public function AvailableMonths() { |
||
433 | ); |
||
434 | } |
||
435 | |||
436 | /** |
||
437 | * Get the updates based on the current query. |
||
438 | */ |
||
439 | public function FilteredUpdates($pageSize = 20) { |
||
454 | } |
||
455 | |||
456 | /** |
||
457 | * @return Form |
||
458 | */ |
||
459 | public function DateRangeForm() { |
||
460 | $dateFromTitle = DBField::create_field('HTMLText', sprintf( |
||
461 | '%s <span class="field-note">%s</span>', |
||
462 | _t('DatedUpdateHolder.FROM_DATE', 'From date'), |
||
463 | _t('DatedUpdateHolder.DATE_EXAMPLE', '(example: 2017/12/30)') |
||
464 | )); |
||
465 | $dateToTitle = DBField::create_field('HTMLText', sprintf( |
||
466 | '%s <span class="field-note">%s</span>', |
||
467 | _t('DatedUpdateHolder.TO_DATE', 'To date'), |
||
468 | _t('DatedUpdateHolder.DATE_EXAMPLE', '(example: 2017/12/30)') |
||
469 | )); |
||
470 | |||
471 | $fields = new FieldList( |
||
472 | DateField::create('from', $dateFromTitle) |
||
473 | ->setConfig('showcalendar', true), |
||
474 | DateField::create('to', $dateToTitle) |
||
475 | ->setConfig('showcalendar', true), |
||
476 | HiddenField::create('tag') |
||
477 | ); |
||
478 | |||
479 | $actions = new FieldList( |
||
480 | FormAction::create("doDateFilter")->setTitle("Filter")->addExtraClass('btn btn-primary primary'), |
||
481 | FormAction::create("doDateReset")->setTitle("Clear")->addExtraClass('btn') |
||
482 | ); |
||
483 | |||
484 | $form = new Form($this, 'DateRangeForm', $fields, $actions); |
||
485 | $form->loadDataFrom($this->request->getVars()); |
||
486 | $form->setFormMethod('get'); |
||
487 | |||
488 | // Manually extract the message so we can clear it. |
||
489 | $form->ErrorMessage = $form->Message(); |
||
490 | $form->ErrorMessageType = $form->MessageType(); |
||
491 | $form->clearMessage(); |
||
492 | |||
493 | return $form; |
||
494 | } |
||
495 | |||
496 | public function doDateFilter() { |
||
505 | } |
||
506 | |||
507 | public function doDateReset() { |
||
508 | $params = $this->parseParams(false); |
||
515 | } |
||
516 | |||
517 | public function rss() { |
||
524 | } |
||
525 | |||
526 | View Code Duplication | public function atom() { |
|
533 | } |
||
534 | } |
||
535 | |||
536 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths