Merge pull request #19 from woocommerce/add/cron_job_trigger

Add cron trigger
This commit is contained in:
Fernando 2021-06-21 09:57:14 -03:00 committed by GitHub
commit 85dbb03504
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 298 additions and 62 deletions

View File

@ -29,6 +29,7 @@ function register_woocommerce_admin_test_helper_rest_route( $route, $callback, $
require( 'admin-notes/delete-all-notes.php' );
require( 'admin-notes/add-note.php' );
require( 'tools/trigger-wca-install.php' );
require( 'tools/trigger-cron-job.php' );
require( 'tools/run-wc-admin-daily.php' );
require( 'options/rest-api.php' );
require( 'tools/delete-all-products.php');

View File

@ -0,0 +1,98 @@
<?php
register_woocommerce_admin_test_helper_rest_route(
'/tools/get-cron-list/v1',
'tools_get_cron_list',
array(
'methods' => 'GET',
)
);
register_woocommerce_admin_test_helper_rest_route(
'/tools/trigger-selected-cron/v1',
'trigger_selected_cron',
array(
'methods' => 'POST',
'args' => array(
'hook' => array(
'description' => 'Name of the cron that will be triggered.',
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
),
'signature' => array(
'description' => 'Signature of the cron to trigger.',
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
),
),
)
);
function tools_get_cron_list() {
$crons = _get_cron_array();
$events = array();
if ( empty( $crons ) ) {
return array();
}
foreach ( $crons as $cron ) {
foreach ( $cron as $hook => $data ) {
foreach ( $data as $signature => $element ) {
$events[ $hook ] = (object) array(
'hook' => $hook,
'signature' => $signature,
);
}
}
}
return new WP_REST_Response( $events, 200 );
}
function trigger_selected_cron( $request ) {
$hook = $request->get_param( 'hook' );
$signature = $request->get_param( 'signature' );
if ( ! isset( $hook ) || ! isset( $signature ) ) {
return;
}
$crons = _get_cron_array();
foreach ( $crons as $cron ) {
if ( isset( $cron[ $hook ][ $signature ] ) ) {
$args = $cron[ $hook ][ $signature ]['args'];
delete_transient( 'doing_cron' );
$scheduled = schedule_event( $hook, $args );
if ( false === $scheduled ) {
return $scheduled;
}
add_filter( 'cron_request', function( array $cron_request ) {
$cron_request['url'] = add_query_arg( 'run-cron', 1, $cron_request['url'] );
return $cron_request;
} );
spawn_cron();
sleep( 1 );
return true;
}
}
return false;
}
function schedule_event( $hook, $args = array() ) {
$event = (object) array(
'hook' => $hook,
'timestamp' => 1,
'schedule' => false,
'args' => $args,
);
$crons = (array) _get_cron_array();
$key = md5( serialize( $event->args ) );
$crons[ $event->timestamp ][ $event->hook ][ $key ] = array(
'schedule' => $event->schedule,
'args' => $event->args,
);
uksort( $crons, 'strnatcasecmp' );
return _set_cron_array( $crons );
}

View File

@ -2,9 +2,8 @@
* External dependencies.
*/
import { useState } from '@wordpress/element';
import { Button } from '@wordpress/components';
import { Button, SelectControl } from '@wordpress/components';
import apiFetch from '@wordpress/api-fetch';
import { SelectControl } from '@wordpress/components';
export const AddNote = () => {

View File

@ -60,6 +60,13 @@
&.command {
white-space: nowrap;
}
.trigger-cron-job {
width: 40%;
padding-top: 4px;
.components-base-control__field {
margin-bottom: 0;
}
}
}
}
.components-notice {

View File

@ -1,3 +1,5 @@
import { TriggerCronJob, TRIGGER_CRON_ACTION_NAME } from './trigger-cron';
export default [
{
command: 'Trigger WCA Install',
@ -39,4 +41,9 @@ export default [
description: 'Delete all products',
action: 'deleteAllProducts',
},
{
command: 'Run a cron job',
description: <TriggerCronJob />,
action: TRIGGER_CRON_ACTION_NAME,
},
];

View File

@ -0,0 +1,48 @@
/**
* External dependencies.
*/
import { SelectControl } from '@wordpress/components';
import { useDispatch, useSelect } from '@wordpress/data';
/**
* Internal dependencies
*/
import { STORE_KEY } from '../data/constants';
export const TRIGGER_CRON_ACTION_NAME = 'runSelectedCronJob';
export const TriggerCronJob = () => {
const { cronList } = useSelect((select) => {
const { getCronJobs } = select(STORE_KEY);
return {
cronList: getCronJobs(),
};
});
const { updateCommandParams } = useDispatch(STORE_KEY);
function onCronChange(selectedValue) {
const { hook, signature } = cronList[selectedValue];
updateCommandParams(TRIGGER_CRON_ACTION_NAME, { hook, signature });
}
function getOptions() {
return Object.keys(cronList).map((name) => {
return { label: name, value: name };
});
}
return (
<div className="trigger-cron-job">
{!cronList ? (
<p>Loading ...</p>
) : (
<SelectControl
label="Select cron job to run"
onChange={onCronChange}
labelPosition="side"
options={getOptions()}
/>
)}
</div>
);
};

View File

@ -4,6 +4,8 @@ const TYPES = {
ADD_MESSAGE: 'ADD_MESSAGE',
UPDATE_MESSAGE: 'UPDATE_MESSAGE',
REMOVE_MESSAGE: 'REMOVE_MESSAGE',
ADD_COMMAND_PARAMS: 'ADD_COMMAND_PARAMS',
SET_CRON_JOBS: 'SET_CRON_JOBS',
};
export default TYPES;

View File

@ -47,6 +47,21 @@ export function removeMessage( source ) {
};
}
export function updateCommandParams(source, params) {
return {
type: TYPES.ADD_COMMAND_PARAMS,
source,
params,
};
}
export function setCronJobs(cronJobs) {
return {
type: TYPES.SET_CRON_JOBS,
cronJobs,
};
}
function* runCommand(commandName, func) {
try {
yield addCurrentlyRunning(commandName);
@ -114,8 +129,7 @@ export function* updateStoreAge() {
if (numberOfDays !== null) {
const dates = numberOfDays.split('/');
const newTimestamp = Math.round(
new Date( dates[ 0 ], dates[ 1 ] - 1, dates[ 2 ] ).getTime() /
1000
new Date(dates[0], dates[1] - 1, dates[2]).getTime() / 1000
);
const payload = {
woocommerce_admin_install_timestamp: JSON.parse(newTimestamp),
@ -151,3 +165,13 @@ export function* deleteAllProducts() {
});
});
}
export function* runSelectedCronJob(params) {
yield runCommand('Run selected cron job', function* () {
yield apiFetch({
path: API_NAMESPACE + '/tools/run-wc-admin-daily/v1',
method: 'POST',
data: params,
});
});
}

View File

@ -8,6 +8,7 @@ import { controls } from '@wordpress/data-controls';
* Internal dependencies
*/
import * as actions from './actions';
import * as resolvers from './resolvers';
import * as selectors from './selectors';
import reducer from './reducer';
import { STORE_KEY } from './constants';
@ -15,6 +16,7 @@ import { STORE_KEY } from './constants';
export default registerStore( STORE_KEY, {
actions,
selectors,
resolvers,
controls,
reducer,
} );

View File

@ -6,7 +6,9 @@ import TYPES from './action-types';
const DEFAULT_STATE = {
currentlyRunning: {},
errorMessages: [],
cronJobs: false,
messages: {},
params: [],
status: '',
};
@ -54,6 +56,18 @@ const reducer = ( state = DEFAULT_STATE, action ) => {
[ action.command ]: false,
},
};
case TYPES.SET_CRON_JOBS:
return {
...state,
cronJobs: action.cronJobs,
};
case TYPES.ADD_COMMAND_PARAMS:
return {
...state,
params: {
[ action.source ]: action.params,
},
};
default:
return state;
}

