| 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