PluginProbe
FV Player 8 / 8.1
FV Player 8 v8.1
trunk 8.0.18 8.0.19 8.0.20 8.0.21 8.0.25 8.0.27 8.1 8.1.3
fv-player / models / db-player-meta.php

db-player-meta.php in FV Player 8 8.1, at models/db-player-meta.php

563 lines 17.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /* FV Player - HTML5 video player
3 Copyright (C) 2013 Foliovision
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 // player meta data instance with options that's stored in a DB
20 class FV_Player_Db_Player_Meta {
21
22 private
23 $id, // automatic ID for the meta data
24 $is_valid = true, // used when loading meta data from DB to determine whether we've found it
25 $id_player, // DB ID of the video to which this meta data belongs
26 $meta_key, // arbitrary meta key
27 $meta_value; // arbitrary meta value
28
29 private static
30 $db_table_name,
31 $DB_Instance = null;
32
33 /**
34 * @param mixed $meta_value
35 */
36 public function setMetaValue( $meta_value ) {
37 $this->meta_value = $meta_value;
38 }
39
40 /**
41 * @return int
42 */
43 public function getId() {
44 return $this->id;
45 }
46
47 /**
48 * @return int
49 */
50 public function getIdPlayer() {
51 return $this->id_player;
52 }
53
54 /**
55 * @return string
56 */
57 public function getMetaKey() {
58 return $this->meta_key;
59 }
60
61 /**
62 * @return mixed
63 */
64 public function getMetaValue() {
65 return $this->meta_value;
66 }
67
68 /**
69 * @return bool
70 */
71 public function getIsValid() {
72 return $this->is_valid;
73 }
74
75 /**
76 * Initializes database name, including WP prefix
77 * once WPDB class is initialized.
78 *
79 * @return string Returns the actual table name for this ORM class.
80 */
81 public static function init_db_name() {
82 global $wpdb;
83
84 self::$db_table_name = $wpdb->prefix.'fv_player_playermeta';
85 return self::$db_table_name;
86 }
87
88 /**
89 * Returns name of the video DB table.
90 *
91 * @return mixed The name of the video DB table.
92 */
93 public static function get_db_table_name() {
94 if ( !self::$db_table_name ) {
95 self::init_db_name();
96 }
97
98 return self::$db_table_name;
99 }
100
101 /**
102 * Checks for DB tables existence and creates it as necessary.
103 *
104 * @param $force Forces to run dbDelta.
105 */
106 public static function initDB($force = false) {
107 global $wpdb, $fv_fp, $fv_wp_flowplayer_ver;
108
109 self::init_db_name();
110
111 $res = false;
112
113 if( defined('PHPUnitTestMode') || !$fv_fp->_get_option('player_meta_model_db_checked') || $fv_fp->_get_option('player_meta_model_db_checked') != $fv_wp_flowplayer_ver || $force ) {
114 $sql = "
115 CREATE TABLE " . self::$db_table_name . " (
116 id bigint(20) unsigned NOT NULL auto_increment,
117 id_player bigint(20) unsigned NOT NULL default '0',
118 meta_key varchar(255) NOT NULL,
119 meta_value longtext NOT NULL,
120 PRIMARY KEY (id),
121 KEY id_player (id_player),
122 KEY meta_key (meta_key(191))
123 )" . $wpdb->get_charset_collate() . ";";
124 require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
125 $res = dbDelta( $sql );
126 $fv_fp->_set_option('player_meta_model_db_checked', $fv_wp_flowplayer_ver);
127 }
128
129 return $res;
130 }
131
132 /**
133 * Makes this meta data object linked to a record in database.
134 * Used for player preview purposes.
135 *
136 * @param int $id The DB ID to which we'll link this meta data record.
137 * @param bool $id_is_player If true, link to an actual player ID will be made.
138 */
139 public function link2db($id, $id_is_player = false) {
140 if (!$id_is_player) {
141 $this->id = (int) $id;
142 } else {
143 $this->id_player = (int) $id;
144 }
145 }
146
147 /**
148 * FV_Player_Db_Player_Meta constructor.
149 *
150 * @param int $id ID of player meta data to load data from the DB for.
151 * @param array $options Options for a newly created player meta data that will be stored in a DB.
152 * @param FV_Player_Db $DB_Cache Instance of the DB shortcode global object that handles caching
153 * of videos, players and their meta data.
154 *
155 * @throws Exception When no valid ID nor options are provided.
156 */
157 function __construct($id, $options = array(), $DB_Cache = null) {
158 global $wpdb;
159
160 if ($DB_Cache) {
161 self::$DB_Instance = $DB_Cache;
162 } else {
163 global $FV_Player_Db;
164 self::$DB_Instance = $DB_Cache = $FV_Player_Db;
165 }
166
167 self::initDB();
168 $multiID = is_array($id);
169
170 // don't load anything, if we've only created this instance
171 // to initialize the database (this comes from list-table.php and unit tests)
172 if ($id === -1) {
173 return;
174 }
175
176 // check whether we're not trying to load data for a single player
177 // rather than meta data by its own ID
178 $load_for_player = false;
179 $force_cache_update = false;
180
181 // first, check if we're not trying to search for a meta item from the database
182 if (is_array($options) && count($options) && !empty($options['meta_find_player'])) {
183 $db_data = $wpdb->get_row(
184 $wpdb->prepare(
185 "SELECT id_player FROM `{$wpdb->prefix}fv_player_playermeta` WHERE meta_key = %s AND meta_value = %s",
186 $options['meta_find_player']['key'],
187 $options['meta_find_player']['value']
188 ),
189 ARRAY_A
190 );
191
192 unset($options['meta_find_player']);
193
194 // DB data found, load meta data for the player
195 if (isset($db_data) && $db_data !== -1 && is_array($db_data) && count($db_data)) {
196 $options['id_player'] = array($db_data['id_player']);
197 }
198 }
199
200 if (is_array($options) && count($options) && isset($options['id_player']) && is_array($options['id_player'])) {
201 $load_for_player = true;
202 $multiID = true;
203 $id = $options['id_player'];
204 // reset this, so we don't try to create a new record below
205 $options = array();
206 }
207
208 // if we've got options, fill them in instead of querying the DB,
209 // since we're storing new player meta data into the DB in such case
210 if (is_array($options) && count($options)) {
211 foreach ($options as $key => $value) {
212 if (property_exists($this, $key)) {
213 if ($key !== 'id') {
214 $this->$key = FV_Player_Db::sanitize( $value );
215 }
216 } else {
217 // generate warning
218 trigger_error('Unknown property for new DB player meta data item: ' . $key);
219 }
220 }
221 } else if ($multiID || (is_numeric($id) && $id > 0)) {
222 /* @var $cache FV_Player_Db_Player_Meta[] */
223 $cache = ($DB_Cache ? $DB_Cache->getPlayerMetaCache() : array());
224 $all_cached = false;
225 $some_meta_exist = false;
226
227 // no options, load data from DB
228 if ($multiID) {
229 $query_ids = array();
230
231 // make sure we have numeric IDs and that they're not cached yet
232 $is_cached = false;
233 foreach ($id as $id_key => $id_value) {
234 if ($load_for_player) {
235 $is_cached = isset($cache[$id_value]);
236 $some_meta_exist = ($is_cached ? count($cache[$id_value]) : false);
237 } else {
238 // run through all the cached data and check
239 // whether our meta data ID was not cached yet
240 foreach ($cache as $player_meta) {
241 if (isset($player_meta[$id_value])) {
242 $is_cached = true;
243 $some_meta_exist = (count($player_meta[$id_value]) ? true : false);
244 }
245 }
246 }
247
248 // select from DB if not cached yet
249 if (!$is_cached) {
250 $query_ids[ $id_key ] = $id_value;
251 }
252
253 $id[$id_key] = (int) $id_value;
254 }
255
256 if (count($query_ids)) {
257 // load multiple player metas via their IDs but a single query and return their values
258 $placeholders = implode( ', ', array_fill( 0, count( $query_ids ), '%d' ) );
259
260 if ( $load_for_player ) {
261 $meta_data = $wpdb->get_results(
262 $wpdb->prepare(
263 // $placeholders is a string of %d created above
264 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
265 "SELECT * FROM `{$wpdb->prefix}fv_player_playermeta` WHERE id_player IN( $placeholders )",
266 $query_ids
267 )
268 );
269
270 } else {
271 $meta_data = $wpdb->get_results(
272 $wpdb->prepare(
273 // $placeholders is a string of %d created above
274 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
275 "SELECT * FROM `{$wpdb->prefix}fv_player_playermeta` WHERE id IN( $placeholders )",
276 $query_ids
277 )
278 );
279 }
280
281 // run through all of the meta data and
282 // fill the ones that were not found with blank arrays
283 // for cache-filling purposes
284 if (!is_array($meta_data)) {
285 $meta_data = array();
286 }
287
288 foreach ($query_ids as $q_id) {
289 $meta_found = false;
290 foreach ($meta_data as $m_data) {
291 if (($load_for_player && $m_data->id_player == $q_id) || (!$load_for_player && $m_data->id == $q_id)) {
292 $meta_found = true;
293 break;
294 }
295 }
296
297 // if we have no meta data for the requested ID,
298 // fill it with an empty array
299 if (!$meta_found) {
300 $force_cache_update = true;
301
302 if ($load_for_player) {
303 // for player, create an empty array with no meta
304 $cache[$q_id] = array();
305 } else {
306 // for a single meta, initialize it with null value
307 // on a 0-id player (which obviously cannot exist,
308 // so we can use it for cache-checking purposes)
309 $cache[0][$q_id] = null;
310 }
311 }
312 }
313 } else {
314 $all_cached = true;
315 }
316 } else {
317 $is_cached = false;
318 if ($load_for_player) {
319 $is_cached = isset($cache[$id]);
320 $some_meta_exist = ($is_cached ? count($cache[$id]) : false);
321 } else {
322 // run through all the cached data and check
323 // whether our meta data ID was not cached yet
324 foreach ($cache as $player_id => $player_meta) {
325 if (isset($player_meta[$id])) {
326 $is_cached = true;
327 $some_meta_exist = is_array( $player_meta[ $id ] ) && count( $player_meta[ $id ] ) ? true : false;
328 }
329 }
330 }
331
332 if (!$is_cached) {
333 // load a single player meta data record
334 $meta_data = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM `{$wpdb->prefix}fv_player_playermeta` WHERE id = %d", $id ) );
335
336 // run through all of the meta data and
337 // fill the ones that were not found with blank arrays
338 // for cache-filling purposes
339 if (!is_array($meta_data)) {
340 $meta_data = array();
341 }
342
343 $meta_found = false;
344 foreach ($meta_data as $m_data) {
345 if (($load_for_player && $m_data->id_player == $id) || (!$load_for_player && $m_data->id == $id)) {
346 $meta_found = true;
347 break;
348 }
349 }
350
351 // if we have no meta data for the requested ID,
352 // fill it with an empty array
353 if (!$meta_found) {
354 $force_cache_update = true;
355
356 if ($load_for_player) {
357 // for player, create an empty array with no meta
358 $cache[$id] = array();
359 } else {
360 // for a single meta, initialize it with null value
361 // on a 0-id player (which obviously cannot exist,
362 // so we can use it for cache-checking purposes)
363 $cache[0][$id] = null;
364 }
365 }
366 } else {
367 $all_cached = true;
368 }
369 }
370
371 if (isset($meta_data) && $meta_data && count($meta_data)) {
372 // single ID, just populate our own data
373 if (!$multiID) {
374 // fill-in our internal variables, as they have the same name as DB fields (ORM baby!)
375 foreach ( $meta_data as $key => $value ) {
376 $this->$key = FV_Player_Db::sanitize( $value );
377 }
378
379 // cache this meta in DB object
380 if ($DB_Cache) {
381 $cache[$this->id_player][$this->id] = $this;
382 }
383 } else {
384 // multiple IDs, create new player meta objects for each of them except the first one,
385 // for which we'll use this instance
386 $first_done = false;
387 foreach ($meta_data as $db_record) {
388 if (!$first_done) {
389 // fill-in our internal variables
390 foreach ( $db_record as $key => $value ) {
391 $this->$key = FV_Player_Db::sanitize( $value );
392 }
393
394 $first_done = true;
395
396 // cache this meta in DB object
397 if ($DB_Cache) {
398 $cache[$db_record->id_player][$this->id] = $this;
399 }
400 } else {
401 // create a new player meta object and populate it with DB values
402 $record_id = $db_record->id;
403 // if we don't unset this, we'll get warnings
404 unset($db_record->id);
405
406 if ($DB_Cache && !$DB_Cache->isPlayerMetaCached($db_record->id_player, $record_id)) {
407 $player_meta_object = new FV_Player_Db_Player_Meta( null, get_object_vars( $db_record ), $DB_Cache );
408 $player_meta_object->link2db( $record_id );
409
410 // cache this meta in DB object
411 if ( $DB_Cache ) {
412 $cache[ $db_record->id_player ][ $record_id ] = $player_meta_object;
413 }
414 }
415 }
416 }
417 }
418 } else if ($all_cached && $some_meta_exist) {
419 // fill the data for this class with data of the cached class
420 if ($multiID) {
421 $cached_meta = reset($id);
422 } else {
423 $cached_meta = $id;
424 }
425
426 // find the meta in cache and reassign $cached_meta
427 foreach ($cache as $player_id => $player) {
428 if ($load_for_player && $player_id == $cached_meta ) {
429 // load first meta for the requested player
430 $cached_meta = reset( $player );
431 break;
432 } else if (!$load_for_player && isset($player[$cached_meta])) {
433 $cached_meta = $player[$cached_meta];
434 break;
435 }
436 }
437
438 // $cached_meta will remain numeric if there are no meta data in the database
439 if ($cached_meta instanceof FV_Player_Db_Player_Meta) {
440 foreach ( $cached_meta->getAllDataValues() as $key => $value ) {
441 $this->$key = FV_Player_Db::sanitize( $value );
442 }
443 }
444 } else {
445 $this->is_valid = false;
446 }
447 }
448
449 // update cache, if changed
450 if (isset($cache) && ($force_cache_update || !isset($all_cached) || !$all_cached)) {
451 self::$DB_Instance->setPlayerMetaCache($cache);
452 }
453 }
454
455 /**
456 * Returns all options data for this player meta object.
457 *
458 * @return array Returns all options data for this player meta object.
459 */
460 public function getAllDataValues() {
461 $data = array();
462 foreach (get_object_vars($this) as $property => $value) {
463 if ($property != 'is_valid' && $property != 'db_table_name' && $property != 'DB_Instance') {
464 $data[$property] = $value;
465 }
466 }
467
468 return $data;
469 }
470
471 /**
472 * Stores new player meta data item or updates and existing one
473 * in the database.
474 *
475 * @return bool|int Returns record ID if successful, false otherwise.
476 */
477 public function save() {
478 global $wpdb;
479
480 $is_update = ($this->id ? true : false);
481 $data_values = array();
482
483 foreach (get_object_vars($this) as $property => $value) {
484 if ($property != 'id' && $property != 'is_valid' && $property != 'db_table_name' && $property != 'DB_Instance') {
485 $data_values[ $property ] = $value;
486 }
487 }
488
489 if ($is_update) {
490 $wpdb->update( self::$db_table_name, $data_values, array( 'id' => $this->id ) );
491
492 } else {
493 $wpdb->insert( self::$db_table_name, $data_values );
494 }
495
496 if (!$is_update) {
497 $this->id = $wpdb->insert_id;
498 }
499
500 if (!$wpdb->last_error) {
501 // add this meta into cache
502 $cache = self::$DB_Instance->getPlayerMetaCache();
503 $cache[$this->id_player][$this->id] = $this;
504 self::$DB_Instance->setPlayerMetaCache($cache);
505
506 return $this->id;
507 } else {
508 /*var_export($wpdb->last_error);
509 var_export($wpdb->last_query);*/
510 return false;
511 }
512 }
513
514 /**
515 * Prepares this class' properties for export
516 * and returns them in an associative array.
517 *
518 * @return array Returns an associative array of this class' properties and their values.
519 */
520 public function export() {
521 $export_data = array();
522 foreach (get_object_vars($this) as $property => $value) {
523 if ($property != 'id' && $property != 'id_player' && $property != 'is_valid' && $property != 'db_table_name' && $property != 'DB_Instance') {
524 $export_data[$property] = $value;
525 }
526 }
527
528 return $export_data;
529 }
530
531
532 /**
533 * Removes meta data instance from the database.
534 *
535 * @return bool Returns true if the delete was successful, false otherwise.
536 */
537 public function delete() {
538 // not a DB meta? no delete
539 if (!$this->is_valid) {
540 return false;
541 }
542
543 global $wpdb;
544
545 $wpdb->delete(self::$db_table_name, array('id' => $this->id));
546
547 if (!$wpdb->last_error) {
548 // remove this meta from cache
549 $cache = self::$DB_Instance->getPlayerMetaCache();
550 if (isset($cache[$this->id_player][$this->id])) {
551 unset($cache[$this->id_player][$this->id]);
552 self::$DB_Instance->setPlayerMetaCache($cache);
553 }
554
555 return true;
556 } else {
557 /*var_export($wpdb->last_error);
558 var_export($wpdb->last_query);*/
559 return false;
560 }
561 }
562 }
563