| [ Index ] |
PHP Cross Reference of GlotPress |
[Summary view] [Print] [Text view]
1 <?php 2 class GP_Thing { 3 4 var $table = null; 5 var $field_names = array(); 6 var $non_db_field_names = array(); 7 var $errors = array(); 8 var $validation_rules = null; 9 var $per_page = 30; 10 var $map_results = true; 11 var $static = array(); 12 13 static $static_by_class = array(); 14 static $validation_rules_by_class = array(); 15 16 function __construct( $fields = array() ) { 17 global $gpdb; 18 $this->class = get_class( $this ); 19 $this->table = $gpdb->{$this->table_basename}; 20 foreach( $this->field_names as $field_name ) { 21 $this->$field_name = null; 22 } 23 $this->set_fields( $fields ); 24 25 if ( isset( self::$validation_rules_by_class[$this->class] ) ) { 26 $this->validation_rules = &self::$validation_rules_by_class[$this->class]; 27 } else { 28 $this->validation_rules = new GP_Validation_Rules( array_merge( $this->field_names, $this->non_db_field_names ) ); 29 // we give the rules as a parameter here solely as a syntax sugar 30 $this->restrict_fields( $this->validation_rules ); 31 self::$validation_rules_by_class[$this->class] = &$this->validation_rules; 32 } 33 if ( !$this->get_static( 'static-vars-are-set' ) ) { 34 foreach( get_class_vars( $this->class ) as $name => $value ) { 35 $this->set_static( $name, $value ); 36 } 37 $this->set_static( 'static-vars-are-set', true ); 38 } 39 } 40 41 function get_static( $name, $default = null ) { 42 return isset( self::$static_by_class[$this->class][$name] )? self::$static_by_class[$this->class][$name] : $default; 43 } 44 45 function has_static( $name ) { 46 return isset( self::$static_by_class[$this->class][$name] ); 47 } 48 49 function set_static( $name, $value ) { 50 self::$static_by_class[$this->class][$name] = $value; 51 } 52 53 function __call( $name, $args ) { 54 $suffix = '_no_map'; 55 if ( gp_endswith( $name, $suffix ) ) { 56 $name = substr( $name, 0, strlen( $name ) - strlen( $suffix ) ); 57 $this->map_results = false; 58 return call_user_func_array( array( &$this, $name ), $args ); 59 $this->map_results = true; 60 } 61 trigger_error(sprintf('Call to undefined function: %s::%s().', get_class($this), $name), E_USER_ERROR); 62 } 63 64 // CRUD 65 66 /** 67 * Retrieves all rows from this table 68 */ 69 function all( $order = null ) { 70 return $this->many( $this->select_all_from_conditions_and_order( array(), $order ) ); 71 } 72 73 /** 74 * Reloads the object data from the database, based on its id 75 */ 76 function reload() { 77 $this->set_fields( $this->get( $this->id ) ); 78 return $this; 79 } 80 81 /** 82 * Retrieves a single row from this table 83 * 84 * For parameters description see BPDB::prepare() 85 * @return mixed an object, containing the selected row or false on error 86 */ 87 function one() { 88 global $gpdb; 89 $args = func_get_args(); 90 return $this->coerce( $gpdb->get_row( $this->prepare( $args ) ) ); 91 } 92 93 /** 94 * Retrieves a single value from this table 95 * 96 * For parameters description see BPDB::prepare() 97 * @return scalar the result of the query or false on error 98 */ 99 function value() { 100 global $gpdb; 101 $args = func_get_args(); 102 $res = $gpdb->get_var( $this->prepare( $args ) ); 103 return is_null( $res )? false : $res; 104 } 105 106 function prepare( $args ) { 107 global $gpdb; 108 if ( 1 == count( $args ) ) { 109 return $args[0]; 110 } else { 111 $query = array_shift( $args ); 112 return $gpdb->prepare( $query, $args ); 113 } 114 } 115 116 /** 117 * Retrieves multiple rows from this table 118 * 119 * For parameters description see BPDB::prepare() 120 * @return mixed an object, containing the selected row or false on error 121 */ 122 function many() { 123 global $gpdb; 124 $args = func_get_args(); 125 return $this->map( $gpdb->get_results( $this->prepare( $args ) ) ); 126 } 127 128 function find_many( $conditions, $order = null ) { 129 return $this->many( $this->select_all_from_conditions_and_order( $conditions, $order ) ); 130 } 131 132 function find_one( $conditions, $order = null ) { 133 return $this->one( $this->select_all_from_conditions_and_order( $conditions, $order ) ); 134 } 135 136 function find( $conditions, $order = null ) { 137 return $this->find_many( $conditions, $order ); 138 } 139 140 function query() { 141 global $gpdb; 142 $args = func_get_args(); 143 return $gpdb->query( $this->prepare( $args ) ); 144 } 145 146 /** 147 * Inserts a new row 148 * 149 * @param $args array associative array with fields as keys and values as values 150 * @return mixed the object corresponding to the inserted row or false on error 151 */ 152 function create( $args ) { 153 global $gpdb; 154 $args = $this->prepare_fields_for_save( $args ); 155 $args = $this->prepare_fields_for_create( $args ); 156 $res = $gpdb->insert( $this->table, $args ); 157 if ( $res === false ) return false; 158 $class = $this->class; 159 $inserted = new $class( $args ); 160 $inserted->id = $gpdb->insert_id; 161 $inserted->after_create(); 162 return $inserted; 163 } 164 165 /** 166 * Inserts a record and then selects it back based on the id 167 * 168 * @param $args array see create() 169 * @return mixed the selected object or false on error 170 */ 171 function create_and_select( $args ) { 172 $created = $this->create( $args ); 173 if ( !$created ) return false; 174 $created->reload(); 175 return $created; 176 } 177 178 /** 179 * Updates a single row 180 * 181 * @param $data array associative array with fields as keys and updated values as values 182 */ 183 function update( $data, $where = null ) { 184 global $gpdb; 185 if ( !$data ) return false; 186 $where = is_null( $where )? array( 'id' => $this->id ) : $where; 187 $fields_for_save = $this->prepare_fields_for_save( $data ); 188 if ( is_array( $fields_for_save ) && empty( $fields_for_save ) ) return true; 189 return !is_null( $gpdb->update( $this->table, $fields_for_save, $where ) ); 190 } 191 192 function get( $thing_or_id ) { 193 global $gpdb; 194 if ( !$thing_or_id ) return false; 195 $id = is_object( $thing_or_id )? $thing_or_id->id : $thing_or_id; 196 return $this->find_one( array( 'id' => $id ) ); 197 } 198 199 function save( $args = null ) { 200 if ( is_null( $args ) ) $args = get_object_vars( $this ); 201 if ( !is_array( $args ) ) $args = (array)$args; 202 $args = $this->prepare_fields_for_save( $args ); 203 $update_res = $this->update( $args ); 204 $this->set_fields( $args ); 205 if ( !$update_res ) return null; 206 $update_res = $this->after_save(); 207 return $update_res; 208 } 209 210 function delete() { 211 return $this->delete_all( array( 'id' => $this->id ) ); 212 } 213 214 function delete_all( $where = null ) { 215 $query = "DELETE FROM $this->table"; 216 $conditions_sql = $this->sql_from_conditions( $where ); 217 if ( $conditions_sql ) $query .= " WHERE $conditions_sql"; 218 return $this->query( $query, $this->id ); 219 } 220 221 // Fields handling 222 223 function set_fields( $db_object ) { 224 $db_object = $this->normalize_fields( $db_object ); 225 foreach( $db_object as $key => $value ) { 226 $this->$key = $value; 227 } 228 } 229 230 /** 231 * Normalizes an array with key-value pairs representing 232 * a GP_Thing object. 233 * 234 * @todo Include default type handling. For example dates 0000-00-00 should be set to null 235 */ 236 function normalize_fields( $args ) { 237 return $args; 238 } 239 240 /** 241 * Prepares for enetering the database an array with 242 * key-value pairs, preresenting a GP_Thing object. 243 * 244 */ 245 function prepare_fields_for_save( $args ) { 246 $args = (array)$args; 247 $args = $this->normalize_fields( $args ); 248 unset( $args['id'] ); 249 foreach( $this->non_updatable_attributes as $attribute ) { 250 unset( $args[$attribute] ); 251 } 252 foreach( $args as $key => $value ) { 253 if ( !in_array( $key, $this->field_names ) ) { 254 unset( $args[$key] ); 255 } 256 } 257 258 if ( in_array( 'date_modified', $this->field_names ) ) { 259 $args['date_modified'] = $this->now_in_mysql_format(); 260 } 261 262 return $args; 263 } 264 265 function now_in_mysql_format() { 266 $now = new DateTime( 'now', new DateTimeZone( 'UTC' ) ); 267 return $now->format( DATE_MYSQL ); 268 } 269 270 function prepare_fields_for_create( $args ) { 271 if ( in_array( 'date_added', $this->field_names ) ) { 272 $args['date_added'] = $this->now_in_mysql_format(); 273 } 274 return $args; 275 } 276 277 function coerce( $thing ) { 278 if ( !$thing || is_wp_error( $thing ) ) { 279 return false; 280 } else { 281 $class = $this->class; 282 return new $class( $thing ); 283 } 284 } 285 286 function map( $results ) { 287 if ( isset( $this->map_results ) && !$this->map_results ) return $results; 288 if ( !$results || !is_array( $results ) ) $results = array(); 289 $mapped = array(); 290 foreach( $results as $result ) { 291 $mapped[] = $this->coerce( $result ); 292 } 293 return $mapped; 294 } 295 296 // Triggers 297 298 function after_create() { 299 return true; 300 } 301 302 function after_save() { 303 return true; 304 } 305 306 function sql_condition_from_php_value( $php_value ) { 307 global $gpdb; 308 if ( is_array( $php_value ) ) { 309 return array_map( array( &$this, 'sql_condition_from_php_value' ), $php_value ); 310 } 311 $operator = '='; 312 if ( is_integer( $php_value ) || ctype_digit( $php_value) ) 313 $sql_value = $php_value; 314 else 315 $sql_value = "'".$gpdb->escape( $php_value )."'"; 316 if ( is_null( $php_value ) ) { 317 $operator = 'IS'; 318 $sql_value = 'NULL'; 319 } 320 return "$operator $sql_value"; 321 } 322 323 function sql_from_conditions( $conditions ) { 324 if ( is_string( $conditions ) ) { 325 $conditions; 326 } elseif ( is_array( $conditions ) ) { 327 $conditions = array_map( array( &$this, 'sql_condition_from_php_value' ), $conditions ); 328 $string_conditions = array(); 329 foreach( $conditions as $field => $sql_condition ) { 330 if ( is_array( $sql_condition ) ) 331 $string_conditions[] = '('. implode( ' OR ', array_map( lambda( '$cond', '"$field $cond"', compact('field') ), $sql_condition ) ) . ')'; 332 else 333 $string_conditions[] = "$field $sql_condition"; 334 } 335 $conditions = implode( ' AND ', $string_conditions ); 336 } 337 return $this->apply_default_conditions( $conditions ); 338 } 339 340 function sql_from_order( $order_by, $order_how = '' ) { 341 if ( is_array( $order_by ) ) { 342 $order_by = implode( ' ', $order_by ); 343 $order_how = ''; 344 } 345 $order_by = trim( $order_by ); 346 if ( !$order_by ) return gp_member_get( $this, 'default_order' ); 347 return 'ORDER BY ' . $order_by . ( $order_how? " $order_how" : '' ); 348 } 349 350 function select_all_from_conditions_and_order( $conditions, $order = null ) { 351 $query = "SELECT * FROM $this->table"; 352 $conditions_sql = $this->sql_from_conditions( $conditions ); 353 if ( $conditions_sql ) $query .= " WHERE $conditions_sql"; 354 $order_sql = $this->sql_from_order( $order ); 355 if ( $order_sql ) $query .= " $order_sql"; 356 return $query; 357 } 358 359 function restrict_fields( $thing ) { 360 // Don't restrict any fields by default 361 } 362 363 function validate() { 364 $verdict = $this->validation_rules->run( $this ); 365 $this->errors = $this->validation_rules->errors; 366 return $verdict; 367 } 368 369 function force_false_to_null( $value ) { 370 return $value? $value : null; 371 } 372 373 function fields() { 374 $result = array(); 375 foreach( array_merge( $this->field_names, $this->non_db_field_names ) as $field_name ) { 376 if ( isset( $this->$field_name ) ) { 377 $result[$field_name] = $this->$field_name; 378 } 379 } 380 return $result; 381 } 382 383 function sql_limit_for_paging( $page, $per_page = null ) { 384 $per_page = is_null( $per_page )? $this->per_page : $per_page; 385 if ( 'no-limit' == $per_page || 'no-limit' == $page ) return ''; 386 $page = intval( $page )? intval( $page ) : 1; 387 return sprintf( "LIMIT %d OFFSET %d", $per_page, ($page-1)*$per_page ); 388 } 389 390 function found_rows() { 391 global $gpdb; 392 return $gpdb->get_var("SELECT FOUND_ROWS();"); 393 } 394 395 function like_escape_printf( $s ) { 396 return str_replace( '%', '%%', like_escape( $s ) ); 397 } 398 399 function apply_default_conditions( $conditions_str ) { 400 $conditions = array(); 401 if ( isset( $this->default_conditions ) ) $conditions[] = $this->default_conditions; 402 if ( $conditions_str ) $conditions[] = $conditions_str; 403 return implode( ' AND ', $conditions ); 404 } 405 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Tue May 21 03:59:56 2013 | Hosted by follow the white rabbit. |