Completed
Pull Request — master (#325)
by Paul
09:55
created

WidgetMapBuilder   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 182
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 12
Bugs 1 Features 1
Metric Value
wmc 34
c 12
b 1
f 1
lcom 1
cbo 2
dl 0
loc 182
rs 9.2

6 Methods

Rating   Name   Duplication   Size   Complexity  
C build() 0 48 10
C getAvailablePosition() 0 28 7
A orderizeWidgetMap() 0 19 4
B removeOverwritedWidgetMaps() 0 21 6
A removeDeletedWidgetMaps() 0 10 4
A findRootWidgetMap() 0 12 3
1
<?php
2
3
namespace Victoire\Bundle\WidgetMapBundle\Builder;
4
5
use Doctrine\ORM\EntityManager;
6
use Victoire\Bundle\CoreBundle\Entity\View;
7
use Victoire\Bundle\WidgetMapBundle\Entity\WidgetMap;
8
9
/**
10
 * View WidgetMap builder.
11
 *
12
 * ref: victoire_widget_map.builder
13
 */
14
class WidgetMapBuilder
15
{
16
    /**
17
     * This method build widgetmaps relativly to given view and it's templates
18
     *
19
     * @param View          $view
20
     * @param EntityManager $em
21
     * @param bool          $updatePage
22
     *
23
     * @return array
24
     */
25
    public function build(View $view, EntityManager $em = null, $updatePage = true)
0 ignored issues
show
Unused Code introduced by
The parameter $em is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
26
    {
27
        $widgetMaps = [];
28
        // populate a $widgetmaps array with widgetmaps of given view + widgetmaps of it's templates
29
        if ($view->getWidgetMaps()) {
30
            $widgetMaps = $view->getWidgetMaps()->toArray();
0 ignored issues
show
Bug introduced by
The method toArray cannot be called on $view->getWidgetMaps() (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
31
        }
32
        $template = clone $view;
33
        $builtWidgetMap = [];
34
35
        while (null !== $template = $template->getTemplate()) {
36
            if ($template->getWidgetMaps()) {
37
                foreach ($template->getWidgetMaps()->toArray() as $item) {
38
                    $widgetMaps[] = $item;
39
                }
40
            }
41
        }
42
43
        $slots = $this->removeOverwritedWidgetMaps($widgetMaps);
44
45
        $this->removeDeletedWidgetMaps($slots);
46
47
        foreach ($slots as $slot => $widgetMaps) {
48
            $mainWidgetMap = null;
0 ignored issues
show
Unused Code introduced by
$mainWidgetMap is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
49
            $builtWidgetMap[$slot] = [];
50
51
            $rootWidgetMap = $this->findRootWidgetMap($widgetMaps);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $rootWidgetMap is correct as $this->findRootWidgetMap($widgetMaps) (which targets Victoire\Bundle\WidgetMa...er::findRootWidgetMap()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
52
53
            if ($rootWidgetMap) {
54
                $builtWidgetMap[$slot][] = $rootWidgetMap;
55
                $builtWidgetMap = $this->orderizeWidgetMap($rootWidgetMap, $builtWidgetMap, $slot, $widgetMaps, $view);
56
            }
57
        }
58
        $_builtWidgetMap = $builtWidgetMap;
59
        $builtWidgetMap = [];
60
        foreach ($_builtWidgetMap as $slot => $__builtWidgetMap) {
61
            foreach ($__builtWidgetMap as $key => $item) {
62
                // store each widgetmap in an array with the widget id as key to make the "View::getWidgetMapByWidgetAndView"
63
                // method more efficient
64
                $builtWidgetMap[$slot][$item->getWidget()->getId()] = $item;
65
            }
66
        }
67
        if ($updatePage) {
68
            $view->setBuiltWidgetMap($builtWidgetMap);
0 ignored issues
show
Documentation introduced by
$builtWidgetMap is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
69
        }
70
71
        return $builtWidgetMap;
72
    }
73
74
    /**
75
     * This method takes the builtWidgetMap for view and creates an array that indicate, for
76
     * each widgetmap, if the position "after" and "before" are available
77
     * @param  View  $view
78
     * @return array
79
     */
80
    public function getAvailablePosition(View $view)
81
    {
82
        $widgetMaps = $view->getBuiltWidgetMap();
83
84
        $availablePositions = [];
85
        foreach ($widgetMaps as $slot => $widgetMap) {
86
            foreach ($widgetMap as $_widgetMap) {
87
                $availablePositions[$slot][$_widgetMap->getId()]['id'] = $_widgetMap->getId();
88
                $availablePositions[$slot][$_widgetMap->getId()][WidgetMap::POSITION_BEFORE] = true;
89
                $availablePositions[$slot][$_widgetMap->getId()][WidgetMap::POSITION_AFTER] = true;
90
                if ($_widgetMap->getReplaced()) {
91
                    $availablePositions[$slot][$_widgetMap->getId()]['replaced'] = $_widgetMap->getReplaced()->getId();
92
                }
93
            }
94
            /** @var WidgetMap $_widgetMap */
95
            foreach ($widgetMap as $_widgetMap) {
96
                if ($_widgetMap->getParent()) {
97
                    if ($substitute = $_widgetMap->getParent()->getSubstituteForView($view)) {
98
                        $availablePositions[$slot][$substitute->getId()][$_widgetMap->getPosition()] = false;
99
                    } else {
100
                        $availablePositions[$slot][$_widgetMap->getParent()->getId()][$_widgetMap->getPosition()] = false;
101
                    }
102
                }
103
            }
104
        }
105
106
        return $availablePositions;
107
    }
108
109
    /*
110
     * Get the children of given WidgetMap and place them recursively in the "builtWidgetMap" array at the right place
111
     * depending of the children parents and positions
112
     * @param WidgetMap $currentWidgetMap
113
     */
114
    protected function orderizeWidgetMap($currentWidgetMap, $builtWidgetMap, $slot, $widgetMaps, $view)
115
    {
116
        $children = $currentWidgetMap->getChildren($view);
117
        foreach ($children as $child) {
118
            // check if the founded child belongs to the view
119
            if (in_array($child, $widgetMaps)
120
            ) {
121
                // Find the position of the "currentWidgetMap" inside the builtWidgetMap,
122
                // add "1" to this position if wanted position is "after", 0 is it's before.
123
                $offset = array_search($currentWidgetMap, $builtWidgetMap[$slot]) + ($child->getPosition() == WidgetMap::POSITION_AFTER ? 1 : 0);
124
                // insert the child in builtWidgetMap at offset position
125
                array_splice($builtWidgetMap[$slot], $offset, 0, [$child]);
126
                // call myself with child
127
                $builtWidgetMap = $this->orderizeWidgetMap($child, $builtWidgetMap, $slot, $widgetMaps, $view);
128
            }
129
        }
130
131
        return $builtWidgetMap;
132
    }
133
134
    /**
135
     * Create a $slot array that'll contain, for each slot, a widgetmap id as key and a widgetmap as value
136
     * Do not keeps widgetMaps that are overwrited
137
     *
138
     * @param $widgetMaps
139
     * @return array
140
     */
141
    protected function removeOverwritedWidgetMaps($widgetMaps)
142
    {
143
        $slots = [];
144
        /** @var WidgetMap $widgetMapItem */
145
        foreach ($widgetMaps as $widgetMapItem) {
146
            $id = $widgetMapItem->getId();
147
            // If the widgetmap replace one (has a "replaced"), use the replaced id as key
148
            if ($widgetMapItem->getReplaced()) {
149
                $id = $widgetMapItem->getReplaced()->getId();
150
            }
151
            // If "id" is not present in slot array or
152
            if (empty($slots[$widgetMapItem->getSlot()][$id])
153
                // or if the id exists AND the inserted widgetmap is overwrite|delete, then erase the initial widget by it
154
                || !empty($slots[$widgetMapItem->getSlot()][$id])
155
                && $widgetMapItem->getAction() !== WidgetMap::ACTION_CREATE) {
156
                $slots[$widgetMapItem->getSlot()][$id] = $widgetMapItem;
157
            }
158
        }
159
160
        return $slots;
161
    }
162
163
    /**
164
     * If "delete" widgetmaps are found, remove it because they're not rendered
165
     * @param $slots
166
     */
167
    protected function removeDeletedWidgetMaps(&$slots)
168
    {
169
        foreach ($slots as $slot => $widgetMaps) {
170
            foreach ($widgetMaps as $key => $widgetMap) {
171
                if ($widgetMap->getAction() == WidgetMap::ACTION_DELETE) {
172
                    unset($slots[$slot][$key]);
173
                }
174
            }
175
        }
176
    }
177
178
    /**
179
     * Find the "root" widgetmap (the one that has no parent)
180
     * @param WidgetMap[] $widgetMaps
181
     */
182
    private function findRootWidgetMap($widgetMaps)
183
    {
184
        $rootWidgetMap = null;
185
        foreach ($widgetMaps as $_widgetMap) {
186
            if (!$_widgetMap->getParent()) {
187
                $rootWidgetMap = $_widgetMap;
188
                break;
189
            }
190
        }
191
192
        return $rootWidgetMap;
193
    }
194
195
}
196