From 3b6300ec350c3fa60bdae03c32bc8d5c4b9cb7f9 Mon Sep 17 00:00:00 2001 From: Michael Lee <38788055+jeawhanlee@users.noreply.github.com> Date: Fri, 26 May 2023 07:13:16 +0100 Subject: [PATCH] Fixes #5801: PHP Deprecated notice (#5908) * Updated BerlinDB * Updated berlinDB --------- Co-authored-by: Vasilis Manthos --- inc/Dependencies/Database/Base.php | 13 +- inc/Dependencies/Database/Column.php | 58 ++--- inc/Dependencies/Database/Queries/Compare.php | 85 ++++--- inc/Dependencies/Database/Queries/Date.php | 4 +- inc/Dependencies/Database/Queries/Meta.php | 4 +- inc/Dependencies/Database/Query.php | 240 ++++++++++++------ inc/Dependencies/Database/Row.php | 4 +- inc/Dependencies/Database/Schema.php | 4 +- inc/Dependencies/Database/Table.php | 82 +++++- 9 files changed, 327 insertions(+), 167 deletions(-) diff --git a/inc/Dependencies/Database/Base.php b/inc/Dependencies/Database/Base.php index 8617f3d2af..20fcdb52d9 100644 --- a/inc/Dependencies/Database/Base.php +++ b/inc/Dependencies/Database/Base.php @@ -4,8 +4,8 @@ * * @package Database * @subpackage Base - * @copyright Copyright (c) 2020 - * @license https://opensource.org/licenses/gpl-2.0.php GNU Public License + * @copyright Copyright (c) 2021 + * @license https://opensource.org/licenses/MIT MIT * @since 1.0.0 */ namespace WP_Rocket\Dependencies\Database; @@ -22,6 +22,7 @@ * * @since 1.0.0 */ +#[\AllowDynamicProperties] class Base { /** @@ -177,8 +178,14 @@ protected function first_letters( $string = '', $sep = '_' ) { // Trim spaces off the ends $unspace = trim( $string ); + + // Only non-accented table names (avoid truncation) $accents = remove_accents( $unspace ); + + // Only lowercase letters are allowed $lower = strtolower( $accents ); + + // Explode into parts $parts = explode( $sep, $lower ); // Loop through parts and concatenate the first letters together @@ -290,7 +297,7 @@ protected function get_db() { * Developer note: * * It should be impossible for a database table to be interacted with - * before the primary database interface it is setup. + * before the primary database interface is setup. * * However, because applications are complicated, it is unsafe to assume * anything, so this silently returns false instead of halting everything. diff --git a/inc/Dependencies/Database/Column.php b/inc/Dependencies/Database/Column.php index 948d06ed06..97cedaa055 100644 --- a/inc/Dependencies/Database/Column.php +++ b/inc/Dependencies/Database/Column.php @@ -4,8 +4,8 @@ * * @package Database * @subpackage Column - * @copyright Copyright (c) 2020 - * @license https://opensource.org/licenses/gpl-2.0.php GNU Public License + * @copyright Copyright (c) 2021 + * @license https://opensource.org/licenses/MIT MIT * @since 1.0.0 */ namespace WP_Rocket\Dependencies\Database; @@ -433,39 +433,39 @@ private function parse_args( $args = array() ) { $r = wp_parse_args( $args, array( // Table - 'name' => '', - 'type' => '', - 'length' => '', - 'unsigned' => false, - 'zerofill' => false, - 'binary' => false, - 'allow_null' => false, - 'default' => '', - 'extra' => '', - 'encoding' => $this->get_db()->charset, - 'collation' => $this->get_db()->collate, - 'comment' => '', + 'name' => '', + 'type' => '', + 'length' => '', + 'unsigned' => false, + 'zerofill' => false, + 'binary' => false, + 'allow_null' => false, + 'default' => '', + 'extra' => '', + 'encoding' => $this->get_db()->charset, + 'collation' => $this->get_db()->collate, + 'comment' => '', // Query - 'pattern' => false, - 'searchable' => false, - 'sortable' => false, - 'date_query' => false, - 'transition' => false, - 'in' => true, - 'not_in' => true, + 'pattern' => false, + 'searchable' => false, + 'sortable' => false, + 'date_query' => false, + 'transition' => false, + 'in' => true, + 'not_in' => true, // Special - 'primary' => false, - 'created' => false, - 'modified' => false, - 'uuid' => false, + 'primary' => false, + 'created' => false, + 'modified' => false, + 'uuid' => false, // Cache - 'cache_key' => false, + 'cache_key' => false, // Validation - 'validate' => '', + 'validate' => '', // Capabilities 'caps' => array(), @@ -692,10 +692,10 @@ private function sanitize_default( $default = '' ) { * Sanitize the pattern * * @since 1.0.0 - * @param mixed $pattern + * @param string $pattern * @return string */ - private function sanitize_pattern( $pattern = false ) { + private function sanitize_pattern( $pattern = '%s' ) { // Allowed patterns $allowed_patterns = array( '%s', '%d', '%f' ); diff --git a/inc/Dependencies/Database/Queries/Compare.php b/inc/Dependencies/Database/Queries/Compare.php index 15eb42dee6..4091af0384 100644 --- a/inc/Dependencies/Database/Queries/Compare.php +++ b/inc/Dependencies/Database/Queries/Compare.php @@ -4,8 +4,8 @@ * * @package Database * @subpackage Compare - * @copyright Copyright (c) 2020 - * @license https://opensource.org/licenses/gpl-2.0.php GNU Public License + * @copyright Copyright (c) 2021 + * @license https://opensource.org/licenses/MIT MIT * @since 1.0.0 */ namespace WP_Rocket\Dependencies\Database\Queries; @@ -24,6 +24,35 @@ */ class Compare extends Meta { + // All supported SQL comparisons + const ALL_COMPARES = array( + '=', + '!=', + '>', + '>=', + '<', + '<=', + 'LIKE', + 'NOT LIKE', + 'IN', + 'NOT IN', + 'BETWEEN', + 'NOT BETWEEN', + 'EXISTS', + 'NOT EXISTS', + 'REGEXP', + 'NOT REGEXP', + 'RLIKE', + ); + + // IN and BETWEEN + const IN_BETWEEN_COMPARES = array( + 'IN', + 'NOT IN', + 'BETWEEN', + 'NOT BETWEEN' + ); + /** * Generate SQL WHERE clauses for a first-order query clause. * @@ -44,65 +73,57 @@ class Compare extends Meta { public function get_sql_for_clause( &$clause, $parent_query, $clause_key = '' ) { global $wpdb; + // Default chunks $sql_chunks = array( 'where' => array(), 'join' => array(), ); + // Maybe format compare clause if ( isset( $clause['compare'] ) ) { $clause['compare'] = strtoupper( $clause['compare'] ); + + // Or set compare clause based on value } else { - $clause['compare'] = isset( $clause['value'] ) && is_array( $clause['value'] ) ? 'IN' : '='; + $clause['compare'] = isset( $clause['value'] ) && is_array( $clause['value'] ) + ? 'IN' + : '='; } - if ( ! in_array( - $clause['compare'], array( - '=', - '!=', - '>', - '>=', - '<', - '<=', - 'LIKE', - 'NOT LIKE', - 'IN', - 'NOT IN', - 'BETWEEN', - 'NOT BETWEEN', - 'EXISTS', - 'NOT EXISTS', - 'REGEXP', - 'NOT REGEXP', - 'RLIKE', - ), true - ) ) { + // Fallback to equals + if ( ! in_array( $clause['compare'], self::ALL_COMPARES, true ) ) { $clause['compare'] = '='; } - if ( isset( $clause['compare_key'] ) && 'LIKE' === strtoupper( $clause['compare_key'] ) ) { + // Uppercase or equals + if ( isset( $clause['compare_key'] ) && ( 'LIKE' === strtoupper( $clause['compare_key'] ) ) ) { $clause['compare_key'] = strtoupper( $clause['compare_key'] ); } else { $clause['compare_key'] = '='; } - $compare = $clause['compare']; - $compare_key = $clause['compare_key']; + // Get comparison from clause + $compare = $clause['compare']; - // Build the WHERE clause. + /** Build the WHERE clause ********************************************/ // Column name and value. if ( array_key_exists( 'key', $clause ) && array_key_exists( 'value', $clause ) ) { $column = sanitize_key( $clause['key'] ); $value = $clause['value']; - if ( in_array( $compare, array( 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ), true ) ) { + // IN or BETWEEN + if ( in_array( $compare, self::IN_BETWEEN_COMPARES, true ) ) { if ( ! is_array( $value ) ) { $value = preg_split( '/[,\s]+/', $value ); } + + // Anything else } else { $value = trim( $value ); } + // Format WHERE from compare value(s) switch ( $compare ) { case 'IN': case 'NOT IN': @@ -139,7 +160,8 @@ public function get_sql_for_clause( &$clause, $parent_query, $clause_key = '' ) } - if ( $where ) { + // Maybe add column, compare, & where to chunks + if ( ! empty( $where ) ) { $sql_chunks['where'][] = "{$column} {$compare} {$where}"; } } @@ -152,6 +174,7 @@ public function get_sql_for_clause( &$clause, $parent_query, $clause_key = '' ) $sql_chunks['where'] = array( '( ' . implode( ' AND ', $sql_chunks['where'] ) . ' )' ); } + // Return return $sql_chunks; } -} +} \ No newline at end of file diff --git a/inc/Dependencies/Database/Queries/Date.php b/inc/Dependencies/Database/Queries/Date.php index 10a141b539..d67223e2c8 100644 --- a/inc/Dependencies/Database/Queries/Date.php +++ b/inc/Dependencies/Database/Queries/Date.php @@ -4,8 +4,8 @@ * * @package Database * @subpackage Date - * @copyright Copyright (c) 2020 - * @license https://opensource.org/licenses/gpl-2.0.php GNU Public License + * @copyright Copyright (c) 2021 + * @license https://opensource.org/licenses/MIT MIT * @since 1.0.0 */ namespace WP_Rocket\Dependencies\Database\Queries; diff --git a/inc/Dependencies/Database/Queries/Meta.php b/inc/Dependencies/Database/Queries/Meta.php index 8b36a713fa..07aaa859b1 100644 --- a/inc/Dependencies/Database/Queries/Meta.php +++ b/inc/Dependencies/Database/Queries/Meta.php @@ -4,8 +4,8 @@ * * @package Database * @subpackage Meta - * @copyright Copyright (c) 2020 - * @license https://opensource.org/licenses/gpl-2.0.php GNU Public License + * @copyright Copyright (c) 2021 + * @license https://opensource.org/licenses/MIT MIT * @since 1.1.0 */ namespace WP_Rocket\Dependencies\Database\Queries; diff --git a/inc/Dependencies/Database/Query.php b/inc/Dependencies/Database/Query.php index dddb5f5228..dfd8f86733 100644 --- a/inc/Dependencies/Database/Query.php +++ b/inc/Dependencies/Database/Query.php @@ -4,8 +4,8 @@ * * @package Database * @subpackage Query - * @copyright Copyright (c) 2020 - * @license https://opensource.org/licenses/gpl-2.0.php GNU Public License + * @copyright Copyright (c) 2021 + * @license https://opensource.org/licenses/MIT MIT * @since 1.0.0 */ namespace WP_Rocket\Dependencies\Database; @@ -31,12 +31,13 @@ * @property string $item_name_plural * @property string $item_shape * @property string $cache_group - * @property string $columns - * @property string $query_clauses - * @property string $request_clauses + * @property int $last_changed + * @property array $columns + * @property array $query_clauses + * @property array $request_clauses * @property Queries\Meta $meta_query * @property Queries\Date $date_query - * @property Queries\Compare $compare + * @property Queries\Compare $compare_query * @property array $query_vars * @property array $query_var_originals * @property array $query_var_defaults @@ -45,7 +46,6 @@ * @property int $found_items * @property int $max_num_pages * @property string $request - * @property int $last_changed */ class Query extends Base { @@ -305,8 +305,8 @@ class Query extends Base { * @type bool $no_found_rows Whether to disable the `SQL_CALC_FOUND_ROWS` query. * Default true. * @type string|array $orderby Accepts false, an empty array, or 'none' to disable `ORDER BY` clause. - * Default 'id'. - * @type string $item How to item retrieved items. Accepts 'ASC', 'DESC'. + * Default '', to primary column ID. + * @type string $order How to order retrieved items. Accepts 'ASC', 'DESC'. * Default 'DESC'. * @type string $search Search term(s) to retrieve matching items for. * Default empty. @@ -344,10 +344,10 @@ public function __construct( $query = array() ) { * @param string|array $query Array or URL query string of parameters. * @return array|int List of items, or number of items when 'count' is passed as a query var. */ - public function query( $query = array(), bool $use_cache = true ) { + public function query( $query = array() ) { $this->parse_query( $query ); - return $this->get_items( $use_cache ); + return $this->get_items(); } /** Private Setters *******************************************************/ @@ -434,21 +434,28 @@ private function set_query_var_defaults() { ? $this->apply_prefix( bin2hex( random_bytes( 18 ) ) ) : $this->apply_prefix( uniqid( '_', true ) ); + // Get the primary column name + $primary = $this->get_primary_column_name(); + // Default query variables $this->query_var_defaults = array( 'fields' => '', 'number' => 100, 'offset' => '', - 'orderby' => 'id', + 'orderby' => $primary, 'order' => 'DESC', 'groupby' => '', 'search' => '', 'search_columns' => array(), 'count' => false, + + // Disable SQL_CALC_FOUND_ROWS? + 'no_found_rows' => true, + + // Queries 'meta_query' => null, // See Queries\Meta 'date_query' => null, // See Queries\Date 'compare_query' => null, // See Queries\Compare - 'no_found_rows' => true, // Caching 'update_item_cache' => true, @@ -749,6 +756,9 @@ private function get_primary_column_name() { * * @since 1.0.0 * + * @param array $args Arguments to get a column by. + * @param string $field Field to get from a column. + * @param mixed $default Default to use if no field is set. * @return mixed Column object, or false */ private function get_column_field( $args = array(), $field = '', $default = false ) { @@ -767,6 +777,7 @@ private function get_column_field( $args = array(), $field = '', $default = fals * * @since 1.0.0 * + * @param array $args Arguments to get a column by. * @return mixed Column object, or false */ private function get_column_by( $args = array() ) { @@ -784,6 +795,12 @@ private function get_column_by( $args = array() ) { * Get columns from an array of arguments. * * @since 1.0.0 + * + * @param array $args Arguments to filter columns by. + * @param string $operator Optional. The logical operation to perform. + * @param string $field Optional. A field from the object to place + * instead of the entire object. Default false. + * @return array Array of column. */ private function get_columns( $args = array(), $operator = 'and', $field = false ) { @@ -842,7 +859,7 @@ private function get_item_raw( $column_name = '', $column_value = '' ) { * * @return array|int List of items, or number of items when 'count' is passed as a query var. */ - private function get_items( bool $use_cache = true ) { + private function get_items() { /** * Fires before object items are retrieved. @@ -863,7 +880,7 @@ private function get_items( bool $use_cache = true ) { // Check the cache $cache_key = $this->get_cache_key(); - $cache_value = $use_cache ? $this->cache_get( $cache_key, $this->cache_group ) : false; + $cache_value = $this->cache_get( $cache_key, $this->cache_group ); // No cache value if ( false === $cache_value ) { @@ -872,16 +889,14 @@ private function get_items( bool $use_cache = true ) { // Set the number of found items $this->set_found_items( $item_ids ); - if ( $use_cache ) { - // Format the cached value - $cache_value = array( - 'item_ids' => $item_ids, - 'found_items' => intval( $this->found_items ), - ); + // Format the cached value + $cache_value = array( + 'item_ids' => $item_ids, + 'found_items' => intval( $this->found_items ), + ); - // Add value to the cache - $this->cache_add( $cache_key, $cache_value, $this->cache_group ); - } + // Add value to the cache + $this->cache_add( $cache_key, $cache_value, $this->cache_group ); // Value exists in cache } else { @@ -1284,9 +1299,13 @@ private function parse_where() { /** Query Classes *****************************************************/ - // Get the primary column name & meta table + // Get the primary column name $primary = $this->get_primary_column_name(); + + // Get the meta table $table = $this->get_meta_type(); + + // Set the " AND " regex pattern $and = '/^\s*AND\s*/'; // Maybe perform a meta query. @@ -1303,8 +1322,12 @@ private function parse_where() { $join['meta_query'] = $clauses['join']; } - // Remove " AND " from meta_query query where clause - $where['meta_query'] = preg_replace( $and, '', $clauses['where'] ); + // Set where + if ( ! empty( $clauses['where'] ) ) { + + // Remove " AND " from query query where clause + $where['meta_query'] = preg_replace( $and, '', $clauses['where'] ); + } } } @@ -1322,8 +1345,12 @@ private function parse_where() { $join['compare_query'] = $clauses['join']; } - // Remove " AND " from query where clause. - $where['compare_query'] = preg_replace( $and, '', $clauses['where'] ); + // Set where + if ( ! empty( $clauses['where'] ) ) { + + // Remove " AND " from query where clause. + $where['compare_query'] = preg_replace( $and, '', $clauses['where'] ); + } } } @@ -1345,14 +1372,18 @@ private function parse_where() { $join['date_query'] = $clauses['join']; } - // Remove " AND " from query where clause. - $where['date_query'] = preg_replace( $and, '', $clauses['where'] ); + // Set where + if ( ! empty( $clauses['where'] ) ) { + + // Remove " AND " from query where clause. + $where['date_query'] = preg_replace( $and, '', $clauses['where'] ); + } } } - // Set where and join clauses - $this->query_clauses['where'] = $where; - $this->query_clauses['join'] = $join; + // Set where and join clauses, removing possible empties + $this->query_clauses['where'] = array_filter( $where ); + $this->query_clauses['join'] = array_filter( $join ); } /** @@ -1366,8 +1397,10 @@ private function parse_where() { */ private function parse_fields( $fields = '', $alias = true ) { - // Default return value + // Get the primary column name $primary = $this->get_primary_column_name(); + + // Default return value $retval = ( true === $alias ) ? "{$this->table_alias}.{$primary}" : $primary; @@ -1376,7 +1409,7 @@ private function parse_fields( $fields = '', $alias = true ) { if ( empty( $fields ) && ! empty( $this->query_vars['count'] ) ) { // Possible fields to group by - $groupby_names = $this->parse_groupby( $this->query_vars['groupby'], false ); + $groupby_names = $this->parse_groupby( $this->query_vars['groupby'], $alias ); $groupby_names = ! empty( $groupby_names ) ? "{$groupby_names}" : ''; @@ -1414,7 +1447,7 @@ private function parse_groupby( $groupby = '', $alias = true ) { $columns = array_flip( $this->get_column_names() ); // Get the intersection of allowed column names to groupby columns - $intersect = array_intersect( $columns, $groupby ); + $intersect = array_intersect( $groupby, $columns ); // Bail if invalid column if ( empty( $intersect ) ) { @@ -1443,12 +1476,19 @@ private function parse_groupby( $groupby = '', $alias = true ) { * @param string $orderby Field for the items to be ordered by. * @return string|false Value to used in the ORDER clause. False otherwise. */ - private function parse_orderby( $orderby = 'id' ) { + private function parse_orderby( $orderby = '' ) { - // Default value + // Get the primary column name $primary = $this->get_primary_column_name(); + + // Default return value $parsed = "{$this->table_alias}.{$primary}"; + // Default to primary column + if ( empty( $orderby ) ) { + $orderby = $primary; + } + // __in if ( false !== strstr( $orderby, '__in' ) ) { $column_name = str_replace( '__in', '', $orderby ); @@ -1558,6 +1598,8 @@ private function get_item_fields( $items = array() ) { // Get the primary column name $primary = $this->get_primary_column_name(); + + // Get the query var fields $fields = $this->query_vars['fields']; // Strings need to be single columns @@ -1681,7 +1723,7 @@ public function get_item_by( $column_name = '', $column_value = '' ) { return $retval; } - // Get the column names + // Get all of the column names $columns = $this->get_column_names(); // Bail if column does not exist @@ -1689,7 +1731,7 @@ public function get_item_by( $column_name = '', $column_value = '' ) { return $retval; } - // Cache groups + // Get all of the cache groups $groups = $this->get_cache_groups(); // Check cache @@ -1700,7 +1742,7 @@ public function get_item_by( $column_name = '', $column_value = '' ) { // Item not cached if ( false === $retval ) { - // Try to get item directly from DB + // Get item by column name & value (from database, not cache) $retval = $this->get_item_raw( $column_name, $column_value ); // Bail on failure @@ -1708,7 +1750,7 @@ public function get_item_by( $column_name = '', $column_value = '' ) { return false; } - // Cache + // Update item cache(s) $this->update_item_cache( $retval ); } @@ -1764,6 +1806,11 @@ public function add_item( $data = array() ) { $meta = array_diff_key( $data, $columns ); $save = array_intersect_key( $data, $columns ); + // Bail if nothing to save + if ( empty( $save ) && empty( $meta ) ) { + return false; + } + // Get the current time (maybe used by created/modified) $time = $this->get_current_time(); @@ -1800,11 +1847,11 @@ public function add_item( $data = array() ) { $this->save_extra_item_meta( $item_id, $meta ); } - // Use get item to prime caches + // Update item cache(s) $this->update_item_cache( $item_id ); // Transition item data - $this->transition_item( $save, $item_id ); + $this->transition_item( $save, array(), $item_id ); // Return result return $item_id; @@ -1858,8 +1905,15 @@ public function copy_item( $item_id = 0, $data = array() ) { */ public function update_item( $item_id = 0, $data = array() ) { - // Bail if no item ID + // Bail early if no data to update + if ( empty( $data ) ) { + return false; + } + + // Shape the item ID $item_id = $this->shape_item_id( $item_id ); + + // Bail if no item ID if ( empty( $item_id ) ) { return false; } @@ -1878,12 +1932,15 @@ public function update_item( $item_id = 0, $data = array() ) { // Cast as an array for easier manipulation $item = (array) $item; - // Unset the primary key from data to parse - unset( $data[ $primary ] ); + // Unset the primary key from item & data + unset( + $data[ $primary ], + $item[ $primary ] + ); - // Splice new data into item, and cut out non-keys for meta + // Slice data that has columns, and cut out non-keys for meta $columns = $this->get_column_names(); - $data = array_merge( $item, $data ); + $data = array_diff_assoc( $data, $item ); $meta = array_diff_key( $data, $columns ); $save = array_intersect_key( $data, $columns ); @@ -1892,15 +1949,12 @@ public function update_item( $item_id = 0, $data = array() ) { $this->save_extra_item_meta( $item_id, $meta ); } - // Bail if no change - if ( (array) $save === (array) $item ) { - return true; + // Bail if nothing to save + if ( empty( $save ) ) { + return false; } - // Unset the primary key from data to save - unset( $save[ $primary ] ); - - // If date-modified is empty, use the current time + // If date-modified exists, use the current time $modified = $this->get_column_by( array( 'modified' => true ) ); if ( ! empty( $modified ) ) { $save[ $modified->name ] = $this->get_current_time(); @@ -1920,11 +1974,11 @@ public function update_item( $item_id = 0, $data = array() ) { return false; } - // Use get item to prime caches + // Update item cache(s) $this->update_item_cache( $item_id ); // Transition item data - $this->transition_item( $save, $item ); + $this->transition_item( $save, $item, $item_id ); // Return result return $result; @@ -1940,8 +1994,10 @@ public function update_item( $item_id = 0, $data = array() ) { */ public function delete_item( $item_id = 0 ) { - // Bail if no item ID + // Shape the item ID $item_id = $this->shape_item_id( $item_id ); + + // Bail if no item ID if ( empty( $item_id ) ) { return false; } @@ -1949,7 +2005,7 @@ public function delete_item( $item_id = 0 ) { // Get the primary column name $primary = $this->get_primary_column_name(); - // Get item (before it's deleted) + // Get item by ID (from database, not cache) $item = $this->get_item_raw( $primary, $item_id ); // Bail if item does not exist to delete @@ -2046,11 +2102,6 @@ private function validate_item( $item = array() ) { // Loop through item attributes foreach ( $item as $key => $value ) { - // Strip slashes from all strings - /*if ( is_string( $value ) ) { - $value = stripslashes( $value );// We removed this line at PR #3847 to solve if the content has backslash. - }*/ - // Get the column $column = $this->get_column_by( array( 'name' => $key ) ); @@ -2173,10 +2224,12 @@ private function default_item() { * * @since 1.0.0 * - * @param array $item + * @param array $new_data + * @param array $old_data + * @param int $item_id * @return array */ - private function transition_item( $new_data = array(), $old_data = array() ) { + private function transition_item( $new_data = array(), $old_data = array(), $item_id = 0 ) { // Look for transition columns $columns = $this->get_columns( array( 'transition' => true ), 'and', 'name' ); @@ -2186,16 +2239,16 @@ private function transition_item( $new_data = array(), $old_data = array() ) { return; } - // Get the item ID - $item_id = $this->shape_item_id( $old_data ); + // Shape the item ID + $item_id = $this->shape_item_id( $item_id ); - // Bail if item ID cannot be retrieved + // Bail if no item ID if ( empty( $item_id ) ) { return; } // If no old value(s), it's new - if ( ! is_array( $old_data ) ) { + if ( empty( $old_data ) || ! is_array( $old_data ) ) { $old_data = $new_data; // Set all old values to "new" @@ -2252,8 +2305,10 @@ private function transition_item( $new_data = array(), $old_data = array() ) { */ protected function add_item_meta( $item_id = 0, $meta_key = '', $meta_value = '', $unique = false ) { - // Bail if no meta was returned + // Shape the item ID $item_id = $this->shape_item_id( $item_id ); + + // Bail if no meta to add if ( empty( $item_id ) || empty( $meta_key ) ) { return false; } @@ -2282,8 +2337,10 @@ protected function add_item_meta( $item_id = 0, $meta_key = '', $meta_value = '' */ protected function get_item_meta( $item_id = 0, $meta_key = '', $single = false ) { - // Bail if no meta was returned + // Shape the item ID $item_id = $this->shape_item_id( $item_id ); + + // Bail if no meta was returned if ( empty( $item_id ) || empty( $meta_key ) ) { return false; } @@ -2313,8 +2370,10 @@ protected function get_item_meta( $item_id = 0, $meta_key = '', $single = false */ protected function update_item_meta( $item_id = 0, $meta_key = '', $meta_value = '', $prev_value = '' ) { - // Bail if no meta was returned + // Shape the item ID $item_id = $this->shape_item_id( $item_id ); + + // Bail if no meta was returned if ( empty( $item_id ) || empty( $meta_key ) ) { return false; } @@ -2344,8 +2403,10 @@ protected function update_item_meta( $item_id = 0, $meta_key = '', $meta_value = */ protected function delete_item_meta( $item_id = 0, $meta_key = '', $meta_value = '', $delete_all = false ) { - // Bail if no meta was returned + // Shape the item ID $item_id = $this->shape_item_id( $item_id ); + + // Bail if no meta was returned if ( empty( $item_id ) || empty( $meta_key ) ) { return false; } @@ -2389,8 +2450,10 @@ private function get_registered_meta_keys( $object_subtype = '' ) { */ private function save_extra_item_meta( $item_id = 0, $meta = array() ) { - // Bail if there is no bulk meta to save + // Shape the item ID $item_id = $this->shape_item_id( $item_id ); + + // Bail if there is no bulk meta to save if ( empty( $item_id ) || empty( $meta ) ) { return; } @@ -2426,8 +2489,10 @@ private function save_extra_item_meta( $item_id = 0, $meta = array() ) { */ private function delete_all_item_meta( $item_id = 0 ) { - // Bail if no meta was returned + // Shape the item ID $item_id = $this->shape_item_id( $item_id ); + + // Bail if no item ID if ( empty( $item_id ) ) { return; } @@ -2440,9 +2505,11 @@ private function delete_all_item_meta( $item_id = 0 ) { return; } + // Get the primary column name + $primary = $this->get_primary_column_name(); + // Guess the item ID column for the meta table - $primary_id = $this->get_primary_column_name(); - $item_id_column = $this->apply_prefix( "{$this->item_name}_{$primary_id}" ); + $item_id_column = $this->apply_prefix( "{$this->item_name}_{$primary}" ); // Get meta IDs $query = "SELECT meta_id FROM {$table} WHERE {$item_id_column} = %d"; @@ -2486,7 +2553,7 @@ private function get_meta_table_name() { // If not empty, return table name if ( ! empty( $db->{$table_name} ) ) { - return $table_name; + return $db->{$table_name}; } // Default return false @@ -2639,7 +2706,7 @@ private function prime_item_caches( $item_ids = array(), $force = false ) { $prepare = sprintf( $query, $ids ); $results = $this->get_db()->get_results( $prepare ); - // Update item caches + // Update item cache(s) $this->update_item_cache( $results ); } @@ -2667,7 +2734,11 @@ private function update_item_cache( $items = array() ) { // Maybe query for single item if ( is_numeric( $items ) ) { + + // Get the primary column name $primary = $this->get_primary_column_name(); + + // Get item by ID (from database, not cache) $items = $this->get_item_raw( $primary, $items ); } @@ -2809,6 +2880,8 @@ private function get_last_changed_cache( $group = '' ) { * @return array */ private function get_non_cached_ids( $item_ids = array(), $group = '' ) { + + // Default return value $retval = array(); // Bail if no item IDs @@ -2818,8 +2891,11 @@ private function get_non_cached_ids( $item_ids = array(), $group = '' ) { // Loop through item IDs foreach ( $item_ids as $id ) { + + // Shape the item ID $id = $this->shape_item_id( $id ); + // Add to return value if not cached if ( false === $this->cache_get( $id, $group ) ) { $retval[] = $id; } diff --git a/inc/Dependencies/Database/Row.php b/inc/Dependencies/Database/Row.php index 9c986474e4..1614d6bb0d 100644 --- a/inc/Dependencies/Database/Row.php +++ b/inc/Dependencies/Database/Row.php @@ -4,8 +4,8 @@ * * @package Database * @subpackage Row - * @copyright Copyright (c) 2020 - * @license https://opensource.org/licenses/gpl-2.0.php GNU Public License + * @copyright Copyright (c) 2021 + * @license https://opensource.org/licenses/MIT MIT * @since 1.0.0 */ namespace WP_Rocket\Dependencies\Database; diff --git a/inc/Dependencies/Database/Schema.php b/inc/Dependencies/Database/Schema.php index 2d40a45625..a7ed3e36e3 100644 --- a/inc/Dependencies/Database/Schema.php +++ b/inc/Dependencies/Database/Schema.php @@ -4,8 +4,8 @@ * * @package Database * @subpackage Schema - * @copyright Copyright (c) 2020 - * @license https://opensource.org/licenses/gpl-2.0.php GNU Public License + * @copyright Copyright (c) 2021 + * @license https://opensource.org/licenses/MIT MIT * @since 1.0.0 */ namespace WP_Rocket\Dependencies\Database; diff --git a/inc/Dependencies/Database/Table.php b/inc/Dependencies/Database/Table.php index 8aaa85fcb6..e85054e066 100644 --- a/inc/Dependencies/Database/Table.php +++ b/inc/Dependencies/Database/Table.php @@ -4,8 +4,8 @@ * * @package Database * @subpackage Table - * @copyright Copyright (c) 2020 - * @license https://opensource.org/licenses/gpl-2.0.php GNU Public License + * @copyright Copyright (c) 2021 + * @license https://opensource.org/licenses/MIT MIT * @since 1.0.0 */ namespace WP_Rocket\Dependencies\Database; @@ -160,6 +160,24 @@ public function __construct() { } } + /** + * Compatibility for clone() method for PHP versions less than 7.0. + * + * See: https://github.com/sugarcalendar/core/issues/105 + * + * This shim will be removed at a later date. + * + * @since 2.0.20 + * + * @param string $function + * @param array $args + */ + public function __call( $function = '', $args = array() ) { + if ( 'clone' === $function ) { + call_user_func_array( array( $this, '_clone' ), $args ); + } + } + /** Abstract **************************************************************/ /** @@ -285,11 +303,15 @@ public function get_version() { } /** - * Install a database table by creating the table and setting the version. + * Install a database table + * + * Creates the table and sets the version information if successful. * * @since 1.0.0 */ public function install() { + + // Try to create the table $created = $this->create(); // Set the DB version if create was successful @@ -299,15 +321,20 @@ public function install() { } /** - * Destroy a database table by dropping the table and deleting the version. + * Uninstall a database table + * + * Drops the table and deletes the version information if successful and/or + * the table does not exist anymore. * * @since 1.0.0 */ public function uninstall() { + + // Try to drop the table $dropped = $this->drop(); - // Delete the DB version if drop was successful - if ( true === $dropped ) { + // Delete the DB version if drop was successful or table does not exist + if ( ( true === $dropped ) || ! $this->exists() ) { $this->delete_db_version(); } } @@ -341,6 +368,33 @@ public function exists() { return $this->is_success( $result ); } + /** + * Get columns from table. + * + * @since 1.2.0 + * + * @return array + */ + public function columns() { + + // Get the database interface + $db = $this->get_db(); + + // Bail if no database interface is available + if ( empty( $db ) ) { + return false; + } + + // Query statement + $query = "SHOW FULL COLUMNS FROM {$this->table_name}"; + $result = $db->get_results( $query ); + + // Return the results + return $this->is_success( $result ) + ? $result + : false; + } + /** * Create the table. * @@ -434,11 +488,11 @@ public function delete_all() { } // Query statement - $query = "DELETE FROM {$this->table_name}"; - $deleted = $db->query( $query ); + $query = "DELETE FROM {$this->table_name}"; + $result = $db->query( $query ); - // Did the table get emptied? - return $deleted; + // Return the results + return $result; } /** @@ -452,7 +506,7 @@ public function delete_all() { * * @return bool */ - public function clone( $new_table_name = '' ) { + public function _clone( $new_table_name = '' ) { // Get the database interface $db = $this->get_db(); @@ -535,11 +589,11 @@ public function count() { } // Query statement - $query = "SELECT COUNT(*) FROM {$this->table_name}"; - $count = $db->get_var( $query ); + $query = "SELECT COUNT(*) FROM {$this->table_name}"; + $result = $db->get_var( $query ); // Query success/fail - return intval( $count ); + return intval( $result ); } /**