DB_Delta_Validator   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 159
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 53
dl 0
loc 159
rs 10
c 2
b 0
f 0
wmc 17

7 Methods

Rating   Name   Duplication   Size   Complexity  
A validate_primary_key() 0 11 2
A get_errors() 0 2 1
A validate_columns() 0 20 3
A validate() 0 10 1
A validate_index_columns() 0 15 3
A has_errors() 0 2 1
A validate_foreign_keys() 0 33 6
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * WPDB DB_Delta table validator.
7
 *
8
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
9
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
10
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
11
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
12
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
13
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
14
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
15
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
16
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
17
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
18
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
 *
20
 * @since 0.3.0
21
 * @author Glynn Quelch <[email protected]>
22
 * @license http://www.opensource.org/licenses/mit-license.html  MIT License
23
 * @package PinkCrab\Table_Builder
24
 */
25
26
namespace PinkCrab\Table_Builder\Engines\WPDB_DB_Delta;
27
28
use PinkCrab\Table_Builder\Index;
29
use PinkCrab\Table_Builder\Column;
30
use PinkCrab\Table_Builder\Schema;
31
use PinkCrab\Table_Builder\Foreign_Key;
32
33
class DB_Delta_Validator {
34
35
	/**
36
	 * All errors found while validating
37
	 *
38
	 * @var array<string>
39
	 */
40
	protected $errors = array();
41
42
	/**
43
	 * Valdiates the schema passed.
44
	 *
45
	 * @param Schema $schema
46
	 * @return bool
47
	 */
48
	public function validate( Schema $schema ): bool {
49
		// Reset errors.
50
		$this->errors = array();
51
52
		$this->validate_columns( $schema );
53
		$this->validate_primary_key( $schema );
54
		$this->validate_index_columns( $schema );
55
		$this->validate_foreign_keys( $schema );
56
57
		return ! $this->has_errors();
58
	}
59
60
	/**
61
	 * Returns all errors encountered during validation.
62
	 *
63
	 * @return array<string>
64
	 */
65
	public function get_errors(): array {
66
		return $this->errors;
67
	}
68
69
	/**
70
	 * Checks if any error generated, validating.
71
	 *
72
	 * @return bool
73
	 */
74
	public function has_errors(): bool {
75
		return count( $this->errors ) !== 0;
76
	}
77
78
	/**
79
	 * Ensure all defined columns have unique names and have types defined.
80
	 *
81
	 * @return void
82
	 */
83
	protected function validate_columns( Schema $schema ): void {
84
		$result = array_reduce(
85
			$schema->get_columns(),
86
			function( array $result, Column $column ): array {
87
				if ( is_null( $column->get_type() ) ) {
88
					$result[] = $column;
89
				}
90
				return $result;
91
			},
92
			array()
93
		);
94
95
		if ( count( $result ) !== 0 ) {
96
			$this->errors = array_merge(
97
				$this->errors,
98
				array_map(
99
					function( Column $column ): string {
100
						return \sprintf( 'Column "%s" has no type defined', $column->get_name() );
101
					},
102
					$result
103
				)
104
			);
105
		}
106
	}
107
108
	/**
109
	 * Ensure that only a single primary key has been defined.
110
	 *
111
	 * @param \PinkCrab\Table_Builder\Schema $schema
112
	 * @return void
113
	 */
114
	protected function validate_primary_key( Schema $schema ): void {
115
116
		$primary_keys = array_filter(
117
			$schema->get_indexes(),
118
			function( Index $index ): bool {
119
				return $index->is_primary();
120
			}
121
		);
122
123
		if ( count( $primary_keys ) > 1 ) {
124
			$this->errors[] = \sprintf( '%d Primary keys are defined in schema, only a single primary key can be set.', count( $primary_keys ) );
125
		}
126
	}
127
128
	/**
129
	 * Validate all indexes columnd are defined.
130
	 *
131
	 * @param \PinkCrab\Table_Builder\Schema $schema
132
	 * @return void
133
	 */
134
	protected function validate_index_columns( Schema $schema ): void {
135
		// All defined colum names.
136
		$column_names = array_keys( $schema->get_columns() );
137
138
		/** @var array<Index> */
139
		$missing_columns = array_filter(
140
			$schema->get_indexes(),
141
			function( Index $index ) use ( $column_names ): bool {
142
				return ! in_array( $index->get_column(), $column_names, true );
143
			}
144
		);
145
146
		if ( count( $missing_columns ) > 0 ) {
147
			foreach ( $missing_columns as $missing_column ) {
148
				$this->errors[] = \sprintf( 'Index column %s not defined as a column in schema', $missing_column->get_column() );
149
			}
150
		}
151
	}
152
153
	/**
154
	 * Ensure all foreign keys are set again valid columns and have both refence table and column defined.
155
	 *
156
	 * @param \PinkCrab\Table_Builder\Schema $schema
157
	 * @return void
158
	 */
159
	public function validate_foreign_keys( Schema $schema ): void {
160
		// All defined colum names.
161
		$column_names = array_keys( $schema->get_columns() );
162
163
		// Missing columns in local table
164
165
		/** @var array<Foreign_Key> */
166
		$missing_columns = array_filter(
167
			$schema->get_foreign_keys(),
168
			function( Foreign_Key $foreign_key ) use ( $column_names ): bool {
169
				return ! in_array( $foreign_key->get_column(), $column_names, true );
170
			}
171
		);
172
173
		if ( count( $missing_columns ) > 0 ) {
174
			foreach ( $missing_columns as $missing_column ) {
175
				$this->errors[] = \sprintf( 'Foreign Keys column %s not defined as a column in schema', $missing_column->get_column() );
176
			}
177
		}
178
179
		// Missing reference details.
180
181
		/** @var array<Foreign_Key> */
182
		$missing_references = array_filter(
183
			$schema->get_foreign_keys(),
184
			function( Foreign_Key $foreign_key ) : bool {
185
				return $foreign_key->get_reference_table() === null || $foreign_key->get_reference_column() === null;
186
			}
187
		);
188
189
		if ( count( $missing_references ) > 0 ) {
190
			foreach ( $missing_references as $missing_reference ) {
191
				$this->errors[] = \sprintf( 'Foreign Keys column %s has missing reference table or column details', $missing_reference->get_key_name() );
192
			}
193
		}
194
	}
195
}
196