diff --git a/client-mu-plugins/goodbids/README.md b/client-mu-plugins/goodbids/README.md index b79a61b86..c32597e92 100644 --- a/client-mu-plugins/goodbids/README.md +++ b/client-mu-plugins/goodbids/README.md @@ -67,3 +67,19 @@ Returns the Auction's Goal value. If `$auction_id` is not provided, the current `goodbids()->auctions->get_expected_high_bid( int $auction_id )` Returns the Auction's Expected High Bid value. If `$auction_id` is not provided, the current post ID will be used. +### ACF Block Functions + +`goodbids()->acf->blocks()->get_all_blocks()` +Get all custom registered blocks. + +`goodbids()->acf->blocks()->get_block( string $block_name )` +Get block array by block name. + +`goodbids()->acf->blocks()->block_attr()` +_Use the global `block_attr()` helper function instead._ This will render the block attributes for the current block. + +`goodbids()->acf->blocks()->get_block_location( string $block_name, string $return )` +Get the location of a block. Return values can be: "directory" (Default) or "json" (Returns the path to block.json. _Can also be found in the `path` key of the block array._ + +`goodbids()->acf->blocks()->get_block_locations()` +Get all directories where blocks can be found. diff --git a/client-mu-plugins/goodbids/blocks/authentication/block.json b/client-mu-plugins/goodbids/blocks/authentication/block.json new file mode 100644 index 000000000..92f634df5 --- /dev/null +++ b/client-mu-plugins/goodbids/blocks/authentication/block.json @@ -0,0 +1,14 @@ +{ + "name": "authentication", + "title": "User Authentication Form", + "description": "Displays a user login and registration form for GoodBids.", + "icon": "feedback", + "category": "goodbids", + "keywords": ["custom", "sign", "up", "register", "registration", "form", "users", "authentication"], + "acf": { + "mode": "preview" + }, + "supports": { + "jsx": false + } +} diff --git a/client-mu-plugins/goodbids/blocks/authentication/render.php b/client-mu-plugins/goodbids/blocks/authentication/render.php new file mode 100644 index 000000000..8fb9d30d9 --- /dev/null +++ b/client-mu-plugins/goodbids/blocks/authentication/render.php @@ -0,0 +1,21 @@ +%s

