Completed
Push — master ( 2700b4...4ccb05 )
by Torben
04:03 queued 02:37
created

PageViewHelper::render()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.6333
c 0
b 0
f 0
ccs 4
cts 4
cp 1
cc 1
nc 1
nop 11
crap 1

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
namespace DERHANSEN\SfEventMgt\ViewHelpers\Uri;
3
4
/*
5
 * This file is part of the TYPO3 CMS project.
6
 *
7
 * It is free software; you can redistribute it and/or modify it under
8
 * the terms of the GNU General Public License, either version 2
9
 * of the License, or any later version.
10
 *
11
 * For the full copyright and license information, please read the
12
 * LICENSE.txt file that was distributed with this source code.
13
 *
14
 * The TYPO3 project - inspiring people to share!
15
 */
16
17
use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
18
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
19
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
20
21
/**
22
 * Modified version of TYPO3 f:uri.page viewHelper, which always generates frontend URLs, so views created in
23
 * backend context can render links in frontend context
24
 */
25
class PageViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper
26
{
27
    use CompileWithRenderStatic;
28
29
    /**
30
     * Initialize arguments
31
     */
32 4
    public function initializeArguments()
33
    {
34 4
        parent::initializeArguments();
35 2
        $this->registerArgument('pageUid', 'int', 'target PID');
36 2
        $this->registerArgument('additionalParams', 'array', 'query parameters to be attached to the resulting URI', false, []);
37 2
        $this->registerArgument('pageType', 'int', 'type of the target page. See typolink.parameter', false, 0);
38 4
        $this->registerArgument('noCache', 'bool', 'set this to disable caching for the target page. You should not need this.', false, false);
39 4
        $this->registerArgument('noCacheHash', 'bool', 'set this to suppress the cHash query parameter created by TypoLink. You should not need this.', false, false);
40 4
        $this->registerArgument('section', 'string', 'the anchor to be added to the URI', false, '');
41 4
        $this->registerArgument('linkAccessRestrictedPages', 'bool', 'If set, links pointing to access restricted pages will still link to the page even though the page cannot be accessed.', false, false);
42 4
        $this->registerArgument('absolute', 'bool', 'If set, the URI of the rendered link is absolute', false, false);
43 4
        $this->registerArgument('addQueryString', 'bool', 'If set, the current query parameters will be kept in the URI', false, false);
44 4
        $this->registerArgument('argumentsToBeExcludedFromQueryString', 'array', 'arguments to be removed from the URI. Only active if $addQueryString = TRUE', false, []);
45
        $this->registerArgument('addQueryStringMethod', 'string', 'Set which parameters will be kept. Only active if $addQueryString = TRUE');
46
    }
47
48
    /**
49
     * @param array $arguments
50
     * @param \Closure $renderChildrenClosure
51 2
     * @param RenderingContextInterface $renderingContext
52
     * @return string Rendered page URI
53 2
     */
54 2
    public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
55 2
    {
56
        $pageUid = $arguments['pageUid'];
57
        $additionalParams = $arguments['additionalParams'];
58
        $pageType = $arguments['pageType'];
59
        $noCache = $arguments['noCache'];
60
        $noCacheHash = $arguments['noCacheHash'];
61
        $section = $arguments['section'];
62
        $linkAccessRestrictedPages = $arguments['linkAccessRestrictedPages'];
63 2
        $absolute = $arguments['absolute'];
64
        $addQueryString = $arguments['addQueryString'];
65 2
        $argumentsToBeExcludedFromQueryString = $arguments['argumentsToBeExcludedFromQueryString'];
66
        $addQueryStringMethod = $arguments['addQueryStringMethod'];
67
68
        /** @var UriBuilder $uriBuilder */
69
        $uriBuilder = $renderingContext->getControllerContext()->getUriBuilder();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface TYPO3Fluid\Fluid\Core\Re...nderingContextInterface as the method getControllerContext() does only exist in the following implementations of said interface: Nimut\TestingFramework\R...RenderingContextFixture, TYPO3\CMS\Fluid\Core\Rendering\RenderingContext.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
70
        $uri = $uriBuilder->setTargetPageUid($pageUid)->setTargetPageType($pageType)->setNoCache($noCache)->setUseCacheHash(!$noCacheHash)->setSection($section)->setLinkAccessRestrictedPages($linkAccessRestrictedPages)->setArguments($additionalParams)->setCreateAbsoluteUri($absolute)->setAddQueryString($addQueryString)->setArgumentsToBeExcludedFromQueryString($argumentsToBeExcludedFromQueryString)->setAddQueryStringMethod($addQueryStringMethod)->buildFrontendUri();
71
72
        return $uri;
73
    }
74
}
75