and size. * * @since 6.12.0 * @param int $post_id The post ID. * @param int $size The size of the QR code image. * @return void */ private function delete_qr_image( int $post_id, int $size ): void { $file_name = 'qr_' . $post_id . '_' . (int) $size * 35; $file_path = $this->qr_dir . $file_name . '.png'; if ( file_exists( $file_path ) ) { // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_unlink unlink( $file_path ); } } /** * Renders the QR code modal. * * @since 6.12.0 * @return void */ public function render_modal(): void { // Verify nonce for CSRF protection. check_ajax_referer( 'tec_qr_code_modal', '_wpnonce' ); $post = get_post( tec_get_request_var( 'post_id' ) ); if ( ! $post ) { wp_die( esc_html__( 'No post found.', 'the-events-calendar' ) ); } // Verify user has permission to edit this post. if ( ! current_user_can( 'edit_post', $post->ID ) ) { wp_die( esc_html__( 'You do not have permission to access this content.', 'the-events-calendar' ), 403 ); } $allowed_types = [ TEC::POSTTYPE ]; /** * Filters the post types that support QR codes. * * @since 6.12.0 * * @param array $allowed_types Array of allowed post types. */ $allowed_types = apply_filters( 'tec_events_qr_code_post_types', $allowed_types ); if ( ! in_array( $post->post_type, $allowed_types ) ) { wp_die( esc_html__( 'Not a supported post type.', 'the-events-calendar' ) ); } if ( is_wp_error( $this->qr_code ) ) { wp_die( esc_html__( 'Error generating QR code.', 'the-events-calendar' ) ); } /** * Filters the redirection type for QR codes. * * @since 6.12.0 * * @param string $redirection The redirection type ('specific' or 'next'). * @param WP_Post $post The post object. */ $redirection = apply_filters( 'tec_events_qr_code_redirection_type', 'specific', $post ); $qr_url = $this->routes->get_qr_url( $post->ID, $redirection ); $qr_images = []; for ( $i = 4; $i <= 28; $i += 4 ) { $uploaded = $this->generate_qr_image( $post->ID, $qr_url, $i ); $qr_images[ $i ] = $uploaded['error'] ? '' : $uploaded['url']; } $template_vars = [ 'title' => get_the_title( $post ), 'placeholder' => $this->qr_code->level( 1 )->size( 6 )->margin( 1 )->get_png_as_base64( $qr_url ), 'qr_images' => $qr_images, 'qr_url' => $qr_url, 'alt' => sprintf( /* translators: %s: The event title or type of QR code */ esc_attr__( 'QR Code for %s', 'the-events-calendar' ), get_the_title( $post ) ), ]; /** * Filters the template variables for the QR code modal. * * @since 6.12.0 * * @param array $template_vars The template variables. * @param WP_Post $post The post object. */ $template_vars = apply_filters( 'tec_events_qr_code_modal_vars', $template_vars, $post ); $template = new \Tribe__Template(); $template->set_template_origin( TEC::instance() ); $template->set_template_folder( 'src/admin-views' ); $template->set_template_folder_lookup( true ); $template->set_template_context_extract( true ); $template->template( 'qr-code-modal', $template_vars ); wp_die(); } /** * Generates the QR image for a given link and stores it in /wp-content/uploads. * Returns the uploaded image information. * * @param int $post_id The event/series ID. * @param string $link The QR link. * @param int $size The size of the QR image. * * @return ?array { * @type string $file The path to the QR code image file. * @type string $url The URL to the QR code image file. * @type string $type The MIME type of the QR code image file. * @type string $error The error message if the QR code image file could not be generated. * } */ public function generate_qr_image( int $post_id, string $link, int $size = 6 ): ?array { if ( empty( $link ) || ! tribe( Controller::class )->is_active() ) { return null; } $file_name = 'qr_' . $post_id . '_' . (int) $size * 35; $file_path = $this->qr_dir . $file_name . '.png'; $file_url = $this->qr_url . $file_name . '.png'; /** * Filters whether to regenerate the QR code image. * * @since 6.12.0 * * @param bool $regenerate Whether to regenerate the QR code image. * @param int $post_id The post ID. * @param int $size The size of the QR code image. */ $regenerate = apply_filters( 'tec_events_qr_code_regenerate', false, $post_id, $size ); if ( file_exists( $file_path ) && ! $regenerate ) { return [ 'file' => $file_path, 'url' => $file_url, 'type' => 'image/png', 'error' => '', ]; } elseif ( $regenerate ) { $this->delete_qr_image( $post_id, $size ); } return $this->qr_code->level( 1 )->size( $size )->margin( 1 )->get_png_as_file( $link, $file_name ); } }