Site Builder
Editing:
business-listing-subscription.php
writable 0666
<?php /** * Plugin Name: Business Listing Subscription for WooCommerce * Plugin URI: https://yourdomain.com/business-listing-subscription * Description: Self-service directory subscription product. 10-digit phone = unique SKU. Auto-page + sign-up form. HPOS compatible. * Version: 1.1.4 * Author: Your Name * Author URI: https://yourdomain.com * License: GPLv2 or later * License URI: https://www.gnu.org/licenses/gpl-2.0.html * Text Domain: business-listing-subscription */ if ( ! defined( 'ABSPATH' ) ) { exit; } // phpcs:disable } // phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.EscapeOutput.OutputNotEscaped /** * Activation: deactivate if dependencies missing. */ register_activation_hook( __FILE__, 'bls_activation_check' ); function bls_activation_check() { if ( ! class_exists( 'WooCommerce' ) ) { deactivate_plugins( plugin_basename( __FILE__ ) ); wp_die( esc_html__( 'Business Listing Subscription requires WooCommerce. Plugin has been deactivated.', 'business-listing-subscription' ) ); } if ( ! class_exists( 'WC_Product_Subscription' ) && ! class_exists( 'WC_Subscriptions' ) ) { deactivate_plugins( plugin_basename( __FILE__ ) ); wp_die( esc_html__( 'Business Listing Subscription requires WooCommerce Subscriptions. Plugin has been deactivated.', 'business-listing-subscription' ) ); } } /** * Admin notice if dependencies missing. */ add_action( 'admin_init', 'bls_check_dependencies' ); function bls_check_dependencies() { if ( ! class_exists( 'WooCommerce' ) ) { add_action( 'admin_notices', function() { echo '<div class="error"><p>' . esc_html__( 'Business Listing Subscription requires WooCommerce. Please install & activate WooCommerce.', 'business-listing-subscription' ) . '</p></div>'; } ); } if ( ! class_exists( 'WC_Product_Subscription' ) && ! class_exists( 'WC_Subscriptions' ) ) { add_action( 'admin_notices', function() { echo '<div class="error"><p>' . esc_html__( 'Business Listing Subscription requires WooCommerce Subscriptions. Please install & activate it.', 'business-listing-subscription' ) . '</p></div>'; } ); } } // Bail if dependencies not met. if ( ! class_exists( 'WooCommerce' ) || ( ! class_exists( 'WC_Product_Subscription' ) && ! class_exists( 'WC_Subscriptions' ) ) ) { return; } /** * Declare HPOS compatibility. */ add_action( 'before_woocommerce_init', 'bls_declare_hpos' ); function bls_declare_hpos() { if ( class_exists( '\\Automattic\\WooCommerce\\Utilities\\FeaturesUtil' ) ) { \\Automattic\\WooCommerce\\Utilities\\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true ); } } /** * Create sign-up page on activation. */ register_activation_hook( __FILE__, 'bls_create_signup_page' ); function bls_create_signup_page() { if ( ! get_option( 'bls_signup_page_id' ) ) { $title = wp_strip_all_tags( __( 'Business Sign-Up', 'business-listing-subscription' ) ); $page_id = wp_insert_post( [ 'post_title' => $title, 'post_name' => 'business-signup', 'post_content' => '[business_listing_signup]', 'post_status' => 'publish', 'post_type' => 'page', ] ); if ( ! is_wp_error( $page_id ) ) { update_option( 'bls_signup_page_id', intval( $page_id ) ); } } } /** * Register custom subscription product type. */ add_action( 'init', 'bls_register_product_type', 20 ); function bls_register_product_type() { if ( ! class_exists( 'WC_Product_Subscription' ) ) { return; } class WC_Product_Business_Listing_Subscription extends WC_Product_Subscription { public function __construct( $product = 0 ) { $this->product_type = 'business_listing_subscription'; parent::__construct( $product ); } } add_filter( 'product_type_selector', function( $types ) { $types['business_listing_subscription'] = __( 'Business Listing Subscription', 'business-listing-subscription' ); return $types; } ); } /** * Admin: add custom fields to product. */ add_action( 'woocommerce_product_options_general_product_data', 'bls_admin_fields' ); function bls_admin_fields() { global $product; if ( ! $product || 'business_listing_subscription' !== $product->get_type() ) { return; } echo '<div class="options_group">'; bls_admin_input( '_bls_phone', __( 'Phone (10-digit)', 'business-listing-subscription' ), true, '1234567890' ); bls_admin_input( '_bls_name', __( 'Business Name', 'business-listing-subscription' ), true ); bls_admin_input( '_bls_slogan', __( 'Slogan', 'business-listing-subscription' ), false ); bls_admin_input( '_bls_website', __( 'Website URL', 'business-listing-subscription' ), false, esc_attr__( 'https://example.com', 'business-listing-subscription' ) ); bls_admin_textarea( '_bls_description', __( 'Business Description', 'business-listing-subscription' ), true ); bls_admin_input( '_bls_address', __( 'Street Address', 'business-listing-subscription' ), true ); bls_admin_input( '_bls_city', __( 'City', 'business-listing-subscription' ), true ); bls_admin_input( '_bls_state', __( 'State/Province', 'business-listing-subscription' ), true ); bls_admin_input( '_bls_postcode', __( 'Post/Zip Code', 'business-listing-subscription' ), true ); bls_admin_input( '_bls_country', __( 'Country', 'business-listing-subscription' ), true ); foreach ( [ 'Mon','Tue','Wed','Thu','Fri','Sat','Sun' ] as $d ) { // translators: %s is day of week. bls_admin_input( "_bls_hours_{$d}", sprintf( __( '%s Hours', 'business-listing-subscription' ), $d ), false, '09:00-17:00' ); } $socials = [ 'facebook','instagram','linkedin','x','tiktok','pinterest','snapchat','youtube','yelp','nextdoor','reddit','tripadvisor','groupon','whatsapp','telegram','wechat','amazon','shopify','walmart','etsy','ebay' ]; foreach ( $socials as $soc ) { // translators: %s social network name bls_ff_field( $soc, sprintf( __( '%s URL', 'business-listing-subscription' ), ucfirst( $soc ) ) ); }", sprintf( __( '%s URL', 'business-listing-subscription' ), ucfirst( $soc ) ), false ); } bls_admin_input( '_bls_service_tags', __( 'Service Tags (comma-separated)', 'business-listing-subscription' ), true ); bls_admin_input( '_bls_location_tags', __( 'Location Tags (comma-separated)', 'business-listing-subscription' ), true ); bls_admin_input( '_bls_best_deal', __( 'Best Deal / Coupon', 'business-listing-subscription' ), false ); echo '</div>'; } function bls_admin_input( $id, $label, $required = false, $placeholder = '' ) { woocommerce_wp_text_input( [ 'id' => $id, 'label' => $label . ( $required ? ' *' : '' ), 'placeholder' => $placeholder, 'custom_attributes' => $required ? [ 'required' => 'required' ] : [], ] ); } function bls_admin_textarea( $id, $label, $required = false ) { woocommerce_wp_textarea_input( [ 'id' => $id, 'label' => $label . ( $required ? ' *' : '' ), 'custom_attributes' => $required ? [ 'required' => 'required' ] : [], ] ); } /** * Admin: save custom fields. */ // phpcs:ignore WordPress.Security.NonceVerification.Missing add_action( 'woocommerce_admin_process_product_object', 'bls_save_admin_meta' ); function bls_save_admin_meta( $product ) { if ( 'business_listing_subscription' !== $product->get_type() ) { return; } foreach ( $_POST as $key => $value ) { if ( 0 === strpos( $key, '_bls_' ) ) { $product->update_meta_data( $key, sanitize_text_field( wp_unslash( $value ) ) ); } } $raw_phone = isset( $_POST['_bls_phone'] ) ? wp_unslash( $_POST['_bls_phone'] ) : ''; $digits = preg_replace( '/\D+/', '', sanitize_text_field( $raw_phone ) ); if ( 10 === strlen( $digits ) ) { $product->set_sku( $digits ); } } /** * Front-end shortcode: display sign-up form. */ add_shortcode( 'business_listing_signup', 'bls_render_signup_form' ); function bls_render_signup_form() { if ( ! is_user_logged_in() ) { return '<p>' . esc_html__( 'Please log in to create your listing.', 'business-listing-subscription' ) . '</p>'; } ob_start(); ?> <form method="post" id="bls-signup-form"> <?php wp_nonce_field( 'bls_signup_action', 'bls_signup_nonce' ); ?> <h3><?php esc_html_e( 'Business Details', 'business-listing-subscription' ); ?></h3> <?php bls_ff_field( 'phone', __( 'Phone (10 digits)*', 'business-listing-subscription' ) ); ?> <?php bls_ff_field( 'name', __( 'Business Name*', 'business-listing-subscription' ) ); ?> <?php bls_ff_field( 'slogan', __( 'Slogan', 'business-listing-subscription' ) ); ?> <?php bls_ff_field( 'website', __( 'Website URL', 'business-listing-subscription' ) ); ?> <h3><?php esc_html_e( 'Address', 'business-listing-subscription' ); ?></h3> <?php bls_ff_field( 'address', __( 'Street Address*', 'business-listing-subscription' ) ); ?> <?php bls_ff_field( 'city', __( 'City*', 'business-listing-subscription' ) ); ?> <?php bls_ff_field( 'state', __( 'State/Province*','business-listing-subscription' ) ); ?> <?php bls_ff_field( 'postcode', __( 'Post/Zip Code*', 'business-listing-subscription' ) ); ?> <?php bls_ff_field( 'country', __( 'Country*', 'business-listing-subscription' ) ); ?> <h3><?php esc_html_e( 'Description', 'business-listing-subscription' ); ?></h3> <?php bls_ff_field( 'description', __( 'Describe your business*', 'business-listing-subscription' ), 'textarea' ); ?> <h3><?php esc_html_e( 'Hours of Operation', 'business-listing-subscription' ); ?></h3> <?php foreach ( [ 'Mon','Tue','Wed','Thu','Fri','Sat','Sun' ] as $d ) { // translators: %s day of week bls_ff_field( "hours_{$d}", sprintf( __( '%s (e.g. 09:00–17:00)', 'business-listing-subscription' ), $d ) ); } ?> <h3><?php esc_html_e( 'Social & Marketplace Links', 'business-listing-subscription' ); ?></h3> <?php foreach ( $socials as $soc ) { bls_ff_field( $soc, sprintf( __( '%s URL', 'business-listing-subscription' ), ucfirst( $soc ) ) ); } ?> <h3><?php esc_html_e( 'Tags & Deal', 'business-listing-subscription' ); ?></h3> <?php bls_ff_field( 'service_tags', __( 'Service Tags (comma-sep)*', 'business-listing-subscription' ) ); ?> <?php bls_ff_field( 'location_tags', __( 'Location Tags (comma-sep)*', 'business-listing-subscription' ) ); ?> <?php bls_ff_field( 'best_deal', __( 'Best Deal / Coupon', 'business-listing-subscription' ) ); ?> <p><button type="submit" class="button button-primary"><?php esc_html_e( 'Create Listing & Subscribe', 'business-listing-subscription' ); ?></button></p> </form> <?php return ob_get_clean(); } function bls_ff_field( $slug, $label, $type = 'text' ) { $name = 'bls_' . $slug; $raw = isset( $_POST[ $name ] ) ? wp_unslash( $_POST[ $name ] ) : ''; $val = 'textarea' === $type ? esc_textarea( sanitize_text_field( $raw ) ) : esc_attr( sanitize_text_field( $raw ) ); if ( 'textarea' === $type ) { printf( '<p><label>%s<br><textarea name="%1$s" rows="4" style="width:100%%;">%s</textarea></label></p>', esc_attr( $name ), $val ); } else { printf( '<p><label>%s<br><input type="%s" name="%s" value="%s" style="width:100%%;" /></label></p>', esc_html( $label ), esc_attr( $type ), esc_attr( $name ), $val ); } } /** * Handle form submission: create product & add to cart. */ // phpcs:ignore WordPress.Security.NonceVerification.Missing add_action( 'template_redirect', 'bls_handle_signup_submission' ); function bls_handle_signup_submission() { if ( empty( $_POST['bls_signup_nonce'] ) || ! wp_verify_nonce( wp_unslash( $_POST['bls_signup_nonce'] ), 'bls_signup_action' ) ) { return; } if ( ! is_user_logged_in() ) { return; } $posted = []; $required = [ 'phone','name','address','city','state','postcode','country','description','service_tags','location_tags' ]; foreach ( $required as $r ) { $key = 'bls_' . $r; $posted[ $r ] = isset( $_POST[ $key ] ) ? sanitize_text_field( wp_unslash( $_POST[ $key ] ) ) : ''; if ( empty( $posted[ $r ] ) ) { wc_add_notice( sprintf( /* translators: %s field name */ esc_html__( '%s is required.', 'business-listing-subscription' ), ucfirst( $r ) ), 'error' ); return; } } // Validate phone $digits = preg_replace( '/\D+/', '', $posted['phone'] ); if ( 10 !== strlen( $digits ) ) { wc_add_notice( esc_html__( 'Phone number must be exactly 10 digits.', 'business-listing-subscription' ), 'error' ); return; } if ( wc_get_product_id_by_sku( $digits ) ) { wc_add_notice( esc_html__( 'That phone number is already registered.', 'business-listing-subscription' ), 'error' ); return; } // Create subscription product $product = new WC_Product_Business_Listing_Subscription(); $product->set_name( $posted['name'] ); $product->set_status( 'publish' ); $product->set_catalog_visibility( 'hidden' ); $product->set_sku( $digits ); $product->set_price( 49 ); $product->set_regular_price( 49 ); $product->set_manage_stock( true ); $product->set_stock_quantity( 1 ); $product->set_sold_individually( true ); // Subscription terms $product->update_meta_data( '_subscription_period', 'month' ); $product->update_meta_data( '_subscription_period_interval', 1 ); $product->update_meta_data( '_subscription_sign_up_fee', 0 ); // Save all posted fields foreach ( $posted as $field => $value ) { $product->update_meta_data( '_bls_' . $field, $value ); } $pid = $product->save(); WC()->cart->empty_cart(); WC()->cart->add_to_cart( $pid, 1 ); wp_safe_redirect( wc_get_checkout_url() ); exit; } /** * Prevent duplicate purchase if stock=0. */ add_filter( 'woocommerce_add_to_cart_validation', 'bls_prevent_duplicate', 10, 2 ); function bls_prevent_duplicate( $ok, $pid ) { $p = wc_get_product( $pid ); if ( $p && 'business_listing_subscription' === $p->get_type() && 0 === $p->get_stock_quantity() ) { wc_add_notice( esc_html__( 'This phone number has already been claimed.', 'business-listing-subscription' ), 'error' ); return false; } return $ok; }
Save changes
Create folder
writable 0777
Create
Cancel