172 * @var array |
173 * @var array |
173 */ |
174 */ |
174 protected $col_info; |
175 protected $col_info; |
175 |
176 |
176 /** |
177 /** |
177 * Saved queries that were executed |
178 * Log of queries that were executed, for debugging purposes. |
178 * |
179 * |
179 * @since 1.5.0 |
180 * @since 1.5.0 |
180 * @var array |
181 * @since 2.5.0 The third element in each query log was added to record the calling functions. |
|
182 * @since 5.1.0 The fourth element in each query log was added to record the start time. |
|
183 * |
|
184 * @var array[] { |
|
185 * Array of queries that were executed. |
|
186 * |
|
187 * @type array ...$0 { |
|
188 * Data for each query. |
|
189 * |
|
190 * @type string $0 The query's SQL. |
|
191 * @type float $1 Total time spent on the query, in seconds. |
|
192 * @type string $2 Comma separated list of the calling functions. |
|
193 * @type float $3 Unix timestamp of the time at the start of the query. |
|
194 * } |
|
195 * } |
181 */ |
196 */ |
182 var $queries; |
197 var $queries; |
183 |
198 |
184 /** |
199 /** |
185 * The number of times to retry reconnecting before dying. |
200 * The number of times to retry reconnecting before dying. |
239 * |
254 * |
240 * @since 2.5.0 |
255 * @since 2.5.0 |
241 * @see wpdb::tables() |
256 * @see wpdb::tables() |
242 * @var array |
257 * @var array |
243 */ |
258 */ |
244 var $tables = array( 'posts', 'comments', 'links', 'options', 'postmeta', |
259 var $tables = array( |
245 'terms', 'term_taxonomy', 'term_relationships', 'termmeta', 'commentmeta' ); |
260 'posts', |
|
261 'comments', |
|
262 'links', |
|
263 'options', |
|
264 'postmeta', |
|
265 'terms', |
|
266 'term_taxonomy', |
|
267 'term_relationships', |
|
268 'termmeta', |
|
269 'commentmeta', |
|
270 ); |
246 |
271 |
247 /** |
272 /** |
248 * List of deprecated WordPress tables |
273 * List of deprecated WordPress tables |
249 * |
274 * |
250 * categories, post2cat, and link2cat were deprecated in 2.3.0, db version 5539 |
275 * categories, post2cat, and link2cat were deprecated in 2.3.0, db version 5539 |
565 * @param string $dbhost MySQL database host |
611 * @param string $dbhost MySQL database host |
566 */ |
612 */ |
567 public function __construct( $dbuser, $dbpassword, $dbname, $dbhost ) { |
613 public function __construct( $dbuser, $dbpassword, $dbname, $dbhost ) { |
568 register_shutdown_function( array( $this, '__destruct' ) ); |
614 register_shutdown_function( array( $this, '__destruct' ) ); |
569 |
615 |
570 if ( WP_DEBUG && WP_DEBUG_DISPLAY ) |
616 if ( WP_DEBUG && WP_DEBUG_DISPLAY ) { |
571 $this->show_errors(); |
617 $this->show_errors(); |
|
618 } |
572 |
619 |
573 // Use ext/mysqli if it exists unless WP_USE_EXT_MYSQL is defined as true |
620 // Use ext/mysqli if it exists unless WP_USE_EXT_MYSQL is defined as true |
574 if ( function_exists( 'mysqli_connect' ) ) { |
621 if ( function_exists( 'mysqli_connect' ) ) { |
575 $this->use_mysqli = true; |
622 $this->use_mysqli = true; |
576 |
623 |
577 if ( defined( 'WP_USE_EXT_MYSQL' ) ) { |
624 if ( defined( 'WP_USE_EXT_MYSQL' ) ) { |
578 $this->use_mysqli = ! WP_USE_EXT_MYSQL; |
625 $this->use_mysqli = ! WP_USE_EXT_MYSQL; |
579 } |
626 } |
580 } |
627 } |
581 |
628 |
582 $this->dbuser = $dbuser; |
629 $this->dbuser = $dbuser; |
583 $this->dbpassword = $dbpassword; |
630 $this->dbpassword = $dbpassword; |
584 $this->dbname = $dbname; |
631 $this->dbname = $dbname; |
585 $this->dbhost = $dbhost; |
632 $this->dbhost = $dbhost; |
586 |
633 |
587 // wp-config.php creation will manually connect when ready. |
634 // wp-config.php creation will manually connect when ready. |
588 if ( defined( 'WP_SETUP_CONFIG' ) ) { |
635 if ( defined( 'WP_SETUP_CONFIG' ) ) { |
589 return; |
636 return; |
590 } |
637 } |
742 * @param resource $dbh The resource given by mysql_connect |
790 * @param resource $dbh The resource given by mysql_connect |
743 * @param string $charset Optional. The character set. Default null. |
791 * @param string $charset Optional. The character set. Default null. |
744 * @param string $collate Optional. The collation. Default null. |
792 * @param string $collate Optional. The collation. Default null. |
745 */ |
793 */ |
746 public function set_charset( $dbh, $charset = null, $collate = null ) { |
794 public function set_charset( $dbh, $charset = null, $collate = null ) { |
747 if ( ! isset( $charset ) ) |
795 if ( ! isset( $charset ) ) { |
748 $charset = $this->charset; |
796 $charset = $this->charset; |
749 if ( ! isset( $collate ) ) |
797 } |
|
798 if ( ! isset( $collate ) ) { |
750 $collate = $this->collate; |
799 $collate = $this->collate; |
|
800 } |
751 if ( $this->has_cap( 'collation' ) && ! empty( $charset ) ) { |
801 if ( $this->has_cap( 'collation' ) && ! empty( $charset ) ) { |
752 $set_charset_succeeded = true; |
802 $set_charset_succeeded = true; |
753 |
803 |
754 if ( $this->use_mysqli ) { |
804 if ( $this->use_mysqli ) { |
755 if ( function_exists( 'mysqli_set_charset' ) && $this->has_cap( 'set_charset' ) ) { |
805 if ( function_exists( 'mysqli_set_charset' ) && $this->has_cap( 'set_charset' ) ) { |
756 $set_charset_succeeded = mysqli_set_charset( $dbh, $charset ); |
806 $set_charset_succeeded = mysqli_set_charset( $dbh, $charset ); |
757 } |
807 } |
758 |
808 |
759 if ( $set_charset_succeeded ) { |
809 if ( $set_charset_succeeded ) { |
760 $query = $this->prepare( 'SET NAMES %s', $charset ); |
810 $query = $this->prepare( 'SET NAMES %s', $charset ); |
761 if ( ! empty( $collate ) ) |
811 if ( ! empty( $collate ) ) { |
762 $query .= $this->prepare( ' COLLATE %s', $collate ); |
812 $query .= $this->prepare( ' COLLATE %s', $collate ); |
|
813 } |
763 mysqli_query( $dbh, $query ); |
814 mysqli_query( $dbh, $query ); |
764 } |
815 } |
765 } else { |
816 } else { |
766 if ( function_exists( 'mysql_set_charset' ) && $this->has_cap( 'set_charset' ) ) { |
817 if ( function_exists( 'mysql_set_charset' ) && $this->has_cap( 'set_charset' ) ) { |
767 $set_charset_succeeded = mysql_set_charset( $charset, $dbh ); |
818 $set_charset_succeeded = mysql_set_charset( $charset, $dbh ); |
768 } |
819 } |
769 if ( $set_charset_succeeded ) { |
820 if ( $set_charset_succeeded ) { |
770 $query = $this->prepare( 'SET NAMES %s', $charset ); |
821 $query = $this->prepare( 'SET NAMES %s', $charset ); |
771 if ( ! empty( $collate ) ) |
822 if ( ! empty( $collate ) ) { |
772 $query .= $this->prepare( ' COLLATE %s', $collate ); |
823 $query .= $this->prepare( ' COLLATE %s', $collate ); |
|
824 } |
773 mysql_query( $query, $dbh ); |
825 mysql_query( $query, $dbh ); |
774 } |
826 } |
775 } |
827 } |
776 } |
828 } |
777 } |
829 } |
850 * @param bool $set_table_names Optional. Whether the table names, e.g. wpdb::$posts, should be updated or not. |
902 * @param bool $set_table_names Optional. Whether the table names, e.g. wpdb::$posts, should be updated or not. |
851 * @return string|WP_Error Old prefix or WP_Error on error |
903 * @return string|WP_Error Old prefix or WP_Error on error |
852 */ |
904 */ |
853 public function set_prefix( $prefix, $set_table_names = true ) { |
905 public function set_prefix( $prefix, $set_table_names = true ) { |
854 |
906 |
855 if ( preg_match( '|[^a-z0-9_]|i', $prefix ) ) |
907 if ( preg_match( '|[^a-z0-9_]|i', $prefix ) ) { |
856 return new WP_Error('invalid_db_prefix', 'Invalid database prefix' ); |
908 return new WP_Error( 'invalid_db_prefix', 'Invalid database prefix' ); |
|
909 } |
857 |
910 |
858 $old_prefix = is_multisite() ? '' : $prefix; |
911 $old_prefix = is_multisite() ? '' : $prefix; |
859 |
912 |
860 if ( isset( $this->base_prefix ) ) |
913 if ( isset( $this->base_prefix ) ) { |
861 $old_prefix = $this->base_prefix; |
914 $old_prefix = $this->base_prefix; |
|
915 } |
862 |
916 |
863 $this->base_prefix = $prefix; |
917 $this->base_prefix = $prefix; |
864 |
918 |
865 if ( $set_table_names ) { |
919 if ( $set_table_names ) { |
866 foreach ( $this->tables( 'global' ) as $table => $prefixed_table ) |
920 foreach ( $this->tables( 'global' ) as $table => $prefixed_table ) { |
867 $this->$table = $prefixed_table; |
921 $this->$table = $prefixed_table; |
868 |
922 } |
869 if ( is_multisite() && empty( $this->blogid ) ) |
923 |
|
924 if ( is_multisite() && empty( $this->blogid ) ) { |
870 return $old_prefix; |
925 return $old_prefix; |
|
926 } |
871 |
927 |
872 $this->prefix = $this->get_blog_prefix(); |
928 $this->prefix = $this->get_blog_prefix(); |
873 |
929 |
874 foreach ( $this->tables( 'blog' ) as $table => $prefixed_table ) |
930 foreach ( $this->tables( 'blog' ) as $table => $prefixed_table ) { |
875 $this->$table = $prefixed_table; |
931 $this->$table = $prefixed_table; |
876 |
932 } |
877 foreach ( $this->tables( 'old' ) as $table => $prefixed_table ) |
933 |
|
934 foreach ( $this->tables( 'old' ) as $table => $prefixed_table ) { |
878 $this->$table = $prefixed_table; |
935 $this->$table = $prefixed_table; |
|
936 } |
879 } |
937 } |
880 return $old_prefix; |
938 return $old_prefix; |
881 } |
939 } |
882 |
940 |
883 /** |
941 /** |
897 $old_blog_id = $this->blogid; |
955 $old_blog_id = $this->blogid; |
898 $this->blogid = $blog_id; |
956 $this->blogid = $blog_id; |
899 |
957 |
900 $this->prefix = $this->get_blog_prefix(); |
958 $this->prefix = $this->get_blog_prefix(); |
901 |
959 |
902 foreach ( $this->tables( 'blog' ) as $table => $prefixed_table ) |
960 foreach ( $this->tables( 'blog' ) as $table => $prefixed_table ) { |
903 $this->$table = $prefixed_table; |
961 $this->$table = $prefixed_table; |
904 |
962 } |
905 foreach ( $this->tables( 'old' ) as $table => $prefixed_table ) |
963 |
|
964 foreach ( $this->tables( 'old' ) as $table => $prefixed_table ) { |
906 $this->$table = $prefixed_table; |
965 $this->$table = $prefixed_table; |
|
966 } |
907 |
967 |
908 return $old_blog_id; |
968 return $old_blog_id; |
909 } |
969 } |
910 |
970 |
911 /** |
971 /** |
915 * @param int $blog_id Optional. |
975 * @param int $blog_id Optional. |
916 * @return string Blog prefix. |
976 * @return string Blog prefix. |
917 */ |
977 */ |
918 public function get_blog_prefix( $blog_id = null ) { |
978 public function get_blog_prefix( $blog_id = null ) { |
919 if ( is_multisite() ) { |
979 if ( is_multisite() ) { |
920 if ( null === $blog_id ) |
980 if ( null === $blog_id ) { |
921 $blog_id = $this->blogid; |
981 $blog_id = $this->blogid; |
|
982 } |
922 $blog_id = (int) $blog_id; |
983 $blog_id = (int) $blog_id; |
923 if ( defined( 'MULTISITE' ) && ( 0 == $blog_id || 1 == $blog_id ) ) |
984 if ( defined( 'MULTISITE' ) && ( 0 == $blog_id || 1 == $blog_id ) ) { |
924 return $this->base_prefix; |
985 return $this->base_prefix; |
925 else |
986 } else { |
926 return $this->base_prefix . $blog_id . '_'; |
987 return $this->base_prefix . $blog_id . '_'; |
|
988 } |
927 } else { |
989 } else { |
928 return $this->base_prefix; |
990 return $this->base_prefix; |
929 } |
991 } |
930 } |
992 } |
931 |
993 |
956 * @param int $blog_id Optional. The blog_id to prefix. Defaults to wpdb::$blogid. Used only when prefix is requested. |
1018 * @param int $blog_id Optional. The blog_id to prefix. Defaults to wpdb::$blogid. Used only when prefix is requested. |
957 * @return array Table names. When a prefix is requested, the key is the unprefixed table name. |
1019 * @return array Table names. When a prefix is requested, the key is the unprefixed table name. |
958 */ |
1020 */ |
959 public function tables( $scope = 'all', $prefix = true, $blog_id = 0 ) { |
1021 public function tables( $scope = 'all', $prefix = true, $blog_id = 0 ) { |
960 switch ( $scope ) { |
1022 switch ( $scope ) { |
961 case 'all' : |
1023 case 'all': |
962 $tables = array_merge( $this->global_tables, $this->tables ); |
1024 $tables = array_merge( $this->global_tables, $this->tables ); |
963 if ( is_multisite() ) |
1025 if ( is_multisite() ) { |
964 $tables = array_merge( $tables, $this->ms_global_tables ); |
1026 $tables = array_merge( $tables, $this->ms_global_tables ); |
|
1027 } |
965 break; |
1028 break; |
966 case 'blog' : |
1029 case 'blog': |
967 $tables = $this->tables; |
1030 $tables = $this->tables; |
968 break; |
1031 break; |
969 case 'global' : |
1032 case 'global': |
970 $tables = $this->global_tables; |
1033 $tables = $this->global_tables; |
971 if ( is_multisite() ) |
1034 if ( is_multisite() ) { |
972 $tables = array_merge( $tables, $this->ms_global_tables ); |
1035 $tables = array_merge( $tables, $this->ms_global_tables ); |
|
1036 } |
973 break; |
1037 break; |
974 case 'ms_global' : |
1038 case 'ms_global': |
975 $tables = $this->ms_global_tables; |
1039 $tables = $this->ms_global_tables; |
976 break; |
1040 break; |
977 case 'old' : |
1041 case 'old': |
978 $tables = $this->old_tables; |
1042 $tables = $this->old_tables; |
979 break; |
1043 break; |
980 default : |
1044 default: |
981 return array(); |
1045 return array(); |
982 } |
1046 } |
983 |
1047 |
984 if ( $prefix ) { |
1048 if ( $prefix ) { |
985 if ( ! $blog_id ) |
1049 if ( ! $blog_id ) { |
986 $blog_id = $this->blogid; |
1050 $blog_id = $this->blogid; |
987 $blog_prefix = $this->get_blog_prefix( $blog_id ); |
1051 } |
988 $base_prefix = $this->base_prefix; |
1052 $blog_prefix = $this->get_blog_prefix( $blog_id ); |
|
1053 $base_prefix = $this->base_prefix; |
989 $global_tables = array_merge( $this->global_tables, $this->ms_global_tables ); |
1054 $global_tables = array_merge( $this->global_tables, $this->ms_global_tables ); |
990 foreach ( $tables as $k => $table ) { |
1055 foreach ( $tables as $k => $table ) { |
991 if ( in_array( $table, $global_tables ) ) |
1056 if ( in_array( $table, $global_tables ) ) { |
992 $tables[ $table ] = $base_prefix . $table; |
1057 $tables[ $table ] = $base_prefix . $table; |
993 else |
1058 } else { |
994 $tables[ $table ] = $blog_prefix . $table; |
1059 $tables[ $table ] = $blog_prefix . $table; |
|
1060 } |
995 unset( $tables[ $k ] ); |
1061 unset( $tables[ $k ] ); |
996 } |
1062 } |
997 |
1063 |
998 if ( isset( $tables['users'] ) && defined( 'CUSTOM_USER_TABLE' ) ) |
1064 if ( isset( $tables['users'] ) && defined( 'CUSTOM_USER_TABLE' ) ) { |
999 $tables['users'] = CUSTOM_USER_TABLE; |
1065 $tables['users'] = CUSTOM_USER_TABLE; |
1000 |
1066 } |
1001 if ( isset( $tables['usermeta'] ) && defined( 'CUSTOM_USER_META_TABLE' ) ) |
1067 |
|
1068 if ( isset( $tables['usermeta'] ) && defined( 'CUSTOM_USER_META_TABLE' ) ) { |
1002 $tables['usermeta'] = CUSTOM_USER_META_TABLE; |
1069 $tables['usermeta'] = CUSTOM_USER_META_TABLE; |
|
1070 } |
1003 } |
1071 } |
1004 |
1072 |
1005 return $tables; |
1073 return $tables; |
1006 } |
1074 } |
1007 |
1075 |
1015 * |
1083 * |
1016 * @param string $db MySQL database name |
1084 * @param string $db MySQL database name |
1017 * @param resource|null $dbh Optional link identifier. |
1085 * @param resource|null $dbh Optional link identifier. |
1018 */ |
1086 */ |
1019 public function select( $db, $dbh = null ) { |
1087 public function select( $db, $dbh = null ) { |
1020 if ( is_null($dbh) ) |
1088 if ( is_null( $dbh ) ) { |
1021 $dbh = $this->dbh; |
1089 $dbh = $this->dbh; |
|
1090 } |
1022 |
1091 |
1023 if ( $this->use_mysqli ) { |
1092 if ( $this->use_mysqli ) { |
1024 $success = mysqli_select_db( $dbh, $db ); |
1093 $success = mysqli_select_db( $dbh, $db ); |
1025 } else { |
1094 } else { |
1026 $success = mysql_select_db( $db, $dbh ); |
1095 $success = mysql_select_db( $db, $dbh ); |
1042 $message .= '<li>' . __( 'Are you sure it exists?' ) . "</li>\n"; |
1111 $message .= '<li>' . __( 'Are you sure it exists?' ) . "</li>\n"; |
1043 |
1112 |
1044 $message .= '<li>' . sprintf( |
1113 $message .= '<li>' . sprintf( |
1045 /* translators: 1: database user, 2: database name */ |
1114 /* translators: 1: database user, 2: database name */ |
1046 __( 'Does the user %1$s have permission to use the %2$s database?' ), |
1115 __( 'Does the user %1$s have permission to use the %2$s database?' ), |
1047 '<code>' . htmlspecialchars( $this->dbuser, ENT_QUOTES ) . '</code>', |
1116 '<code>' . htmlspecialchars( $this->dbuser, ENT_QUOTES ) . '</code>', |
1048 '<code>' . htmlspecialchars( $db, ENT_QUOTES ) . '</code>' |
1117 '<code>' . htmlspecialchars( $db, ENT_QUOTES ) . '</code>' |
1049 ) . "</li>\n"; |
1118 ) . "</li>\n"; |
1050 |
1119 |
1051 $message .= '<li>' . sprintf( |
1120 $message .= '<li>' . sprintf( |
1052 /* translators: %s: database name */ |
1121 /* translators: %s: database name */ |
1053 __( 'On some systems the name of your database is prefixed with your username, so it would be like <code>username_%1$s</code>. Could that be the problem?' ), |
1122 __( 'On some systems the name of your database is prefixed with your username, so it would be like <code>username_%1$s</code>. Could that be the problem?' ), |
1054 htmlspecialchars( $db, ENT_QUOTES ) |
1123 htmlspecialchars( $db, ENT_QUOTES ) |
1055 ). "</li>\n"; |
1124 ) . "</li>\n"; |
1056 |
1125 |
1057 $message .= "</ul>\n"; |
1126 $message .= "</ul>\n"; |
1058 |
1127 |
1059 $message .= '<p>' . sprintf( |
1128 $message .= '<p>' . sprintf( |
1060 /* translators: %s: support forums URL */ |
1129 /* translators: %s: support forums URL */ |
1061 __( 'If you don’t know how to set up a database you should <strong>contact your host</strong>. If all else fails you may find help at the <a href="%s">WordPress Support Forums</a>.' ), |
1130 __( 'If you don’t know how to set up a database you should <strong>contact your host</strong>. If all else fails you may find help at the <a href="%s">WordPress Support Forums</a>.' ), |
1062 __( 'https://wordpress.org/support/' ) |
1131 __( 'https://wordpress.org/support/forums/' ) |
1063 ) . "</p>\n"; |
1132 ) . "</p>\n"; |
1064 |
1133 |
1065 $this->bail( $message, 'db_select_fail' ); |
1134 $this->bail( $message, 'db_select_fail' ); |
1066 } |
1135 } |
1067 } |
1136 } |
1079 * |
1148 * |
1080 * @param string $string |
1149 * @param string $string |
1081 * @return string |
1150 * @return string |
1082 */ |
1151 */ |
1083 function _weak_escape( $string ) { |
1152 function _weak_escape( $string ) { |
1084 if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) ) |
1153 if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) ) { |
1085 _deprecated_function( __METHOD__, '3.6.0', 'wpdb::prepare() or esc_sql()' ); |
1154 _deprecated_function( __METHOD__, '3.6.0', 'wpdb::prepare() or esc_sql()' ); |
|
1155 } |
1086 return addslashes( $string ); |
1156 return addslashes( $string ); |
1087 } |
1157 } |
1088 |
1158 |
1089 /** |
1159 /** |
1090 * Real escape, using mysqli_real_escape_string() or mysql_real_escape_string() |
1160 * Real escape, using mysqli_real_escape_string() or mysql_real_escape_string() |
1128 */ |
1198 */ |
1129 public function _escape( $data ) { |
1199 public function _escape( $data ) { |
1130 if ( is_array( $data ) ) { |
1200 if ( is_array( $data ) ) { |
1131 foreach ( $data as $k => $v ) { |
1201 foreach ( $data as $k => $v ) { |
1132 if ( is_array( $v ) ) { |
1202 if ( is_array( $v ) ) { |
1133 $data[$k] = $this->_escape( $v ); |
1203 $data[ $k ] = $this->_escape( $v ); |
1134 } else { |
1204 } else { |
1135 $data[$k] = $this->_real_escape( $v ); |
1205 $data[ $k ] = $this->_real_escape( $v ); |
1136 } |
1206 } |
1137 } |
1207 } |
1138 } else { |
1208 } else { |
1139 $data = $this->_real_escape( $data ); |
1209 $data = $this->_real_escape( $data ); |
1140 } |
1210 } |
1154 * |
1224 * |
1155 * @param mixed $data |
1225 * @param mixed $data |
1156 * @return mixed |
1226 * @return mixed |
1157 */ |
1227 */ |
1158 public function escape( $data ) { |
1228 public function escape( $data ) { |
1159 if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) ) |
1229 if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) ) { |
1160 _deprecated_function( __METHOD__, '3.6.0', 'wpdb::prepare() or esc_sql()' ); |
1230 _deprecated_function( __METHOD__, '3.6.0', 'wpdb::prepare() or esc_sql()' ); |
|
1231 } |
1161 if ( is_array( $data ) ) { |
1232 if ( is_array( $data ) ) { |
1162 foreach ( $data as $k => $v ) { |
1233 foreach ( $data as $k => $v ) { |
1163 if ( is_array( $v ) ) |
1234 if ( is_array( $v ) ) { |
1164 $data[$k] = $this->escape( $v, 'recursive' ); |
1235 $data[ $k ] = $this->escape( $v, 'recursive' ); |
1165 else |
1236 } else { |
1166 $data[$k] = $this->_weak_escape( $v, 'internal' ); |
1237 $data[ $k ] = $this->_weak_escape( $v, 'internal' ); |
|
1238 } |
1167 } |
1239 } |
1168 } else { |
1240 } else { |
1169 $data = $this->_weak_escape( $data, 'internal' ); |
1241 $data = $this->_weak_escape( $data, 'internal' ); |
1170 } |
1242 } |
1171 |
1243 |
1199 * For compatibility with old behavior, numbered or formatted string placeholders (eg, %1$s, %5s) will not have quotes |
1272 * For compatibility with old behavior, numbered or formatted string placeholders (eg, %1$s, %5s) will not have quotes |
1200 * added by this function, so should be passed with appropriate quotes around them for your usage. |
1273 * added by this function, so should be passed with appropriate quotes around them for your usage. |
1201 * |
1274 * |
1202 * Literal percentage signs (%) in the query string must be written as %%. Percentage wildcards (for example, |
1275 * Literal percentage signs (%) in the query string must be written as %%. Percentage wildcards (for example, |
1203 * to use in LIKE syntax) must be passed via a substitution argument containing the complete LIKE string, these |
1276 * to use in LIKE syntax) must be passed via a substitution argument containing the complete LIKE string, these |
1204 * cannot be inserted directly in the query string. Also see {@see esc_like()}. |
1277 * cannot be inserted directly in the query string. Also see wpdb::esc_like(). |
1205 * |
1278 * |
1206 * Arguments may be passed as individual arguments to the method, or as a single array containing all arguments. A combination |
1279 * Arguments may be passed as individual arguments to the method, or as a single array containing all arguments. A combination |
1207 * of the two is not supported. |
1280 * of the two is not supported. |
1208 * |
1281 * |
1209 * Examples: |
1282 * Examples: |
1235 |
1308 |
1236 // If args were passed as an array (as in vsprintf), move them up. |
1309 // If args were passed as an array (as in vsprintf), move them up. |
1237 $passed_as_array = false; |
1310 $passed_as_array = false; |
1238 if ( is_array( $args[0] ) && count( $args ) == 1 ) { |
1311 if ( is_array( $args[0] ) && count( $args ) == 1 ) { |
1239 $passed_as_array = true; |
1312 $passed_as_array = true; |
1240 $args = $args[0]; |
1313 $args = $args[0]; |
1241 } |
1314 } |
1242 |
1315 |
1243 foreach ( $args as $arg ) { |
1316 foreach ( $args as $arg ) { |
1244 if ( ! is_scalar( $arg ) && ! is_null( $arg ) ) { |
1317 if ( ! is_scalar( $arg ) && ! is_null( $arg ) ) { |
1245 wp_load_translations_early(); |
1318 wp_load_translations_early(); |
1260 |
1333 |
1261 /* |
1334 /* |
1262 * If a %s placeholder already has quotes around it, removing the existing quotes and re-inserting them |
1335 * If a %s placeholder already has quotes around it, removing the existing quotes and re-inserting them |
1263 * ensures the quotes are consistent. |
1336 * ensures the quotes are consistent. |
1264 * |
1337 * |
1265 * For backwards compatibility, this is only applied to %s, and not to placeholders like %1$s, which are frequently |
1338 * For backward compatibility, this is only applied to %s, and not to placeholders like %1$s, which are frequently |
1266 * used in the middle of longer strings, or as table name placeholders. |
1339 * used in the middle of longer strings, or as table name placeholders. |
1267 */ |
1340 */ |
1268 $query = str_replace( "'%s'", '%s', $query ); // Strip any existing single quotes. |
1341 $query = str_replace( "'%s'", '%s', $query ); // Strip any existing single quotes. |
1269 $query = str_replace( '"%s"', '%s', $query ); // Strip any existing double quotes. |
1342 $query = str_replace( '"%s"', '%s', $query ); // Strip any existing double quotes. |
1270 $query = preg_replace( '/(?<!%)%s/', "'%s'", $query ); // Quote the strings, avoiding escaped strings like %%s. |
1343 $query = preg_replace( '/(?<!%)%s/', "'%s'", $query ); // Quote the strings, avoiding escaped strings like %%s. |
1271 |
1344 |
1272 $query = preg_replace( "/(?<!%)(%($allowed_format)?f)/" , '%\\2F', $query ); // Force floats to be locale unaware. |
1345 $query = preg_replace( "/(?<!%)(%($allowed_format)?f)/", '%\\2F', $query ); // Force floats to be locale unaware. |
1273 |
1346 |
1274 $query = preg_replace( "/%(?:%|$|(?!($allowed_format)?[sdF]))/", '%%\\1', $query ); // Escape any unescaped percents. |
1347 $query = preg_replace( "/%(?:%|$|(?!($allowed_format)?[sdF]))/", '%%\\1', $query ); // Escape any unescaped percents. |
1275 |
1348 |
1276 // Count the number of valid placeholders in the query. |
1349 // Count the number of valid placeholders in the query. |
1277 $placeholders = preg_match_all( "/(^|[^%]|(%%)+)%($allowed_format)?[sdF]/", $query, $matches ); |
1350 $placeholders = preg_match_all( "/(^|[^%]|(%%)+)%($allowed_format)?[sdF]/", $query, $matches ); |
1287 /* |
1360 /* |
1288 * If we don't have the right number of placeholders, but they were passed as individual arguments, |
1361 * If we don't have the right number of placeholders, but they were passed as individual arguments, |
1289 * or we were expecting multiple arguments in an array, throw a warning. |
1362 * or we were expecting multiple arguments in an array, throw a warning. |
1290 */ |
1363 */ |
1291 wp_load_translations_early(); |
1364 wp_load_translations_early(); |
1292 _doing_it_wrong( 'wpdb::prepare', |
1365 _doing_it_wrong( |
|
1366 'wpdb::prepare', |
1293 /* translators: 1: number of placeholders, 2: number of arguments passed */ |
1367 /* translators: 1: number of placeholders, 2: number of arguments passed */ |
1294 sprintf( __( 'The query does not contain the correct number of placeholders (%1$d) for the number of arguments passed (%2$d).' ), |
1368 sprintf( |
|
1369 __( 'The query does not contain the correct number of placeholders (%1$d) for the number of arguments passed (%2$d).' ), |
1295 $placeholders, |
1370 $placeholders, |
1296 count( $args ) ), |
1371 count( $args ) |
|
1372 ), |
1297 '4.8.3' |
1373 '4.8.3' |
1298 ); |
1374 ); |
1299 } |
1375 } |
1300 } |
1376 } |
1301 |
1377 |
1342 * @return false|void False if the showing of errors is disabled. |
1418 * @return false|void False if the showing of errors is disabled. |
1343 */ |
1419 */ |
1344 public function print_error( $str = '' ) { |
1420 public function print_error( $str = '' ) { |
1345 global $EZSQL_ERROR; |
1421 global $EZSQL_ERROR; |
1346 |
1422 |
1347 if ( !$str ) { |
1423 if ( ! $str ) { |
1348 if ( $this->use_mysqli ) { |
1424 if ( $this->use_mysqli ) { |
1349 $str = mysqli_error( $this->dbh ); |
1425 $str = mysqli_error( $this->dbh ); |
1350 } else { |
1426 } else { |
1351 $str = mysql_error( $this->dbh ); |
1427 $str = mysql_error( $this->dbh ); |
1352 } |
1428 } |
1353 } |
1429 } |
1354 $EZSQL_ERROR[] = array( 'query' => $this->last_query, 'error_str' => $str ); |
1430 $EZSQL_ERROR[] = array( |
1355 |
1431 'query' => $this->last_query, |
1356 if ( $this->suppress_errors ) |
1432 'error_str' => $str, |
|
1433 ); |
|
1434 |
|
1435 if ( $this->suppress_errors ) { |
1357 return false; |
1436 return false; |
|
1437 } |
1358 |
1438 |
1359 wp_load_translations_early(); |
1439 wp_load_translations_early(); |
1360 |
1440 |
1361 if ( $caller = $this->get_caller() ) { |
1441 if ( $caller = $this->get_caller() ) { |
1362 /* translators: 1: Database error message, 2: SQL query, 3: Name of the calling function */ |
1442 /* translators: 1: Database error message, 2: SQL query, 3: Name of the calling function */ |
1446 * @see wpdb::hide_errors() |
1527 * @see wpdb::hide_errors() |
1447 * @param bool $suppress Optional. New value. Defaults to true. |
1528 * @param bool $suppress Optional. New value. Defaults to true. |
1448 * @return bool Old value |
1529 * @return bool Old value |
1449 */ |
1530 */ |
1450 public function suppress_errors( $suppress = true ) { |
1531 public function suppress_errors( $suppress = true ) { |
1451 $errors = $this->suppress_errors; |
1532 $errors = $this->suppress_errors; |
1452 $this->suppress_errors = (bool) $suppress; |
1533 $this->suppress_errors = (bool) $suppress; |
1453 return $errors; |
1534 return $errors; |
1454 } |
1535 } |
1455 |
1536 |
1456 /** |
1537 /** |
1457 * Kill cached query results. |
1538 * Kill cached query results. |
1458 * |
1539 * |
1459 * @since 0.71 |
1540 * @since 0.71 |
1460 */ |
1541 */ |
1461 public function flush() { |
1542 public function flush() { |
1462 $this->last_result = array(); |
1543 $this->last_result = array(); |
1463 $this->col_info = null; |
1544 $this->col_info = null; |
1464 $this->last_query = null; |
1545 $this->last_query = null; |
1465 $this->rows_affected = $this->num_rows = 0; |
1546 $this->rows_affected = $this->num_rows = 0; |
1466 $this->last_error = ''; |
1547 $this->last_error = ''; |
1467 |
1548 |
1468 if ( $this->use_mysqli && $this->result instanceof mysqli_result ) { |
1549 if ( $this->use_mysqli && $this->result instanceof mysqli_result ) { |
1469 mysqli_free_result( $this->result ); |
1550 mysqli_free_result( $this->result ); |
1470 $this->result = null; |
1551 $this->result = null; |
1471 |
1552 |
1472 // Sanity check before using the handle |
1553 // Sanity check before using the handle |
1473 if ( empty( $this->dbh ) || !( $this->dbh instanceof mysqli ) ) { |
1554 if ( empty( $this->dbh ) || ! ( $this->dbh instanceof mysqli ) ) { |
1474 return; |
1555 return; |
1475 } |
1556 } |
1476 |
1557 |
1477 // Clear out any results from a multi-query |
1558 // Clear out any results from a multi-query |
1478 while ( mysqli_more_results( $this->dbh ) ) { |
1559 while ( mysqli_more_results( $this->dbh ) ) { |
1500 |
1581 |
1501 /* |
1582 /* |
1502 * Deprecated in 3.9+ when using MySQLi. No equivalent |
1583 * Deprecated in 3.9+ when using MySQLi. No equivalent |
1503 * $new_link parameter exists for mysqli_* functions. |
1584 * $new_link parameter exists for mysqli_* functions. |
1504 */ |
1585 */ |
1505 $new_link = defined( 'MYSQL_NEW_LINK' ) ? MYSQL_NEW_LINK : true; |
1586 $new_link = defined( 'MYSQL_NEW_LINK' ) ? MYSQL_NEW_LINK : true; |
1506 $client_flags = defined( 'MYSQL_CLIENT_FLAGS' ) ? MYSQL_CLIENT_FLAGS : 0; |
1587 $client_flags = defined( 'MYSQL_CLIENT_FLAGS' ) ? MYSQL_CLIENT_FLAGS : 0; |
1507 |
1588 |
1508 if ( $this->use_mysqli ) { |
1589 if ( $this->use_mysqli ) { |
1509 $this->dbh = mysqli_init(); |
1590 $this->dbh = mysqli_init(); |
1510 |
1591 |
1536 if ( $this->dbh->connect_errno ) { |
1617 if ( $this->dbh->connect_errno ) { |
1537 $this->dbh = null; |
1618 $this->dbh = null; |
1538 |
1619 |
1539 /* |
1620 /* |
1540 * It's possible ext/mysqli is misconfigured. Fall back to ext/mysql if: |
1621 * It's possible ext/mysqli is misconfigured. Fall back to ext/mysql if: |
1541 * - We haven't previously connected, and |
1622 * - We haven't previously connected, and |
1542 * - WP_USE_EXT_MYSQL isn't set to false, and |
1623 * - WP_USE_EXT_MYSQL isn't set to false, and |
1543 * - ext/mysql is loaded. |
1624 * - ext/mysql is loaded. |
1544 */ |
1625 */ |
1545 $attempt_fallback = true; |
1626 $attempt_fallback = true; |
1546 |
1627 |
1547 if ( $this->has_connected ) { |
1628 if ( $this->has_connected ) { |
1548 $attempt_fallback = false; |
1629 $attempt_fallback = false; |
1549 } elseif ( defined( 'WP_USE_EXT_MYSQL' ) && ! WP_USE_EXT_MYSQL ) { |
1630 } elseif ( defined( 'WP_USE_EXT_MYSQL' ) && ! WP_USE_EXT_MYSQL ) { |
1575 } |
1656 } |
1576 |
1657 |
1577 $message = '<h1>' . __( 'Error establishing a database connection' ) . "</h1>\n"; |
1658 $message = '<h1>' . __( 'Error establishing a database connection' ) . "</h1>\n"; |
1578 |
1659 |
1579 $message .= '<p>' . sprintf( |
1660 $message .= '<p>' . sprintf( |
1580 /* translators: 1: wp-config.php. 2: database host */ |
1661 /* translators: 1: wp-config.php, 2: database host */ |
1581 __( 'This either means that the username and password information in your %1$s file is incorrect or we can’t contact the database server at %2$s. This could mean your host’s database server is down.' ), |
1662 __( 'This either means that the username and password information in your %1$s file is incorrect or we can’t contact the database server at %2$s. This could mean your host’s database server is down.' ), |
1582 '<code>wp-config.php</code>', |
1663 '<code>wp-config.php</code>', |
1583 '<code>' . htmlspecialchars( $this->dbhost, ENT_QUOTES ) . '</code>' |
1664 '<code>' . htmlspecialchars( $this->dbhost, ENT_QUOTES ) . '</code>' |
1584 ) . "</p>\n"; |
1665 ) . "</p>\n"; |
1585 |
1666 |
1590 $message .= "</ul>\n"; |
1671 $message .= "</ul>\n"; |
1591 |
1672 |
1592 $message .= '<p>' . sprintf( |
1673 $message .= '<p>' . sprintf( |
1593 /* translators: %s: support forums URL */ |
1674 /* translators: %s: support forums URL */ |
1594 __( 'If you’re unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href="%s">WordPress Support Forums</a>.' ), |
1675 __( 'If you’re unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href="%s">WordPress Support Forums</a>.' ), |
1595 __( 'https://wordpress.org/support/' ) |
1676 __( 'https://wordpress.org/support/forums/' ) |
1596 ) . "</p>\n"; |
1677 ) . "</p>\n"; |
1597 |
1678 |
1598 $this->bail( $message, 'db_connect_fail' ); |
1679 $this->bail( $message, 'db_connect_fail' ); |
1599 |
1680 |
1600 return false; |
1681 return false; |
1638 |
1719 |
1639 // First peel off the socket parameter from the right, if it exists. |
1720 // First peel off the socket parameter from the right, if it exists. |
1640 $socket_pos = strpos( $host, ':/' ); |
1721 $socket_pos = strpos( $host, ':/' ); |
1641 if ( $socket_pos !== false ) { |
1722 if ( $socket_pos !== false ) { |
1642 $socket = substr( $host, $socket_pos + 1 ); |
1723 $socket = substr( $host, $socket_pos + 1 ); |
1643 $host = substr( $host, 0, $socket_pos ); |
1724 $host = substr( $host, 0, $socket_pos ); |
1644 } |
1725 } |
1645 |
1726 |
1646 // We need to check for an IPv6 address first. |
1727 // We need to check for an IPv6 address first. |
1647 // An IPv6 address will always contain at least two colons. |
1728 // An IPv6 address will always contain at least two colons. |
1648 if ( substr_count( $host, ':' ) > 1 ) { |
1729 if ( substr_count( $host, ':' ) > 1 ) { |
1748 $message .= "</ul>\n"; |
1829 $message .= "</ul>\n"; |
1749 |
1830 |
1750 $message .= '<p>' . sprintf( |
1831 $message .= '<p>' . sprintf( |
1751 /* translators: %s: support forums URL */ |
1832 /* translators: %s: support forums URL */ |
1752 __( 'If you’re unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href="%s">WordPress Support Forums</a>.' ), |
1833 __( 'If you’re unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href="%s">WordPress Support Forums</a>.' ), |
1753 __( 'https://wordpress.org/support/' ) |
1834 __( 'https://wordpress.org/support/forums/' ) |
1754 ) . "</p>\n"; |
1835 ) . "</p>\n"; |
1755 |
1836 |
1756 // We weren't able to reconnect, so we better bail. |
1837 // We weren't able to reconnect, so we better bail. |
1757 $this->bail( $message, 'db_connect_fail' ); |
1838 $this->bail( $message, 'db_connect_fail' ); |
1758 |
1839 |
1766 * More information can be found on the codex page. |
1847 * More information can be found on the codex page. |
1767 * |
1848 * |
1768 * @since 0.71 |
1849 * @since 0.71 |
1769 * |
1850 * |
1770 * @param string $query Database query |
1851 * @param string $query Database query |
1771 * @return int|false Number of rows affected/selected or false on error |
1852 * @return int|bool Boolean true for CREATE, ALTER, TRUNCATE and DROP queries. Number of rows |
|
1853 * affected/selected for all other queries. Boolean false on error. |
1772 */ |
1854 */ |
1773 public function query( $query ) { |
1855 public function query( $query ) { |
1774 if ( ! $this->ready ) { |
1856 if ( ! $this->ready ) { |
1775 $this->check_current_query = true; |
1857 $this->check_current_query = true; |
1776 return false; |
1858 return false; |
1885 $return_val = $this->rows_affected; |
1968 $return_val = $this->rows_affected; |
1886 } else { |
1969 } else { |
1887 $num_rows = 0; |
1970 $num_rows = 0; |
1888 if ( $this->use_mysqli && $this->result instanceof mysqli_result ) { |
1971 if ( $this->use_mysqli && $this->result instanceof mysqli_result ) { |
1889 while ( $row = mysqli_fetch_object( $this->result ) ) { |
1972 while ( $row = mysqli_fetch_object( $this->result ) ) { |
1890 $this->last_result[$num_rows] = $row; |
1973 $this->last_result[ $num_rows ] = $row; |
1891 $num_rows++; |
1974 $num_rows++; |
1892 } |
1975 } |
1893 } elseif ( is_resource( $this->result ) ) { |
1976 } elseif ( is_resource( $this->result ) ) { |
1894 while ( $row = mysql_fetch_object( $this->result ) ) { |
1977 while ( $row = mysql_fetch_object( $this->result ) ) { |
1895 $this->last_result[$num_rows] = $row; |
1978 $this->last_result[ $num_rows ] = $row; |
1896 $num_rows++; |
1979 $num_rows++; |
1897 } |
1980 } |
1898 } |
1981 } |
1899 |
1982 |
1900 // Log number of rows the query returned |
1983 // Log number of rows the query returned |
1926 $this->result = mysql_query( $query, $this->dbh ); |
2009 $this->result = mysql_query( $query, $this->dbh ); |
1927 } |
2010 } |
1928 $this->num_queries++; |
2011 $this->num_queries++; |
1929 |
2012 |
1930 if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) { |
2013 if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) { |
1931 $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() ); |
2014 $this->queries[] = array( |
|
2015 $query, |
|
2016 $this->timer_stop(), |
|
2017 $this->get_caller(), |
|
2018 $this->time_start, |
|
2019 ); |
1932 } |
2020 } |
1933 } |
2021 } |
1934 |
2022 |
1935 /** |
2023 /** |
1936 * Generates and returns a placeholder escape string for use in queries returned by ::prepare(). |
2024 * Generates and returns a placeholder escape string for use in queries returned by ::prepare(). |
1951 $placeholder = '{' . hash_hmac( $algo, uniqid( $salt, true ), $salt ) . '}'; |
2039 $placeholder = '{' . hash_hmac( $algo, uniqid( $salt, true ), $salt ) . '}'; |
1952 } |
2040 } |
1953 |
2041 |
1954 /* |
2042 /* |
1955 * Add the filter to remove the placeholder escaper. Uses priority 0, so that anything |
2043 * Add the filter to remove the placeholder escaper. Uses priority 0, so that anything |
1956 * else attached to this filter will recieve the query with the placeholder string removed. |
2044 * else attached to this filter will receive the query with the placeholder string removed. |
1957 */ |
2045 */ |
1958 if ( ! has_filter( 'query', array( $this, 'remove_placeholder_escape' ) ) ) { |
2046 if ( ! has_filter( 'query', array( $this, 'remove_placeholder_escape' ) ) ) { |
1959 add_filter( 'query', array( $this, 'remove_placeholder_escape' ), 0 ); |
2047 add_filter( 'query', array( $this, 'remove_placeholder_escape' ), 0 ); |
1960 } |
2048 } |
1961 |
2049 |
2152 $conditions[] = "`$field` IS NULL"; |
2240 $conditions[] = "`$field` IS NULL"; |
2153 continue; |
2241 continue; |
2154 } |
2242 } |
2155 |
2243 |
2156 $conditions[] = "`$field` = " . $value['format']; |
2244 $conditions[] = "`$field` = " . $value['format']; |
2157 $values[] = $value['value']; |
2245 $values[] = $value['value']; |
2158 } |
2246 } |
2159 |
2247 |
2160 $fields = implode( ', ', $fields ); |
2248 $fields = implode( ', ', $fields ); |
2161 $conditions = implode( ' AND ', $conditions ); |
2249 $conditions = implode( ' AND ', $conditions ); |
2162 |
2250 |
2163 $sql = "UPDATE `$table` SET $fields WHERE $conditions"; |
2251 $sql = "UPDATE `$table` SET $fields WHERE $conditions"; |
2164 |
2252 |
2165 $this->check_current_query = false; |
2253 $this->check_current_query = false; |
2379 if ( $query ) { |
2467 if ( $query ) { |
2380 $this->query( $query ); |
2468 $this->query( $query ); |
2381 } |
2469 } |
2382 |
2470 |
2383 // Extract var out of cached results based x,y vals |
2471 // Extract var out of cached results based x,y vals |
2384 if ( !empty( $this->last_result[$y] ) ) { |
2472 if ( ! empty( $this->last_result[ $y ] ) ) { |
2385 $values = array_values( get_object_vars( $this->last_result[$y] ) ); |
2473 $values = array_values( get_object_vars( $this->last_result[ $y ] ) ); |
2386 } |
2474 } |
2387 |
2475 |
2388 // If there is a value return it else return null |
2476 // If there is a value return it else return null |
2389 return ( isset( $values[$x] ) && $values[$x] !== '' ) ? $values[$x] : null; |
2477 return ( isset( $values[ $x ] ) && $values[ $x ] !== '' ) ? $values[ $x ] : null; |
2390 } |
2478 } |
2391 |
2479 |
2392 /** |
2480 /** |
2393 * Retrieve one row from the database. |
2481 * Retrieve one row from the database. |
2394 * |
2482 * |
2413 $this->query( $query ); |
2501 $this->query( $query ); |
2414 } else { |
2502 } else { |
2415 return null; |
2503 return null; |
2416 } |
2504 } |
2417 |
2505 |
2418 if ( !isset( $this->last_result[$y] ) ) |
2506 if ( ! isset( $this->last_result[ $y ] ) ) { |
2419 return null; |
2507 return null; |
|
2508 } |
2420 |
2509 |
2421 if ( $output == OBJECT ) { |
2510 if ( $output == OBJECT ) { |
2422 return $this->last_result[$y] ? $this->last_result[$y] : null; |
2511 return $this->last_result[ $y ] ? $this->last_result[ $y ] : null; |
2423 } elseif ( $output == ARRAY_A ) { |
2512 } elseif ( $output == ARRAY_A ) { |
2424 return $this->last_result[$y] ? get_object_vars( $this->last_result[$y] ) : null; |
2513 return $this->last_result[ $y ] ? get_object_vars( $this->last_result[ $y ] ) : null; |
2425 } elseif ( $output == ARRAY_N ) { |
2514 } elseif ( $output == ARRAY_N ) { |
2426 return $this->last_result[$y] ? array_values( get_object_vars( $this->last_result[$y] ) ) : null; |
2515 return $this->last_result[ $y ] ? array_values( get_object_vars( $this->last_result[ $y ] ) ) : null; |
2427 } elseif ( strtoupper( $output ) === OBJECT ) { |
2516 } elseif ( strtoupper( $output ) === OBJECT ) { |
2428 // Back compat for OBJECT being previously case insensitive. |
2517 // Back compat for OBJECT being previously case insensitive. |
2429 return $this->last_result[$y] ? $this->last_result[$y] : null; |
2518 return $this->last_result[ $y ] ? $this->last_result[ $y ] : null; |
2430 } else { |
2519 } else { |
2431 $this->print_error( " \$db->get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N" ); |
2520 $this->print_error( ' $db->get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N' ); |
2432 } |
2521 } |
2433 } |
2522 } |
2434 |
2523 |
2435 /** |
2524 /** |
2436 * Retrieve one column from the database. |
2525 * Retrieve one column from the database. |
2443 * |
2532 * |
2444 * @param string|null $query Optional. SQL query. Defaults to previous query. |
2533 * @param string|null $query Optional. SQL query. Defaults to previous query. |
2445 * @param int $x Optional. Column to return. Indexed from 0. |
2534 * @param int $x Optional. Column to return. Indexed from 0. |
2446 * @return array Database query result. Array indexed from 0 by SQL result row number. |
2535 * @return array Database query result. Array indexed from 0 by SQL result row number. |
2447 */ |
2536 */ |
2448 public function get_col( $query = null , $x = 0 ) { |
2537 public function get_col( $query = null, $x = 0 ) { |
2449 if ( $this->check_current_query && $this->check_safe_collation( $query ) ) { |
2538 if ( $this->check_current_query && $this->check_safe_collation( $query ) ) { |
2450 $this->check_current_query = false; |
2539 $this->check_current_query = false; |
2451 } |
2540 } |
2452 |
2541 |
2453 if ( $query ) { |
2542 if ( $query ) { |
2454 $this->query( $query ); |
2543 $this->query( $query ); |
2455 } |
2544 } |
2456 |
2545 |
2457 $new_array = array(); |
2546 $new_array = array(); |
2458 // Extract the column values |
2547 // Extract the column values |
2459 for ( $i = 0, $j = count( $this->last_result ); $i < $j; $i++ ) { |
2548 if ( $this->last_result ) { |
2460 $new_array[$i] = $this->get_var( null, $x, $i ); |
2549 for ( $i = 0, $j = count( $this->last_result ); $i < $j; $i++ ) { |
|
2550 $new_array[ $i ] = $this->get_var( null, $x, $i ); |
|
2551 } |
2461 } |
2552 } |
2462 return $new_array; |
2553 return $new_array; |
2463 } |
2554 } |
2464 |
2555 |
2465 /** |
2556 /** |
2495 // Return an integer-keyed array of row objects |
2586 // Return an integer-keyed array of row objects |
2496 return $this->last_result; |
2587 return $this->last_result; |
2497 } elseif ( $output == OBJECT_K ) { |
2588 } elseif ( $output == OBJECT_K ) { |
2498 // Return an array of row objects with keys from column 1 |
2589 // Return an array of row objects with keys from column 1 |
2499 // (Duplicates are discarded) |
2590 // (Duplicates are discarded) |
2500 foreach ( $this->last_result as $row ) { |
2591 if ( $this->last_result ) { |
2501 $var_by_ref = get_object_vars( $row ); |
2592 foreach ( $this->last_result as $row ) { |
2502 $key = array_shift( $var_by_ref ); |
2593 $var_by_ref = get_object_vars( $row ); |
2503 if ( ! isset( $new_array[ $key ] ) ) |
2594 $key = array_shift( $var_by_ref ); |
2504 $new_array[ $key ] = $row; |
2595 if ( ! isset( $new_array[ $key ] ) ) { |
|
2596 $new_array[ $key ] = $row; |
|
2597 } |
|
2598 } |
2505 } |
2599 } |
2506 return $new_array; |
2600 return $new_array; |
2507 } elseif ( $output == ARRAY_A || $output == ARRAY_N ) { |
2601 } elseif ( $output == ARRAY_A || $output == ARRAY_N ) { |
2508 // Return an integer-keyed array of... |
2602 // Return an integer-keyed array of... |
2509 if ( $this->last_result ) { |
2603 if ( $this->last_result ) { |
2557 } |
2651 } |
2558 |
2652 |
2559 $charsets = $columns = array(); |
2653 $charsets = $columns = array(); |
2560 |
2654 |
2561 $table_parts = explode( '.', $table ); |
2655 $table_parts = explode( '.', $table ); |
2562 $table = '`' . implode( '`.`', $table_parts ) . '`'; |
2656 $table = '`' . implode( '`.`', $table_parts ) . '`'; |
2563 $results = $this->get_results( "SHOW FULL COLUMNS FROM $table" ); |
2657 $results = $this->get_results( "SHOW FULL COLUMNS FROM $table" ); |
2564 if ( ! $results ) { |
2658 if ( ! $results ) { |
2565 return new WP_Error( 'wpdb_get_table_charset_failure' ); |
2659 return new WP_Error( 'wpdb_get_table_charset_failure' ); |
2566 } |
2660 } |
2567 |
2661 |
2568 foreach ( $results as $column ) { |
2662 foreach ( $results as $column ) { |
2634 * @param string $column Column name. |
2728 * @param string $column Column name. |
2635 * @return string|false|WP_Error Column character set as a string. False if the column has no |
2729 * @return string|false|WP_Error Column character set as a string. False if the column has no |
2636 * character set. WP_Error object if there was an error. |
2730 * character set. WP_Error object if there was an error. |
2637 */ |
2731 */ |
2638 public function get_col_charset( $table, $column ) { |
2732 public function get_col_charset( $table, $column ) { |
2639 $tablekey = strtolower( $table ); |
2733 $tablekey = strtolower( $table ); |
2640 $columnkey = strtolower( $column ); |
2734 $columnkey = strtolower( $column ); |
2641 |
2735 |
2642 /** |
2736 /** |
2643 * Filters the column charset value before the DB is checked. |
2737 * Filters the column charset value before the DB is checked. |
2644 * |
2738 * |
2699 * @return array|false|WP_Error array( 'length' => (int), 'type' => 'byte' | 'char' ) |
2793 * @return array|false|WP_Error array( 'length' => (int), 'type' => 'byte' | 'char' ) |
2700 * false if the column has no length (for example, numeric column) |
2794 * false if the column has no length (for example, numeric column) |
2701 * WP_Error object if there was an error. |
2795 * WP_Error object if there was an error. |
2702 */ |
2796 */ |
2703 public function get_col_length( $table, $column ) { |
2797 public function get_col_length( $table, $column ) { |
2704 $tablekey = strtolower( $table ); |
2798 $tablekey = strtolower( $table ); |
2705 $columnkey = strtolower( $column ); |
2799 $columnkey = strtolower( $column ); |
2706 |
2800 |
2707 // Skip this entirely if this isn't a MySQL database. |
2801 // Skip this entirely if this isn't a MySQL database. |
2708 if ( empty( $this->is_mysql ) ) { |
2802 if ( empty( $this->is_mysql ) ) { |
2709 return false; |
2803 return false; |
2876 |
2970 |
2877 foreach ( $data as &$value ) { |
2971 foreach ( $data as &$value ) { |
2878 $charset = $value['charset']; |
2972 $charset = $value['charset']; |
2879 |
2973 |
2880 if ( is_array( $value['length'] ) ) { |
2974 if ( is_array( $value['length'] ) ) { |
2881 $length = $value['length']['length']; |
2975 $length = $value['length']['length']; |
2882 $truncate_by_byte_length = 'byte' === $value['length']['type']; |
2976 $truncate_by_byte_length = 'byte' === $value['length']['type']; |
2883 } else { |
2977 } else { |
2884 $length = false; |
2978 $length = false; |
2885 // Since we have no length, we'll never truncate. |
2979 // Since we have no length, we'll never truncate. |
2886 // Initialize the variable to false. true would take us |
2980 // Initialize the variable to false. true would take us |
2905 || |
2999 || |
2906 // ASCII is always OK. |
3000 // ASCII is always OK. |
2907 ( ! isset( $value['ascii'] ) && $this->check_ascii( $value['value'] ) ) |
3001 ( ! isset( $value['ascii'] ) && $this->check_ascii( $value['value'] ) ) |
2908 ) { |
3002 ) { |
2909 $truncate_by_byte_length = true; |
3003 $truncate_by_byte_length = true; |
2910 $needs_validation = false; |
3004 $needs_validation = false; |
2911 } |
3005 } |
2912 |
3006 |
2913 if ( $truncate_by_byte_length ) { |
3007 if ( $truncate_by_byte_length ) { |
2914 mbstring_binary_safe_encoding(); |
3008 mbstring_binary_safe_encoding(); |
2915 if ( false !== $length && strlen( $value['value'] ) > $length ) { |
3009 if ( false !== $length && strlen( $value['value'] ) > $length ) { |
2939 | [\xF1-\xF3][\x80-\xBF]{3} |
3033 | [\xF1-\xF3][\x80-\xBF]{3} |
2940 | \xF4[\x80-\x8F][\x80-\xBF]{2} |
3034 | \xF4[\x80-\x8F][\x80-\xBF]{2} |
2941 '; |
3035 '; |
2942 } |
3036 } |
2943 |
3037 |
2944 $regex .= '){1,40} # ...one or more times |
3038 $regex .= '){1,40} # ...one or more times |
2945 ) |
3039 ) |
2946 | . # anything else |
3040 | . # anything else |
2947 /x'; |
3041 /x'; |
2948 $value['value'] = preg_replace( $regex, '$1', $value['value'] ); |
3042 $value['value'] = preg_replace( $regex, '$1', $value['value'] ); |
2949 |
|
2950 |
3043 |
2951 if ( false !== $length && mb_strlen( $value['value'], 'UTF-8' ) > $length ) { |
3044 if ( false !== $length && mb_strlen( $value['value'], 'UTF-8' ) > $length ) { |
2952 $value['value'] = mb_substr( $value['value'], 0, $length, 'UTF-8' ); |
3045 $value['value'] = mb_substr( $value['value'], 0, $length, 'UTF-8' ); |
2953 } |
3046 } |
2954 continue; |
3047 continue; |
2980 $connection_charset = mysql_client_encoding(); |
3073 $connection_charset = mysql_client_encoding(); |
2981 } |
3074 } |
2982 } |
3075 } |
2983 |
3076 |
2984 if ( is_array( $value['length'] ) ) { |
3077 if ( is_array( $value['length'] ) ) { |
2985 $length = sprintf( '%.0f', $value['length']['length'] ); |
3078 $length = sprintf( '%.0f', $value['length']['length'] ); |
2986 $queries[ $col ] = $this->prepare( "CONVERT( LEFT( CONVERT( %s USING $charset ), $length ) USING $connection_charset )", $value['value'] ); |
3079 $queries[ $col ] = $this->prepare( "CONVERT( LEFT( CONVERT( %s USING $charset ), $length ) USING $connection_charset )", $value['value'] ); |
2987 } else if ( 'binary' !== $charset ) { |
3080 } elseif ( 'binary' !== $charset ) { |
2988 // If we don't have a length, there's no need to convert binary - it will always return the same result. |
3081 // If we don't have a length, there's no need to convert binary - it will always return the same result. |
2989 $queries[ $col ] = $this->prepare( "CONVERT( CONVERT( %s USING $charset ) USING $connection_charset )", $value['value'] ); |
3082 $queries[ $col ] = $this->prepare( "CONVERT( CONVERT( %s USING $charset ) USING $connection_charset )", $value['value'] ); |
2990 } |
3083 } |
2991 |
3084 |
2992 unset( $data[ $col ]['db'] ); |
3085 unset( $data[ $col ]['db'] ); |
3001 |
3094 |
3002 $sql[] = $query . " AS x_$column"; |
3095 $sql[] = $query . " AS x_$column"; |
3003 } |
3096 } |
3004 |
3097 |
3005 $this->check_current_query = false; |
3098 $this->check_current_query = false; |
3006 $row = $this->get_row( "SELECT " . implode( ', ', $sql ), ARRAY_A ); |
3099 $row = $this->get_row( 'SELECT ' . implode( ', ', $sql ), ARRAY_A ); |
3007 if ( ! $row ) { |
3100 if ( ! $row ) { |
3008 return new WP_Error( 'wpdb_strip_invalid_text_failure' ); |
3101 return new WP_Error( 'wpdb_strip_invalid_text_failure' ); |
3009 } |
3102 } |
3010 |
3103 |
3011 foreach ( array_keys( $data ) as $column ) { |
3104 foreach ( array_keys( $data ) as $column ) { |
3012 if ( isset( $row["x_$column"] ) ) { |
3105 if ( isset( $row[ "x_$column" ] ) ) { |
3013 $data[ $column ]['value'] = $row["x_$column"]; |
3106 $data[ $column ]['value'] = $row[ "x_$column" ]; |
3014 } |
3107 } |
3015 } |
3108 } |
3016 } |
3109 } |
3017 |
3110 |
3018 return $data; |
3111 return $data; |
3120 |
3213 |
3121 // Strip everything between parentheses except nested selects. |
3214 // Strip everything between parentheses except nested selects. |
3122 $query = preg_replace( '/\((?!\s*select)[^(]*?\)/is', '()', $query ); |
3215 $query = preg_replace( '/\((?!\s*select)[^(]*?\)/is', '()', $query ); |
3123 |
3216 |
3124 // Quickly match most common queries. |
3217 // Quickly match most common queries. |
3125 if ( preg_match( '/^\s*(?:' |
3218 if ( preg_match( |
|
3219 '/^\s*(?:' |
3126 . 'SELECT.*?\s+FROM' |
3220 . 'SELECT.*?\s+FROM' |
3127 . '|INSERT(?:\s+LOW_PRIORITY|\s+DELAYED|\s+HIGH_PRIORITY)?(?:\s+IGNORE)?(?:\s+INTO)?' |
3221 . '|INSERT(?:\s+LOW_PRIORITY|\s+DELAYED|\s+HIGH_PRIORITY)?(?:\s+IGNORE)?(?:\s+INTO)?' |
3128 . '|REPLACE(?:\s+LOW_PRIORITY|\s+DELAYED)?(?:\s+INTO)?' |
3222 . '|REPLACE(?:\s+LOW_PRIORITY|\s+DELAYED)?(?:\s+INTO)?' |
3129 . '|UPDATE(?:\s+LOW_PRIORITY)?(?:\s+IGNORE)?' |
3223 . '|UPDATE(?:\s+LOW_PRIORITY)?(?:\s+IGNORE)?' |
3130 . '|DELETE(?:\s+LOW_PRIORITY|\s+QUICK|\s+IGNORE)*(?:.+?FROM)?' |
3224 . '|DELETE(?:\s+LOW_PRIORITY|\s+QUICK|\s+IGNORE)*(?:.+?FROM)?' |
3131 . ')\s+((?:[0-9a-zA-Z$_.`-]|[\xC2-\xDF][\x80-\xBF])+)/is', $query, $maybe ) ) { |
3225 . ')\s+((?:[0-9a-zA-Z$_.`-]|[\xC2-\xDF][\x80-\xBF])+)/is', |
|
3226 $query, |
|
3227 $maybe |
|
3228 ) ) { |
3132 return str_replace( '`', '', $maybe[1] ); |
3229 return str_replace( '`', '', $maybe[1] ); |
3133 } |
3230 } |
3134 |
3231 |
3135 // SHOW TABLE STATUS and SHOW TABLES WHERE Name = 'wp_posts' |
3232 // SHOW TABLE STATUS and SHOW TABLES WHERE Name = 'wp_posts' |
3136 if ( preg_match( '/^\s*SHOW\s+(?:TABLE\s+STATUS|(?:FULL\s+)?TABLES).+WHERE\s+Name\s*=\s*("|\')((?:[0-9a-zA-Z$_.-]|[\xC2-\xDF][\x80-\xBF])+)\\1/is', $query, $maybe ) ) { |
3233 if ( preg_match( '/^\s*SHOW\s+(?:TABLE\s+STATUS|(?:FULL\s+)?TABLES).+WHERE\s+Name\s*=\s*("|\')((?:[0-9a-zA-Z$_.-]|[\xC2-\xDF][\x80-\xBF])+)\\1/is', $query, $maybe ) ) { |
3145 if ( preg_match( '/^\s*SHOW\s+(?:TABLE\s+STATUS|(?:FULL\s+)?TABLES)\s+(?:WHERE\s+Name\s+)?LIKE\s*("|\')((?:[\\\\0-9a-zA-Z$_.-]|[\xC2-\xDF][\x80-\xBF])+)%?\\1/is', $query, $maybe ) ) { |
3242 if ( preg_match( '/^\s*SHOW\s+(?:TABLE\s+STATUS|(?:FULL\s+)?TABLES)\s+(?:WHERE\s+Name\s+)?LIKE\s*("|\')((?:[\\\\0-9a-zA-Z$_.-]|[\xC2-\xDF][\x80-\xBF])+)%?\\1/is', $query, $maybe ) ) { |
3146 return str_replace( '\\_', '_', $maybe[2] ); |
3243 return str_replace( '\\_', '_', $maybe[2] ); |
3147 } |
3244 } |
3148 |
3245 |
3149 // Big pattern for the rest of the table-related queries. |
3246 // Big pattern for the rest of the table-related queries. |
3150 if ( preg_match( '/^\s*(?:' |
3247 if ( preg_match( |
|
3248 '/^\s*(?:' |
3151 . '(?:EXPLAIN\s+(?:EXTENDED\s+)?)?SELECT.*?\s+FROM' |
3249 . '(?:EXPLAIN\s+(?:EXTENDED\s+)?)?SELECT.*?\s+FROM' |
3152 . '|DESCRIBE|DESC|EXPLAIN|HANDLER' |
3250 . '|DESCRIBE|DESC|EXPLAIN|HANDLER' |
3153 . '|(?:LOCK|UNLOCK)\s+TABLE(?:S)?' |
3251 . '|(?:LOCK|UNLOCK)\s+TABLE(?:S)?' |
3154 . '|(?:RENAME|OPTIMIZE|BACKUP|RESTORE|CHECK|CHECKSUM|ANALYZE|REPAIR).*\s+TABLE' |
3252 . '|(?:RENAME|OPTIMIZE|BACKUP|RESTORE|CHECK|CHECKSUM|ANALYZE|REPAIR).*\s+TABLE' |
3155 . '|TRUNCATE(?:\s+TABLE)?' |
3253 . '|TRUNCATE(?:\s+TABLE)?' |
3159 . '|CREATE(?:\s+\w+)?\s+INDEX.*\s+ON' |
3257 . '|CREATE(?:\s+\w+)?\s+INDEX.*\s+ON' |
3160 . '|DROP\s+INDEX.*\s+ON' |
3258 . '|DROP\s+INDEX.*\s+ON' |
3161 . '|LOAD\s+DATA.*INFILE.*INTO\s+TABLE' |
3259 . '|LOAD\s+DATA.*INFILE.*INTO\s+TABLE' |
3162 . '|(?:GRANT|REVOKE).*ON\s+TABLE' |
3260 . '|(?:GRANT|REVOKE).*ON\s+TABLE' |
3163 . '|SHOW\s+(?:.*FROM|.*TABLE)' |
3261 . '|SHOW\s+(?:.*FROM|.*TABLE)' |
3164 . ')\s+\(*\s*((?:[0-9a-zA-Z$_.`-]|[\xC2-\xDF][\x80-\xBF])+)\s*\)*/is', $query, $maybe ) ) { |
3262 . ')\s+\(*\s*((?:[0-9a-zA-Z$_.`-]|[\xC2-\xDF][\x80-\xBF])+)\s*\)*/is', |
|
3263 $query, |
|
3264 $maybe |
|
3265 ) ) { |
3165 return str_replace( '`', '', $maybe[1] ); |
3266 return str_replace( '`', '', $maybe[1] ); |
3166 } |
3267 } |
3167 |
3268 |
3168 return false; |
3269 return false; |
3169 } |
3270 } |
3170 |
3271 |
3171 /** |
3272 /** |
3172 * Load the column metadata from the last query. |
3273 * Load the column metadata from the last query. |
3173 * |
3274 * |
3174 * @since 3.5.0 |
3275 * @since 3.5.0 |
3175 * |
|
3176 */ |
3276 */ |
3177 protected function load_col_info() { |
3277 protected function load_col_info() { |
3178 if ( $this->col_info ) |
3278 if ( $this->col_info ) { |
3179 return; |
3279 return; |
|
3280 } |
3180 |
3281 |
3181 if ( $this->use_mysqli ) { |
3282 if ( $this->use_mysqli ) { |
3182 $num_fields = mysqli_num_fields( $this->result ); |
3283 $num_fields = mysqli_num_fields( $this->result ); |
3183 for ( $i = 0; $i < $num_fields; $i++ ) { |
3284 for ( $i = 0; $i < $num_fields; $i++ ) { |
3184 $this->col_info[ $i ] = mysqli_fetch_field( $this->result ); |
3285 $this->col_info[ $i ] = mysqli_fetch_field( $this->result ); |
3203 public function get_col_info( $info_type = 'name', $col_offset = -1 ) { |
3304 public function get_col_info( $info_type = 'name', $col_offset = -1 ) { |
3204 $this->load_col_info(); |
3305 $this->load_col_info(); |
3205 |
3306 |
3206 if ( $this->col_info ) { |
3307 if ( $this->col_info ) { |
3207 if ( $col_offset == -1 ) { |
3308 if ( $col_offset == -1 ) { |
3208 $i = 0; |
3309 $i = 0; |
3209 $new_array = array(); |
3310 $new_array = array(); |
3210 foreach ( (array) $this->col_info as $col ) { |
3311 foreach ( (array) $this->col_info as $col ) { |
3211 $new_array[$i] = $col->{$info_type}; |
3312 $new_array[ $i ] = $col->{$info_type}; |
3212 $i++; |
3313 $i++; |
3213 } |
3314 } |
3214 return $new_array; |
3315 return $new_array; |
3215 } else { |
3316 } else { |
3216 return $this->col_info[$col_offset]->{$info_type}; |
3317 return $this->col_info[ $col_offset ]->{$info_type}; |
3217 } |
3318 } |
3218 } |
3319 } |
3219 } |
3320 } |
3220 |
3321 |
3221 /** |
3322 /** |
3251 * @param string $message The Error message |
3352 * @param string $message The Error message |
3252 * @param string $error_code Optional. A Computer readable string to identify the error. |
3353 * @param string $error_code Optional. A Computer readable string to identify the error. |
3253 * @return false|void |
3354 * @return false|void |
3254 */ |
3355 */ |
3255 public function bail( $message, $error_code = '500' ) { |
3356 public function bail( $message, $error_code = '500' ) { |
3256 if ( !$this->show_errors ) { |
3357 if ( $this->show_errors ) { |
|
3358 $error = ''; |
|
3359 |
|
3360 if ( $this->use_mysqli ) { |
|
3361 if ( $this->dbh instanceof mysqli ) { |
|
3362 $error = mysqli_error( $this->dbh ); |
|
3363 } elseif ( mysqli_connect_errno() ) { |
|
3364 $error = mysqli_connect_error(); |
|
3365 } |
|
3366 } else { |
|
3367 if ( is_resource( $this->dbh ) ) { |
|
3368 $error = mysql_error( $this->dbh ); |
|
3369 } else { |
|
3370 $error = mysql_error(); |
|
3371 } |
|
3372 } |
|
3373 |
|
3374 if ( $error ) { |
|
3375 $message = '<p><code>' . $error . "</code></p>\n" . $message; |
|
3376 } |
|
3377 |
|
3378 wp_die( $message ); |
|
3379 } else { |
3257 if ( class_exists( 'WP_Error', false ) ) { |
3380 if ( class_exists( 'WP_Error', false ) ) { |
3258 $this->error = new WP_Error($error_code, $message); |
3381 $this->error = new WP_Error( $error_code, $message ); |
3259 } else { |
3382 } else { |
3260 $this->error = $message; |
3383 $this->error = $message; |
3261 } |
3384 } |
|
3385 |
3262 return false; |
3386 return false; |
3263 } |
3387 } |
3264 wp_die($message); |
|
3265 } |
3388 } |
3266 |
3389 |
3267 |
3390 |
3268 /** |
3391 /** |
3269 * Closes the current database connection. |
3392 * Closes the current database connection. |
3304 * @return WP_Error|void |
3427 * @return WP_Error|void |
3305 */ |
3428 */ |
3306 public function check_database_version() { |
3429 public function check_database_version() { |
3307 global $wp_version, $required_mysql_version; |
3430 global $wp_version, $required_mysql_version; |
3308 // Make sure the server has the required MySQL version |
3431 // Make sure the server has the required MySQL version |
3309 if ( version_compare($this->db_version(), $required_mysql_version, '<') ) { |
3432 if ( version_compare( $this->db_version(), $required_mysql_version, '<' ) ) { |
3310 /* translators: 1: WordPress version number, 2: Minimum required MySQL version number */ |
3433 /* translators: 1: WordPress version number, 2: Minimum required MySQL version number */ |
3311 return new WP_Error('database_version', sprintf( __( '<strong>ERROR</strong>: WordPress %1$s requires MySQL %2$s or higher' ), $wp_version, $required_mysql_version )); |
3434 return new WP_Error( 'database_version', sprintf( __( '<strong>ERROR</strong>: WordPress %1$s requires MySQL %2$s or higher' ), $wp_version, $required_mysql_version ) ); |
3312 } |
3435 } |
3313 } |
3436 } |
3314 |
3437 |
3315 /** |
3438 /** |
3316 * Whether the database supports collation. |
3439 * Whether the database supports collation. |
3337 * @return string The database character collate. |
3460 * @return string The database character collate. |
3338 */ |
3461 */ |
3339 public function get_charset_collate() { |
3462 public function get_charset_collate() { |
3340 $charset_collate = ''; |
3463 $charset_collate = ''; |
3341 |
3464 |
3342 if ( ! empty( $this->charset ) ) |
3465 if ( ! empty( $this->charset ) ) { |
3343 $charset_collate = "DEFAULT CHARACTER SET $this->charset"; |
3466 $charset_collate = "DEFAULT CHARACTER SET $this->charset"; |
3344 if ( ! empty( $this->collate ) ) |
3467 } |
|
3468 if ( ! empty( $this->collate ) ) { |
3345 $charset_collate .= " COLLATE $this->collate"; |
3469 $charset_collate .= " COLLATE $this->collate"; |
|
3470 } |
3346 |
3471 |
3347 return $charset_collate; |
3472 return $charset_collate; |
3348 } |
3473 } |
3349 |
3474 |
3350 /** |
3475 /** |
3363 */ |
3488 */ |
3364 public function has_cap( $db_cap ) { |
3489 public function has_cap( $db_cap ) { |
3365 $version = $this->db_version(); |
3490 $version = $this->db_version(); |
3366 |
3491 |
3367 switch ( strtolower( $db_cap ) ) { |
3492 switch ( strtolower( $db_cap ) ) { |
3368 case 'collation' : // @since 2.5.0 |
3493 case 'collation': // @since 2.5.0 |
3369 case 'group_concat' : // @since 2.7.0 |
3494 case 'group_concat': // @since 2.7.0 |
3370 case 'subqueries' : // @since 2.7.0 |
3495 case 'subqueries': // @since 2.7.0 |
3371 return version_compare( $version, '4.1', '>=' ); |
3496 return version_compare( $version, '4.1', '>=' ); |
3372 case 'set_charset' : |
3497 case 'set_charset': |
3373 return version_compare( $version, '5.0.7', '>=' ); |
3498 return version_compare( $version, '5.0.7', '>=' ); |
3374 case 'utf8mb4' : // @since 4.1.0 |
3499 case 'utf8mb4': // @since 4.1.0 |
3375 if ( version_compare( $version, '5.5.3', '<' ) ) { |
3500 if ( version_compare( $version, '5.5.3', '<' ) ) { |
3376 return false; |
3501 return false; |
3377 } |
3502 } |
3378 if ( $this->use_mysqli ) { |
3503 if ( $this->use_mysqli ) { |
3379 $client_version = mysqli_get_client_info(); |
3504 $client_version = mysqli_get_client_info(); |
3389 $client_version = preg_replace( '/^\D+([\d.]+).*/', '$1', $client_version ); |
3514 $client_version = preg_replace( '/^\D+([\d.]+).*/', '$1', $client_version ); |
3390 return version_compare( $client_version, '5.0.9', '>=' ); |
3515 return version_compare( $client_version, '5.0.9', '>=' ); |
3391 } else { |
3516 } else { |
3392 return version_compare( $client_version, '5.5.3', '>=' ); |
3517 return version_compare( $client_version, '5.5.3', '>=' ); |
3393 } |
3518 } |
3394 case 'utf8mb4_520' : // @since 4.6.0 |
3519 case 'utf8mb4_520': // @since 4.6.0 |
3395 return version_compare( $version, '5.6', '>=' ); |
3520 return version_compare( $version, '5.6', '>=' ); |
3396 } |
3521 } |
3397 |
3522 |
3398 return false; |
3523 return false; |
3399 } |
3524 } |