# contact-forms/2.3.5/admin/class-fields-list-table.php

Contact Forms by Cimatti, version 2.3.5. 226 lines.

- Page: https://pluginprobe.com/plugins/contact-forms/2.3.5/code/admin/class-fields-list-table.php
- Raw: https://pluginprobe.com/plugins/contact-forms/2.3.5/raw/admin/class-fields-list-table.php
- Modified: 2026-08-21T08:40:42+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/contact-forms/2.3.5/code/admin/class-fields-list-table.php#L10-L20`.

```php
<?php
if ( ! defined( 'ABSPATH' ) ) exit;

if ( ! class_exists( 'WP_List_Table' ) ) {
	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}

class Accua_Forms_Fields_List_Table extends WP_List_Table {

	private $field_types = array();

	/** The current search term, read once in prepare_items(). */
	private $search = '';

	function __construct() {
		parent::__construct( array(
			'singular' => 'field',
			'plural'   => 'fields',
			'ajax'     => false,
		) );
		$this->field_types = accua_forms_fields_get_types();
	}

	function get_columns() {
		return array(
			'cb'          => '<input type="checkbox" />',
			'name'        => __( 'Label', 'contact-forms' ),
			'slug'        => __( 'Slug', 'contact-forms' ),
			'type'        => __( 'Type', 'contact-forms' ),
			'forms'       => __( 'Forms', 'contact-forms' ),
			'description' => __( 'Description', 'contact-forms' ),
		);
	}

	function get_sortable_columns() {
		return array(
			'name'  => array( 'name', false ),
			'slug'  => array( 'slug', false ),
			'type'  => array( 'type', false ),
			'forms' => array( 'forms', false ),
		);
	}

	function get_bulk_actions() {
		return array(
			'delete' => __( 'Delete', 'contact-forms' ),
		);
	}

	function column_cb( $item ) {
		return sprintf(
			'<input type="checkbox" name="fields[]" value="%s" />',
			esc_attr( $item['slug'] )
		);
	}

	function column_default( $item, $column_name ) {
		if ( isset( $item[ $column_name ] ) ) {
			return esc_html( $item[ $column_name ] );
		}
		return '';
	}

	function column_name( $item ) {
		$edit_url = admin_url( 'admin.php?page=accua_forms_fields&edit-fid=' . urlencode( $item['slug'] ) );
		$delete_url = wp_nonce_url(
			admin_url( 'admin.php?page=accua_forms_fields&delete-fid=' . urlencode( $item['slug'] ) ),
			'delete_form_field_' . $item['slug']
		);
		$actions = array(
			'edit' => sprintf(
				'<a href="%s">%s</a>',
				esc_url( $edit_url ),
				esc_html__( 'Edit', 'contact-forms' )
			),
			'delete' => sprintf(
				'<a href="%s" class="delete-tag" onclick="return confirm(\'%s\');">%s</a>',
				esc_url( $delete_url ),
				esc_js( __( 'Are you sure you want to delete this field?', 'contact-forms' ) ),
				esc_html__( 'Delete', 'contact-forms' )
			),
		);
		return sprintf(
			'<strong><a class="row-title" href="%s">%s</a></strong>%s',
			esc_url( $edit_url ),
			esc_html( $item['name'] ),
			$this->row_actions( $actions )
		);
	}

	function column_type( $item ) {
		$type_key = $item['type'];
		if ( isset( $this->field_types[ $type_key ] ) ) {
			return esc_html( $this->field_types[ $type_key ] );
		}
		return esc_html( $type_key );
	}

	function column_forms( $item ) {
		$count = $item['forms'];
		if ( $count > 0 ) {
			return '<span>' . (int) $count . '</span>';
		}
		return '0';
	}

	/**
	 * Whether a row matches the current search.
	 *
	 * Searches the text the table actually shows: label, slug, type and
	 * description. The type is matched on its human-readable label as well as
	 * its key, so "Casella di controllo" finds a checkbox field on an Italian
	 * install just as "checkbox" does on an English one.
	 */
	private function matches_search( $item ) {
		$type_label = isset( $this->field_types[ $item['type'] ] ) ? $this->field_types[ $item['type'] ] : '';

		$haystack = implode( ' ', array(
			$item['name'],
			$item['slug'],
			$item['type'],
			$type_label,
			$item['description'],
		) );

		// mb_stripos keeps the match case-insensitive for accented characters;
		// mbstring is not guaranteed to be installed, hence the fallback.
		if ( function_exists( 'mb_stripos' ) ) {
			return false !== mb_stripos( $haystack, $this->search );
		}
		return false !== stripos( $haystack, $this->search );
	}

	function no_items() {
		if ( '' !== $this->search ) {
			esc_html_e( 'No fields match your search.', 'contact-forms' );
			return;
		}
		esc_html_e( 'No fields found.', 'contact-forms' );
	}

	function prepare_items() {
		$columns  = $this->get_columns();
		$hidden   = array();
		$sortable = $this->get_sortable_columns();

		$this->_column_headers = array( $columns, $hidden, $sortable );

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only search parameter
		$this->search = isset( $_REQUEST['s'] ) ? trim( sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ) ) : '';

		$avail_fields = get_option( 'accua_forms_avail_fields', array() );
		$saved_forms = get_option( 'accua_forms_saved_forms', array() );

		// Count how many forms use each field
		$field_usage = array();
		foreach ( $saved_forms as $form ) {
			if ( ! empty( $form['fields'] ) && is_array( $form['fields'] ) ) {
				foreach ( array_keys( $form['fields'] ) as $field_slug ) {
					if ( ! isset( $field_usage[ $field_slug ] ) ) {
						$field_usage[ $field_slug ] = 0;
					}
					$field_usage[ $field_slug ]++;
				}
			}
		}

		$data = array();
		foreach ( $avail_fields as $id => $field ) {
			$data[] = array(
				'slug'        => $id,
				'name'        => $field['name'] ?? $field['label'] ?? $id,
				'type'        => $field['type'] ?? '',
				'forms'       => $field_usage[ $id ] ?? 0,
				'description' => $field['description'] ?? '',
			);
		}

		// Search first, so the count, the order and the paging are all those of
		// the result set rather than of the whole list.
		if ( '' !== $this->search ) {
			$data = array_values( array_filter( $data, array( $this, 'matches_search' ) ) );
		}

		// Sorting
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only sort parameter
		$orderby = isset( $_GET['orderby'] ) ? sanitize_text_field( wp_unslash( $_GET['orderby'] ) ) : 'slug';
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only sort parameter
		$order = isset( $_GET['order'] ) ? sanitize_text_field( wp_unslash( $_GET['order'] ) ) : 'asc';

		$valid_columns = array( 'name', 'slug', 'type', 'forms' );
		if ( ! in_array( $orderby, $valid_columns, true ) ) {
			$orderby = 'slug';
		}
		$order_asc = ( 'desc' !== strtolower( $order ) );

		usort( $data, function ( $a, $b ) use ( $orderby, $order_asc ) {
			if ( $orderby === 'forms' ) {
				$result = $a['forms'] - $b['forms'];
			} else {
				$result = strcasecmp( $a[ $orderby ], $b[ $orderby ] );
			}
			return $order_asc ? $result : -$result;
		} );

		// Paging. Mostly this is what puts the "N items" count above the table,
		// which is the feedback a search needs; the list is short enough on a
		// normal install that the page links never appear.
		$per_page     = $this->get_items_per_page( 'accua_forms_fields_per_page', 50 );
		$total_items  = count( $data );
		$current_page = $this->get_pagenum();

		$this->set_pagination_args( array(
			'total_items' => $total_items,
			'per_page'    => $per_page,
			'total_pages' => (int) ceil( $total_items / max( 1, $per_page ) ),
		) );

		$this->items = array_slice( $data, ( $current_page - 1 ) * $per_page, $per_page );
	}

	protected function get_default_primary_column_name() {
		return 'name';
	}
}

```
