initial
This commit is contained in:
+341
@@ -0,0 +1,341 @@
|
||||
<?php
|
||||
|
||||
namespace Vrts\List_Tables;
|
||||
|
||||
use Vrts\Core\Utilities\Date_Time_Helpers;
|
||||
use Vrts\Core\Utilities\Url_Helpers;
|
||||
use Vrts\Models\Alert;
|
||||
use Vrts\Models\Test;
|
||||
use Vrts\Models\Test_Run;
|
||||
|
||||
if ( ! class_exists( 'WP_List_Table' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* List table class.
|
||||
*/
|
||||
class Test_Runs_List_Table extends \WP_List_Table {
|
||||
|
||||
/**
|
||||
* Tests.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $tests = [];
|
||||
|
||||
/**
|
||||
* Alerts.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $alerts = [];
|
||||
|
||||
/**
|
||||
* Parent construct.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct([
|
||||
'singular' => 'vrts-run',
|
||||
'plural' => 'vrts-runs',
|
||||
'ajax' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table classes.
|
||||
*/
|
||||
public function get_table_classes() {
|
||||
return [ 'vrts-test-runs-list-table', 'widefat', 'fixed', $this->_args['plural'] ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Message to show if no designation found.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function no_items() {
|
||||
esc_html_e( 'No Runs finished.', 'visual-regression-tests' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column names.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_columns() {
|
||||
$columns = [
|
||||
'cb' => '',
|
||||
'title' => esc_html__( 'Test Run', 'visual-regression-tests' ),
|
||||
'trigger' => esc_html__( 'Trigger', 'visual-regression-tests' ),
|
||||
'status' => esc_html__( 'Status', 'visual-regression-tests' ),
|
||||
];
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sortable columns
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_sortable_columns() {
|
||||
$sortable_columns = [
|
||||
'title' => [ 'finished_at', true ],
|
||||
'trigger' => [ 'trigger', true ],
|
||||
];
|
||||
|
||||
return $sortable_columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of views available on this table.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_views() {
|
||||
$base_link = Url_Helpers::get_page_url( 'runs' );
|
||||
|
||||
$links = [
|
||||
'all' => [
|
||||
'title' => esc_html__( 'All', 'visual-regression-tests' ),
|
||||
'link' => $base_link,
|
||||
'count' => Test_Run::get_total_items(),
|
||||
],
|
||||
'changes-detected' => [
|
||||
'title' => esc_html__( 'Changes detected', 'visual-regression-tests' ),
|
||||
'link' => "{$base_link}&status=changes-detected",
|
||||
'count' => Test_Run::get_total_items( 'changes-detected' ),
|
||||
],
|
||||
];
|
||||
|
||||
$status_links = [];
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- It's status request.
|
||||
$filter_status_query = ( isset( $_REQUEST['status'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['status'] ) ) : 'all' );
|
||||
foreach ( $links as $key => $link ) {
|
||||
$current_class = ( $filter_status_query === $key ? 'class="current" ' : '' );
|
||||
$link = sprintf(
|
||||
'<a %shref="%s">%s <span class="count">(%s)</span></a>',
|
||||
$current_class,
|
||||
$link['link'],
|
||||
$link['title'],
|
||||
$link['count']
|
||||
);
|
||||
$status_links[ $key ] = $link;
|
||||
}
|
||||
|
||||
return $status_links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the class items
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function prepare_items() {
|
||||
$columns = $this->get_columns();
|
||||
$hidden = [];
|
||||
$sortable = $this->get_sortable_columns();
|
||||
$this->_column_headers = [ $columns, $hidden, $sortable ];
|
||||
|
||||
$per_page = $this->get_items_per_page( 'vrts_test_runs_per_page', 20 );
|
||||
$current_page = $this->get_pagenum();
|
||||
$offset = ( $current_page - 1 ) * $per_page;
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- It's the list order parameter.
|
||||
$order = isset( $_REQUEST['order'] ) && 'asc' === $_REQUEST['order'] ? 'ASC' : 'DESC';
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- It's the list order by parameter.
|
||||
$order_by = isset( $_REQUEST['orderby'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['orderby'] ) ) : 'finished_at';
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing -- It's the list search query parameter.
|
||||
$filter_status_query = isset( $_REQUEST['status'] ) && '' !== $_REQUEST['status'] ? sanitize_text_field( wp_unslash( $_REQUEST['status'] ) ) : null;
|
||||
|
||||
$args = [
|
||||
'offset' => $offset,
|
||||
'number' => $per_page,
|
||||
'order' => $order,
|
||||
'orderby' => $order_by,
|
||||
'filter_status' => $filter_status_query,
|
||||
];
|
||||
|
||||
$this->items = Test_Run::get_items( $args );
|
||||
|
||||
$total_items = 0;
|
||||
if ( null !== $args['filter_status'] ) {
|
||||
$total_items = Test_Run::get_total_items( $filter_status_query );
|
||||
} else {
|
||||
$total_items = Test_Run::get_total_items();
|
||||
}
|
||||
|
||||
$this->set_pagination_args([
|
||||
'total_items' => $total_items,
|
||||
'per_page' => $per_page,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates content for a single row of the table.
|
||||
*
|
||||
* @param object|array $item The current item.
|
||||
*/
|
||||
public function single_row( $item ) {
|
||||
$classes = 'iedit test-run-row';
|
||||
$current_time = time();
|
||||
$finished_at = strtotime( $item->finished_at );
|
||||
$is_new_run = $current_time - $finished_at < 20 * MINUTE_IN_SECONDS;
|
||||
?>
|
||||
<tr
|
||||
id="test-<?php echo esc_attr( $item->id ); ?>"
|
||||
class="<?php echo esc_attr( $classes ); ?>"
|
||||
data-test-run-id="<?php echo esc_attr( $item->id ); ?>"
|
||||
data-test-run-new="<?php echo esc_attr( $is_new_run ? 'true' : 'false' ); ?>"
|
||||
<?php echo $item->unread_alerts_count > 0 ? 'data-has-alerts' : ''; ?>
|
||||
>
|
||||
<?php $this->single_row_columns( $item ); ?>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the required HTML for a list of row action links.
|
||||
*
|
||||
* @param string[] $actions An array of action links.
|
||||
* @param bool $always_visible Whether the actions should be always visible.
|
||||
*
|
||||
* @return string The HTML for the row actions.
|
||||
*/
|
||||
protected function row_actions( $actions, $always_visible = false ) {
|
||||
$action_count = count( $actions );
|
||||
|
||||
if ( ! $action_count ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$mode = get_user_setting( 'posts_list_mode', 'list' );
|
||||
|
||||
if ( 'excerpt' === $mode ) {
|
||||
$always_visible = true;
|
||||
}
|
||||
|
||||
$output = '<div class="' . ( $always_visible ? 'row-actions visible' : 'row-actions' ) . '">';
|
||||
|
||||
$i = 0;
|
||||
|
||||
foreach ( $actions as $action => $link ) {
|
||||
$output .= "<span class='$action'>{$link}</span>";
|
||||
}
|
||||
|
||||
$output .= '</div>';
|
||||
|
||||
// $output .= '<button type="button" class="toggle-row"><span class="screen-reader-text">' .
|
||||
// * translators: Hidden accessibility text. */
|
||||
// esc_html__( 'Show more details', 'visual-regression-tests' ) .
|
||||
// '</span></button>';
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the status icon column
|
||||
*
|
||||
* @param object $item column item.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function column_cb( $item ) {
|
||||
$status = Test_Run::get_calculated_status( $item );
|
||||
|
||||
$icons = [
|
||||
'has-alerts' => 'warning',
|
||||
'passed' => 'yes-alt',
|
||||
];
|
||||
|
||||
$icon = $icons[ $status ] ?? 'info';
|
||||
|
||||
return sprintf(
|
||||
'<span class="dashicons dashicons-%s vrts-runs-status--%s"></span>',
|
||||
$icon,
|
||||
$status
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the designation name column.
|
||||
*
|
||||
* @param object $item column item.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function column_title( $item ) {
|
||||
$actions = [];
|
||||
|
||||
$actions['details'] = sprintf(
|
||||
'<a class="vrts-show-test-run-details" href="%s">%s</a>',
|
||||
esc_url( Url_Helpers::get_test_run_page( $item->id ) ),
|
||||
esc_html__( 'Show Details', 'visual-regression-tests' )
|
||||
);
|
||||
|
||||
$row_actions = sprintf(
|
||||
'<strong><a class="row-title vrts-show-test-run-details" href="%1$s">%2$s</a></strong><div class="vrts-test-runs-title-subline">%3$s</div> %4$s',
|
||||
esc_url( Url_Helpers::get_test_run_page( $item->id ) ),
|
||||
sprintf( $item->title ),
|
||||
Date_Time_Helpers::get_formatted_relative_date_time( $item->finished_at ),
|
||||
$this->row_actions( $actions, true )
|
||||
);
|
||||
|
||||
return $row_actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the trigger column.
|
||||
*
|
||||
* @param object $item column item.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function column_trigger( $item ) {
|
||||
$trigger_title = Test_Run::get_trigger_title( $item );
|
||||
$trigger_note = Test_Run::get_trigger_note( $item );
|
||||
|
||||
return sprintf(
|
||||
'<span class="vrts-test-run-trigger vrts-test-run-trigger--%s">%s</span>%s',
|
||||
esc_attr( $item->trigger ),
|
||||
esc_html( $trigger_title ),
|
||||
empty( $trigger_note ) ? '' : sprintf('<p class="vrts-test-run-trigger-notes" title="%1$s">%1$s</p>',
|
||||
$trigger_note
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the status column.
|
||||
*
|
||||
* @param object $item column item.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function column_status( $item ) {
|
||||
$tests_count = count( maybe_unserialize( $item->tests ) ?? [] );
|
||||
if ( $item->alerts_count > 0 ) {
|
||||
$status_class = 'paused';
|
||||
$status_text = esc_html__( 'Changes detected ', 'visual-regression-tests' ) . sprintf( '(%s)', $item->alerts_count );
|
||||
|
||||
} else {
|
||||
$status_class = 'running';
|
||||
$status_text = esc_html__( 'No changes', 'visual-regression-tests' );
|
||||
}
|
||||
$status_instructions = sprintf(
|
||||
// translators: %s: number of alerts, %s: number of tests.
|
||||
esc_html( _n( '%s Test', '%s Tests', $tests_count, 'visual-regression-tests' ) ),
|
||||
$tests_count
|
||||
);
|
||||
|
||||
return sprintf(
|
||||
'<div class="vrts-testing-status-wrapper"><p class="vrts-testing-status"><span class="%s">%s</span></p><p class="vrts-testing-status">%s</p></div>',
|
||||
'vrts-testing-status--' . $status_class,
|
||||
$status_text,
|
||||
$status_instructions
|
||||
);
|
||||
}
|
||||
}
|
||||
+256
@@ -0,0 +1,256 @@
|
||||
<?php
|
||||
|
||||
namespace Vrts\List_Tables;
|
||||
|
||||
use Vrts\Core\Utilities\Date_Time_Helpers;
|
||||
use Vrts\Core\Utilities\Url_Helpers;
|
||||
use Vrts\Models\Test;
|
||||
use Vrts\Models\Test_Run;
|
||||
|
||||
if ( ! class_exists( 'WP_List_Table' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* List table class.
|
||||
*/
|
||||
class Test_Runs_Queue_List_Table extends \WP_List_Table {
|
||||
|
||||
/**
|
||||
* Parent construct.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct([
|
||||
'singular' => 'vrts-run-queue',
|
||||
'plural' => 'vrts-run-queues',
|
||||
'ajax' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table classes.
|
||||
*/
|
||||
public function get_table_classes() {
|
||||
return [ 'vrts-test-runs-list-table', 'vrts-test-runs-list-queue-table', 'widefat', 'fixed', $this->_args['plural'] ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Message to show if no designation found.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function no_items() {
|
||||
printf(
|
||||
/* translators: %1$s, %2$s link wrapper. */
|
||||
esc_html__( 'No Runs in the queue. %1$sAdd Tests%2$s to get started.', 'visual-regression-tests' ),
|
||||
'<a href="' . esc_url( Url_Helpers::get_page_url( 'tests' ) ) . '">',
|
||||
'</a>'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column names.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_columns() {
|
||||
$columns = [
|
||||
'cb' => '',
|
||||
'title' => esc_html__( 'Title', 'visual-regression-tests' ),
|
||||
'trigger' => esc_html__( 'Trigger', 'visual-regression-tests' ),
|
||||
'status' => esc_html__( 'Test Status', 'visual-regression-tests' ),
|
||||
];
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of views available on this table.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_views() {
|
||||
$base_link = Url_Helpers::get_page_url( 'runs' );
|
||||
|
||||
$links = [
|
||||
'all' => [
|
||||
'title' => esc_html__( 'Queue', 'visual-regression-tests' ),
|
||||
'link' => $base_link,
|
||||
'count' => count( Test_Run::get_queued_items() ),
|
||||
],
|
||||
];
|
||||
|
||||
$status_links = [];
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- It's status request.
|
||||
$filter_status_query = ( isset( $_REQUEST['status'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['status'] ) ) : 'all' );
|
||||
foreach ( $links as $key => $link ) {
|
||||
$current_class = ( $filter_status_query === $key ? 'class="current" ' : '' );
|
||||
$link = sprintf(
|
||||
'<a %shref="%s">%s <span class="count">(%s)</span></a>',
|
||||
$current_class,
|
||||
$link['link'],
|
||||
$link['title'],
|
||||
$link['count']
|
||||
);
|
||||
$status_links[ $key ] = $link;
|
||||
}
|
||||
|
||||
return $status_links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the class items
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function prepare_items() {
|
||||
$columns = $this->get_columns();
|
||||
$hidden = [];
|
||||
$sortable = $this->get_sortable_columns();
|
||||
$this->_column_headers = [ $columns, $hidden, $sortable ];
|
||||
$this->items = Test_Run::get_queued_items();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates content for a single row of the table.
|
||||
*
|
||||
* @param object|array $item The current item.
|
||||
*/
|
||||
public function single_row( $item ) {
|
||||
$classes = 'iedit';
|
||||
$status = Test_Run::get_calculated_status( $item );
|
||||
?>
|
||||
<tr id="test-<?php echo esc_attr( $item->id ); ?>" class="<?php echo esc_attr( $classes ); ?>" data-vrts-test-run-status="<?php echo esc_attr( $status ); ?>" data-test-run-id="<?php echo esc_attr( $item->id ); ?>">
|
||||
<?php $this->single_row_columns( $item ); ?>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the table navigation above or below the table
|
||||
*
|
||||
* @param string $which The location of the navigation: Either 'top' or 'bottom'.
|
||||
*/
|
||||
protected function display_tablenav( $which ) {
|
||||
// Don't display the table nav.
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the status icon column
|
||||
*
|
||||
* @param object $item column item.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function column_cb( $item ) {
|
||||
$status = Test_Run::get_calculated_status( $item );
|
||||
|
||||
$icons = [
|
||||
'scheduled' => 'clock',
|
||||
'running' => 'update',
|
||||
];
|
||||
|
||||
$icon = $icons[ $status ] ?? 'info';
|
||||
|
||||
return sprintf(
|
||||
'<span class="dashicons dashicons-%s vrts-runs-status--%s"></span>',
|
||||
$icon,
|
||||
$status
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the designation name column.
|
||||
*
|
||||
* @param object $item column item.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function column_title( $item ) {
|
||||
$actions = [];
|
||||
$status = Test_Run::get_calculated_status( $item );
|
||||
|
||||
if ( 'running' === $status ) {
|
||||
$scheduled_at = __( 'In Progress', 'visual-regression-tests' );
|
||||
} else {
|
||||
$scheduled_at = Date_Time_Helpers::get_formatted_relative_date_time( $item->scheduled_at );
|
||||
}
|
||||
|
||||
$row_actions = sprintf(
|
||||
'<strong><span class="row-title">%1$s</a></strong><div class="row-title-subline">%2$s</div>',
|
||||
$item->title,
|
||||
$scheduled_at
|
||||
);
|
||||
|
||||
return $row_actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the trigger column.
|
||||
*
|
||||
* @param object $item column item.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function column_trigger( $item ) {
|
||||
$trigger_title = Test_Run::get_trigger_title( $item );
|
||||
$trigger_note = Test_Run::get_trigger_note( $item );
|
||||
|
||||
return sprintf(
|
||||
'<span class="vrts-test-run-trigger vrts-test-run-trigger--%s">%s</span><p class="vrts-test-run-trigger-notes" title="%3$s">%3$s</p>',
|
||||
esc_attr( $item->trigger ),
|
||||
esc_html( $trigger_title ),
|
||||
$trigger_note
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the status column.
|
||||
*
|
||||
* @param object $item column item.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function column_status( $item ) {
|
||||
$test_run_status = Test_Run::get_calculated_status( $item );
|
||||
$number_of_tests = count( maybe_unserialize( $item->tests ) ?? [] );
|
||||
if ( 0 === $number_of_tests ) {
|
||||
$number_of_tests = Test::get_all_running( true );
|
||||
}
|
||||
|
||||
if ( 'running' === $test_run_status ) {
|
||||
$class = 'waiting';
|
||||
$text = '';
|
||||
$instructions = sprintf(
|
||||
'<span>%s</span>',
|
||||
sprintf(
|
||||
// translators: %1$s: link start to test runs page. %2$s: link end to test runs page.
|
||||
wp_kses( __( '%1$sRefresh page%2$s to see results', 'visual-regression-tests' ), [ 'a' => [ 'href' => [] ] ] ),
|
||||
'<a href="' . esc_url( Url_Helpers::get_page_url( 'runs' ) ) . '">',
|
||||
'</a>'
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$class = 'waiting';
|
||||
$text = esc_html__( 'Pending', 'visual-regression-tests' );
|
||||
$instructions = sprintf(
|
||||
'<a href="%1$s">%2$s</a> | <a href="%3$s">%4$s</a>',
|
||||
// translators: %s: number of tests.
|
||||
esc_url( Url_Helpers::get_page_url( 'tests' ) ),
|
||||
sprintf(
|
||||
/* translators: %s Test. Test count */
|
||||
esc_html( _n( '%s Test', '%s Tests', $number_of_tests, 'visual-regression-tests' ) ),
|
||||
$number_of_tests
|
||||
),
|
||||
esc_url( Url_Helpers::get_page_url( 'settings' ) ),
|
||||
esc_html__( 'Edit configuration', 'visual-regression-tests' )
|
||||
);
|
||||
}//end if
|
||||
return sprintf(
|
||||
'<div class="vrts-testing-status-wrapper"><div class="vrts-testing-status"><span class="%s">%s</span></div><div>%s</div></div>',
|
||||
'vrts-testing-status--' . $class,
|
||||
$text,
|
||||
$instructions
|
||||
);
|
||||
}
|
||||
}
|
||||
+430
@@ -0,0 +1,430 @@
|
||||
<?php
|
||||
|
||||
namespace Vrts\List_Tables;
|
||||
|
||||
use Vrts\Core\Utilities\Url_Helpers;
|
||||
use Vrts\Models\Test;
|
||||
use Vrts\Features\Service;
|
||||
use Vrts\Features\Subscription;
|
||||
use Vrts\Services\Test_Service;
|
||||
|
||||
if ( ! class_exists( 'WP_List_Table' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* List table class.
|
||||
*/
|
||||
class Tests_List_Table extends \WP_List_Table {
|
||||
|
||||
/**
|
||||
* Parent construct.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct([
|
||||
'singular' => 'test',
|
||||
'plural' => 'tests',
|
||||
'ajax' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table classes.
|
||||
*/
|
||||
public function get_table_classes() {
|
||||
return [ 'widefat', 'fixed', $this->_args['plural'] ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Message to show if no designation found.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function no_items() {
|
||||
esc_attr_e( 'No tests found.', 'visual-regression-tests' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Default column values if no callback found.
|
||||
*
|
||||
* @param object $item comment column item.
|
||||
* @param string $column_name column name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function column_default( $item, $column_name ) {
|
||||
|
||||
switch ( $column_name ) {
|
||||
|
||||
case 'post_title':
|
||||
return $item->post_title;
|
||||
|
||||
case 'internal_url':
|
||||
$parsed_internal_url = wp_parse_url( get_permalink( $item->post_id ) );
|
||||
$internal_url = $parsed_internal_url['path'];
|
||||
|
||||
return sprintf(
|
||||
'<strong><a href="%1$s" title="%2$s" target="_blank">%3$s</a></strong>',
|
||||
get_post_permalink( $item->post_id ),
|
||||
esc_html__( 'Open the page in a new tab', 'visual-regression-tests' ),
|
||||
$internal_url
|
||||
);
|
||||
|
||||
case 'status':
|
||||
return $this->render_column_status( $item );
|
||||
|
||||
case 'base_screenshot_date':
|
||||
return $this->render_column_snapshot( $item );
|
||||
|
||||
default:
|
||||
return isset( $item->$column_name ) ? $item->$column_name : '';
|
||||
}//end switch
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column names.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_columns() {
|
||||
$columns = [
|
||||
'cb' => '<input type="checkbox" />',
|
||||
'post_title' => esc_html__( 'Title', 'visual-regression-tests' ),
|
||||
'internal_url' => esc_html__( 'Path', 'visual-regression-tests' ),
|
||||
'base_screenshot_date' => esc_html__( 'Snapshot', 'visual-regression-tests' ),
|
||||
'status' => esc_html__( 'Test Status', 'visual-regression-tests' ),
|
||||
];
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the designation name column.
|
||||
*
|
||||
* @param object $item column item.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function column_post_title( $item ) {
|
||||
$actions = [];
|
||||
$is_connected = Service::is_connected();
|
||||
|
||||
$actions['edit'] = sprintf(
|
||||
'<a href="%s" data-id="%d" title="%s">%s</a>',
|
||||
get_edit_post_link( $item->post_id ),
|
||||
$item->id,
|
||||
esc_html__( 'Edit this page', 'visual-regression-tests' ),
|
||||
esc_html__( 'Edit Page', 'visual-regression-tests' )
|
||||
);
|
||||
|
||||
$actions['inline hide-if-no-js'] = sprintf(
|
||||
'<button type="button" class="button-link editinline" aria-label="%s" aria-expanded="false">%s</button>',
|
||||
/* translators: %s: Page Title. */
|
||||
esc_attr( sprintf( __( 'Quick edit “%s” inline', 'visual-regression-tests' ), $item->post_title ) ),
|
||||
__( 'Quick Edit', 'visual-regression-tests' )
|
||||
);
|
||||
|
||||
if ( $is_connected ) {
|
||||
$actions['trash'] = sprintf(
|
||||
'<a href="%s" data-id="%d" title="%s">%s</a>',
|
||||
Url_Helpers::get_disable_testing_url( $item->id ),
|
||||
$item->id,
|
||||
esc_html__( 'Disable testing for this page', 'visual-regression-tests' ),
|
||||
esc_html__( 'Disable Testing', 'visual-regression-tests' )
|
||||
);
|
||||
}
|
||||
|
||||
$row_actions = sprintf(
|
||||
'<strong><a class="row-title" href="%1$s" title="%2$s">%3$s</a></strong> %4$s',
|
||||
get_edit_post_link( $item->post_id ),
|
||||
esc_html__( 'Edit this page', 'visual-regression-tests' ),
|
||||
$item->post_title,
|
||||
$this->row_actions( $actions )
|
||||
);
|
||||
|
||||
$quickedit_hidden_fields = "
|
||||
<div class='hidden' id='inline_{$item->id}'>
|
||||
<div class='hide_css_selectors'>$item->hide_css_selectors</div>
|
||||
</div>";
|
||||
|
||||
return $row_actions . $quickedit_hidden_fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sortable columns
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_sortable_columns() {
|
||||
$sortable_columns = [
|
||||
'post_title' => [ 'post_title', true ],
|
||||
'status' => [ 'status', true ],
|
||||
'base_screenshot_date' => [ 'base_screenshot_date', true ],
|
||||
];
|
||||
|
||||
return $sortable_columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bulk actions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_bulk_actions() {
|
||||
$actions = [
|
||||
'set-status-disable' => esc_html__( 'Disable Testing', 'visual-regression-tests' ),
|
||||
];
|
||||
if ( Subscription::get_subscription_status() && count( Test::get_all_running() ) > 0 ) {
|
||||
$actions = array_merge(
|
||||
[ 'run-manual-test' => esc_html__( 'Run Test', 'visual-regression-tests' ) ],
|
||||
$actions
|
||||
);
|
||||
}
|
||||
return $actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process bulk actions.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function process_bulk_action() {
|
||||
// verify the nonce.
|
||||
$nonce = sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ?? '' ) );
|
||||
if ( ! wp_verify_nonce( $nonce, 'bulk-' . $this->_args['plural'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Should be okay for now.
|
||||
$test_ids = wp_unslash( $_POST['id'] ?? 0 );
|
||||
if ( 0 === $test_ids ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'set-status-disable' === $this->current_action() ) {
|
||||
foreach ( $test_ids as $test_id ) {
|
||||
$item = Test::get_item( $test_id );
|
||||
if ( $item ) {
|
||||
$service = new Test_Service();
|
||||
$service->delete_test( (int) $item->id );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the checkbox column
|
||||
*
|
||||
* @param object $item column item.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function column_cb( $item ) {
|
||||
return sprintf(
|
||||
'<input type="checkbox" name="id[]" value="%d" />',
|
||||
$item->id
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of views available on this table.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_views() {
|
||||
$base_link = Url_Helpers::get_page_url( 'tests' );
|
||||
|
||||
$links = [
|
||||
'all' => [
|
||||
'title' => esc_html__( 'All', 'visual-regression-tests' ),
|
||||
'link' => $base_link,
|
||||
'count' => Test::get_total_items(),
|
||||
],
|
||||
'changes-detected' => [
|
||||
'title' => esc_html__( 'Changes detected', 'visual-regression-tests' ),
|
||||
'link' => "{$base_link}&status=changes-detected",
|
||||
'count' => Test::get_total_items( 'changes-detected' ),
|
||||
],
|
||||
];
|
||||
|
||||
$status_links = [];
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- It's status request.
|
||||
$filter_status_query = ( isset( $_REQUEST['status'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['status'] ) ) : 'all' );
|
||||
foreach ( $links as $key => $link ) {
|
||||
$current_class = ( $filter_status_query === $key ? 'class="current" ' : '' );
|
||||
$link = sprintf(
|
||||
'<a %shref="%s">%s <span class="count">(%s)</span></a>',
|
||||
$current_class,
|
||||
$link['link'],
|
||||
$link['title'],
|
||||
$link['count']
|
||||
);
|
||||
$status_links[ $key ] = $link;
|
||||
}
|
||||
|
||||
return $status_links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add extra markup in the toolbars before or after the list.
|
||||
*
|
||||
* @param string $which helps you decide if you add the markup after (bottom) or before (top) the list.
|
||||
*/
|
||||
public function extra_tablenav( $which ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the class items
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function prepare_items() {
|
||||
$columns = $this->get_columns();
|
||||
$hidden = [];
|
||||
$sortable = $this->get_sortable_columns();
|
||||
$this->_column_headers = [ $columns, $hidden, $sortable ];
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- It's the list order parameter.
|
||||
$order = isset( $_REQUEST['order'] ) && 'asc' === $_REQUEST['order'] ? 'ASC' : 'DESC';
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- It's the list order by parameter.
|
||||
$order_by = isset( $_REQUEST['orderby'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['orderby'] ) ) : 'id';
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing -- It's the list search query parameter.
|
||||
$search_query = isset( $_POST['s'] ) && '' !== $_POST['s'] ? sanitize_text_field( wp_unslash( $_POST['s'] ) ) : null;
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing -- It's the list search query parameter.
|
||||
$filter_status_query = isset( $_REQUEST['status'] ) && '' !== $_REQUEST['status'] ? sanitize_text_field( wp_unslash( $_REQUEST['status'] ) ) : null;
|
||||
|
||||
$args = [
|
||||
'number' => -1,
|
||||
'order' => $order,
|
||||
'orderby' => $order_by,
|
||||
's' => $search_query,
|
||||
'filter_status' => $filter_status_query,
|
||||
];
|
||||
|
||||
// Process any bulk actions.
|
||||
$this->process_bulk_action();
|
||||
$this->items = Test::get_items( $args );
|
||||
|
||||
$total_items = count( $this->items );
|
||||
|
||||
$this->set_pagination_args([
|
||||
'total_items' => $total_items,
|
||||
// we set it to a high number to avoid pagination.
|
||||
'per_page' => 100000,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates content for a single row of the table.
|
||||
*
|
||||
* @param object|array $item The current item.
|
||||
*/
|
||||
public function single_row( $item ) {
|
||||
$classes = 'iedit';
|
||||
?>
|
||||
<tr id="test-<?php echo esc_attr( $item->id ); ?>" class="<?php echo esc_attr( $classes ); ?>">
|
||||
<?php $this->single_row_columns( $item ); ?>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the hidden row displayed when inline editing
|
||||
*
|
||||
* @global string $mode List table view mode.
|
||||
*/
|
||||
public function inline_edit() {
|
||||
$screen = $this->screen;
|
||||
?>
|
||||
|
||||
<form method="get">
|
||||
<table style="display: none"><tbody id="inlineedit">
|
||||
<?php
|
||||
$hclass = 'test';
|
||||
$inline_edit_classes = "inline-edit-row inline-edit-row-$hclass";
|
||||
$quick_edit_classes = "quick-edit-row quick-edit-row-$hclass inline-edit-{$screen->post_type}";
|
||||
$classes = $inline_edit_classes . ' ' . $quick_edit_classes;
|
||||
?>
|
||||
<tr id="inline-edit" style="display: none" class="<?php echo esc_attr( $classes ); ?>">
|
||||
<td colspan="<?php echo esc_attr( $this->get_column_count() ); ?>" class="colspanchange">
|
||||
<div class="inline-edit-wrapper" role="region" aria-labelledby="quick-edit-legend">
|
||||
<fieldset class="inline-edit-col-left">
|
||||
<legend class="inline-edit-legend" id="quick-edit-legend"><?php esc_html_e( 'Quick Edit', 'visual-regression-tests' ); ?></legend>
|
||||
<div class="inline-edit-col">
|
||||
<label><?php esc_html_e( 'Hide elements from VRTs' ); ?></label>
|
||||
<textarea name="hide_css_selectors" placeholder="<?php esc_html_e( 'e.g.: .lottie, #ads', 'visual-regression-tests' ); ?>" rows="4" cols="50"></textarea>
|
||||
<p>
|
||||
<?php
|
||||
printf(
|
||||
/* translators: %1$s, %2$s: strong element wrapper. */
|
||||
esc_html__( '%1$sExclude elements on this page:%2$s ', 'visual-regression-tests' ),
|
||||
'<strong>',
|
||||
'</strong>'
|
||||
);
|
||||
printf(
|
||||
/* translators: %1$s, %2$s: link wrapper. */
|
||||
esc_html__( 'Add %1$sCSS selectors%2$s (as comma separated list) to exclude elements from VRTs when a new snapshot gets created.', 'visual-regression-tests' ),
|
||||
'<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors" target="_blank">',
|
||||
'</a>'
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="submit inline-edit-save">
|
||||
<?php wp_nonce_field( 'vrts_test_quick_edit', '_vrts_test_quick_edit_nonce', false ); ?>
|
||||
<button type="button" class="button button-primary save"><?php esc_html_e( 'Update' ); ?></button>
|
||||
<button type="button" class="button cancel"><?php esc_html_e( 'Cancel' ); ?></button>
|
||||
<span class="spinner"></span>
|
||||
<input type="hidden" name="screen" value="<?php echo esc_attr( $screen->id ); ?>" />
|
||||
<div class="notice notice-error notice-alt inline hidden">
|
||||
<p class="error"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the status column.
|
||||
*
|
||||
* @param object $item column item.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function render_column_status( $item ) {
|
||||
$status_data = Test::get_status_data( $item );
|
||||
|
||||
return sprintf(
|
||||
'<div class="vrts-testing-status-wrapper"><p class="vrts-testing-status"><span class="%s">%s</span></p><p class="vrts-testing-status">%s</p></div>',
|
||||
'vrts-testing-status--' . $status_data['class'],
|
||||
$status_data['text'],
|
||||
$status_data['instructions']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the snapshot column.
|
||||
*
|
||||
* @param object $item column item.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function render_column_snapshot( $item ) {
|
||||
$screenshot_data = Test::get_screenshot_data( $item );
|
||||
|
||||
return sprintf(
|
||||
'<div class="vrts-testing-status-wrapper"><p class="vrts-testing-status">%s</p><p class="vrts-testing-status">%s</p></div>',
|
||||
$screenshot_data['text'],
|
||||
$screenshot_data['instructions']
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user