TableSeeder::__destruct()   A
last analyzed

Complexity

Conditions 6
Paths 6

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 12
c 1
b 0
f 0
dl 0
loc 20
rs 9.2222
cc 6
nc 6
nop 0
1
<?php
2
3
namespace diecoding\seeder;
4
5
use Faker\Factory;
6
use Yii;
7
use yii\base\NotSupportedException;
8
use yii\db\Exception;
9
use yii\db\Migration;
10
use yii\helpers\ArrayHelper;
11
12
/**
13
 * Class TableSeeder
14
 * 
15
 * @package diecoding\seeder
16
 *
17
 * @link [sugeng-sulistiyawan.github.io](sugeng-sulistiyawan.github.io)
18
 * @author Sugeng Sulistiyawan <[email protected]>
19
 * @copyright Copyright (c) 2023
20
 */
21
abstract class TableSeeder extends Migration
22
{
23
    /** @var \Faker\Generator|Factory */
24
    public $faker;
25
26
    /** @var bool `true` for truncate tables before run seeder, default `true` */
27
    public $truncateTable = true;
28
29
    /** @var string|null if `null` use `Yii::$app->language`, default `null` */
30
    public $locale;
31
32
    /** @var array */
33
    protected $insertedColumns = [];
34
35
    /** @var array */
36
    protected $batch = [];
37
38
    /**
39
     * TableSeeder constructor.
40
     * 
41
     * @param array $config
42
     */
43
    public function __construct(array $config = [])
44
    {
45
        if ($this->locale === null) {
46
            $this->locale = str_replace('-', '_', Yii::$app->language);
47
        }
48
        $this->faker = Factory::create($this->locale);
49
50
        parent::__construct($config);
51
    }
52
53
    /**
54
     * TableSeeder destructor.
55
     * 
56
     * @throws Exception
57
     * @throws NotSupportedException
58
     */
59
    public function __destruct()
60
    {
61
        if ($this->truncateTable) {
62
            $this->disableForeignKeyChecks();
63
            foreach ($this->batch as $table => $values) {
64
                $this->truncateTable($table);
65
            }
66
            $this->enableForeignKeyChecks();
67
        }
68
69
        foreach ($this->batch as $table => $values) {
70
            $total = 0;
71
            foreach ($values as $columns => $rows) {
72
                $total += count($rows);
73
                parent::batchInsert($table, explode(',', $columns), $rows);
74
            }
75
            echo "      $total row" . ($total > 1 ? 's' : null) . " inserted in $table" . "\n";
76
        }
77
78
        $this->checkMissingColumns($this->insertedColumns);
79
    }
80
81
    /**
82
     * @return void
83
     * @throws Exception
84
     * @throws NotSupportedException
85
     */
86
    public function disableForeignKeyChecks()
87
    {
88
        $this->db->createCommand()->checkIntegrity(false)->execute();
89
    }
90
91
    /**
92
     * @return void
93
     * @throws Exception
94
     * @throws NotSupportedException
95
     */
96
    public function enableForeignKeyChecks()
97
    {
98
        $this->db->createCommand()->checkIntegrity(true)->execute();
99
    }
100
101
    /**
102
     * Creates and executes an INSERT SQL statement.
103
     * The method will properly escape the column names, and bind the values to be inserted.
104
     * @param string $table the table that new rows will be inserted into.
105
     * @param array $columns the column data (name => value) to be inserted into the table.
106
     */
107
    public function insert($table, $columns)
108
    {
109
        $this->insertedColumns[$table] = ArrayHelper::merge(
110
            array_keys($columns),
111
            isset($this->insertedColumns[$table]) ? $this->insertedColumns[$table] : []
112
        );
113
114
        $this->batch[$table][implode(',', array_keys($columns))][] = array_values($columns);
115
    }
116
117
    /**
118
     * Creates and executes a batch INSERT SQL statement.
119
     * The method will properly escape the column names, and bind the values to be inserted.
120
     * @param string $table the table that new rows will be inserted into.
121
     * @param array $columns the column names.
122
     * @param array $rows the rows to be batch inserted into the table
123
     */
124
    public function batchInsert($table, $columns, $rows)
125
    {
126
        $this->insertedColumns[$table] = ArrayHelper::merge(
127
            $columns,
128
            isset($this->insertedColumns[$table]) ? $this->insertedColumns[$table] : []
129
        );
130
131
        foreach ($rows as $row) {
132
            $this->batch[$table][implode(',', $columns)][] = $row;
133
        }
134
    }
135
136
    /**
137
     * @return static
138
     */
139
    public static function create()
140
    {
141
        return new static;
142
    }
143
144
    /**
145
     * @return void
146
     */
147
    abstract public function run();
148
149
    /**
150
     * Check missing column
151
     *
152
     * @param array $insertedColumns
153
     * @return void
154
     */
155
    protected function checkMissingColumns($insertedColumns)
156
    {
157
        $missingColumns = [];
158
159
        foreach ($insertedColumns as $table => $columns) {
160
            $tableColumns = $this->db->getTableSchema($table)->columns;
161
162
            foreach ($tableColumns as $tableColumn) {
163
                if (!$tableColumn->autoIncrement && !in_array($tableColumn->name, $columns, true)) {
164
                    $missingColumns[$table][] = [$tableColumn->name, $tableColumn->dbType];
165
                }
166
            }
167
        }
168
169
        if (count($missingColumns)) {
170
            echo "    > #" . str_pad(' MISSING COLUMNS ', 70, '#', STR_PAD_BOTH) . "#\n";
171
            foreach ($missingColumns as $table => $columns) {
172
                echo "    > #" . str_pad('', 70, ' ') . "#\n";
173
                echo "    > #" . str_pad("    TABLE: {$table}", 70, ' ') . "#\n";
174
                echo "    > # " . str_pad('', 68, '-') . " #\n";
175
                foreach ($columns as [$tableColumn, $type]) {
176
                    echo "    > #" . str_pad("    - $tableColumn => $type", 70, ' ') . "#\n";
177
                }
178
                echo "    > # " . str_pad('', 68, '-') . " #\n";
179
                echo "    > #" . str_pad('', 70, ' ') . "#\n";
180
            }
181
            echo "    > #" . str_pad('', 70, '#') . "#\n";
182
        }
183
    }
184
}
185