Completed
Pull Request — master (#338)
by Leny
06:17
created

WidgetMapBuilder::getAvailablePosition()   C

Complexity

Conditions 7
Paths 13

Size

Total Lines 28
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

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