_db = $registry->get( 'dbi.dbi' ); $this->_database = $registry->get( 'database.helper' ); } /** * remove_instance_duplicates method * * Remove duplicate instances, from `event_instances` table * * @param int $depth Private argument, denoting number of iterations to * try, before reverting to slow approach * * @return bool Success */ public function remove_instance_duplicates( $depth = 5 ) { $use_field = 'id'; if ( $depth < 0 ) { $use_field = 'post_id'; } $table = $this->_table( 'event_instances' ); if ( false === $this->_database->table_exists( $table ) ) { return true; } $duplicates = $this->find_duplicates( $table, $use_field, array( 'post_id', 'start' ) ); $count = count( $duplicates ); if ( $count > 0 ) { $sql_query = 'DELETE FROM ' . $table . ' WHERE ' . $use_field . ' IN ( ' . implode( ', ', $duplicates ) . ' )'; $this->_db->query( $sql_query ); } if ( 'post_id' === $use_field ) { // slow branch $event_instance_model = $this->_registry->get( 'model.event.instance' ); foreach ( $duplicates as $post_id ) { try { $event_instance_model->recreate( $this->_registry->get( 'model.event', $post_id ) ); } catch ( Ai1ec_Exception $excpt ) { // discard any internal errors } } } else if ( $count > 0 ) { // retry return $this->remove_instance_duplicates( --$depth ); } return true; } /** * find_duplicates method * * Find a list of duplicates in table, given search key and groupping fields * * @param string $table Name of table, to search duplicates in * @param string $primary Column, to return values for * @param array $group List of fields, to group values on * * @return array List of primary field values */ public function find_duplicates( $table, $primary, array $group ) { $sql_query = ' SELECT MIN( {{primary}} ) AS dup_primary -- pop oldest FROM {{table}} GROUP BY {{group}} HAVING COUNT( {{primary}} ) > 1 '; $sql_query = str_replace( array( '{{table}}', '{{primary}}', '{{group}}', ), array( $this->_table( $table ), $this->_escape_column( $primary ), implode( ', ', array_map( array( $this, '_escape_column' ), $group ) ), ), $sql_query ); $result = $this->_db->get_col( $sql_query ); return $result; } /** * Check list of tables for consistency. * * @return array List of inconsistencies. */ public function check_db_consistency_for_date_migration() { $db_migration = $this->_registry->get( 'database.datetime-migration' ); /* @var $db_migration Ai1ecdm_Datetime_Migration */ $tables = $db_migration->get_tables(); if ( ! is_array( $tables ) ) { return array(); } // for date migration purposes we can assume // that all columns need to be the same type $info = array(); foreach( $tables as $t_name => $t_columns ) { if ( count( $t_columns ) < 2 ) { continue; } $tbl_error = $this->_check_single_table( $t_name, $db_migration->get_columns( $t_name ), $t_columns ); if ( null !== $tbl_error ) { $info[] = $tbl_error; } } return $info; } /** * Check if single table columns are the same type. * * @param string $t_name Table name for details purposes. * @param array $db_cols Columns from database. * @param array $t_columns Columns to check from DDL. * * @return string|null Inconsistency description, if any. */ protected function _check_single_table( $t_name, array $db_cols, array $t_columns ) { $type = null; foreach ( $db_cols as $c_field => $c_type ) { if ( ! in_array( $c_field, $t_columns ) ) { continue; } if ( null === $type ) { $type = strtolower( $c_type ); } if ( strtolower( $c_type ) !== $type ) { return sprintf( Ai1ec_I18n::__( 'Date columns in table %s have different types.' ), $t_name ); } } return null; } /** * Get fully qualified table name, to use in queries. * * @param string $table Name of table, to convert. * * @return string Qualified table name. */ protected function _table( $table ) { $prefix = $this->_db->get_table_name( 'ai1ec_' ); if ( substr( $table, 0, strlen( $prefix ) ) !== $prefix ) { $table = $prefix . $table; } return $table; } /** * _escape_column method * * Escape column, enquoting it in MySQL specific characters * * @param string $name Name of column to quote * * @return string Escaped column name */ protected function _escape_column( $name ) { return '`' . $name . '`'; } }