Completed
Push — develop ( 44ffbd...b889cd )
by Nate
05:02 queued 01:07
created

Field::save()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 20
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 0
cts 15
cp 0
rs 9.2
c 0
b 0
f 0
cc 4
eloc 10
nc 4
nop 1
crap 20
1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://flipboxfactory.com/software/domains/license
6
 * @link       https://www.flipboxfactory.com/software/domains/
7
 */
8
9
namespace flipbox\domains\services;
10
11
use Craft;
12
use craft\helpers\MigrationHelper;
13
use craft\helpers\StringHelper;
14
use flipbox\domains\db\DomainsQuery;
15
use flipbox\domains\fields\Domains as DomainsField;
16
use flipbox\domains\migrations\CreateDomainsTable;
17
use yii\base\Component;
18
use yii\base\Exception;
19
20
/**
21
 * @author Flipbox Factory <[email protected]>
22
 * @since  1.0.0
23
 */
24
class Field extends Component
25
{
26
    /**
27
     * @param DomainsField $field
28
     * @return bool
29
     * @throws \yii\db\Exception
30
     */
31
    public function delete(DomainsField $field): bool
32
    {
33
        Craft::$app->getDb()->createCommand()
34
            ->dropTable(
35
                $this->getTableName($field)
36
            )
37
            ->execute();
38
39
        return true;
40
    }
41
42
    /**
43
     * @param DomainsField $field
44
     * @return bool
45
     * @throws Exception
46
     * @throws \Exception
47
     * @throws \Throwable
48
     */
49
    public function save(DomainsField $field): bool
50
    {
51
        // Create the content table first since the block type fields will need it
52
        $oldTable = $this->getTableName($field, true);
53
        $newTable = $this->getTableName($field);
54
55
        if (null === $newTable) {
56
            throw new Exception('There was a problem getting the new table name.');
57
        }
58
59
        if (true === Craft::$app->getDb()->tableExists($newTable)) {
60
            throw new Exception('The table name is already in use.');
61
        }
62
63
        if (false === $this->handleTableName($newTable, $oldTable)) {
64
            throw new Exception('There was a problem renaming the table.');
65
        }
66
67
        return true;
68
    }
69
70
    /**
71
     * @param string $newName
72
     * @param string|null $oldName
73
     * @return bool
74
     * @throws \Exception
75
     * @throws \Throwable
76
     */
77
    protected function handleTableName(string $newName, string $oldName = null): bool
78
    {
79
        $transaction = Craft::$app->getDb()->beginTransaction();
80
        try {
81
            if (null === $oldName && false === $this->createTable($newName)) {
82
                $transaction->rollBack();
83
                return false;
84
            }
85
86
            MigrationHelper::renameTable($oldName, $newName);
87
        } catch (\Exception $e) {
88
            $transaction->rollBack();
89
            throw $e;
90
        }
91
92
        $transaction->commit();
93
        return true;
94
    }
95
96
    /**
97
     * Returns the content table name for a given field.
98
     *
99
     * @param DomainsField $field The field.
100
     * @param bool $useOldHandle Whether the method should use the field’s old handle when determining the
101
     * table name (e.g. to get the existing table name, rather than the new one).
102
     *
103
     * @return string|null The table name, or `false` if $useOldHandle was set to `true` and there was no old handle.
104
     */
105
    public function getTableName(DomainsField $field, bool $useOldHandle = false)
106
    {
107
        return '{{%' . $this->getTableAlias($field, $useOldHandle) . '}}';
108
    }
109
110
    /**
111
     * Returns the content table alias for a given field.
112
     *
113
     * @param DomainsField $field The field.
114
     * @param bool $useOldHandle Whether the method should use the field’s old handle when determining the
115
     * table alias (e.g. to get the existing table alias, rather than the new one).
116
     *
117
     * @return string|null The table alias, or `false` if $useOldHandle was set to `true` and there was no old handle.
118
     */
119
    public function getTableAlias(DomainsField $field, bool $useOldHandle = false)
120
    {
121
        $name = '';
122
123
        if ($useOldHandle) {
124
            if (!$field->oldHandle) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $field->oldHandle of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
125
                return null;
126
            }
127
128
            $handle = $field->oldHandle;
129
        } else {
130
            $handle = $field->handle;
131
        }
132
133
        return 'domains_' . StringHelper::toLowerCase($handle) . $name;
134
    }
135
136
    /**
137
     * @param string $tableName
138
     * @return bool
139
     * @throws \Throwable
140
     */
141
    private function createTable(string $tableName): bool
142
    {
143
        $migration = new CreateDomainsTable([
144
            'tableName' => $tableName
145
        ]);
146
147
        ob_start();
148
        $result = $migration->up();
149
        ob_end_clean();
150
151
        return false !== $result;
152
    }
153
154
    /**
155
     * @param DomainsField $field
156
     * @param DomainsQuery $query
157
     * @param bool $static
158
     * @return null|string
159
     * @throws Exception
160
     * @throws \Twig_Error_Loader
161
     */
162
    public function getTableHtml(DomainsField $field, DomainsQuery $query, bool $static)
163
    {
164
        $columns = [
165
            'domain' => [
166
                'heading' => 'Domain',
167
                'handle' => 'domain',
168
                'type' => 'singleline'
169
            ],
170
            'status' => [
171
                'heading' => 'Status',
172
                'handle' => 'status',
173
                'type' => 'select',
174
                'options' => $field->getStatuses()
175
            ]
176
        ];
177
178
        // Translate the column headings
179
        foreach ($columns as &$column) {
180
            if (!empty($column['heading'])) {
181
                $column['heading'] = Craft::t('site', $column['heading']);
0 ignored issues
show
Bug introduced by
It seems like $column['heading'] can also be of type array; however, yii\BaseYii::t() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
182
            }
183
        }
184
        unset($column);
185
186
        return Craft::$app->getView()->renderTemplate(
187
            'domains/_components/fieldtypes/Domains/input',
188
            [
189
                'id' => Craft::$app->getView()->formatInputId($field->handle),
190
                'name' => $field->handle,
191
                'cols' => $columns,
192
                'rows' => $query->all(),
193
                'static' => $static
194
            ]
195
        );
196
    }
197
}
198