Completed
Branch ENH-9844-update-decaf-rating-l... (cc0077)
by
unknown
14:19
created

TableManager::createTable()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 31
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 21
nc 3
nop 3
dl 0
loc 31
rs 8.8571
c 0
b 0
f 0
1
<?php
2
namespace EventEspresso\core\services\database;
3
4
defined( 'EVENT_ESPRESSO_VERSION') || exit('No direct script access allowed');
5
/**
6
 *
7
 * Class TableManager
8
 *
9
 * For performing mysql database table schema manipulation
10
 *
11
 * @package         Event Espresso
12
 * @subpackage
13
 * @author				Mike Nelson
14
 * @since		 	   $VID:$
15
 *
16
 */
17
class TableManager extends \EE_Base {
18
19
	/**
20
	 * @var TableAnalysis $table_analysis
21
	 */
22
	private $table_analysis;
23
24
25
26
	/**
27
	 * TableManager constructor.
28
	 *
29
	 * @param TableAnalysis $TableAnalysis
30
	 */
31
	public function __construct( TableAnalysis $TableAnalysis ) {
32
		$this->table_analysis = $TableAnalysis;
33
	}
34
	
35
	/**
36
	 * Gets the injected table analyzer, or throws an exception
37
	 * @return TableAnalysis
38
	 * @throws \EE_Error
39
	 */
40 View Code Duplication
	protected function getTableAnalysis() {
41
		if( $this->table_analysis instanceof TableAnalysis ) {
42
			return $this->table_analysis;
43
		} else {
44
			throw new \EE_Error( 
45
				sprintf( 
46
					__( 'Table analysis class on class %1$s is not set properly.', 'event_espresso'), 
47
					get_class( $this ) 
48
				) 
49
			);
50
		}
51
	}
52
53
54
55
	/**
56
     * @param string $table_name which can optionally start with $wpdb->prefix or not
57
     * @param string $column_name
58
     * @param string $column_info
59
     * @return bool|false|int
60
     */
61
    public function addColumn( $table_name, $column_name, $column_info='INT UNSIGNED NOT NULL' )
62
	{
63
		if( apply_filters( 'FHEE__EEH_Activation__add_column_if_it_doesnt_exist__short_circuit', FALSE ) ){
64
			return FALSE;
65
		}
66
		global $wpdb;
67
		$full_table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix( $table_name );
68
		$columns = $this->getTableColumns($table_name);
69
		if( !in_array( $column_name, $columns)){
70
			$alter_query="ALTER TABLE $full_table_name ADD $column_name $column_info";
71
			return $wpdb->query($alter_query);
72
		}
73
		return TRUE;
74
	}
75
76
	/**
77
	 * Gets the name of all columns on the  table. $table_name can
78
	 * optionally start with $wpdb->prefix or not
79
	 * @global \wpdb $wpdb
80
	 * @param string $table_name
81
	 * @return array
82
	 */
83
	public function getTableColumns( $table_name )
84
	{
85
		global $wpdb;
86
		$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix( $table_name );
87
		$fieldArray = array();
88
		if ( ! empty( $table_name )) {
89
			$columns = $wpdb->get_results("SHOW COLUMNS FROM $table_name ");
90
			if ($columns !== FALSE) {
91
				foreach( $columns as $column ){
92
					$fieldArray[] = $column->Field;
93
				}
94
			}
95
		}
96
		return $fieldArray;
97
	}
98
99
	/**
100
	 * Drops the specified table from the database. $table_name can
101
	 * optionally start with $wpdb->prefix or not
102
	 *
103
	 * @global \wpdb $wpdb
104
	 * @param string $table_name
105
	 * @return int
106
	 */
107
	public function dropTable( $table_name )
108
	{
109
		global $wpdb;
110
		if (  $this->getTableAnalysis()->tableExists( $table_name ) ) {
111
			$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix( $table_name );
112
			return $wpdb->query( "DROP TABLE IF EXISTS $table_name" );
113
		}
114
		return 0;
115
	}
116
	
117
	/**
118
	 * Drops all the tables mentioned in a single MYSQL query. Double-checks
119
	 * each table name provided has a wpdb prefix attached, and that it exists.
120
	 * Returns the list actually deleted
121
	 * @global WPDB $wpdb
122
	 * @param array $table_names
123
	 * @return array of table names which we deleted
124
	 */
125
	public function dropTables( $table_names )
126
	{
127
		$tables_to_delete = array();
128
		foreach( $table_names as $table_name ) {
129
			$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix( $table_name );
130
			if( $this->getTableAnalysis()->tableExists( $table_name ) ) {
131
				$tables_to_delete[] = $table_name;
132
			}
133
		}
134
		global $wpdb;
135
		$wpdb->query( 'DROP TABLE ' . implode( ', ', $tables_to_delete ) );
136
		return $tables_to_delete;
137
	}
138
139
	/**
140
	 * Drops the specified index from the specified table. $table_name can
141
	 * optionally start with $wpdb->prefix or not
142
	 *
143
	 * @global \wpdb $wpdb
144
	 * @param string $table_name
145
	 * @param string $indexName
146
	 * @return int
147
	 */
148
	public function dropIndex( $table_name, $indexName )
149
	{
150
		if( apply_filters( 'FHEE__EEH_Activation__drop_index__short_circuit', FALSE ) ){
151
			return FALSE;
152
		}
153
		global $wpdb;
154
		$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix( $table_name );
155
		$index_exists_query = "SHOW INDEX FROM $table_name WHERE Key_name = '$indexName'";
156
		if (
157
			$this->getTableAnalysis()->tableExists(  $table_name )
158
			&& $wpdb->get_var( $index_exists_query ) === $table_name //using get_var with the $index_exists_query returns the table's name
159
		) {
160
			return $wpdb->query( "ALTER TABLE $table_name DROP INDEX $indexName" );
161
		}
162
		return 0;
163
	}
164
165
	/**
166
	 * Just creates the requested table. $table_name can
167
	 * optionally start with $wpdb->prefix or not
168
	 * @param string $table_name
169
	 * @param string $createSql defining the table's columns and indexes
170
	 * @param string $engine (no need to specify "ENGINE=", that's implied)
171
	 * @return void
172
	 * @throws \EE_Error
173
	 */
174
	public function createTable( $table_name, $createSql, $engine = 'MyISAM' )
175
	{
176
		// does $sql contain valid column information? ( LPT: https://regex101.com/ is great for working out regex patterns )
177
		if ( preg_match( '((((.*?))(,\s))+)', $createSql, $valid_column_data ) ) {
178
			$table_name = $this->getTableAnalysis()->ensureTableNameHasPrefix( $table_name );
179
			$SQL = "CREATE TABLE $table_name ( $createSql ) ENGINE=$engine DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;";
180
			/** @var \wpdb $wpdb */
181
			global $wpdb;
182
			//get $wpdb to echo errors, but buffer them. This way at least WE know an error
183
			//happened. And then we can choose to tell the end user
184
			$old_show_errors_policy = $wpdb->show_errors( TRUE );
185
			$old_error_suppression_policy = $wpdb->suppress_errors( FALSE );
186
			ob_start();
187
			dbDelta( $SQL );
188
			$output = ob_get_contents();
189
			ob_end_clean();
190
			$wpdb->show_errors( $old_show_errors_policy );
191
			$wpdb->suppress_errors( $old_error_suppression_policy );
192
			if( ! empty( $output ) ){
193
				throw new \EE_Error( $output	);
194
			}
195
		} else {
196
			throw new \EE_Error(
197
				sprintf(
198
					__( 'The following table creation SQL does not contain valid information about the table columns: %1$s %2$s', 'event_espresso' ),
199
					'<br />',
200
					$createSql
201
				)
202
			);
203
		}
204
	}
205
206
}
207