WPDK  1.5.0
WordPress Development Kit
 All Data Structures Files Functions Variables Pages
wpdk-db.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * [DRAFT]
6  *
7  * THE FOLLOWING CODE IS A DRAFT. FEEL FREE TO USE IT TO MAKE SOME EXPERIMENTS, BUT DO NOT USE IT IN ANY CASE IN
8  * PRODUCTION ENVIRONMENT. ALL CLASSES AND RELATIVE METHODS BELOW CAN CHNAGE IN THE FUTURE RELEASES.
9  *
10  */
11 
12 
26 class WPDKDBTableStatus extends WPDKObject {
27  const ALL = 'all';
28  const PUBLISH = 'publish';
29  const DRAFT = 'draft';
30  const TRASH = 'trash';
31 
39  public $__version = '1.0.1';
40 
49  public static function statuses()
50  {
51  $statuses = array(
52  self::ALL => __( 'All', WPDK_TEXTDOMAIN ),
53  self::DRAFT => __( 'Draft', WPDK_TEXTDOMAIN ),
54  self::PUBLISH => __( 'Publish', WPDK_TEXTDOMAIN ),
55  self::TRASH => __( 'Trash', WPDK_TEXTDOMAIN ),
56  );
57  return $statuses;
58  }
59 
71  public static function sanitizeStatus( $status, $statuses = null )
72  {
73  $status = esc_attr( $status );
74  $statuses = is_null( $statuses ) ? self::statuses() : $statuses;
75  $allowed = array_keys( $statuses );
76  if ( !in_array( $status, $allowed ) ) {
77  return false;
78  }
79  return $status;
80  }
81 
82 }
83 
99 class __WPDKDBTable {
100 
108  public $primaryKey;
109 
117  public $sqlFilename;
118 
126  public $tableName;
127 
138  public function __construct( $table_name, $sql_file = '' )
139  {
140  global $wpdb;
141 
142  /* Add the WordPres database prefix. */
143  $this->tableName = sprintf( '%s%s', $wpdb->prefix, $table_name );
144 
145  /* $sql_file must be complete of path. */
146  $this->sqlFilename = $sql_file;
147 
148  /* Get the Primary key. */
149  $this->primaryKey = $this->primaryKey();
150  }
151 
161  public function primaryKey()
162  {
163  global $wpdb;
164 
165  $db = DB_NAME;
166 
167  $sql = <<< SQL
168 SELECT `COLUMN_NAME`
169 FROM `information_schema`.`COLUMNS`
170 WHERE (`TABLE_SCHEMA` = '{$db}')
171  AND (`TABLE_NAME` = '{$this->tableName}')
172  AND (`COLUMN_KEY` = 'PRI');
173 SQL;
174  return $wpdb->get_var( $sql );
175  }
176 
187  public function count( $distinct = '', $status = '' )
188  {
189  global $wpdb;
190 
191  $where = '';
192  if ( !empty( $status ) && is_array( $status ) ) {
193  if ( is_numeric( $status[key( $status )] ) ) {
194  $where = sprintf( 'WHERE %s = %s', key( $status ), $status[key( $status )] );
195  }
196  else {
197  $where = sprintf( "WHERE %s = '%s'", key( $status ), $status[key( $status )] );
198  }
199  }
200 
201  if ( empty( $distinct ) ) {
202  $sql = <<< SQL
203 SELECT COUNT(*) AS count
204  FROM `{$this->tableName}`
205  {$where}
206 SQL;
207  return absint( $wpdb->get_var( $sql ) );
208  }
209  else {
210  $sql = <<< SQL
211 SELECT DISTINCT(`{$distinct}`),
212  COUNT(*) AS count
213  FROM `{$this->tableName}`
214  {$where}
215  GROUP BY `{$distinct}`
216 SQL;
217 
218  $results = $wpdb->get_results( $sql, ARRAY_A );
219  $result = array();
220  foreach ( $results as $res ) {
221  $result[$res[$distinct]] = $res['count'];
222  }
223  return $result;
224  }
225  }
226 
227 
238  public function delete( $pks )
239  {
240  global $wpdb;
241 
242  if ( !is_array( $pks ) ) {
243  $pks = array( $pks );
244  }
245 
246  $ids = implode( ',', $pks );
247 
248  $sql = <<< SQL
249 DELETE FROM `{$this->tableName}`
250 WHERE `$this->primaryKey` IN({$ids})
251 SQL;
252  $result = $wpdb->query( $sql );
253 
254  return $result;
255  }
256 
268  public function groupBy( $column, $order_by = true, $order = 'ASC' )
269  {
270  global $wpdb;
271 
272  $sql_order = $order_by ? sprintf( 'ORDER BY `%s` %s', $column, $order ) : '';
273 
274  $sql = <<< SQL
275 SELECT `$column`
276  FROM `{$this->tableName}`
277  GROUP BY `$column`
278  {$sql_order}
279 SQL;
280  $results = $wpdb->get_results( $sql, ARRAY_A );
281  $result = array();
282  foreach ( $results as $res ) {
283  if ( !empty( $res[$column] ) ) {
284  $result[] = $res[$column];
285  }
286  }
287  return $result;
288  }
289 
301  public function map( $source_row, $destination_object )
302  {
303  if ( is_object( $source_row ) ) {
304  foreach ( $source_row as $field => $value ) {
305  $destination_object->$field = $value;
306  if ( method_exists( $destination_object, 'column_' . $field ) ) {
307  call_user_func( array(
308  $destination_object,
309  'column_' . $field
310  ), $value );
311  }
312  }
313  return $destination_object;
314  }
315  return false;
316  }
317 
338  public function select( $id = false, $order_by = '', $order = 'ASC', $where = '' )
339  {
340  global $wpdb;
341 
342  $sql_where = '';
343  if ( !empty( $id ) ) {
344  if ( is_array( $id ) ) {
345  $id = implode( ',', $id );
346  }
347  $sql_where = sprintf( ' AND %s IN(%s)', $this->primaryKey, $id );
348  }
349 
350  if ( !empty( $where ) ) {
351  $sql_where = sprintf( '%s AND %s ', $sql_where, $where );
352  }
353 
354  $order_by = empty( $order_by ) ? $this->primaryKey : $order_by;
355 
356  $sql = <<< SQL
357 SELECT * FROM `{$this->tableName}`
358 WHERE 1 {$sql_where}
359 ORDER BY {$order_by} {$order}
360 SQL;
361 
362  $rows = $wpdb->get_results( $sql, OBJECT_K );
363 
364  return $rows;
365  }
366 
378  public function _select( $query = null, $order_by = '', $order = 'ASC' )
379  {
380  global $wpdb;
381 
382  /* Sanitize order by. */
383  $order_by = empty( $order_by ) ? $this->primaryKey : $order_by;
384 
385  /* Build where condiction from an obejct (single record). */
386  $where = $this->where( $query );
387 
388  $sql = <<<SQL
389 SELECT * FROM {$this->tableName}
390 WHERE 1 = 1
391 
392 {$where}
393 
394 ORDER BY {$order_by} {$order}
395 SQL;
396 
397  $results = $wpdb->get_results( $sql, OBJECT_K );
398 
399  return $results;
400  }
401 
410  public function update()
411  {
412  global $wpdb;
413 
414  // Hide database warning and error
415  $wpdb->hide_errors();
416  $wpdb->suppress_errors();
417 
418  // Buffering
419  ob_start();
420 
421  if ( !empty( $this->sqlFilename ) && !empty( $this->tableName ) ) {
422  if ( !function_exists( 'dbDelta' ) ) {
423  require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
424  }
425  $content = file_get_contents( $this->sqlFilename );
426  if ( empty( $content ) ) {
427  ob_end_clean();
428  return false;
429  }
430 
431  // Replace table name
432  $sql = str_replace( '%s', $this->tableName, $content );
433 
434  // Remove comments
435  $pattern = '@(([\'"]).*?[^\\\]\2)|((?:\#|--).*?$|/\*(?:[^/*]|/(?!\*)|\*(?!/)|(?R))*\*\/)\s*|(?<=;)\s+@ms';
436  /*
437  * Commented version
438  *
439  * $sqlComments = '@
440  * (([\'"]).*?[^\\\]\2) # $1 : Skip single & double quoted expressions
441  * |( # $3 : Match comments
442  * (?:\#|--).*?$ # - Single line comments
443  * | # - Multi line (nested) comments
444  * /\* # . comment open marker
445  * (?: [^/*] # . non comment-marker characters
446  * |/(?!\*) # . ! not a comment open
447  * |\*(?!/) # . ! not a comment close
448  * |(?R) # . recursive case
449  * )* # . repeat eventually
450  * \*\/ # . comment close marker
451  * )\s* # Trim after comments
452  * |(?<=;)\s+ # Trim after semi-colon
453  * @msx';
454  *
455  */
456  $sql_sanitize = trim( preg_replace( $pattern, '$1', $sql ) );
457  preg_match_all( $pattern, $sql, $comments );
458 
459  // Only commnets
460  //$extractedComments = array_filter( $comments[ 3 ] );
461 
462  // Execute delta
463  @dbDelta( $sql_sanitize );
464 
465  // Clear error
466  global $EZSQL_ERROR;
467  $EZSQL_ERROR = array();
468  }
469  ob_end_clean();
470  return true;
471  }
472 
483  public function where( $query, $prefix = '' )
484  {
485  $result = '';
486 
487  if ( !is_null( $query ) ) {
488 
489  /* Sanitize prefix. */
490  if ( !empty( $prefix ) ) {
491  $prefix = rtrim( $prefix, '.' ) . '.';
492  }
493 
494  $desc = $query->desc();
495  $stack = array();
496 
497  /* Database type to be numeric. */
498  $numeric = array(
499  'bigint',
500  'int',
501  'decimal'
502  );
503 
504  foreach ( $query as $property => $value ) {
505  if ( isset( $desc[$property] ) && !is_null( $value ) ) {
506 
507  /* Remove `(` from type. */
508  $type = $desc[$property]->Type;
509  $pos = strpos( $type, '(' );
510  $type = ( false === $pos ) ? $type : substr( $type, 0, $pos );
511 
512  /* Check for numeric and string. */
513  // TODO Implement array support too when value is an array
514  if ( in_array( $type, $numeric ) ) {
515  $stack[] = sprintf( 'AND %s%s = %s', $prefix, $property, $value );
516  }
517  else {
518  $stack[] = sprintf( 'AND %s%s = \'%s\'', $prefix, $property, $value );
519  }
520  }
521  }
522 
523  if ( !empty( $stack ) ) {
524  $result = implode( ' ', $stack );
525  }
526  }
527 
528  return $result;
529  }
530 
534  public function deleteWherePrimaryKey( $id )
535  {
536  _deprecated_function( __METHOD__, '1.0.0', 'delete()' );
537  $this->delete( $id );
538  }
539 
543  public function selectWhereID( $id, $object, $output = OBJECT )
544  {
545  _deprecated_function( __METHOD__, '1.0.0', 'select()' );
546  $this->select( $id );
547  }
548 
549 }
550 
572 class WPDKDBTableRow {
573 
580  const NULL_VALUE = '!NULL!';
581 
589  public $table;
590 
601  public function __construct( __WPDKDBTable $dbtable, $pk = null )
602  {
603  $this->table = $dbtable;
604 
605  if ( !is_null( $pk ) ) {
606  if ( is_numeric( $pk ) ) {
607  $this->initByID( $pk );
608  }
609  elseif ( is_array( $pk ) ) {
610  /* @todo */
611  }
612  elseif ( is_object( $pk ) ) {
613  /* @todo */
614  }
615  }
616  }
617 
627  private function initByID( $pk )
628  {
629  global $wpdb;
630 
631  /* @todo You can use $this->table->selectWithID( $id ); insetad */
632 
633  $sql = sprintf( 'SELECT * FROM %s WHERE %s = %s', $this->table->tableName, $this->table->primaryKey, $pk );
634 
635  /* Override. */
636  $sql = $this->get_sql( $pk, $sql );
637 
638  /* Notify to all */
639  $sql = apply_filters( 'wpdk_db_table_' . $this->table->tableName . '_sql', $sql );
640 
641  $row = $wpdb->get_row( $sql );
642 
643  if ( !is_null( $row ) ) {
644  foreach ( $row as $property => $value ) {
645  $this->$property = $value;
646  if ( method_exists( $this, 'column_' . $property ) ) {
647  call_user_func( array( $this, 'column_' . $property ), $value );
648  }
649  }
650  return $row;
651  }
652  return false;
653  }
654 
665  public function get_sql( $pk, $sql )
666  {
667  return $sql;
668  }
669 
682  public static function getInstance( __WPDKDBTable $dbtable, $pk = null )
683  {
684  $instance = new WPDKDBTableRow( $dbtable, $pk );
685  return $instance;
686  }
687 
695  public function desc()
696  {
697  global $wpdb;
698  $sql = sprintf( 'DESC %s', $this->table->tableName );
699 
700  $result = $wpdb->get_results( $sql, OBJECT_K );
701 
702  return $result;
703  }
704 
710  public function defaults()
711  {
712  /* Override */
713  return array();
714  }
715 }
716 
718