Completed
Push — master ( f80f32...5d0660 )
by Dmitry
11:45
created

GroupedChargesGridView::chrgeIds()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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