Completed
Push — master ( 6cab57...287bd7 )
by Sam
02:34
created

src/DB/Record.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * This file contains only a single class.
4
 *
5
 * @file
6
 * @package Tabulate
7
 */
8
9
namespace WordPress\Tabulate\DB;
10
11
/**
12
 * A record is a single row from a database table.
13
 */
14
class Record {
15
16
	/**
17
	 * The table that this record belongs to.
18
	 *
19
	 * @var Table
20
	 */
21
	protected $table;
22
23
	/**
24
	 * The raw data of this database row.
25
	 *
26
	 * @var \stdClass
27
	 */
28
	protected $data;
29
30
	/**
31
	 * The suffix that is added to foreign keys when we want to get their
32
	 * 'title' value instead of their raw integer (or whatever) form.
33
	 */
34
	const FKTITLE = 'FKTITLE';
35
36
	/**
37
	 * Create a new Record object.
38
	 *
39
	 * @param Table $table The table object.
40
	 * @param array $data The data of this record.
41
	 */
42
	public function __construct( $table, $data = array() ) {
43
		$this->table = $table;
44
		$this->data = (object) $data;
45
	}
46
47
	/**
48
	 * Magic method to set one item in the data object.
49
	 *
50
	 * @param string $name The name of the column.
51
	 * @param mixed  $value The value to set.
52
	 */
53
	public function __set( $name, $value ) {
54
		$this->data->{$name} = $value;
55
	}
56
57
	/**
58
	 * Set multiple columns' values.
59
	 *
60
	 * @param mixed[] $data An array of column names to data values.
61
	 */
62
	public function set_multiple( $data ) {
63
		if ( ! is_array( $data ) ) {
64
			return;
65
		}
66
		foreach ( $data as $col => $datum ) {
67
			$this->$col = $datum;
68
		}
69
	}
70
71
	/**
72
	 * Get a column's value. If suffixed with 'FKTITLE', then get the title of
73
	 * the foreign record (where applicable).
74
	 *
75
	 * @param string   $name The column name.
76
	 * @param mixed [] $args Parameter not used.
77
	 * @return string|boolean
78
	 * @throws Exception If any arguments are passed (as there should never be any).
79
	 */
80
	public function __call( $name, $args ) {
81
		if ( ! empty( $args ) ) {
82
			throw new Exception( 'Record::colname() functions take no arguments.' );
83
		}
84
85
		// Foreign key 'title' values.
86
		$use_title = substr( $name, -strlen( self::FKTITLE ) ) === self::FKTITLE;
87
		if ( $use_title ) {
88
			$name = substr( $name, 0, -strlen( self::FKTITLE ) );
89
			$col = $this->get_col( $name );
90
			if ( $col->is_foreign_key() && ! empty( $this->data->$name ) ) {
91
				$referenced_table = $col->get_referenced_table();
92
				$fk_record = $referenced_table->get_record( $this->data->$name );
93
				$fk_title_col = $referenced_table->get_title_column();
94
				$fk_title_col_name = $fk_title_col->get_name();
95
				if ( $fk_title_col->is_foreign_key() ) {
96
					// Use title if the FK's title column is also an FK.
97
					$fk_title_col_name .= self::FKTITLE;
98
				}
99
				return $fk_record->$fk_title_col_name();
100
			}
101
		}
102
		$col = $this->get_col( $name );
103
104
		// Booleans.
105
		if ( $col->is_boolean() ) {
106
			// Numbers are fetched from the DB as strings.
107
			if ( '1' === $this->data->$name ) {
108
				return true;
109
			} elseif ( '0' === $this->data->$name ) {
110
				return false;
111
			} else {
112
				return null;
113
			}
114
		}
115
116
		// Standard column values.
117
		if ( isset( $this->data->$name ) ) {
118
			return $this->data->$name;
119
		}
120
	}
121
122
	/**
123
	 * Get a column of this record's table, optionally throwing an Exception if
124
	 * it doesn't exist.
125
	 *
126
	 * @param string  $name The name of the column.
127
	 * @param boolean $required True if this should throw an Exception.
128
	 * @return \WordPress\Tabulate\DB\Column The column.
129
	 * @throws \Exception If the column named doesn't exist.
130
	 */
131
	protected function get_col( $name, $required = true ) {
132
		$col = $this->table->get_column( $name );
0 ignored issues
show
Comprehensibility Best Practice introduced by Sam Wilson
The expression $this->table->get_column($name); of type WordPress\Tabulate\DB\Column|false adds false to the return on line 136 which is incompatible with the return type documented by WordPress\Tabulate\DB\Record::get_col of type WordPress\Tabulate\DB\Column. It seems like you forgot to handle an error condition.
Loading history...
133
		if ( $required && false === $col ) {
134
			throw new \Exception( "Unable to get column $name on table " . $this->table->get_name() );
135
		}
136
		return $col;
137
	}
138
139
	/**
140
	 * Get a string representation of this record.
141
	 *
142
	 * @return string
143
	 */
144
	public function __toString() {
145
		return join( ', ', $this->data );
146
	}
147
148
	/**
149
	 * Get the value of this record's primary key, or false if it doesn't have
150
	 * one.
151
	 *
152
	 * @return string|false
153
	 */
154
	public function get_primary_key() {
155
		if ( $this->table->get_pk_column() ) {
156
			$pk_col_name = $this->table->get_pk_column()->get_name();
157
			if ( isset( $this->data->$pk_col_name ) ) {
158
				return $this->data->$pk_col_name;
159
			}
160
		}
161
		return false;
162
	}
163
164
	/**
165
	 * Get the value of this Record's title column.
166
	 *
167
	 * @return string
168
	 */
169
	public function get_title() {
170
		$title_col = $this->table->get_title_column();
171
		if ( $title_col !== $this->table->get_pk_column() ) {
172
			$title_col_name = $title_col->get_name();
173
			return $this->data->$title_col_name;
174
		} else {
175
			$title_parts = array();
176
			foreach ( $this->table->get_columns() as $col ) {
177
				$col_name = $col->get_name() . self::FKTITLE;
178
				$title_parts[] = $this->$col_name();
179
			}
180
			return '[ ' . join( ' | ', $title_parts ) . ' ]';
181
		}
182
	}
183
184
	/**
185
	 * Get the record that is referenced by this one from the column given.
186
	 *
187
	 * @param string $column_name The name of the column.
188
	 * @return boolean|\WordPress\Tabulate\DB\Record
189
	 */
190
	public function get_referenced_record( $column_name ) {
191
		if ( ! isset( $this->data->$column_name ) ) {
192
			return false;
193
		}
194
		return $this->table
195
			->get_column( $column_name )
196
			->get_referenced_table()
197
			->get_record( $this->data->$column_name );
198
	}
199
200
	/**
201
	 * Get a list of records that reference this record in one of their columns.
202
	 *
203
	 * @param string|\WordPress\Tabulate\DB\Table  $foreign_table The foreign table.
204
	 * @param string|\WordPress\Tabulate\DB\Column $foreign_column The column in the foreign table that references this record's table.
205
	 * @param boolean                              $with_pagination Whether to only return the top N records.
206
	 * @return \WordPress\Tabulate\DB\Record[]
207
	 */
208
	public function get_referencing_records( $foreign_table, $foreign_column, $with_pagination = true ) {
209
		$foreign_table->reset_filters();
210
		$foreign_table->add_filter( $foreign_column, '=', $this->get_primary_key(), true );
211
		return $foreign_table->get_records( $with_pagination );
212
	}
213
214
	/**
215
	 * Get an Admin Area URL.
216
	 *
217
	 * @param string   $action The action.
218
	 * @param boolean  $include_ident Whether to include the record Primary Key.
219
	 * @param string[] $extra_params Other parameters to append to the URL.
220
	 * @return string The URL.
221
	 */
222
	public function get_url( $action = 'index', $include_ident = true, $extra_params = false ) {
223
		$params = array(
224
			'page' => 'tabulate',
225
			'controller' => 'record',
226
			'action' => $action,
227
			'table' => $this->table->get_name(),
228
		);
229
		if ( $include_ident && false !== $this->get_primary_key() ) {
230
			$params['ident'] = $this->get_primary_key();
231
		}
232
		if ( is_array( $extra_params ) ) {
233
			$params = array_merge( $params, $extra_params );
234
		}
235
		return admin_url( 'admin.php?' . http_build_query( $params ) );
236
	}
237
238
	/**
239
	 * Get most recent changes.
240
	 *
241
	 * @return string[]
242
	 */
243
	public function get_changes() {
244
		$wpdb = $this->table->get_database()->get_wpdb();
245
		$sql = "SELECT cs.id AS changeset_id, c.id AS change_id, date_and_time, "
246
			. "user_nicename, table_name, record_ident, column_name, old_value, "
247
			. "new_value, comment "
248
			. "FROM " . ChangeTracker::changes_name() . " c "
249
			. "  JOIN " . ChangeTracker::changesets_name() . " cs ON (c.changeset_id=cs.id) "
250
			. "  JOIN {$wpdb->prefix}users u ON (u.ID=cs.user_id) "
251
			. "WHERE table_name = %s AND record_ident = %s"
252
			. "ORDER BY date_and_time DESC, cs.id DESC "
253
			. "LIMIT 15 ";
254
		$params = array( $this->table->get_name(), $this->get_primary_key() );
255
		return $wpdb->get_results( $wpdb->prepare( $sql, $params ) );
256
	}
257
}
258