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

@ -9,21 +9,21 @@ import { apiFetch } from '@wordpress/data-controls';
import TYPES from './action-types';
import { API_NAMESPACE } from './constants';
export function addCurrentlyRunning( command ) {
export function addCurrentlyRunning(command) {
return {
type: TYPES.ADD_CURRENTLY_RUNNING,
command,
};
}
export function removeCurrentlyRunning( command ) {
export function removeCurrentlyRunning(command) {
return {
type: TYPES.REMOVE_CURRENTLY_RUNNING,
command,
};
}
export function addMessage( source, message ) {
export function addMessage(source, message) {
return {
type: TYPES.ADD_MESSAGE,
source,
@ -31,7 +31,7 @@ export function addMessage( source, message ) {
};
}
export function updateMessage( source, message, status ) {
export function updateMessage(source, message, status) {
return {
type: TYPES.ADD_MESSAGE,
source,
@ -40,69 +40,84 @@ export function updateMessage( source, message, status ) {
};
}
export function removeMessage( source ) {
export function removeMessage(source) {
return {
type: TYPES.REMOVE_MESSAGE,
source,
};
}
function* runCommand( commandName, func ) {
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 );
yield addMessage( commandName, 'Executing...' );
yield addCurrentlyRunning(commandName);
yield addMessage(commandName, 'Executing...');
yield func();
yield removeCurrentlyRunning( commandName );
yield updateMessage( commandName, 'Successful!' );
} catch ( e ) {
yield updateMessage( commandName, e.message, 'error' );
yield removeCurrentlyRunning( commandName );
yield removeCurrentlyRunning(commandName);
yield updateMessage(commandName, 'Successful!');
} catch (e) {
yield updateMessage(commandName, e.message, 'error');
yield removeCurrentlyRunning(commandName);
}
}
export function* triggerWcaInstall() {
yield runCommand( 'Trigger WCA Install', function* () {
yield apiFetch( {
yield runCommand('Trigger WCA Install', function* () {
yield apiFetch({
path: API_NAMESPACE + '/tools/trigger-wca-install/v1',
method: 'POST',
} );
} );
});
});
}
export function* resetOnboardingWizard() {
yield runCommand( 'Reset Onboarding Wizard', function* () {
yield runCommand('Reset Onboarding Wizard', function* () {
const optionsToDelete = [
'woocommerce_task_list_tracked_completed_tasks',
'woocommerce_onboarding_profile',
'_transient_wc_onboarding_themes',
];
yield apiFetch( {
yield apiFetch({
method: 'DELETE',
path: `${ API_NAMESPACE }/options/${ optionsToDelete.join( ',' ) }`,
} );
} );
path: `${API_NAMESPACE}/options/${optionsToDelete.join(',')}`,
});
});
}
export function* resetJetpackConnection() {
yield runCommand( 'Reset Jetpack Connection', function* () {
yield apiFetch( {
yield runCommand('Reset Jetpack Connection', function* () {
yield apiFetch({
method: 'DELETE',
path: `${ API_NAMESPACE }/options/jetpack_options`,
} );
} );
path: `${API_NAMESPACE}/options/jetpack_options`,
});
});
}
export function* enableTrackingDebug() {
yield runCommand( 'Enable WC Admin Tracking Debug Mode', function* () {
window.localStorage.setItem( 'debug', 'wc-admin:*' );
} );
yield runCommand('Enable WC Admin Tracking Debug Mode', function* () {
window.localStorage.setItem('debug', 'wc-admin:*');
});
}
export function* updateStoreAge() {
yield runCommand( 'Update Installation timestamp', function* () {
yield runCommand('Update Installation timestamp', function* () {
const today = new Date();
const dd = String( today.getDate() ).padStart( 2, '0' );
const mm = String( today.getMonth() + 1 ).padStart( 2, '0' ); //January is 0!
const dd = String(today.getDate()).padStart(2, '0');
const mm = String(today.getMonth() + 1).padStart(2, '0'); //January is 0!
const yyyy = today.getFullYear();
// eslint-disable-next-line no-alert
@ -111,43 +126,52 @@ export function* updateStoreAge() {
yyyy + '/' + mm + '/' + dd
);
if ( numberOfDays !== null ) {
const dates = numberOfDays.split( '/' );
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 ),
woocommerce_admin_install_timestamp: JSON.parse(newTimestamp),
};
yield apiFetch( {
yield apiFetch({
method: 'POST',
path: '/wc-admin/options',
headers: { 'content-type': 'application/json' },
body: JSON.stringify( payload ),
} );
body: JSON.stringify(payload),
});
}
} );
});
}
export function* runWcAdminDailyJob() {
yield runCommand( 'Run wc_admin_daily job', function* () {
yield apiFetch( {
yield runCommand('Run wc_admin_daily job', function* () {
yield apiFetch({
path: API_NAMESPACE + '/tools/run-wc-admin-daily/v1',
method: 'POST',
} );
} );
});
});
}
export function* deleteAllProducts() {
if ( ! confirm( 'Are you sure you want to delete all of the products?' ) ) {
if (!confirm('Are you sure you want to delete all of the products?')) {
return;
}
yield runCommand( 'Delete all products', function* () {
yield apiFetch( {
path: `${ API_NAMESPACE }/tools/delete-all-products/v1`,
yield runCommand('Delete all products', function* () {
yield apiFetch({
path: `${API_NAMESPACE}/tools/delete-all-products/v1`,
method: 'POST',
} );
} );
});
});
}
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 ) => {