' . esc_html( $title ) . ' ';
echo '' . wp_kses_post( sprintf( /* translators: %s: URL */ __( 'Please connect your shop first.', 'eazign' ), esc_url( admin_url( 'admin.php?page=eazign' ) ) ) ) . '
';
return false;
}
/**
* Stops AJAX requests of users without the WooCommerce capability.
*/
private static function ajax_guard() {
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_send_json_error( array( 'message' => __( 'Sorry, you are not allowed to do this.', 'eazign' ) ), 403 );
}
}
// ---- motifs ----------------------------------------------------------------
/**
* Motif gallery.
*/
public static function page_motifs() {
if ( ! self::connected_or_hint( __( 'Motifs', 'eazign' ) ) ) {
return;
}
$data = Eazign_Client::get( 'motifs' );
$motifs = is_wp_error( $data ) ? array() : $data['motifs'];
$categories = array_values( array_unique( wp_list_pluck( $motifs, 'category' ) ) );
?>
', esc_html( $data->get_error_message() ) );
}
?>
__( 'Please choose a file.', 'eazign' ) ) );
}
$bytes = file_get_contents( $_FILES['file']['tmp_name'] ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents, WordPress.Security.ValidatedSanitizedInput
$result = Eazign_Client::post(
'motifs',
array(
'name' => isset( $_FILES['file']['name'] ) ? sanitize_file_name( wp_unslash( $_FILES['file']['name'] ) ) : '',
'category' => isset( $_POST['category'] ) ? sanitize_text_field( wp_unslash( $_POST['category'] ) ) : '',
'data' => base64_encode( $bytes ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode -- binary upload in JSON.
),
array( 'timeout' => 120 )
);
if ( is_wp_error( $result ) ) {
wp_send_json_error( array( 'message' => $result->get_error_message() ) );
}
wp_send_json_success( $result );
}
/**
* Rename / recategorise a motif.
*/
public static function save_motif() {
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_die( esc_html__( 'Sorry, you are not allowed to do this.', 'eazign' ) );
}
$id = isset( $_POST['motif'] ) ? sanitize_key( wp_unslash( $_POST['motif'] ) ) : '';
check_admin_referer( 'eazign_save_motif_' . $id );
$result = Eazign_Client::post(
'motifs/' . rawurlencode( $id ),
array(
'name' => isset( $_POST['name'] ) ? sanitize_text_field( wp_unslash( $_POST['name'] ) ) : '',
'category' => isset( $_POST['category'] ) ? sanitize_text_field( wp_unslash( $_POST['category'] ) ) : '',
)
);
Eazign_Admin::notice( is_wp_error( $result ) ? 'error' : 'success', is_wp_error( $result ) ? $result->get_error_message() : __( 'Motif saved.', 'eazign' ) );
wp_safe_redirect( admin_url( 'admin.php?page=eazign-motifs' ) );
exit;
}
/**
* Delete a motif.
*/
public static function delete_motif() {
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_die( esc_html__( 'Sorry, you are not allowed to do this.', 'eazign' ) );
}
$id = isset( $_GET['motif'] ) ? sanitize_key( wp_unslash( $_GET['motif'] ) ) : '';
check_admin_referer( 'eazign_delete_motif_' . $id );
$result = Eazign_Client::post( 'motifs/' . rawurlencode( $id ) . '/delete' );
Eazign_Admin::notice( is_wp_error( $result ) ? 'error' : 'success', is_wp_error( $result ) ? $result->get_error_message() : __( 'Motif deleted.', 'eazign' ) );
wp_safe_redirect( admin_url( 'admin.php?page=eazign-motifs' ) );
exit;
}
// ---- generator -------------------------------------------------------------
/**
* Generator: choose motifs, blanks with colours, placement; then runs.
*/
public static function page_generator() {
if ( ! self::connected_or_hint( __( 'Generator', 'eazign' ) ) ) {
return;
}
$motifs = Eazign_Client::get( 'motifs' );
$blanks = Eazign_Client::get( 'blanks' );
$ids = (array) get_option( self::JOBS, array() );
$jobs = $ids ? Eazign_Client::get( 'generator?ids=' . rawurlencode( implode( ',', $ids ) ) ) : array( 'jobs' => array() );
echo '' . esc_html__( 'Generator', 'eazign' ) . ' ';
echo '
' . esc_html__( 'Prints each selected motif on each selected blank and creates one variable product per combination (colour × size) with prices, SKUs and a mockup per colour. Orders of these products get print files automatically.', 'eazign' ) . '
';
foreach ( array( $motifs, $blanks, $jobs ) as $result ) {
if ( is_wp_error( $result ) ) {
printf( '
', esc_html( $result->get_error_message() ) );
return;
}
}
$motifs = $motifs['motifs'];
$blanks = $blanks['blanks'];
if ( ! $motifs || ! $blanks ) {
echo '' . wp_kses_post(
sprintf(
/* translators: 1: motifs URL, 2: blanks URL */
__( 'The generator needs at least one motif and one blank with a base photo.', 'eazign' ),
esc_url( admin_url( 'admin.php?page=eazign-motifs' ) ),
esc_url( admin_url( 'admin.php?page=eazign-blanks' ) )
)
) . '
';
return;
}
$view_names = array();
foreach ( $blanks as $blank ) {
foreach ( $blank['views'] as $view ) {
$view_names[ $view['name'] ] = true;
}
}
$categories = get_terms(
array(
'taxonomy' => 'product_cat',
'hide_empty' => false,
)
);
$sizes = array();
foreach ( $blanks as $blank ) {
$sizes[ $blank['id'] ] = max( 1, count( $blank['sizes'] ) );
}
?>
' . esc_html( $date ) . ' · ';
/* translators: 1: done, 2: total */
echo esc_html( sprintf( __( '%1$d of %2$d products', 'eazign' ), $job['done'], $job['total'] ) );
if ( 'running' === $job['status'] ) {
echo ' · ' . esc_html__( 'running…', 'eazign' );
}
echo ' ';
foreach ( $job['results'] as $result ) {
echo '';
if ( ! empty( $result['error'] ) ) {
echo '' . esc_html( $result['error'] ) . ' ';
} elseif ( ! empty( $result['productId'] ) && get_post( (int) $result['productId'] ) ) {
echo '' . esc_html( $result['title'] ) . ' ';
} else {
echo esc_html( $result['title'] );
}
echo ' ';
}
echo ' ';
}
/**
* Starts a generator run (background job at the service).
*/
public static function ajax_generate() {
check_ajax_referer( 'eazign_sync' );
self::ajax_guard();
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- JSON, every field is sanitized below.
$items_in = isset( $_POST['items'] ) ? json_decode( wp_unslash( $_POST['items'] ), true ) : array();
$placement = isset( $_POST['placement'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['placement'] ) ), true ) : array();
$items = array();
foreach ( is_array( $items_in ) ? $items_in : array() as $item ) {
$items[] = array(
'motifId' => sanitize_key( $item['motifId'] ?? '' ),
'darkMotifId' => sanitize_key( $item['darkMotifId'] ?? '' ),
'blankId' => sanitize_key( $item['blankId'] ?? '' ),
'colors' => array_map( 'sanitize_text_field', (array) ( $item['colors'] ?? array() ) ),
);
}
$placement = is_array( $placement ) ? $placement : array();
$result = Eazign_Client::post(
'generator',
array(
'items' => $items,
'placement' => array(
'view' => sanitize_text_field( $placement['view'] ?? '' ),
'align' => sanitize_key( $placement['align'] ?? 'center' ),
'topMm' => (float) ( $placement['topCm'] ?? 3 ) * 10,
'widthMm' => (float) ( $placement['widthCm'] ?? 26 ) * 10,
),
'status' => isset( $_POST['status'] ) && 'publish' === $_POST['status'] ? 'publish' : 'draft',
'categoryIds' => isset( $_POST['categories'] ) ? array_map( 'absint', explode( ',', sanitize_text_field( wp_unslash( $_POST['categories'] ) ) ) ) : array(),
)
);
if ( is_wp_error( $result ) ) {
wp_send_json_error( array( 'message' => $result->get_error_message() ) );
}
$ids = (array) get_option( self::JOBS, array() );
array_unshift( $ids, sanitize_key( $result['jobId'] ) );
update_option( self::JOBS, array_slice( $ids, 0, 10 ), false );
wp_send_json_success( $result );
}
/**
* Progress of a generator run.
*/
public static function ajax_status() {
check_ajax_referer( 'eazign_sync' );
self::ajax_guard();
$job = isset( $_POST['job'] ) ? sanitize_key( wp_unslash( $_POST['job'] ) ) : '';
$result = Eazign_Client::get( 'generator/' . rawurlencode( $job ) );
if ( is_wp_error( $result ) ) {
wp_send_json_error( array( 'message' => $result->get_error_message() ) );
}
foreach ( $result['job']['results'] as &$entry ) {
if ( ! empty( $entry['productId'] ) && get_post( (int) $entry['productId'] ) ) {
$entry['editUrl'] = get_edit_post_link( (int) $entry['productId'], 'raw' );
}
}
unset( $entry );
wp_send_json_success( $result['job'] );
}
}