Completed
Push — develop ( 35ebd6...f6916d )
by Mohamed
13:11 queued 06:49
created

GroupField   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 99
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 76.92%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 7
c 1
b 0
f 0
lcom 1
cbo 1
dl 0
loc 99
ccs 20
cts 26
cp 0.7692
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A fields() 0 10 1
A getUniqueId() 0 4 1
A render() 0 8 1
A getContent() 0 9 2
A getValue() 0 10 2
1
<?php
2
3
/*
4
 * This file is part of the Tinyissue package.
5
 *
6
 * (c) Mohamed Alsharaf <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Tinyissue\Form\Former\Fields;
13
14
use Former\Traits\Field;
15
16
/**
17
 * GroupField is a Former field class to generate a group of fields as one field.
18
 *
19
 * @author Mohamed Alsharaf <[email protected]>
20
 */
21
class GroupField extends Field
22
{
23
    /**
24
     * A list of class properties to be added to attributes.
25
     *
26
     * @var array
27
     */
28
    protected $injectedProperties = [];
29
30
    /**
31
     * The field's default element.
32
     *
33
     * @var string
34
     */
35
    protected $element = 'div';
36
37
    /**
38
     * List of managed fields.
39
     *
40
     * @var array
41
     */
42
    protected $fields = [];
43
44
    /**
45
     * Set managed fields.
46
     *
47
     * @param array $fields
48
     *
49
     * @return $this
50
     */
51 8
    public function fields(array $fields)
52
    {
53
        array_walk($fields, function (&$field, $name) {
54 8
            $field = \Form::element($this->name . '[' . $name . ']', $field);
1 ignored issue
show
Bug introduced by
The method element() does not seem to exist on object<form>.

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...
55 8
            $field->setAttribute('id', $this->name . '-' . $name);
56 8
        });
57 8
        $this->fields = $fields;
58
59 8
        return $this;
60
    }
61
62
    /**
63
     * Render the field.
64
     *
65
     * @return string
66
     */
67 8
    public function render()
68
    {
69 8
        $this->addClass('group-fields');
70 8
        $this->setId();
71 8
        $this->removeAttribute('value');
72
73 8
        return $this->open() . $this->getContent() . $this->close();
74 8
    }
75
76
    /**
77
     * Render the field content. Rendering the managed fields.
78
     *
79
     * @return string
80
     */
81 8
    public function getContent()
82
    {
83 8
        $output = '';
84 8
        foreach ($this->fields as $field) {
85 8
            $output .= $field->__toString();
86 8
        }
87
88 8
        return $output;
89
    }
90
91
    /**
92
     * Returns values stored in managed fields.
93
     *
94
     * @return array
95
     */
96
    public function getValue()
97
    {
98
        if (!is_array($this->fields)) {
99
            return [];
1 ignored issue
show
Bug Best Practice introduced by
The return type of return array(); (array) is incompatible with the return type of the parent method HtmlObject\Traits\Tag::getValue of type string|null|HtmlObject\Traits\Tag.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
100
        }
101
102
        return array_map(function (Field $field) {
1 ignored issue
show
Bug Best Practice introduced by
The return type of return array_map(functio...e(); }, $this->fields); (array) is incompatible with the return type of the parent method HtmlObject\Traits\Tag::getValue of type string|null|HtmlObject\Traits\Tag.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
103
            return $field->getValue();
104
        }, $this->fields);
105
    }
106
107
    /**
108
     * Set the matching ID on a field if possible
109
     * Override to prefix the id with group-.
110
     *
111
     * @param string $name
112
     *
113
     * @return string
114
     */
115 8
    protected function getUniqueId($name)
116
    {
117 8
        return 'group-' . parent::getUniqueId($name);
118
    }
119
}
120