View File

@ -0,0 +1,24 @@
/**
* External dependencies
*/
import { apiFetch } from '@wordpress/data-controls';
/**
* Internal dependencies
*/
import { API_NAMESPACE } from './constants';
import { setCronJobs } from './actions';
export function* getCronJobs() {
const path = `${ API_NAMESPACE }/tools/get-cron-list/v1`;
try {
const response = yield apiFetch( {
path,
method: 'GET',
} );
yield setCronJobs( response );
} catch ( error ) {
throw new Error( error );
}
}

View File

@ -9,3 +9,11 @@ export function getMessages( state ) {
export function getStatus( state ) {
return state.status;
}
export function getCommandParams( state ) {
return state.params;
}
export function getCronJobs( state ) {
return state.cronJobs;
}

View File

@ -12,7 +12,7 @@ import { default as commands } from './commands';
import { STORE_KEY } from './data/constants';
import './data';
function Tools( { actions, currentlyRunningCommands, messages } ) {
function Tools( { actions, currentlyRunningCommands, messages, comandParams } ) {
actions = actions();
return (
<div id="wc-admin-test-helper-tools">
@ -38,17 +38,18 @@ function Tools( { actions, currentlyRunningCommands, messages } ) {
</tr>
</thead>
<tbody>
{ commands.map( ( command, index ) => {
{ commands.map( ( { action, command, description }, index ) => {
const params = comandParams[ action ] ?? false;
return (
<tr key={ index }>
<td className="command">{ command.command }</td>
<td>{ command.description }</td>
<td className="command">{ command }</td>
<td>{ description }</td>
<td>
<Button
onClick={ actions[ command.action ] }
onClick={ () => actions[ action ]( params ) }
disabled={
currentlyRunningCommands[
command.command
command
]
}
isPrimary
@ -67,10 +68,11 @@ function Tools( { actions, currentlyRunningCommands, messages } ) {
export default compose(
withSelect( ( select ) => {
const { getCurrentlyRunning, getMessages } = select( STORE_KEY );
const { getCurrentlyRunning, getMessages, getCommandParams } = select( STORE_KEY );
return {
currentlyRunningCommands: getCurrentlyRunning(),
messages: getMessages(),
comandParams: getCommandParams(),
};
} ),
withDispatch( ( dispatch ) => {