self::SLUG ), $args ), admin_url( 'admin.php' ) );
}
public static function action_links( $links ) {
array_unshift( $links, '' . esc_html__( 'Galleries', 'equaframe' ) . '' );
return $links;
}
public static function menu() {
add_menu_page(
__( 'EquaFrame', 'equaframe' ),
__( 'Galleries', 'equaframe' ),
self::cap(),
self::SLUG,
array( __CLASS__, 'page_main' ),
EQUAFRAME_URL . 'assets/images/icon-menu.svg',
26
);
add_submenu_page( self::SLUG, __( 'All Galleries', 'equaframe' ), __( 'All Galleries', 'equaframe' ), self::cap(), self::SLUG, array( __CLASS__, 'page_main' ) );
add_submenu_page( self::SLUG, __( 'Add New Gallery', 'equaframe' ), __( 'Add New', 'equaframe' ), self::cap(), self::SLUG . '-new', array( __CLASS__, 'page_new' ) );
}
/* ------------------------------------------------------------------ assets */
public static function assets( $hook ) {
if ( false === strpos( $hook, self::SLUG ) ) {
return;
}
wp_enqueue_style( 'eqfr-admin', EQUAFRAME_URL . 'assets/css/admin.css', array( 'wp-color-picker' ), EQUAFRAME_VERSION );
$deps = array( 'jquery', 'wp-color-picker', 'jquery-ui-sortable', 'wp-a11y' );
$gallery_id = self::editing_id();
if ( $gallery_id ) {
wp_enqueue_media();
}
wp_enqueue_script( 'eqfr-admin', EQUAFRAME_URL . 'assets/js/admin.js', $deps, EQUAFRAME_VERSION, true );
wp_localize_script(
'eqfr-admin',
'eqfrAdmin',
array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'equaframe_images' ),
'galleryId' => $gallery_id,
'i18n' => array(
'mediaTitle' => __( 'Choose images for this gallery', 'equaframe' ),
'mediaButton' => __( 'Add to gallery', 'equaframe' ),
'saving' => __( 'Saving…', 'equaframe' ),
'saved' => __( 'All changes saved.', 'equaframe' ),
'saveFailed' => __( 'Could not save. Check your connection and try again.', 'equaframe' ),
/* translators: 1: new position, 2: total images */
'moved' => __( 'Moved to position %1$d of %2$d.', 'equaframe' ),
'removed' => __( 'Image removed from gallery.', 'equaframe' ),
/* translators: %d: image number */
'imageN' => __( 'Image %d', 'equaframe' ),
/* translators: %s: image name */
'removeImage' => __( 'Remove %s from gallery', 'equaframe' ),
'confirmRemove' => __( 'Remove this image from the gallery? The file stays in your media library.', 'equaframe' ),
'confirmDelete' => __( 'Delete this gallery? This cannot be undone.', 'equaframe' ),
/* translators: %d: number of images */
'added' => __( '%d image(s) added.', 'equaframe' ),
/* translators: %d: number of images */
'count' => __( '%d image(s) in this gallery', 'equaframe' ),
'copied' => __( 'Shortcode copied to the clipboard.', 'equaframe' ),
'copyFailed' => __( 'Press Ctrl+C (Cmd+C on Mac) to copy the selected text.', 'equaframe' ),
/* translators: %s: contrast ratio, for example 4.52 */
'contrastOk' => __( 'Contrast %s:1. This passes.', 'equaframe' ),
/* translators: 1: measured contrast ratio, 2: minimum ratio required */
'contrastLow' => __( 'Contrast is only %1$s:1. WCAG needs at least %2$s:1 here. Choose colors that are further apart.', 'equaframe' ),
'unsaved' => __( 'You have unsaved changes.', 'equaframe' ),
),
)
);
}
public static function editing_id() {
// phpcs:ignore WordPress.Security.NonceVerification
if ( ! isset( $_GET['page'], $_GET['action'], $_GET['gallery'] ) || self::SLUG !== $_GET['page'] || 'edit' !== $_GET['action'] ) {
return 0;
}
// phpcs:ignore WordPress.Security.NonceVerification
$id = absint( $_GET['gallery'] );
return EquaFrame_Gallery::get( $id ) ? $id : 0;
}
/**
* One image row. Used for server-rendered rows and for the that
* admin.js clones when images are added. Button labels are refreshed by JS.
*/
public static function render_row( $image, $thumb ) {
$fields = array(
'title' => __( 'Title', 'equaframe' ),
'alt' => __( 'Alt text', 'equaframe' ),
'caption' => __( 'Caption', 'equaframe' ),
'css_id' => __( 'CSS ID (optional)', 'equaframe' ),
);
?>
array( 'success', __( 'Gallery created. Add some images to get started.', 'equaframe' ) ),
'saved' => array( 'success', __( 'Settings saved.', 'equaframe' ) ),
'deleted' => array( 'success', __( 'Gallery deleted.', 'equaframe' ) ),
'duplicated' => array( 'success', __( 'Gallery duplicated.', 'equaframe' ) ),
'noname' => array( 'error', __( 'Please enter a name for the gallery.', 'equaframe' ) ),
'failed' => array( 'error', __( 'Something went wrong. Please try again.', 'equaframe' ) ),
);
if ( isset( $map[ $code ] ) ) {
printf( '', esc_attr( $map[ $code ][0] ), esc_html( $map[ $code ][1] ) );
}
}
public static function shortcode( $id ) {
return '[equaframe id="' . (int) $id . '"]';
}
/* ------------------------------------------------------------------ handlers */
private static function require_cap() {
if ( ! current_user_can( self::cap() ) ) {
wp_die( esc_html__( 'You do not have permission to manage galleries.', 'equaframe' ), 403 );
}
}
public static function handle_create() {
self::require_cap();
check_admin_referer( 'equaframe_create' );
$name = isset( $_POST['equaframe_name'] ) ? sanitize_text_field( wp_unslash( $_POST['equaframe_name'] ) ) : '';
$layout = isset( $_POST['equaframe_layout'] ) ? sanitize_key( wp_unslash( $_POST['equaframe_layout'] ) ) : 'grid';
if ( '' === $name ) {
wp_safe_redirect( add_query_arg( array( 'page' => self::SLUG . '-new', 'equaframe_notice' => 'noname' ), admin_url( 'admin.php' ) ) );
exit;
}
$id = EquaFrame_Gallery::create( $name, $layout );
if ( is_wp_error( $id ) ) {
wp_safe_redirect( self::url( array( 'equaframe_notice' => 'failed' ) ) );
exit;
}
wp_safe_redirect( self::url( array( 'action' => 'edit', 'gallery' => $id, 'tab' => 'images', 'equaframe_notice' => 'created' ) ) );
exit;
}
public static function handle_save() {
self::require_cap();
check_admin_referer( 'equaframe_save' );
$id = isset( $_POST['gallery_id'] ) ? absint( $_POST['gallery_id'] ) : 0;
if ( ! EquaFrame_Gallery::get( $id ) ) {
wp_safe_redirect( self::url( array( 'equaframe_notice' => 'failed' ) ) );
exit;
}
$name = isset( $_POST['equaframe_name'] ) ? sanitize_text_field( wp_unslash( $_POST['equaframe_name'] ) ) : '';
$input = isset( $_POST['eqfr'] ) ? wp_unslash( $_POST['eqfr'] ) : array(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
$tab = isset( $_POST['tab'] ) ? sanitize_key( $_POST['tab'] ) : 'layout';
EquaFrame_Gallery::save_settings( $id, $input, $name );
wp_safe_redirect( self::url( array( 'action' => 'edit', 'gallery' => $id, 'tab' => $tab, 'equaframe_notice' => 'saved' ) ) );
exit;
}
public static function handle_delete() {
self::require_cap();
$id = isset( $_GET['gallery'] ) ? absint( $_GET['gallery'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- The ID only picks which nonce to verify on the next line.
check_admin_referer( 'equaframe_delete_' . $id );
$deleted = EquaFrame_Gallery::delete( $id );
wp_safe_redirect( self::url( array( 'equaframe_notice' => $deleted ? 'deleted' : 'failed' ) ) );
exit;
}
public static function handle_duplicate() {
self::require_cap();
$id = isset( $_GET['gallery'] ) ? absint( $_GET['gallery'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- The ID only picks which nonce to verify on the next line.
check_admin_referer( 'equaframe_duplicate_' . $id );
$new = EquaFrame_Gallery::duplicate( $id );
wp_safe_redirect( self::url( array( 'equaframe_notice' => $new ? 'duplicated' : 'failed' ) ) );
exit;
}
/**
* Autosave endpoint for the Images tab. Receives the whole ordered list, so
* saving after a drop, a move or a field blur is the same idempotent call.
*/
public static function ajax_save_images() {
check_ajax_referer( 'equaframe_images', 'nonce' );
if ( ! current_user_can( self::cap() ) ) {
wp_send_json_error( null, 403 );
}
$id = isset( $_POST['gallery'] ) ? absint( $_POST['gallery'] ) : 0;
if ( ! EquaFrame_Gallery::get( $id ) ) {
wp_send_json_error( null, 404 );
}
// A missing or unreadable list (for example a request cut short by a server limit) must
// never be saved as "no images", or one bad request would empty the gallery.
$raw = isset( $_POST['images'] ) ? json_decode( wp_unslash( $_POST['images'] ), true ) : null; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
if ( ! is_array( $raw ) ) {
wp_send_json_error( null, 400 );
}
$images = EquaFrame_Gallery::sanitize_images( $raw );
EquaFrame_Gallery::save_images( $id, $images );
wp_send_json_success( array( 'count' => count( $images ), 'images' => $images ) );
}
}