', + esc_html__( 'This will render the Login and Registration form if the user is currently not signed in.', 'goodbids' ) + ); + return; +endif; +?> +
> + +
diff --git a/client-mu-plugins/goodbids/blocks/index.php b/client-mu-plugins/goodbids/blocks/index.php new file mode 100644 index 000000000..8142269b1 --- /dev/null +++ b/client-mu-plugins/goodbids/blocks/index.php @@ -0,0 +1 @@ +get_bid_product_id( $auction_id ) ); } @@ -207,7 +207,7 @@ public function has_bid_product( int $auction_id ) : bool { * * @return int */ - public function get_bid_product_id( int $auction_id ) : int { + public function get_bid_product_id( int $auction_id ): int { return intval( get_post_meta( $auction_id, Bids::AUCTION_BID_META_KEY, true ) ); } @@ -221,7 +221,7 @@ public function get_bid_product_id( int $auction_id ) : int { * * @return void */ - public function set_bid_product_id( int $auction_id, int $bid_product_id ) : void { + public function set_bid_product_id( int $auction_id, int $bid_product_id ): void { update_post_meta( $auction_id, Bids::AUCTION_BID_META_KEY, $bid_product_id ); } @@ -235,7 +235,7 @@ public function set_bid_product_id( int $auction_id, int $bid_product_id ) : voi * * @return mixed */ - public function get_setting( string $meta_key, int $auction_id = null ) : mixed { + public function get_setting( string $meta_key, int $auction_id = null ): mixed { if ( ! $auction_id ) { $auction_id = get_the_ID(); } @@ -278,7 +278,7 @@ public function get_estimated_value( int $auction_id = null ) : int { * * @return string */ - public function get_start_date_time( int $auction_id = null ) : string { + public function get_start_date_time( int $auction_id = null ): string { return $this->get_setting( 'auction_start', $auction_id ); } @@ -309,7 +309,7 @@ public function has_started( int $auction_id = null ): bool { * * @return int */ - public function get_bid_increment( int $auction_id = null ) : int { + public function get_bid_increment( int $auction_id = null ): int { return intval( $this->get_setting( 'bid_increment', $auction_id ) ); } @@ -353,7 +353,7 @@ public function calculate_starting_bid( int $auction_id = null ): int { * * @return int */ - public function get_goal( int $auction_id = null ) : int { + public function get_goal( int $auction_id = null ): int { return intval( $this->get_setting( 'auction_goal', $auction_id ) ); } diff --git a/client-mu-plugins/goodbids/src/classes/Core.php b/client-mu-plugins/goodbids/src/classes/Core.php index d62ca6338..16da17a94 100644 --- a/client-mu-plugins/goodbids/src/classes/Core.php +++ b/client-mu-plugins/goodbids/src/classes/Core.php @@ -12,6 +12,7 @@ use GoodBids\Auctions\Auctions; use GoodBids\Network\Sites; use GoodBids\Plugins\ACF; +use GoodBids\Plugins\WooCommerce; /** * Core Class @@ -60,6 +61,12 @@ class Core { */ public Auctions $auctions; + /** + * @since 1.0.0 + * @var WooCommerce + */ + public WooCommerce $woocommerce; + /** * Constructor * @@ -111,6 +118,7 @@ public function init(): void { return; } + $this->load_dependencies(); $this->load_plugins(); $this->load_modules(); @@ -152,6 +160,17 @@ public function get_config( string $key ): mixed { return $this->config[ $key ] ?? null; } + /** + * Load plugin dependencies. + * + * @since 1.0.0 + * + * @return void + */ + private function load_dependencies() : void { + require_once GOODBIDS_PLUGIN_PATH . '/src/helpers.php'; + } + /** * Load 3rd Party Plugins. * @@ -200,10 +219,11 @@ private function load_modules(): void { add_action( 'mu_plugin_loaded', function () { - $this->acf = new ACF(); - $this->sites = new Sites(); - $this->admin = new Admin(); - $this->auctions = new Auctions(); + $this->acf = new ACF(); + $this->sites = new Sites(); + $this->admin = new Admin(); + $this->auctions = new Auctions(); + $this->woocommerce = new WooCommerce(); } ); } diff --git a/client-mu-plugins/goodbids/src/classes/Network/Sites.php b/client-mu-plugins/goodbids/src/classes/Network/Sites.php index 11b0ddf9c..bff589d35 100644 --- a/client-mu-plugins/goodbids/src/classes/Network/Sites.php +++ b/client-mu-plugins/goodbids/src/classes/Network/Sites.php @@ -36,11 +36,17 @@ class Sites { */ public function __construct() { $this->init_np_fields(); + + // Process New Site Custom Meta Fields. + $this->new_site_form_fields(); $this->validate_new_site_fields(); $this->save_new_site_fields(); - $this->save_edit_site_fields(); - $this->new_site_form_fields(); + + // Process Edit Site Custom Meta Fields. $this->edit_site_form_fields(); + $this->save_edit_site_fields(); + + // New Site Actions $this->activate_child_theme_on_new_site(); } @@ -185,7 +191,7 @@ function () { return; } - check_admin_referer( 'add-blog', '_wpnonce_add-blog' ); + check_admin_referer( 'add-np-site', '_wpnonce_add-np-site' ); if ( empty( $_POST[ self::OPTION_SLUG ] ) || ! is_array( $_POST[ self::OPTION_SLUG ] ) ) { wp_die( esc_html__( 'Missing required Nonprofit data.' ) ); @@ -298,6 +304,8 @@ function ( WP_Site $new_site, array $args ) { $meta_value = sanitize_text_field( $data[ $key ] ); update_site_meta( $new_site->id, $meta_key, $meta_value ); } + + $this->init_site_defaults( $new_site->id ); }, 10, 2 @@ -313,12 +321,13 @@ function ( WP_Site $new_site, array $args ) { */ private function save_edit_site_fields(): void { add_action( - 'wp_initialize_site', + 'wp_update_site', + /** * @param WP_Site $new_site New site object. * @param WP_Site $old_site Old site object. */ - function ( WP_Site $new_site, WP_Site $old_site ) { + function ( WP_Site $new_site, WP_Site $old_site ): void { if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { return; } @@ -328,7 +337,7 @@ function ( WP_Site $new_site, WP_Site $old_site ) { return; } - check_admin_referer( 'edit-site' ); + check_admin_referer( 'edit-np-site', '_wpnonce_edit-np-site' ); $data = $_POST[ self::OPTION_SLUG ]; // phpcs:ignore @@ -356,22 +365,32 @@ function ( WP_Site $new_site, WP_Site $old_site ) { */ private function activate_child_theme_on_new_site(): void { add_action( - 'wp_initialize_site', + 'goodbids_init_site', function ( $site_id ) { $stylesheet = 'goodbids-nonprofit'; - // Switch to the new site - switch_to_blog( $site_id ); - - // Check if the Goodbids child theme exists - if ( ! wp_get_theme( $stylesheet )->exists() ) { - return; + // Check if the Goodbids child theme exists first. + if ( wp_get_theme( $stylesheet )->exists() ) { + switch_theme( $stylesheet ); } - - switch_theme( $stylesheet ); - - restore_current_blog(); } ); } + + /** + * Initialize new site defaults. + * + * @since 1.0.0 + * + * @param int $site_id + * + * @return void + */ + private function init_site_defaults( int $site_id ): void { + switch_to_blog( $site_id ); + + do_action( 'goodbids_init_site', $site_id ); + + restore_current_blog(); + } } diff --git a/client-mu-plugins/goodbids/src/classes/Plugins/ACF.php b/client-mu-plugins/goodbids/src/classes/Plugins/ACF.php index be66743f9..b73bd2033 100644 --- a/client-mu-plugins/goodbids/src/classes/Plugins/ACF.php +++ b/client-mu-plugins/goodbids/src/classes/Plugins/ACF.php @@ -2,11 +2,14 @@ /** * ACF Functionality * + * @since 1.0.0 * @package GoodBids */ namespace GoodBids\Plugins; +use GoodBids\Plugins\ACF\Blocks; + /** * Class for Advanced Custom Fields Pro * @@ -20,6 +23,12 @@ class ACF { */ private string $slug = 'advanced-custom-fields-pro/acf.php'; + /** + * @since 1.0.0 + * @var Blocks + */ + private Blocks $blocks; + /** * Initialize ACF Functionality * @@ -30,12 +39,26 @@ public function __construct() { return; } + // Initialize Submodules. + $this->blocks = new Blocks(); + $this->disable_admin(); $this->discourage_the_field_usage(); $this->modify_save_directory(); $this->disable_database_storage(); } + /** + * Return the Blocks submodule + * + * @since 1.0.0 + * + * @return Blocks + */ + public function blocks() : Blocks { + return $this->blocks; + } + /** * Disable ACF Admin per WP VIP Documentation * diff --git a/client-mu-plugins/goodbids/src/classes/plugins/ACF/Blocks.php b/client-mu-plugins/goodbids/src/classes/plugins/ACF/Blocks.php new file mode 100644 index 000000000..69ab66740 --- /dev/null +++ b/client-mu-plugins/goodbids/src/classes/plugins/ACF/Blocks.php @@ -0,0 +1,314 @@ +register_block_category(); + $this->register_blocks(); + $this->set_block_callback(); + } + + /** + * Register Custom Blocks + * + * @since 1.0.0 + * + * @return void + */ + private function register_blocks() : void { + add_action( + 'acf/init', + function () { + $blocks = $this->get_all_blocks(); + + foreach ( $blocks as $block ) { + $include = $block['path'] . '/block.php'; + + // Autoload block.php within block directory + if ( file_exists( $include ) ) { + require $include; + } + + register_block_type( trailingslashit( $block['path'] ) . 'block.json' ); + } + } + ); + } + + /** + * Get All Available Blocks + * + * @since 1.0.0 + * + * @return array + */ + public function get_all_blocks() : array { + $blocks = []; + $locations = $this->get_block_locations(); + + foreach ( $locations as $location ) { + $group = glob( trailingslashit( $location ) . '**/block.json' ); + + foreach ( $group as $block_path ) { + $block = json_decode( wpcom_vip_file_get_contents( $block_path ), true ); + + // Add path as a property. + $block['path'] = dirname( $block_path ); + + $blocks[] = $block; + } + } + + return $blocks; + } + + /** + * Get block array + * + * @since 1.0.0 + * + * @param string $block_name + * + * @return array|false + */ + public function get_block( string $block_name ) : array|false { + $block_path = $this->get_block_location( $block_name, 'json' ); + + if ( ! $block_path ) { + return false; + } + + $block = json_decode( wpcom_vip_file_get_contents( $block_path ), true ); + + $block['path'] = dirname( $block_path ); + + return $block; + } + + /** + * Get locations where custom blocks can be found. + * + * @since 1.0.0 + * + * @return array + */ + public function get_block_locations() : array { + return apply_filters( + 'goodbids_block_locations', + [ + GOODBIDS_PLUGIN_PATH . '/blocks', + ] + ); + } + + /** + * Get path to block by name. + * + * @since 1.0.0 + * + * @param string $block_name + * @param string $return + * + * @return false|string + */ + public function get_block_location( string $block_name, string $return = 'directory' ) : false|string { + // Only allow ACF blocks + if ( str_contains( $block_name, '/' ) && ! str_starts_with( $block_name, $this->block_prefix . '/' ) ) { + return false; + } + + $block_name = str_replace( $this->block_prefix . '/', '', $block_name ); + $blocks = $this->get_all_blocks(); + + foreach ( $blocks as $block ) { + if ( $block_name !== $block['name'] ) { + continue; + } + + if ( 'json' === $return ) { + return trailingslashit( $block['path'] ) . 'block.json'; + } + + return $block['path']; + } + + return false; + } + + /** + * Register a custom Block Category. + * + * @since 1.0.0 + * @return void + */ + private function register_block_category() : void { + add_filter( + 'block_categories_all', + function ( array $categories ) : array { + return array_merge( + [ + [ + 'slug' => 'goodbids', + 'title' => __( 'GoodBids', 'goodbids' ), + ] + ], + $categories + ); + } + ); + } + + /** + * Automatically add block render callbacks for custom blocks. + * + * @since 1.0.0 + * + * @return void + */ + private function set_block_callback() : void { + add_filter( + 'block_type_metadata', + function ( array $metadata ) : array { // phpcs:ignore + if ( ! function_exists( '\acf_is_acf_block_json' ) || ! \acf_is_acf_block_json( $metadata ) ) { + return $metadata; + } + + if ( ! empty( $metadata['acf']['renderCallback'] ) || ! empty( $metadata['acf']['renderTemplate'] ) || empty( $metadata['name'] ) ) { + return $metadata; + } + + $metadata['acf']['renderCallback'] = function( array $block ) : void { + $block_name = str_replace( $this->block_prefix . '/', '', $block['name'] ); + $block['slug'] = sanitize_title( $block_name ); + if ( empty( $block['path'] ) ) { + $block['path'] = $this->get_block_location( $block_name ); + } + $render = $block['path'] . '/render.php'; + + if ( ! file_exists( $render ) ) { + // TODO: Log error. + return; + } + + require $render; + }; + + return $metadata; + }, + 5 + ); + } + + /** + * Render the ACF block attributes + * + * @since 1.0.0 + * + * @param array $block + * @param string $addl_class + * @param array $attr + * + * @return void + */ + public function block_attr( array $block, string $addl_class = '', array $attr = [] ) : void { + $extra = [ + 'id' => $this->get_block_id( $block ), + 'class' => $this->get_block_class( $block, $addl_class ), + ]; + + if ( ! empty( $block['support']['jsx'] ) ) { + $extra['data-supports-jsx'] = 'true'; + } + + $extra = array_merge( $extra, $attr ); + + // Attributes are escaped within get_block_wrapper_attributes. + echo get_block_wrapper_attributes( $extra ); // phpcs:ignore + + do_action( 'goodbids_block_attr', $block ); + } + + /** + * Get unique block ID. + * + * @since 1.0.0 + * + * @param array $block + * + * @return string + */ + private function get_block_id( array $block ) : string { + if ( ! empty( $block['anchor'] ) ) { + return $block['anchor']; + } + + $prefix = str_replace( $this->block_prefix . '/', '', $block['name'] ); + + if ( empty( $block['id'] ) ) { + return $prefix . '_' . uniqid(); + } + + return $prefix . '_' . $block['id']; + } + + /** + * Get custom block classes. + * + * @since 1.0.0 + * + * @param array $block + * @param string $addl_class + * + * @return string + */ + private function get_block_class( array $block, string $addl_class = '' ) : string { + $class = array_merge( + [ + str_replace( $this->block_prefix . '/', '', $block['name'] ), + ], + explode( ' ', $addl_class ) + ); + + if ( ! empty( $block['className'] ) ) { + $class[] = $block['className']; + } + + if ( ! empty( $block['align'] ) ) { + $class[] = 'align' . $block['align']; + } + + if ( ! empty( $block['align_content'] ) ) { + $class[] = 'align-content-' . $block['align_content']; + } + + $class = apply_filters( 'goodbids_block_class', $class, $block ); + + return trim( implode( ' ', array_unique( $class ) ) ); + } +} diff --git a/client-mu-plugins/goodbids/src/classes/plugins/WooCommerce.php b/client-mu-plugins/goodbids/src/classes/plugins/WooCommerce.php new file mode 100644 index 000000000..7603c2e99 --- /dev/null +++ b/client-mu-plugins/goodbids/src/classes/plugins/WooCommerce.php @@ -0,0 +1,274 @@ +is_plugin_active( $this->slug ) ) { + return; + } + + $this->configure_new_site(); + $this->create_auth_page(); + $this->add_auth_page_setting(); + $this->display_post_states(); + $this->authentication_redirect(); + $this->prevent_wp_login_access(); + } + + /** + * Configure WooCommerce settings for new sites. + * + * @since 1.0.0 + * + * @return void + */ + private function configure_new_site() : void { + add_action( + 'goodbids_init_site', + function ( int $site_id ) : void { + // Disable Guest Checkout. + update_option( 'woocommerce_enable_guest_checkout', 'no' ); + + // Enable Log in during Checkout. + update_option( 'woocommerce_enable_checkout_login_reminder', 'yes' ); + + // Enable Account Creation during Checkout. + update_option( 'woocommerce_enable_signup_and_login_from_checkout', 'yes' ); + + // Enable Account Creation from My Account Page. + update_option( 'woocommerce_enable_myaccount_registration', 'yes' ); + + // Allow for personal data removal. + update_option( 'woocommerce_erasure_request_removes_order_data', 'yes' ); + update_option( 'woocommerce_allow_bulk_remove_personal_data', 'yes' ); + }, + 5 + ); + } + + /** + * Create a new Authentication Page + * + * @since 1.0.0 + * + * @return void + */ + private function create_auth_page() : void { + add_action( + 'woocommerce_page_created', + function ( int $page_id, array $page_data ) : void { + if ( empty( $page_data['post_name'] ) || 'my-account' !== $page_data['post_name'] ) { + return; + } + + $auth_page_id = wp_insert_post( + [ + 'post_title' => __( 'Authentication', 'goodbids' ), + 'post_name' => 'authentication', + 'post_status' => 'publish', + 'post_type' => 'page', + 'comment_status' => 'closed', + 'ping_status' => 'closed', + 'post_content' => '', + 'post_parent' => $page_id, + ], + true + ); + + if ( ! $auth_page_id ) { + // TODO: Log Error. + return; + } + + update_option( 'woocommerce_authentication_page_id', $auth_page_id ); + }, + 6, + 2 + ); + } + + /** + * Add Authentication Page setting to WooCommerce Advanced Settings + * + * @since 1.0.0 + * + * @return void + */ + private function add_auth_page_setting() : void { + add_filter( + 'woocommerce_settings_pages', + function ( array $settings ) : array { + $auth_setting = [ + 'title' => __( 'Authentication', 'goodbids' ), + 'desc' => __( 'Page contents: GoodBids Authentication Block.', 'goodbids' ), + 'id' => 'woocommerce_authentication_page_id', + 'type' => 'single_select_page_with_search', + 'default' => '', + 'class' => 'wc-page-search', + 'css' => 'min-width:300px;', + 'args' => [ + 'exclude' => [ // phpcs:ignore + wc_get_page_id( 'cart' ), + wc_get_page_id( 'checkout' ), + wc_get_page_id( 'my-account' ), + ], + ], + 'desc_tip' => true, + 'autoload' => false, + ]; + + $new_settings = []; + + foreach ( $settings as $setting ) { + $new_settings[] = $setting; + + if ( 'woocommerce_myaccount_page_id' === $setting['id'] ) { + $new_settings[] = $auth_setting; + } + } + + return $new_settings; + } + ); + } + + /** + * Add a post display state for special GoodBids pages. + * + * @since 1.0.0 + * + * @return void + */ + private function display_post_states() : void { + add_filter( + 'display_post_states', + function ( array $post_states, \WP_Post $post ) : array { + if ( wc_get_page_id( 'authentication' ) === $post->ID ) { + $post_states['wc_page_for_authentication'] = __( 'Authentication Page', 'goodbids' ); + } + + return $post_states; + }, + 10, + 2 + ); + } + + /** + * Redirect to Authentication Page if user is not logged in. + * + * @since 1.0.0 + * + * @return void + */ + private function authentication_redirect() : void { + add_action( + 'template_redirect', + function () : void { + global $wp; + + // Make sure we have a My Account & Authentication page. + $auth_page_id = wc_get_page_id( 'authentication' ); + $account_page_id = wc_get_page_id( 'myaccount' ); + + if ( ! $auth_page_id || ! $account_page_id ) { + return; + } + + // If logged in, perform WooCommerce Login Redirect. + if ( is_user_logged_in() ) { + if ( $auth_page_id === get_queried_object_id() ) { + $redirect = apply_filters( 'woocommerce_login_redirect', wc_get_page_permalink( 'myaccount' ) ); + + if ( $redirect ) { + wp_safe_redirect( $redirect ); + exit; + } + } + + return; + } + + if ( $account_page_id !== get_queried_object_id() ) { + return; + } + + $auth_page_url = wc_get_page_permalink( 'authentication' ); + + if ( ! $auth_page_url ) { + return; + } + + $auth_page_url = add_query_arg( + 'redirect_to', + urlencode( home_url( $wp->request ) ), + $auth_page_url + ); + + wp_safe_redirect( $auth_page_url ); + exit; + } + ); + } + + /** + * Prevent access to WP Login page unless user can manage options. + * + * @since 1.0.0 + * + * @return void + */ + private function prevent_wp_login_access() : void { + add_action( + 'login_head', + function () { + $request = ! empty( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( $_SERVER['REQUEST_URI'] ) : ''; + + // Check if the current URL contains /wp-admin or /wp-login.php + if ( ! str_contains( $request, '/wp-admin' ) && ! str_contains( $request, '/wp-login.php' ) ) { + return; + } + + // Allow logged-in users with manage_options permissions. + if ( is_user_logged_in() && current_user_can( 'manage_options' ) ) { + return; + } + + $auth_page_url = wc_get_page_permalink( 'authentication' ); + + if ( ! $auth_page_url ) { + return; + } + + // Redirect to custom Auth page. + wp_safe_redirect( $auth_page_url ); + exit; + }, + 2 + ); + } +} diff --git a/client-mu-plugins/goodbids/src/helpers.php b/client-mu-plugins/goodbids/src/helpers.php new file mode 100644 index 000000000..019858d58 --- /dev/null +++ b/client-mu-plugins/goodbids/src/helpers.php @@ -0,0 +1,24 @@ +acf->blocks()->block_attr( $block, $addl_class, $attr ); + } +} diff --git a/client-mu-plugins/goodbids/views/network/edit-site-fields.php b/client-mu-plugins/goodbids/views/network/edit-site-fields.php index 0a38bfb74..0eb3ccf85 100644 --- a/client-mu-plugins/goodbids/views/network/edit-site-fields.php +++ b/client-mu-plugins/goodbids/views/network/edit-site-fields.php @@ -13,6 +13,8 @@ ?>

+ + $field ) : diff --git a/client-mu-plugins/goodbids/views/network/new-site-fields.php b/client-mu-plugins/goodbids/views/network/new-site-fields.php index 11bac99d3..0d7fc0259 100644 --- a/client-mu-plugins/goodbids/views/network/new-site-fields.php +++ b/client-mu-plugins/goodbids/views/network/new-site-fields.php @@ -12,6 +12,8 @@ ?>

+ + $field ) : diff --git a/docs/hooks/actions.md b/docs/hooks/actions.md index c9068cd3f..104318906 100644 --- a/docs/hooks/actions.md +++ b/docs/hooks/actions.md @@ -1,3 +1,14 @@ ## Action Hooks -Coming soon. +### goodbids_init_site + +Action performed when a new site is created. `switch_to_blog()` has already been called to change to the new site. + +```php +add_action( + 'goodbids_init_site', + function( int $site_id ) : void { + update_option( 'my_option_name', 'my_value' ); + } +); +``` diff --git a/docs/hooks/filters.md b/docs/hooks/filters.md index ee2fd0746..d2dd1a6ac 100644 --- a/docs/hooks/filters.md +++ b/docs/hooks/filters.md @@ -33,3 +33,30 @@ add_filter( } ); ``` + +### goodbids_block_class + +Modifies the classes for custom blocks. + +```php +add_filter( + 'goodbids_block_class', + function( array $class, array $block ) : array { + $class[] = 'my-custom-class'; + return $class; + } +); +``` +### goodbids_block_locations + +Adds support for additional custom block directories. + +```php +add_filter( + 'goodbids_block_locations', + function( array $locations ) : array { + $locations[] = get_stylesheet_directory() . '/blocks'; + return $locations; + } +); +``` diff --git a/themes/goodbids-nonprofit/parts/header.html b/themes/goodbids-nonprofit/parts/header.html index 37f1c5eb5..fae3420f2 100644 --- a/themes/goodbids-nonprofit/parts/header.html +++ b/themes/goodbids-nonprofit/parts/header.html @@ -16,7 +16,8 @@ - + +