mn_type_sql; } /** * Adds column options. * * @param string $type The native type. * @param array $options The options. * * @return string The SQL statement for the column options. * * @throws Exception If invalid arguments are supplied. */ public function add_column_options( $type, $options ) { $sql = ''; if ( ! \is_array( $options ) ) { return $sql; } if ( \array_key_exists( 'unsigned', $options ) && $options['unsigned'] === true ) { $sql .= ' UNSIGNED'; } if ( \array_key_exists( 'character', $options ) ) { $sql .= \sprintf( ' CHARACTER SET %s', $this->identifier( $options['character'] ) ); } if ( \array_key_exists( 'collate', $options ) ) { $sql .= \sprintf( ' COLLATE %s', $this->identifier( $options['collate'] ) ); } if ( \array_key_exists( 'auto_increment', $options ) && $options['auto_increment'] === true ) { $sql .= ' auto_increment'; } if ( \array_key_exists( 'default', $options ) && $options['default'] !== null ) { if ( $this->is_sql_method_call( $options['default'] ) ) { throw new Exception( 'MySQL does not support function calls as default values, constants only.' ); } if ( \is_int( $options['default'] ) ) { $default_format = '%d'; } elseif ( \is_bool( $options['default'] ) ) { $default_format = "'%d'"; } elseif ( $options['default'] === 'CURRENT_TIMESTAMP' ) { $default_format = '%s'; } else { $default_format = "'%s'"; } $default_value = \sprintf( $default_format, $options['default'] ); $sql .= \sprintf( ' DEFAULT %s', $default_value ); } if ( \array_key_exists( 'null', $options ) ) { if ( $options['null'] === false || $options['null'] === 'NO' ) { $sql .= ' NOT NULL'; } elseif ( $type === 'timestamp' ) { $sql .= ' NULL'; } } if ( \array_key_exists( 'comment', $options ) ) { $sql .= \sprintf( " COMMENT '%s'", $this->quote_string( $options['comment'] ) ); } if ( \array_key_exists( 'extra', $options ) ) { $sql .= \sprintf( ' %s', $this->quote_string( $options['extra'] ) ); } if ( \array_key_exists( 'after', $options ) ) { $sql .= \sprintf( ' AFTER %s', $this->identifier( $options['after'] ) ); } return $sql; } /** * Returns a list of all versions that have been migrated. * * @return string[] The version numbers that have been migrated. */ public function get_migrated_versions() { $result = $this->select_all( \sprintf( 'SELECT version FROM %s', $this->get_schema_version_table_name() ) ); return \array_column( $result, 'version' ); } /** * Adds a migrated version. * * @param string $version The version. * * @return bool Whether or not the version was succesfully set. */ public function add_version( $version ) { $sql = \sprintf( "INSERT INTO %s (version) VALUES ('%s')", $this->get_schema_version_table_name(), $version ); return $this->execute_ddl( $sql ); } /** * Removes a migrated version. * * @param string $version The version. * * @return bool Whether or not the version was succesfully removed. */ public function remove_version( $version ) { $sql = \sprintf( "DELETE FROM %s WHERE version = '%s'", $this->get_schema_version_table_name(), $version ); return $this->execute_ddl( $sql ); } /** * Returns a message displaying the current version * * @return string */ public function __toString() { return self::class . ', version ' . $this->version; } /** * Returns an index name. * * @param string $table_name The table name. * @param string $column_name The column name. * * @return string The index name. */ private function get_index_name( $table_name, $column_name ) { $name = \preg_replace( '/\\W/', '_', $table_name ); $name = \preg_replace( '/\\_{2,}/', '_', $name ); // If the column parameter is an array then the user wants to create a multi-column index. if ( \is_array( $column_name ) ) { $column_str = \implode( '_and_', $column_name ); } else { $column_str = $column_name; } $name .= \sprintf( '_%s', $column_str ); return $name; } /** * Returns the type of a query. * * @param string $query The query to run. * * @return int The query type. */ private function determine_query_type( $query ) { $query = \strtolower( \trim( $query ) ); $match = []; \preg_match( '/^(\\w)*/i', $query, $match ); $type = $match[0]; switch ( $type ) { case 'select': return Constants::SQL_SELECT; case 'update': return Constants::SQL_UPDATE; case 'delete': return Constants::SQL_DELETE; case 'insert': return Constants::SQL_INSERT; case 'alter': return Constants::SQL_ALTER; case 'drop': return Constants::SQL_DROP; case 'create': return Constants::SQL_CREATE; case 'show': return Constants::SQL_SHOW; case 'rename': return Constants::SQL_RENAME; case 'set': return Constants::SQL_SET; default: return Constants::SQL_UNKNOWN_QUERY_TYPE; } } /** * Detect whether or not the string represents a function call and if so * do not wrap it in single-quotes, otherwise do wrap in single quotes. * * @param string $text The string. * * @return bool Whether or not it's a SQL function call. */ private function is_sql_method_call( $text ) { $text = \trim( $text ); if ( \substr( $text, -2, 2 ) === '()' ) { return true; } return false; } /** * Checks if a transaction is active. * * @return bool */ private function in_transaction() { return $this->in_transaction; } /** * Starts a transaction. * * @return void * * @throws Exception If a transaction was already started. */ private function begin_transaction() { global $wpdb; if ( $this->in_transaction === true ) { throw new Exception( 'Transaction already started' ); } $wpdb->query( 'START TRANSACTION' ); $this->in_transaction = true; } /** * Commits a transaction. * * @return void * * @throws Exception If no transaction was strated. */ private function commit() { global $wpdb; if ( $this->in_transaction === false ) { throw new Exception( 'Transaction not started' ); } $wpdb->query( 'COMMIT' ); $this->in_transaction = false; } /** * Rollbacks a transaction. * * @return void * * @throws Exception If no transaction was started. */ private function rollback() { global $wpdb; if ( $this->in_transaction === false ) { throw new Exception( 'Transaction not started' ); } $wpdb->query( 'ROLLBACK' ); $this->in_transaction = false; } }