initial
This commit is contained in:
@@ -0,0 +1,581 @@
|
||||
<?php
|
||||
namespace Vrts\Models;
|
||||
|
||||
use Vrts\Tables\Alerts_Table;
|
||||
use Vrts\Services\Test_Service;
|
||||
use Vrts\Tables\Test_Runs_Table;
|
||||
use Vrts\Tables\Tests_Table;
|
||||
|
||||
/**
|
||||
* Model Alert Page.
|
||||
*/
|
||||
class Alert {
|
||||
|
||||
/**
|
||||
* Get all test items from database
|
||||
*
|
||||
* @param array $args Optional.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public static function get_items( $args = [] ) {
|
||||
global $wpdb;
|
||||
|
||||
$alerts_table = Alerts_Table::get_table_name();
|
||||
$test_runs_table = Test_Runs_Table::get_table_name();
|
||||
|
||||
$defaults = [
|
||||
's' => '',
|
||||
'number' => 20,
|
||||
'offset' => 0,
|
||||
'orderby' => 'id',
|
||||
'order' => 'DESC',
|
||||
'filter_status' => 0,
|
||||
];
|
||||
|
||||
$args = wp_parse_args( $args, $defaults );
|
||||
|
||||
// 0 = Open
|
||||
// 1 = Archived.
|
||||
// 2 = False Positive.
|
||||
switch ( $args['filter_status'] ?? null ) {
|
||||
case 'archived':
|
||||
$alert_states = [ 1, 2 ];
|
||||
break;
|
||||
case 'all':
|
||||
$alert_states = [];
|
||||
break;
|
||||
default:
|
||||
$alert_states = [ 0 ];
|
||||
break;
|
||||
}
|
||||
if ( ! empty( $alert_states ) ) {
|
||||
$alert_states_placeholders = implode( ', ', array_fill( 0, count( $alert_states ), '%d' ) );
|
||||
|
||||
$where = $wpdb->prepare(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- It's ok.
|
||||
"WHERE alert_state IN ($alert_states_placeholders)",
|
||||
$alert_states
|
||||
);
|
||||
} else {
|
||||
$where = 'WHERE 1=1';
|
||||
}
|
||||
|
||||
if ( ! empty( $args['s'] ) ) {
|
||||
$where .= $wpdb->prepare(
|
||||
' AND ( title LIKE %s OR test_run_title LIKE %s )',
|
||||
'%' . $wpdb->esc_like( $args['s'] ) . '%',
|
||||
'%' . $wpdb->esc_like( $args['s'] ) . '%'
|
||||
);
|
||||
}
|
||||
|
||||
if ( isset( $args['ids'] ) ) {
|
||||
$where .= $wpdb->prepare(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- It's ok.
|
||||
' AND id IN (' . implode( ',', array_fill( 0, count( $args['ids'] ), '%d' ) ) . ')',
|
||||
$args['ids']
|
||||
);
|
||||
}
|
||||
|
||||
if ( isset( $args['test_run_id'] ) ) {
|
||||
$where .= $wpdb->prepare(
|
||||
' AND test_run_id = %d',
|
||||
$args['test_run_id']
|
||||
);
|
||||
}
|
||||
|
||||
$whitelist_orderby = [ 'id', 'title', 'differences', 'target_screenshot_finish_date' ];
|
||||
$whitelist_order = [ 'ASC', 'DESC' ];
|
||||
|
||||
$orderby = in_array( $args['orderby'], $whitelist_orderby, true ) ? $args['orderby'] : 'id';
|
||||
$order = in_array( $args['order'], $whitelist_order, true ) ? $args['order'] : 'DESC';
|
||||
|
||||
$orderby = "ORDER BY $orderby $order";
|
||||
|
||||
$limit = $args['number'] > 100 ? 100 : $args['number'];
|
||||
|
||||
$limits = $wpdb->prepare(
|
||||
'LIMIT %d, %d',
|
||||
$args['offset'],
|
||||
$limit
|
||||
);
|
||||
|
||||
$alert_title = sprintf(
|
||||
"CONCAT( '%s', alert.id ) as title",
|
||||
esc_html__( 'Alert #', 'visual-regression-tests' )
|
||||
);
|
||||
|
||||
$run_title = sprintf(
|
||||
"CONCAT( '%s', run.id ) as test_run_title",
|
||||
esc_html__( 'Run #', 'visual-regression-tests' )
|
||||
);
|
||||
|
||||
$query = "
|
||||
SELECT
|
||||
*
|
||||
FROM (
|
||||
SELECT
|
||||
alert.id,
|
||||
$alert_title,
|
||||
alert.post_id,
|
||||
alert.screenshot_test_id,
|
||||
alert.target_screenshot_url,
|
||||
alert.target_screenshot_finish_date,
|
||||
alert.base_screenshot_url,
|
||||
alert.base_screenshot_finish_date,
|
||||
alert.comparison_screenshot_url,
|
||||
alert.comparison_id,
|
||||
alert.differences,
|
||||
alert.alert_state,
|
||||
alert.test_run_id,
|
||||
alert.meta,
|
||||
$run_title
|
||||
FROM $alerts_table as alert
|
||||
LEFT JOIN $test_runs_table as run ON run.id = alert.test_run_id
|
||||
) alerts
|
||||
$where
|
||||
$orderby
|
||||
$limits
|
||||
";
|
||||
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Query is prepared above.
|
||||
$items = $wpdb->get_results( $query );
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single test from database
|
||||
*
|
||||
* @param int $id the id of the item.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public static function get_item( $id = 0 ) {
|
||||
global $wpdb;
|
||||
|
||||
$alerts_table = Alerts_Table::get_table_name();
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return $wpdb->get_row(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- It's ok
|
||||
$wpdb->prepare( "SELECT * FROM $alerts_table WHERE id = %d LIMIT 1", $id )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get multiple alerts from database by id
|
||||
*
|
||||
* @param array $ids the ids of the items.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_items_by_ids( $ids = [] ) {
|
||||
global $wpdb;
|
||||
|
||||
$alerts_table = Alerts_Table::get_table_name();
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- It's ok.
|
||||
"SELECT * FROM $alerts_table WHERE id IN (" . implode( ',', array_fill( 0, count( $ids ), '%d' ) ) . ')',
|
||||
$ids
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get multiple alerts from database by test run id
|
||||
*
|
||||
* @param int $id the id of the test run.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_items_by_test_run( $id = 0 ) {
|
||||
global $wpdb;
|
||||
|
||||
$alerts_table = Alerts_Table::get_table_name();
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- It's ok.
|
||||
"SELECT * FROM $alerts_table WHERE test_run_id = %d ORDER BY post_id DESC",
|
||||
$id
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get latest alert ids by post ids
|
||||
*
|
||||
* @param array $post_ids the ids of the posts.
|
||||
* @param int $alert_state the state of the item.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_latest_alert_ids_by_post_ids( $post_ids = [], $alert_state = 0 ) {
|
||||
global $wpdb;
|
||||
|
||||
$alerts_table = Alerts_Table::get_table_name();
|
||||
|
||||
$placeholders = implode( ', ', array_fill( 0, count( $post_ids ), '%d' ) );
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return $wpdb->get_results(
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
$wpdb->prepare(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- It's ok.
|
||||
"SELECT id, post_id FROM $alerts_table WHERE alert_state = %d AND post_id IN ($placeholders) ORDER BY id DESC",
|
||||
array_merge(
|
||||
$alert_state,
|
||||
$post_ids
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total test items from database
|
||||
*
|
||||
* @param int $filter_status_query the id of status.
|
||||
* @param int $test_run_id the id of the test run.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_total_items( $filter_status_query = null, $test_run_id = null ) {
|
||||
global $wpdb;
|
||||
|
||||
$alerts_table = Alerts_Table::get_table_name();
|
||||
|
||||
// 0 = Open
|
||||
// 1 = Archived.
|
||||
// 2 = False Positive.
|
||||
switch ( $filter_status_query ?? null ) {
|
||||
case 'archived':
|
||||
$alert_states = [ 1, 2 ];
|
||||
break;
|
||||
case 'all':
|
||||
$alert_states = [];
|
||||
break;
|
||||
default:
|
||||
$alert_states = [ 0 ];
|
||||
break;
|
||||
}
|
||||
if ( ! empty( $alert_states ) ) {
|
||||
$alert_states_placeholders = implode( ', ', array_fill( 0, count( $alert_states ), '%d' ) );
|
||||
|
||||
$status_where = $wpdb->prepare(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- It's ok.
|
||||
"WHERE alert_state IN ($alert_states_placeholders)",
|
||||
$alert_states
|
||||
);
|
||||
} else {
|
||||
$status_where = 'WHERE 1=1';
|
||||
}
|
||||
|
||||
$test_run_where = '';
|
||||
if ( null !== $test_run_id ) {
|
||||
$test_run_where = $wpdb->prepare(
|
||||
' AND test_run_id = %d',
|
||||
$test_run_id
|
||||
);
|
||||
}
|
||||
|
||||
$where = "{$status_where}{$test_run_where}";
|
||||
|
||||
$query = "
|
||||
SELECT COUNT(*) FROM $alerts_table
|
||||
$where
|
||||
";
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared -- It's prepared above
|
||||
return (int) $wpdb->get_var( $query );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total test items grouped by test run from database
|
||||
*
|
||||
* @param int $filter_status_query the id of status.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_total_items_grouped_by_test_run( $filter_status_query = null ) {
|
||||
global $wpdb;
|
||||
|
||||
$alerts_table = Alerts_Table::get_table_name();
|
||||
|
||||
// 0 = Open
|
||||
// 1 = Archived.
|
||||
// 2 = False Positive.
|
||||
switch ( $filter_status_query ?? null ) {
|
||||
case 'archived':
|
||||
$alert_states = [ 1, 2 ];
|
||||
break;
|
||||
case 'all':
|
||||
$alert_states = [];
|
||||
break;
|
||||
default:
|
||||
$alert_states = [ 0 ];
|
||||
break;
|
||||
}
|
||||
if ( ! empty( $alert_states ) ) {
|
||||
$alert_states_placeholders = implode( ', ', array_fill( 0, count( $alert_states ), '%d' ) );
|
||||
|
||||
$status_where = $wpdb->prepare(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- It's ok.
|
||||
"WHERE alert_state IN ($alert_states_placeholders)",
|
||||
$alert_states
|
||||
);
|
||||
} else {
|
||||
$status_where = 'WHERE 1=1';
|
||||
}
|
||||
|
||||
$where = "{$status_where} AND test_run_id IS NOT NULL";
|
||||
|
||||
$query = "
|
||||
SELECT COUNT(DISTINCT test_run_id) FROM $alerts_table
|
||||
$where
|
||||
";
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared -- It's prepared above
|
||||
return (int) $wpdb->get_var( $query );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update alert status.
|
||||
*
|
||||
* @param int $id the id of the item.
|
||||
* @param int $new_alert_state the new state of the item.
|
||||
*/
|
||||
public static function set_alert_state( $id = 0, $new_alert_state = null ) {
|
||||
// 0 = Unread / 1 = Read
|
||||
if ( in_array( $new_alert_state, [ 0, 1 ], true ) ) {
|
||||
global $wpdb;
|
||||
|
||||
$alerts_table = Alerts_Table::get_table_name();
|
||||
$data = [ 'alert_state' => $new_alert_state ];
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return $wpdb->update( $alerts_table, $data, [ 'id' => $id ] );
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update all alert statuses for post id.
|
||||
*
|
||||
* @param int $post_id the id of the item.
|
||||
* @param int $new_alert_state the new state of the item.
|
||||
*/
|
||||
public static function set_alert_state_for_post_id( $post_id = 0, $new_alert_state = null ) {
|
||||
// 0 = Unread / 1 = Read
|
||||
if ( in_array( $new_alert_state, [ 0, 1 ], true ) ) {
|
||||
global $wpdb;
|
||||
|
||||
$alerts_table = Alerts_Table::get_table_name();
|
||||
$data = [ 'alert_state' => $new_alert_state ];
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return $wpdb->update( $alerts_table, $data, [ 'post_id' => $post_id ] );
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next open alert id.
|
||||
*/
|
||||
public static function get_next_open_alert_id() {
|
||||
global $wpdb;
|
||||
|
||||
$alerts_table = Alerts_Table::get_table_name();
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return $wpdb->get_var(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- It's ok.
|
||||
$wpdb->prepare( "SELECT id FROM $alerts_table WHERE alert_state = %d LIMIT 1", 0 )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next alert id for the pagination.
|
||||
*
|
||||
* @param int $id the id of the item.
|
||||
* @param array $test_run_id the id of the test run.
|
||||
*/
|
||||
public static function get_pagination_next_alert_id( $id = 0, $test_run_id = 0 ) {
|
||||
global $wpdb;
|
||||
|
||||
$alerts_table = Alerts_Table::get_table_name();
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return (int) $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- It's ok.
|
||||
"SELECT id FROM $alerts_table
|
||||
WHERE id > %d
|
||||
AND test_run_id = %d
|
||||
ORDER BY id ASC
|
||||
LIMIT 1",
|
||||
$id,
|
||||
$test_run_id
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the prev alert id for the pagination.
|
||||
*
|
||||
* @param int $id the id of the item.
|
||||
* @param array $test_run_id the id of the test run.
|
||||
*/
|
||||
public static function get_pagination_prev_alert_id( $id = 0, $test_run_id = 0 ) {
|
||||
global $wpdb;
|
||||
|
||||
$alerts_table = Alerts_Table::get_table_name();
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return (int) $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- It's ok.
|
||||
"SELECT id FROM $alerts_table
|
||||
WHERE id < %d
|
||||
AND test_run_id = %d
|
||||
ORDER BY id DESC
|
||||
LIMIT 1",
|
||||
$id,
|
||||
$test_run_id
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current position inside the pagination.
|
||||
*
|
||||
* @param int $id the id of the item.
|
||||
* @param array $test_run_id the id of the test run.
|
||||
*/
|
||||
public static function get_pagination_current_position( $id = 0, $test_run_id = 0 ) {
|
||||
global $wpdb;
|
||||
|
||||
$alerts_table = Alerts_Table::get_table_name();
|
||||
|
||||
// Let's get the count of the alerts that are before the current one.
|
||||
$query = $wpdb->prepare(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- It's ok.
|
||||
"SELECT count(*) FROM `$alerts_table`
|
||||
WHERE id < %d
|
||||
AND test_run_id = %d
|
||||
ORDER BY id DESC",
|
||||
$id,
|
||||
$test_run_id
|
||||
);
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared -- It's ok.
|
||||
$count = (int) $wpdb->get_var( $query );
|
||||
|
||||
// We need to add 1. E.g. if the count is 0, the position is 1.
|
||||
return $count + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a test from database and update its post meta.
|
||||
*
|
||||
* @param int $id the id of the item.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function delete( $id = 0 ) {
|
||||
global $wpdb;
|
||||
|
||||
$alerts_table = Alerts_Table::get_table_name();
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return $wpdb->delete( $alerts_table, [ 'id' => $id ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the alert state.
|
||||
*
|
||||
* @param object $alert the alert object.
|
||||
*/
|
||||
public static function is_archived( $alert ) {
|
||||
// 0 = Open
|
||||
// 1 = Archived.
|
||||
// 2 = False Positive.
|
||||
//phpcs:ignore WordPress.PHP.StrictInArray.FoundNonStrictFalse -- It's ok.
|
||||
return in_array( $alert->alert_state, [ 1, 2 ], false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unread alerts count by test run ids.
|
||||
*
|
||||
* @param array|int $test_run_ids the ids of the test runs.
|
||||
*/
|
||||
public static function get_unread_count_by_test_run_ids( $test_run_ids ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( empty( $test_run_ids ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if ( is_int( $test_run_ids ) || is_string( $test_run_ids ) ) {
|
||||
$test_run_ids = [ $test_run_ids ];
|
||||
}
|
||||
|
||||
$alerts_table = Alerts_Table::get_table_name();
|
||||
|
||||
$placeholders = implode( ', ', array_fill( 0, count( $test_run_ids ), '%d' ) );
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- It's ok.
|
||||
"SELECT test_run_id, COUNT(*) as count FROM $alerts_table WHERE test_run_id IN ($placeholders) AND alert_state = 0 GROUP BY test_run_id",
|
||||
$test_run_ids
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set read status by test run.
|
||||
*
|
||||
* @param int $test_run_id the id of the test run.
|
||||
* @param int $read_status the state of the item.
|
||||
*/
|
||||
public static function set_read_status_by_test_run( $test_run_id, $read_status = 1 ) {
|
||||
global $wpdb;
|
||||
|
||||
$alerts_table = Alerts_Table::get_table_name();
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return $wpdb->update(
|
||||
$alerts_table,
|
||||
[ 'alert_state' => $read_status ],
|
||||
[ 'test_run_id' => intval( $test_run_id ) ]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or remove alert as false positive.
|
||||
*
|
||||
* @param int $alert_id the id of the item.
|
||||
* @param int $is_false_positive the state of the item.
|
||||
*/
|
||||
public static function set_false_positive( $alert_id, $is_false_positive = 1 ) {
|
||||
global $wpdb;
|
||||
|
||||
$alerts_table = Alerts_Table::get_table_name();
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return $wpdb->update(
|
||||
$alerts_table,
|
||||
[ 'is_false_positive' => $is_false_positive ],
|
||||
[ 'id' => intval( $alert_id ) ]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,630 @@
|
||||
<?php
|
||||
|
||||
namespace Vrts\Models;
|
||||
|
||||
use Vrts\Core\Utilities\Date_Time_Helpers;
|
||||
use Vrts\Core\Utilities\Url_Helpers;
|
||||
use Vrts\Features\Service;
|
||||
use Vrts\Features\Subscription;
|
||||
use Vrts\Tables\Alerts_Table;
|
||||
use Vrts\Tables\Test_Runs_Table;
|
||||
|
||||
/**
|
||||
* Model Tests Page.
|
||||
*/
|
||||
class Test_Run {
|
||||
|
||||
/**
|
||||
* Get all test items from database
|
||||
*
|
||||
* @param array $args Optional.
|
||||
* @param bool $return_count Optional.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public static function get_items( $args = [], $return_count = false ) {
|
||||
global $wpdb;
|
||||
|
||||
$test_runs_table = Test_Runs_Table::get_table_name();
|
||||
$alerts_table = Alerts_Table::get_table_name();
|
||||
|
||||
$defaults = [
|
||||
'number' => 20,
|
||||
'offset' => 0,
|
||||
'orderby' => 'id',
|
||||
'order' => 'DESC',
|
||||
];
|
||||
|
||||
$args = wp_parse_args( $args, $defaults );
|
||||
|
||||
$select = $return_count ? 'SELECT COUNT(*)' : 'SELECT *';
|
||||
$where = 'WHERE started_at IS NOT NULL AND finished_at IS NOT NULL';
|
||||
|
||||
if ( isset( $args['filter_status'] ) && null !== $args['filter_status'] ) {
|
||||
if ( 'changes-detected' === $args['filter_status'] ) {
|
||||
$where .= ' AND alerts_count > 0';
|
||||
}
|
||||
}
|
||||
|
||||
$whitelist_orderby = [ 'id', 'title', 'started_at', 'finished_at', 'trigger' ];
|
||||
$whitelist_order = [ 'ASC', 'DESC' ];
|
||||
|
||||
$orderby = in_array( $args['orderby'], $whitelist_orderby, true ) ? $args['orderby'] : 'id';
|
||||
$order = in_array( $args['order'], $whitelist_order, true ) ? $args['order'] : 'DESC';
|
||||
|
||||
if ( 'status' === $orderby ) {
|
||||
$orderby = "ORDER BY calculated_status $order, calculated_date $order";
|
||||
} else {
|
||||
$orderby = "ORDER BY `$orderby` $order";
|
||||
}
|
||||
|
||||
$limit = $args['number'] > 100 ? 100 : $args['number'];
|
||||
|
||||
if ( $args['number'] < 1 ) {
|
||||
$limits = '';
|
||||
} else {
|
||||
$limits = $wpdb->prepare(
|
||||
'LIMIT %d, %d',
|
||||
$args['offset'],
|
||||
$limit
|
||||
);
|
||||
}
|
||||
|
||||
$run_title = $wpdb->prepare(
|
||||
'CONCAT( %s, runs.id ) as title',
|
||||
esc_html__( 'Run #', 'visual-regression-tests' )
|
||||
);
|
||||
|
||||
$query = "
|
||||
$select
|
||||
FROM (
|
||||
SELECT
|
||||
runs.id,
|
||||
$run_title,
|
||||
runs.tests,
|
||||
SUM( IF( alerts.id IS NOT NULL, 1, 0 ) ) as alerts_count,
|
||||
SUM( IF( alerts.id IS NOT NULL and alerts.alert_state = 0, 1, 0 ) ) as unread_alerts_count,
|
||||
runs.trigger,
|
||||
runs.trigger_notes,
|
||||
runs.trigger_meta,
|
||||
runs.started_at,
|
||||
runs.scheduled_at,
|
||||
runs.finished_at
|
||||
FROM $test_runs_table as runs
|
||||
LEFT JOIN $alerts_table as alerts
|
||||
ON runs.id = alerts.test_run_id
|
||||
GROUP BY runs.id
|
||||
) runs
|
||||
$where
|
||||
$orderby
|
||||
$limits
|
||||
";
|
||||
|
||||
if ( $return_count ) {
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Query is prepared above.
|
||||
$items = $wpdb->get_var( $query );
|
||||
} else {
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Query is prepared above.
|
||||
$items = $wpdb->get_results( $query );
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all queued test items from database
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public static function get_queued_items() {
|
||||
global $wpdb;
|
||||
|
||||
$test_runs_table = Test_Runs_Table::get_table_name();
|
||||
|
||||
$run_title = $wpdb->prepare(
|
||||
'CONCAT( %s, id ) as title',
|
||||
esc_html__( 'Run #', 'visual-regression-tests' )
|
||||
);
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return $wpdb->get_results(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- It's ok.
|
||||
"SELECT *, $run_title FROM $test_runs_table WHERE finished_at is NULL ORDER BY scheduled_at ASC"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single test from database
|
||||
*
|
||||
* @param int $id the id of the item.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public static function get_item( $id = 0 ) {
|
||||
global $wpdb;
|
||||
|
||||
$test_runs_table = Test_Runs_Table::get_table_name();
|
||||
|
||||
$run_title = $wpdb->prepare(
|
||||
'CONCAT( %s, id ) as title',
|
||||
esc_html__( 'Run #', 'visual-regression-tests' )
|
||||
);
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return $wpdb->get_row(
|
||||
$wpdb->prepare(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- It's ok.
|
||||
"SELECT *, $run_title FROM $test_runs_table WHERE id = %d",
|
||||
$id
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get multiple tests from database by id
|
||||
*
|
||||
* @param array $ids the ids of the items.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public static function get_items_by_ids( $ids = [] ) {
|
||||
global $wpdb;
|
||||
|
||||
$test_runs_table = Test_Runs_Table::get_table_name();
|
||||
|
||||
$run_title = $wpdb->prepare(
|
||||
'CONCAT( %s, id ) as title',
|
||||
esc_html__( 'Run #', 'visual-regression-tests' )
|
||||
);
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- It's ok.
|
||||
"SELECT *, $run_title FROM $test_runs_table WHERE id IN (" . implode( ',', array_fill( 0, count( $ids ), '%d' ) ) . ')',
|
||||
$ids
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get test run by service test id
|
||||
*
|
||||
* @param int $test_run_id Service test run id.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public static function get_by_service_test_run_id( $test_run_id ) {
|
||||
global $wpdb;
|
||||
|
||||
$test_runs_table = Test_Runs_Table::get_table_name();
|
||||
|
||||
$run_title = $wpdb->prepare(
|
||||
'CONCAT( %s, id ) as title',
|
||||
esc_html__( 'Run #', 'visual-regression-tests' )
|
||||
);
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return $wpdb->get_row(
|
||||
$wpdb->prepare(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- It's ok.
|
||||
"SELECT *, $run_title FROM $test_runs_table WHERE service_test_run_id = %s",
|
||||
$test_run_id
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total test items from database
|
||||
*
|
||||
* @param int $filter_status_query the id of status.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_total_items( $filter_status_query = null ) {
|
||||
return (int) self::get_items( [
|
||||
'number' => -1,
|
||||
'filter_status' => $filter_status_query,
|
||||
], true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert or update test data
|
||||
*
|
||||
* @param array $args The arguments to insert.
|
||||
* @param int $row_id The row id to update.
|
||||
*
|
||||
* @return int|void
|
||||
*/
|
||||
public static function save( $args = [], $row_id = null ) {
|
||||
global $wpdb;
|
||||
|
||||
$test_runs_table = Test_Runs_Table::get_table_name();
|
||||
|
||||
if ( ! $row_id ) {
|
||||
// Insert a new row.
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- It's ok.
|
||||
if ( $wpdb->insert( $test_runs_table, $args ) ) {
|
||||
return $wpdb->insert_id;
|
||||
}
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
} elseif ( $wpdb->update( $test_runs_table, $args, [ 'id' => $row_id ] ) ) {
|
||||
return $row_id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete duplicate test runs by service_test_run_id from database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function delete_duplicates() {
|
||||
global $wpdb;
|
||||
|
||||
$test_runs_table = Test_Runs_Table::get_table_name();
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
$wpdb->query(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- It's ok.
|
||||
"DELETE t1 FROM $test_runs_table t1 INNER JOIN $test_runs_table t2 WHERE t1.id > t2.id AND t1.service_test_run_id = t2.service_test_run_id"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete empty test runs from database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function delete_empty() {
|
||||
global $wpdb;
|
||||
|
||||
$test_runs_table = Test_Runs_Table::get_table_name();
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
$wpdb->query(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- It's ok.
|
||||
"DELETE FROM $test_runs_table WHERE service_test_run_id IS NULL"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert multiple test data
|
||||
*
|
||||
* @param array $data Data to update (in multi array column => value pairs).
|
||||
*
|
||||
* @return int|false The number of rows affected, or false on error.
|
||||
*/
|
||||
public static function save_multiple( $data = [] ) {
|
||||
global $wpdb;
|
||||
|
||||
$test_runs_table = Test_Runs_Table::get_table_name();
|
||||
|
||||
// If there is no data, return false.
|
||||
if ( ! isset( $data[0] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$fields = '`' . implode( '`, `', array_keys( $data[0] ) ) . '`';
|
||||
$formats = implode( ', ', array_map(function ( $row ) {
|
||||
return '(' . implode( ', ', array_fill( 0, count( $row ), '%s' ) ) . ')';
|
||||
}, $data ) );
|
||||
$values = [];
|
||||
|
||||
foreach ( $data as $row ) {
|
||||
foreach ( $row as $value ) {
|
||||
$values[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add support for update.
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return $wpdb->query(
|
||||
$wpdb->prepare(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- It's ok.
|
||||
"INSERT INTO `$test_runs_table` ($fields) VALUES $formats",
|
||||
$values
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get test run trigger title
|
||||
*
|
||||
* @param int|object $test_run test run id or test object.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_trigger_title( $test_run ) {
|
||||
if ( is_int( $test_run ) ) {
|
||||
$test_run = self::get_item( $test_run );
|
||||
}
|
||||
|
||||
$trigger_titles = [
|
||||
'manual' => __( 'Manual', 'visual-regression-tests' ),
|
||||
'scheduled' => __( 'Schedule', 'visual-regression-tests' ),
|
||||
'api' => __( 'API', 'visual-regression-tests' ),
|
||||
'update' => __( 'Update', 'visual-regression-tests' ),
|
||||
'legacy' => __( 'Legacy', 'visual-regression-tests' ),
|
||||
];
|
||||
|
||||
return $trigger_titles[ $test_run->trigger ] ?? __( 'Unknown', 'visual-regression-tests' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get test run trigger text color
|
||||
*
|
||||
* @param int|object $test_run test run id or test object.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_trigger_text_color( $test_run ) {
|
||||
if ( is_int( $test_run ) ) {
|
||||
$test_run = self::get_item( $test_run );
|
||||
}
|
||||
|
||||
$trigger_colours = [
|
||||
'manual' => '#045495',
|
||||
'scheduled' => '#591b98',
|
||||
'api' => '#ae4204',
|
||||
'update' => '#a51d7f',
|
||||
];
|
||||
|
||||
return $trigger_colours[ $test_run->trigger ] ?? '#2c3338';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get test run trigger background color
|
||||
*
|
||||
* @param int|object $test_run test run id or test object.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_trigger_background_color( $test_run ) {
|
||||
if ( is_int( $test_run ) ) {
|
||||
$test_run = self::get_item( $test_run );
|
||||
}
|
||||
|
||||
$trigger_colours = [
|
||||
'manual' => 'rgba(5, 116, 206, 0.1)',
|
||||
'scheduled' => 'rgba(106, 26, 185, 0.1)',
|
||||
'api' => 'rgba(224, 84, 6, 0.15)',
|
||||
'update' => 'rgba(200, 11, 147, 0.1)',
|
||||
];
|
||||
|
||||
return $trigger_colours[ $test_run->trigger ] ?? 'rgba(192, 192, 192, 0.15)';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get test run calculated status
|
||||
*
|
||||
* @param int|object $test_run test run id or test object.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_calculated_status( $test_run ) {
|
||||
if ( is_int( $test_run ) ) {
|
||||
$test_run = self::get_item( $test_run );
|
||||
}
|
||||
|
||||
$has_alerts = ( $test_run->alerts_count ?? 0 ) > 0;
|
||||
|
||||
if ( $has_alerts ) {
|
||||
return 'has-alerts';
|
||||
}
|
||||
|
||||
if ( ! empty( $test_run->started_at ) && empty( $test_run->finished_at ) ) {
|
||||
return 'running';
|
||||
}
|
||||
|
||||
if ( ! empty( $test_run->scheduled_at ) && empty( $test_run->finished_at ) ) {
|
||||
return 'scheduled';
|
||||
}
|
||||
|
||||
return 'passed';
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a test from database.
|
||||
*
|
||||
* @param int $test_id the id of the item.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function delete( $test_id = 0 ) {
|
||||
global $wpdb;
|
||||
|
||||
$test_runs_table = Test_Runs_Table::get_table_name();
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return $wpdb->delete( $test_runs_table, [ 'id' => $test_id ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all not finished test runs from database.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function delete_all_not_finished() {
|
||||
global $wpdb;
|
||||
|
||||
$test_runs_table = Test_Runs_Table::get_table_name();
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- It's ok.
|
||||
return $wpdb->query( "DELETE FROM $test_runs_table WHERE finished_at IS NULL" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert values to correct type.
|
||||
*
|
||||
* @param object $test_run The test run object.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public static function cast_values( $test_run ) {
|
||||
$test_run->id = ! is_null( $test_run->id ) ? (int) $test_run->id : null;
|
||||
$test_run->tests = ! is_null( $test_run->tests ) ? maybe_unserialize( $test_run->tests ) : [];
|
||||
$test_run->alerts = ! is_null( $test_run->alerts ) ? maybe_unserialize( $test_run->alerts ) : [];
|
||||
$test_run->started_at = ! is_null( $test_run->started_at ) ? mysql2date( 'c', $test_run->started_at ) : null;
|
||||
$test_run->scheduled_at = ! is_null( $test_run->scheduled_at ) ? mysql2date( 'c', $test_run->scheduled_at ) : null;
|
||||
$test_run->finished_at = ! is_null( $test_run->finished_at ) ? mysql2date( 'c', $test_run->finished_at ) : null;
|
||||
|
||||
return $test_run;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get test run status data
|
||||
*
|
||||
* @param int|object $test_run test run id or test run object.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_status_data( $test_run ) {
|
||||
if ( is_int( $test_run ) ) {
|
||||
$test_run = self::get_item( $test_run );
|
||||
}
|
||||
|
||||
$test_run_status = self::get_calculated_status( $test_run );
|
||||
$instructions = '';
|
||||
|
||||
switch ( $test_run_status ) {
|
||||
case 'has-alerts':
|
||||
$alerts_count = $test_run->alerts_count;
|
||||
$class = 'paused';
|
||||
$text = esc_html__( 'Changes detected', 'visual-regression-tests' );
|
||||
$instructions = Date_Time_Helpers::get_formatted_relative_date_time( $test_run->finished_at );
|
||||
$instructions .= sprintf(
|
||||
'<a href="%1$s" class="vrts-test-run-view-alerts"><i class="dashicons dashicons-image-flip-horizontal"></i> %2$s</a>',
|
||||
esc_url( Url_Helpers::get_alerts_page( $test_run ) ),
|
||||
sprintf(
|
||||
// translators: %s: number of alerts.
|
||||
esc_html( _n( 'View Alert (%s)', 'View Alerts (%s)', $alerts_count, 'visual-regression-tests' ) ),
|
||||
$alerts_count
|
||||
)
|
||||
);
|
||||
break;
|
||||
case 'running':
|
||||
$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>'
|
||||
)
|
||||
);
|
||||
break;
|
||||
case 'scheduled':
|
||||
$class = 'waiting';
|
||||
$text = esc_html__( 'Pending', 'visual-regression-tests' );
|
||||
$instructions .= sprintf(
|
||||
'<a href="%1$s">%2$s</a>',
|
||||
esc_url( Url_Helpers::get_page_url( 'settings' ) ),
|
||||
esc_html__( 'Edit Test Configuration', 'visual-regression-tests' )
|
||||
);
|
||||
break;
|
||||
case 'passed':
|
||||
default:
|
||||
$class = 'running';
|
||||
$text = esc_html__( 'Passed', 'visual-regression-tests' );
|
||||
if ( $test_run->finished_at ) {
|
||||
$instructions .= Date_Time_Helpers::get_formatted_relative_date_time( $test_run->finished_at );
|
||||
}
|
||||
$instructions .= esc_html__( 'No changes detected', 'visual-regression-tests' );
|
||||
break;
|
||||
}//end switch
|
||||
|
||||
return [
|
||||
'status' => $test_run_status,
|
||||
'class' => $class,
|
||||
'text' => $text,
|
||||
'instructions' => $instructions,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete test run by service test run id
|
||||
*
|
||||
* @param string $test_run_id the service test run id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function delete_by_service_test_run_id( $test_run_id ) {
|
||||
global $wpdb;
|
||||
|
||||
$test_runs_table = Test_Runs_Table::get_table_name();
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
return $wpdb->delete( $test_runs_table, [ 'service_test_run_id' => $test_run_id ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get test run trigger note
|
||||
*
|
||||
* @param object $test_run test run object.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_trigger_note( $test_run ) {
|
||||
if ( ( $test_run->trigger ?? null ) === 'update' ) {
|
||||
$updates = maybe_unserialize( $test_run->trigger_meta ) ?? [];
|
||||
$updates = array_merge( ...$updates );
|
||||
|
||||
$trigger_notes = implode(', ', array_map(function ( $update ) {
|
||||
if ( 'core' === $update['type'] ) {
|
||||
$update_name = 'WordPress';
|
||||
} else {
|
||||
$update_name = $update['name'] ?? $update['slug'] ?? null;
|
||||
}
|
||||
$update_info = $update['version'] ?? $update['language'] ?? null;
|
||||
|
||||
return $update_name . ( empty( $update_info ) ? '' : ' (' . $update_info . ')' );
|
||||
}, $updates));
|
||||
return $trigger_notes;
|
||||
} else {
|
||||
return $test_run->trigger_notes ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next scheduled run
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public static function get_next_scheduled_run() {
|
||||
global $wpdb;
|
||||
|
||||
$test_runs_table = Test_Runs_Table::get_table_name();
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
$test_run = $wpdb->get_row(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- It's ok.
|
||||
"SELECT * FROM $test_runs_table WHERE finished_at IS NULL AND scheduled_at IS NOT NULL ORDER BY scheduled_at ASC LIMIT 1"
|
||||
);
|
||||
return $test_run;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get test run by service test run id
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get_stalled_test_run_ids() {
|
||||
global $wpdb;
|
||||
|
||||
$test_runs_table = Test_Runs_Table::get_table_name();
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- It's ok.
|
||||
$test_runs = $wpdb->get_results(
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- It's ok.
|
||||
"SELECT service_test_run_id FROM $test_runs_table
|
||||
WHERE ( finished_at IS NULL AND started_at IS NULL AND scheduled_at < DATE_SUB( now(), INTERVAL 1 HOUR ) )
|
||||
OR ( finished_at IS NULL AND started_at IS NOT NULL AND started_at < DATE_SUB( NOW(), INTERVAL 1 HOUR ) )
|
||||
OR ( finished_at IS NULL AND started_at IS NULL AND scheduled_at IS NULL )
|
||||
"
|
||||
);
|
||||
return $test_runs;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user