Completed
Push — develop ( c185af...7af18d )
by
unknown
20:14 queued 11:28
created

SummaryForm::render()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 58
Code Lines 33

Duplication

Lines 6
Ratio 10.34 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 6
loc 58
rs 8.7275
cc 5
eloc 33
nc 6
nop 3

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * YAWIK
4
 *
5
 * @filesource
6
 * @copyright (c) 2013-2015 Cross Solution (http://cross-solution.de)
7
 * @license   MIT
8
 */
9
10
/**  */
11
namespace Core\Form\View\Helper;
12
13
use Core\Form\SummaryFormInterface;
14
use Zend\Form\Element\Hidden;
15
use Zend\Form\FormInterface;
16
use Zend\Form\View\Helper\AbstractHelper;
17
use Zend\Form\ElementInterface;
18
use Zend\Form\FieldsetInterface;
19
use Core\Form\ViewPartialProviderInterface;
20
use Core\Form\DescriptionAwareFormInterface;
21
use Core\Form\EmptySummaryAwareInterface;
22
23
/**
24
 * Helper to render a summary form container.
25
 *
26
 * @author Mathias Gelhausen <[email protected]>
27
 */
28
class SummaryForm extends AbstractHelper
29
{
30
    
31
    /**
32
     * Invoke as function.
33
     *
34
     * @param null|SummaryFormInterface $form
35
     * @param string $layout
36
     * @param array $parameter
37
     * @return \Core\Form\View\Helper\SummaryForm|string
0 ignored issues
show
Documentation introduced by
Should the return type not be SummaryForm|string|\Zend\View\Helper\Partial?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
38
     */
39
    public function __invoke(SummaryFormInterface $form = null, $layout = Form::LAYOUT_HORIZONTAL, $parameter = array())
40
    {
41
        if (null === $form) {
42
            return $this;
43
        }
44
        
45
        $mode = $form->getRenderMode();
46
        if (SummaryFormInterface::RENDER_FORM == $mode) {
47
            return $this->renderForm($form, $layout, $parameter);
48
        }
49
        if (SummaryFormInterface::RENDER_SUMMARY == $mode) {
50
            return $this->renderSummary($form);
51
        }
52
        
53
        return $this->render($form, $layout, $parameter);
54
    }
55
    
56
    /**
57
     * Renders a summary form container.
58
     *
59
     * @param SummaryFormInterface $form
60
     * @param string $layout
61
     * @param array $parameter
62
     * @return string
63
     */
64
    public function render(SummaryFormInterface $form, $layout = Form::LAYOUT_HORIZONTAL, $parameter = array())
65
    {
66
        $renderer = $this->getView();
67
        $renderer->headscript()->appendFile($renderer->basePath('Core/js/jquery.summary-form.js'));
68
        
69
        $label = $form->getLabel();
70
        $labelContent = $label ? '<div class="sf-headline"><h3>' . $this->getView()->translate($label) . '</h3></div>' : '';
0 ignored issues
show
Bug introduced by
The method translate() does not seem to exist on object<Zend\View\Renderer\RendererInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
71
        $formContent  = $this->renderForm($form, $layout, $parameter);
72
        $summaryContent = $this->renderSummary($form);
73
        
74
        $formContent = sprintf(
75
            '<div class="sf-form"><div class="panel panel-info"><div class="panel-body">%s</div></div></div>
76
                 <div class="sf-summary">%s</div>
77
                ',
78
            $formContent,
79
            $summaryContent
80
        );
81
        
82
        if ($form instanceof DescriptionAwareFormInterface && $form->isDescriptionsEnabled()) {
83
            $this->getView()->headscript()->appendFile(
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\View\Renderer\RendererInterface as the method headscript() does only exist in the following implementations of said interface: Zend\View\Renderer\PhpRenderer.

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...
84
                $this->getView()->basepath('Core/js/forms.descriptions.js')
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\View\Renderer\RendererInterface as the method basepath() does only exist in the following implementations of said interface: Zend\View\Renderer\PhpRenderer.

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...
85
            );
86
        
87 View Code Duplication
            if ($desc = $form->getOption('description', '')) {
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...
88
                $translator = $this->getTranslator();
89
                $textDomain = $this->getTranslatorTextDomain();
90
        
91
                $desc = $translator->translate($desc, $textDomain);
92
            }
93
        
94
            $formContent = sprintf(
95
                '<div class="daf-form-container row">
96
                        <div class="daf-form col-md-8">%s</div>
97
                        <div class="daf-desc col-md-4">
98
                            <div class="daf-desc-content alert alert-info">%s</div>
99
                        </div>
100
                    </div>',
101
                $formContent,
102
                $desc
103
            );
104
        }
105
        
106
        $markup = '<div id="sf-%s" class="sf-container" data-display-mode="%s">'
107
                . '%s'
108
                . '%s'
109
                . '</div>';
110
        
111
        $content = sprintf(
112
            $markup,
113
            $form->getAttribute('name'),
114
            $form->getDisplayMode(),
115
            $labelContent,
116
            $formContent
117
        );
118
        
119
        
120
        return $content;
121
    }
122
123
    /**
124
     * Only renders the form representation of a summary form.
125
     *
126
     * @param SummaryFormInterface $form
127
     * @param string $layout
128
     * @param array $parameter
129
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|\Zend\View\Helper\Partial?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
130
     */
131
    public function renderForm(SummaryFormInterface $form, $layout = Form::LAYOUT_HORIZONTAL, $parameter = array())
132
    {
133
                                                    /* @var $form SummaryFormInterface|\Core\Form\SummaryForm */
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
134
        $renderer     = $this->getView();           /* @var $renderer \Zend\View\Renderer\PhpRenderer */
135
        $formHelper   = $renderer->plugin('form');  /* @var $formHelper \Core\Form\View\Helper\Form */
136
        $fieldset     = $form->getBaseFieldset();
137
        $resetPartial = false;
138
139
        if ($fieldset instanceof ViewPartialProviderInterface) {
140
            $origPartial = $fieldset->getViewPartial();
141
            $partial     = "$origPartial.form";
142
            if ($renderer->resolver($partial)) {
143
                $fieldset->setViewPartial($partial);
144
                $resetPartial = true;
145
            }
146
        }
147
148
        $markup = $formHelper->renderBare($form, $layout, $parameter);
149
150
        if ($resetPartial) {
151
            /** @noinspection PhpUndefinedVariableInspection */
152
            $fieldset->setViewPartial($origPartial);
0 ignored issues
show
Bug introduced by
The variable $origPartial does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
153
        }
154
155
        return $markup;
156
    }
157
    
158
    /**
159
     * Only renders the summary representation of a summary form
160
     *
161
     * @param SummaryFormInterface $form
162
     * @return string
163
     */
164
    public function renderSummary(SummaryFormInterface $form)
165
    {
166
        $baseFieldset = $form->getBaseFieldset();
167
        if (!isset($baseFieldset)) {
168
            throw new \InvalidArgumentException('For the Form ' . get_class($form) . ' there is no Basefieldset');
169
        }
170
171
        $markup = '<div class="panel panel-default" style="min-height: 100px;">
172
                    <div class="panel-body">%s%s</div></div>';
173
174
        $buttonMarkup = false === $form->getOption('editable')
175
                      ? ''
176
                      : '<button type="button" class="pull-right btn btn-default btn-xs sf-edit">'
177
                        . '<span class="yk-icon yk-icon-edit"></span> '
178
                        . $this->getView()->translate('Edit')
0 ignored issues
show
Bug introduced by
The method translate() does not seem to exist on object<Zend\View\Renderer\RendererInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
179
                        . '</button>';
180
181
        $elementMarkup = $this->renderSummaryElement($baseFieldset);
182
183
184
        return sprintf($markup, $buttonMarkup, $elementMarkup);
185
    }
186
    
187
    /**
188
     * Helper function to recurse into form elements when rendering summary.
189
     *
190
     * @param ElementInterface $element
191
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|\Zend\View\Helper\Partial?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
192
     */
193
    protected function renderSummaryElement(ElementInterface $element)
194
    {
195
        if ($element instanceof Hidden || false === $element->getOption('render_summary')) {
196
            return '';
197
        }
198
        
199
        if ($element instanceof ViewPartialProviderInterface) {
200
            $renderer    = $this->getView();                 /* @var $renderer \Zend\View\Renderer\PhpRenderer */
201
            $origPartial = $element->getViewPartial();
202
            $partial     = "$origPartial.view";
203
            $partialParams  = array(
204
                'element' => $element
205
            );
206
            if (!$renderer->resolver($partial)) {
207
                $partial = $origPartial;
208
                $partialParams['renderSummary'] = true;
209
            }
210
    
211
            return $renderer->partial($partial, $partialParams);
212
        }
213
        
214
        if ($element instanceof EmptySummaryAwareInterface && $element->isSummaryEmpty()) {
215
            /* @var $element EmptySummaryAwareInterface|ElementInterface */
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
216
            $emptySummaryNotice = $this->getTranslator()->translate(
217
                $element->getEmptySummaryNotice(),
0 ignored issues
show
Bug introduced by
The method getEmptySummaryNotice does only exist in Core\Form\EmptySummaryAwareInterface, but not in Zend\Form\ElementInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
218
                $this->getTranslatorTextDomain()
219
            );
220
            
221
            $markup = sprintf(
222
                '<div id="%s-empty-alert" class="empty-summary-notice alert alert-info"><p>%s</p></div>',
223
                $element->getAttribute('id'),
0 ignored issues
show
Bug introduced by
The method getAttribute does only exist in Zend\Form\ElementInterface, but not in Core\Form\EmptySummaryAwareInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
224
                $emptySummaryNotice
225
            );
226
            return $markup;
227
        }
228
    
229
        $label  = $this->getTranslator()->translate($element->getLabel());
230
        $markup = '';
231
        
232
        if ($element instanceof FieldsetInterface) {
233
            if (!$element instanceof FormInterface && $label) {
234
                $markup .= '<h4>' . $label . '</h4>';
235
            }
236
            foreach ($element as $el) {
237
                $markup .= $this->renderSummaryElement($el);
238
            }
239
            return $markup;
240
        }
241
    
242
        $elementValue = $element instanceof \Zend\Form\Element\Textarea
243
                      ? nl2br($element->getValue())
244
                      : $element->getValue();
245
246
        if ('' != $elementValue && $element instanceof \Zend\Form\Element\Select) {
247
            $options = $element->getValueOptions();
248
            $translator = $this->getTranslator();
249
            if (true == $element->getAttribute('multiple')) {
250
251
                $multiOptions = [];
252
                foreach ($elementValue as $optionKey) {
253
                    if (isset($options[$optionKey])) {
254
                        $multiOptions['__general__'][] = $translator->translate($options[$optionKey]);
255
                        continue;
256
                    }
257
258
                    foreach ($options as $optKey => $optVal) {
259
                        if (!is_array($optVal) || !array_key_exists($optionKey, $optVal['options'])) { continue; }
260
261
                        $optGroupLabel = isset($optVal['label']) ? $translator->translate($optVal['label']) : $optKey;
262
                        $multiOptions[$optGroupLabel][] = $translator->translate($optVal['options'][$optionKey]);
263
                    }
264
                }
265
266
                $elementValue = [];
267
                foreach ($multiOptions as $optGroupLabel => $vals) {
268
                    $elementValue[] = "<b>$optGroupLabel</b><br>" . join(', ', $vals);
269
                }
270
                $elementValue = join('<br>', $elementValue) . '<br>';
271
272
            } else {
273
                $elementValue = $translator->translate($options[$elementValue]);
274
            }
275
        }
276
277
        if ('' != $elementValue && $element instanceOf \Zend\Form\Element\File) {
278
            return '';
279
        }
280
                      
281
        $markup .= '<div class="row">';
282
        $col = 12;
283
        if ($label) {
284
            $markup .= '<div class="col-md-3 yk-label"><label>' . $label . '</label></div>';
285
            $col = 9;
286
        }
287
        $markup .= '<div class="col-md-' . $col . '">' . $elementValue . '</div>'
288
            . '</div>';
289
        return $markup;
290
    }
291
}
292