PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.2.1
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.2.1
6.2.2 6.2.1 6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 All 155 releases
← All changes | class/class-mainwp-db-client.php +21 -3 6.1.8 → 6.2.1 View file →
@@ -1195,9 +1195,12 @@
1195 1195 *
1196 1196 * @return mixed bool|results.
1197 1197 */
1198 1198 public function add_client_field( $field ) {
1199 - if ( ! empty( $field['field_name'] ) && isset( $field['client_id'] ) ) {
1199 + // "0" is a name the column stores, so the write is refused only for a name that is missing
1200 + // or empty, not for every name PHP reads as falsy. A name that is not a string is refused
1201 + // outright: false is set and is not '', and it would reach the column as an empty name.
1202 + if ( isset( $field['field_name'] ) && is_string( $field['field_name'] ) && '' !== $field['field_name'] && isset( $field['client_id'] ) ) {
1200 1203 if ( $this->get_client_fields_by( 'field_name', $field['field_name'], $field['client_id'] ) ) { // field name existed for the client can not create.
1201 1204 return false;
1202 1205 }
1203 1206 if ( $this->wpdb->insert( $this->table_name( 'wp_clients_fields' ), $field ) ) {
@@ -1217,9 +1220,11 @@
1217 1220 *
1218 1221 * @return mixed|false field.
1219 1222 */
1220 1223 public function update_client_field( $field_id, $field ) {
1221 - if ( $field_id && ! empty( $field['field_name'] ) ) {
1224 + // Same as the add above: a rename to "0" is a rename, not a name left out, and a name that
1225 + // is not a string would be written over the stored name as an empty one.
1226 + if ( $field_id && isset( $field['field_name'] ) && is_string( $field['field_name'] ) && '' !== $field['field_name'] ) {
1222 1227 $current = $this->get_client_fields_by( 'field_id', $field_id );
1223 1228 if ( $current && $this->wpdb->update( $this->table_name( 'wp_clients_fields' ), $field, array( 'field_id' => $field_id ) ) ) {
1224 1229 return $this->get_client_fields_by( 'field_id', $current->field_id );
1225 1230 }
@@ -1273,9 +1278,15 @@
1273 1278 * @return mixed|null $field field data.
1274 1279 */
1275 1280 public function get_client_fields_by( $by = 'field_id', $value = null, $client_id = 0 ) {
1276 1281
1277 - if ( empty( $by ) || empty( $value ) ) {
1282 + // "0" is a name the column stores, so a falsy test here would make a field named "0" unfindable
1283 + // and let a second one be created under the same name. Only the name lookup takes that
1284 + // exception: every other column keeps refusing a falsy value, so a client_id of 0 stays "no
1285 + // client" instead of matching every general field.
1286 + $missing = 'field_name' === $by ? ( null === $value || '' === $value ) : empty( $value );
1287 +
1288 + if ( empty( $by ) || $missing ) {
1278 1289 return null;
1279 1290 }
1280 1291
1281 1292 $sql = '';
@@ -1376,8 +1387,15 @@
1376 1387 // Handle search.
1377 1388 if ( isset( $params['search'] ) && ! empty( $params['search'] ) ) {
1378 1389 $search_term = $this->escape( htmlspecialchars( $params['search'] ) );
1379 1390 $where .= ' AND clients_fields.field_name LIKE "%' . $search_term . '%"';
1391 + }
1392 +
1393 + // Handle exact field name. The value is queried as it is stored, with no bracket stripping, so
1394 + // the column collation decides equality the same way the unique index does. An empty string
1395 + // filters on an empty name; pass null to leave the filter off.
1396 + if ( isset( $params['field_name_exact'] ) && is_string( $params['field_name_exact'] ) ) {
1397 + $where .= $this->wpdb->prepare( ' AND clients_fields.field_name = %s', $params['field_name_exact'] );
1380 1398 }
1381 1399
1382 1400 // Handle client id.
1383 1401 if ( isset( $params['client_id'] ) && ! empty( $params['client_id'] ) ) {