class-database-proxy.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. <?php
  2. /**
  3. * WPSEO plugin file.
  4. *
  5. * @package WPSEO\Admin
  6. */
  7. /**
  8. * Represents the proxy for communicating with the database
  9. */
  10. class WPSEO_Database_Proxy {
  11. /** @var string */
  12. protected $table_name;
  13. /** @var bool */
  14. protected $suppress_errors = true;
  15. /** @var bool */
  16. protected $is_multisite_table = false;
  17. /** @var bool */
  18. protected $last_suppressed_state;
  19. /** @var wpdb */
  20. protected $database;
  21. /**
  22. * Sets the class attributes and registers the table.
  23. *
  24. * @param wpdb $database The database object.
  25. * @param string $table_name The table name that is represented.
  26. * @param bool $suppress_errors Should the errors be suppressed.
  27. * @param bool $is_multisite_table Should the table be global in multisite.
  28. */
  29. public function __construct( $database, $table_name, $suppress_errors = true, $is_multisite_table = false ) {
  30. $this->table_name = $table_name;
  31. $this->suppress_errors = (bool) $suppress_errors;
  32. $this->is_multisite_table = (bool) $is_multisite_table;
  33. $this->database = $database;
  34. // If the table prefix was provided, strip it as it's handled automatically.
  35. $table_prefix = $this->get_table_prefix();
  36. if ( ! empty( $table_prefix ) && strpos( $this->table_name, $table_prefix ) === 0 ) {
  37. $this->table_prefix = substr( $this->table_name, strlen( $table_prefix ) );
  38. }
  39. if ( ! $this->is_table_registered() ) {
  40. $this->register_table();
  41. }
  42. }
  43. /**
  44. * Inserts data into the database.
  45. *
  46. * @param array $data Data to insert.
  47. * @param null $format Formats for the data.
  48. *
  49. * @return false|int Total amount of inserted rows or false on error.
  50. */
  51. public function insert( array $data, $format = null ) {
  52. $this->pre_execution();
  53. $result = $this->database->insert( $this->get_table_name(), $data, $format );
  54. $this->post_execution();
  55. return $result;
  56. }
  57. /**
  58. * Updates data in the database.
  59. *
  60. * @param array $data Data to update on the table.
  61. * @param array $where Where condition as key => value array.
  62. * @param null $format Optional. data prepare format.
  63. * @param null $where_format Optional. Where prepare format.
  64. *
  65. * @return false|int False when the update request is invalid, int on number of rows changed.
  66. */
  67. public function update( array $data, array $where, $format = null, $where_format = null ) {
  68. $this->pre_execution();
  69. $result = $this->database->update( $this->get_table_name(), $data, $where, $format, $where_format );
  70. $this->post_execution();
  71. return $result;
  72. }
  73. /**
  74. * Upserts data in the database.
  75. *
  76. * Performs an insert into and if key is duplicate it will update the existing record.
  77. *
  78. * @param array $data Data to update on the table.
  79. * @param array $where Unused. Where condition as key => value array.
  80. * @param null $format Optional. Data prepare format.
  81. * @param null $where_format Deprecated. Where prepare format.
  82. *
  83. * @return false|int False when the upsert request is invalid, int on number of rows changed.
  84. */
  85. public function upsert( array $data, array $where = null, $format = null, $where_format = null ) {
  86. if ( $where_format !== null ) {
  87. _deprecated_argument( __METHOD__, '7.7.0', 'The where_format argument is deprecated' );
  88. }
  89. $this->pre_execution();
  90. $update = array();
  91. $keys = array();
  92. $columns = array_keys( $data );
  93. foreach ( $columns as $column ) {
  94. $keys[] = '`' . $column . '`';
  95. $update[] = sprintf( '`%1$s` = VALUES(`%1$s`)', $column );
  96. }
  97. $query = sprintf(
  98. 'INSERT INTO `%1$s` (%2$s) VALUES ( %3$s ) ON DUPLICATE KEY UPDATE %4$s',
  99. $this->get_table_name(),
  100. implode( ', ', $keys ),
  101. implode( ', ', array_fill( 0, count( $data ), '%s' ) ),
  102. implode( ', ', $update )
  103. );
  104. $result = $this->database->query(
  105. $this->database->prepare(
  106. $query,
  107. array_values( $data )
  108. )
  109. );
  110. $this->post_execution();
  111. return $result;
  112. }
  113. /**
  114. * Deletes a record from the database.
  115. *
  116. * @param array $where Where clauses for the query.
  117. * @param null|array $format Formats for the data.
  118. *
  119. * @return false|int
  120. */
  121. public function delete( array $where, $format = null ) {
  122. $this->pre_execution();
  123. $result = $this->database->delete( $this->get_table_name(), $where, $format );
  124. $this->post_execution();
  125. return $result;
  126. }
  127. /**
  128. * Executes the given query and returns the results.
  129. *
  130. * @param string $query The query to execute.
  131. *
  132. * @return array|null|object The resultset
  133. */
  134. public function get_results( $query ) {
  135. $this->pre_execution();
  136. $results = $this->database->get_results( $query );
  137. $this->post_execution();
  138. return $results;
  139. }
  140. /**
  141. * Creates a table to the database.
  142. *
  143. * @param array $columns The columns to create.
  144. * @param array $indexes The indexes to use.
  145. *
  146. * @return bool True when creation is successful.
  147. */
  148. public function create_table( array $columns, array $indexes = array() ) {
  149. $create_table = sprintf( '
  150. CREATE TABLE IF NOT EXISTS %1$s ( %2$s ) %3$s',
  151. $this->get_table_name(),
  152. implode( ',', array_merge( $columns, $indexes ) ),
  153. $this->database->get_charset_collate()
  154. );
  155. $this->pre_execution();
  156. $is_created = (bool) $this->database->query( $create_table );
  157. $this->post_execution();
  158. return $is_created;
  159. }
  160. /**
  161. * Checks if there is an error.
  162. *
  163. * @return bool Returns true when there is an error.
  164. */
  165. public function has_error() {
  166. return ( $this->database->last_error !== '' );
  167. }
  168. /**
  169. * Executed before a query will be ran.
  170. */
  171. protected function pre_execution() {
  172. if ( $this->suppress_errors ) {
  173. $this->last_suppressed_state = $this->database->suppress_errors();
  174. }
  175. }
  176. /**
  177. * Executed after a query has been ran.
  178. */
  179. protected function post_execution() {
  180. if ( $this->suppress_errors ) {
  181. $this->database->suppress_errors( $this->last_suppressed_state );
  182. }
  183. }
  184. /**
  185. * Returns the full table name.
  186. *
  187. * @return string Full table name including prefix.
  188. */
  189. public function get_table_name() {
  190. return $this->get_table_prefix() . $this->table_name;
  191. }
  192. /**
  193. * Returns the prefix to use for the table.
  194. *
  195. * @return string The table prefix depending on the database context.
  196. */
  197. protected function get_table_prefix() {
  198. if ( $this->is_multisite_table ) {
  199. return $this->database->base_prefix;
  200. }
  201. return $this->database->get_blog_prefix();
  202. }
  203. /**
  204. * Registers the table with WordPress.
  205. *
  206. * @return void
  207. */
  208. protected function register_table() {
  209. $table_name = $this->table_name;
  210. $full_table_name = $this->get_table_name();
  211. $this->database->$table_name = $full_table_name;
  212. if ( $this->is_multisite_table ) {
  213. $this->database->ms_global_tables[] = $table_name;
  214. return;
  215. }
  216. $this->database->tables[] = $table_name;
  217. }
  218. /**
  219. * Checks if the table has been registered with WordPress.
  220. *
  221. * @return bool True if the table is registered, false otherwise.
  222. */
  223. protected function is_table_registered() {
  224. if ( $this->is_multisite_table ) {
  225. return in_array( $this->table_name, $this->database->ms_global_tables, true );
  226. }
  227. return in_array( $this->table_name, $this->database->tables, true );
  228. }
  229. }