Completed
Push — master ( 26d7a8...6f1a87 )
by Dmitry
05:33
created

GroupedChargesGridView::renderChildCharges()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 0
cts 15
cp 0
rs 9.6
c 0
b 0
f 0
cc 3
nc 2
nop 3
crap 12
1
<?php
2
3
namespace hipanel\modules\finance\grid;
4
5
use hipanel\modules\finance\logic\bill\QuantityFormatterFactoryInterface;
6
use hipanel\modules\finance\models\Charge;
7
use hipanel\modules\finance\widgets\ColoredBalance;
8
use hipanel\modules\finance\widgets\PriceType;
9
use Yii;
10
use yii\base\DynamicModel;
11
12
/**
13
 * Class GroupedChargesGridView
14
 *
15
 * @author Dmytro Naumenko <[email protected]>
16
 */
17
class GroupedChargesGridView extends ChargeGridView
18
{
19
    /**
20
     * @var int|null
21
     */
22
    public $allowedParentId;
23
    /**
24
     * @var string[]|null array of columns that were originally requested to render.
25
     * Used to generate nested grids with the same columns.
26
     */
27
    protected $requestedColumns;
28
29
    public function __construct(QuantityFormatterFactoryInterface $formatterFactory, array $config = [])
30
    {
31
        parent::__construct($formatterFactory, $config);
32
33
        $this->afterRow = \Closure::fromCallable([$this, 'renderChildCharges']);
34
    }
35
36
    protected function initColumns()
37
    {
38
        if ($this->requestedColumns === null) {
39
            $this->requestedColumns = $this->columns;
40
        }
41
42
        parent::initColumns();
43
    }
44
45
    public function columns()
46
    {
47
        return array_merge(parent::columns(), [
48
            'type_label' => [
49
                'label' => Yii::t('hipanel', 'Type'),
50
                'format' => 'raw',
51
                'value' => function ($model) {
52
                    $html = '';
53
54
                    if ($this->allowedParentId !== null) {
55
                        $html .= '<i style="color: #717171" class="fa fa-arrow-up"></i>&nbsp;';
56
                    }
57
                    return $html . PriceType::widget([
58
                        'model' => $model,
59
                        'field' => 'ftype'
60
                    ]);
61
                },
62
            ],
63
            'sum_with_children' => [
64
                'label' => '',
65
                'format' => 'raw',
66
                'value' => function (Charge $model) {
67
                    $children = $this->findChargeChildren($model);
68
                    if (empty($children)) {
69
                        return '';
70
                    }
71
72
                    $sum = array_reduce([$model] + $children, function ($accumulator, Charge $model) {
73
                        return $model->sum + $accumulator;
74
                    }, 0);
75
                    return ColoredBalance::widget([
76
                        'model' => new DynamicModel(['sum' => $sum, 'currency' => $model->currency]),
77
                        'attribute' => 'sum',
78
                        'url' => false
79
                    ]);
80
                }
81
            ]
82
        ]);
83
    }
84
85
    /**
86
     * @param Charge $model
87
     * @param mixed $key
88
     * @param int $index
89
     * @return string
90
     */
91
    public function renderTableRow($model, $key, $index)
92
    {
93
        // Prevent rendering child prices, unless it is intended
94
        if ($model->parent_id !== $this->allowedParentId) {
95
            return '';
96
        }
97
98
        return parent::renderTableRow($model, $key, $index);
99
    }
100
101
    /**
102
     * @param Charge $parent
103
     * @return Charge[]
104
     */
105
    private function findChargeChildren(Charge $parent): array
106
    {
107
        return array_filter($this->dataProvider->getModels(),
108
            function (Charge $charge) use ($parent) {
109
                return $charge->parent_id === $parent->id;
110
            }
111
        );
112
    }
113
114
    private function renderChildCharges(Charge $parent, $key, $index): string
115
    {
116
        $children = $this->findChargeChildren($parent);
117
        if (empty($children)) {
118
            return '';
119
        }
120
121
        return $this->assumeRenderingForParent($parent, function () use ($children, $key, $index) {
122
            $columns = $this->requestedColumns;
123
            $columns[0] = 'parent_mark_and_type';
124
125
            $result = [];
126
            foreach ($children as $charge) {
127
                $result[] = $this->renderTableRow($charge, $key, $index);
128
            }
129
130
            return implode('', $result);
131
        });
132
133
    }
134
135
    private function assumeRenderingForParent(Charge $parent, $callback)
136
    {
137
        $allowedParent = $this->allowedParentId;
138
        $this->allowedParentId = $parent->id;
139
140
        $result = $callback();
141
142
        $this->allowedParentId = $allowedParent;
143
144
        return $result;
145
    }
146
}
147