[Pro Sites] Pending sites for admin

Hello again.
Since I am with updates I have came across another small downfall when it comes to creating new sites from the front-end.
Not 100% sure but I think it may only involve free registrations but having this as a whole would be great advantage should anything go wrong from the user side.
When a user creates a site it says thank you for reserving your site (something like that) and from this point on the only record of the site ever being created is from the email sent to the user as the network admin does't get a pending copy of the site name and user.
if this user made a mistake with payment or email address and they contact support (us) we are powerless in doing anything to help in any way.

May I suggest: have a pending site tab which displays all newly created sites including activation key should it require one and user name. Once there having the option to activate it from our end would also be great as well.

Once the site has been activated either by the user or the admin it then transfers down into the usual site list page in admin.

This would also be so helpful in development stages as we wouldn't need to go through the whole process of waiting for email to activate the site to see if everything works.

Just a thorught.

Cheers

  • Adam Czajczyk
    • Support Gorilla

    Hi Philippe

    I hope you're well today and thank you for your suggestion.

    You're right about it: currently up until the site is paid/activated there's no way for the super-admin to find it out in the back-end as it's not on the "Network Admin -> Sites" list, neither it's listed anywhere in user profile.

    As far as I'm aware this is partially related to the way these sites are created, where only some information are stored before the transaction is finalized, when the actual site gets created.

    However, since there are these information in the db anyway, I believe it would be possible to create something like that. I think that adding some additional page (e.g. right after "Statistics" page) in the plugin containing a list of those pending sites with some actions - like "delete", "edit" (to edit those basic information like title etc) and "activate" - should do the job.

    Am I on a right track with this? Are there any other "options" that you think would be useful there, on such "pending sites" list?

    Best regards,
    Adam

  • Philippe
    • Flash Drive

    Hello. Sorry I have been away.

    Yes you are on the right track and just in case it was forgotten or missed, including a copy of that sites verification code should also be helpful should the new user have a problem and even a (RESEND verification code) link on the page that the code gets inputted in by the new user would also be a great advantage and most certainly wouldn't hurt to have it there.

    (e.g. right after "Statistics" page

    Or just simply as an extra tab (page) where sites are currently listed.

    Thanks for the considering looking into this addon feature.

  • Adam Czajczyk
    • Support Gorilla

    Hi Philippe

    Thank you for getting back to me and for confirmation and additional ideas.

    I'm not able to give you an ETA or, actually, promise anything at this stage but I have suggested it to our developers and I have also asked if there'd be some possible "workaround" (e.g. some code snippet) that you could add to the site meanwhile.

    Please keep an eye on this ticket and we'll update you here as soon as we get to know more.

    Best regards,.
    Adam

  • Konstantinos Xenos
    • Rubber Duck Debugger

    Hey Philippe ,

    I've made a mu-plugin as a companion to assist you in what you're requesting for the time being.

    How to install:
    Always make sure to keep a backup of your site before changing/adding custom code.

    1] Navigate to your /wp-content/ directory and create a new one named mu-plugins if it doesn't exist.
    2] Download the attached .zip and extract it. You will find a file named class-wpmudev-ps-pending-sites.php
    3] Upload the file from the .zip into the mu-plugins directory.
    4] The final path should look like /wp-content/mu-plugins/class-wpmudev-ps-pending-sites.php
    5] Everything should work after that automatically.

    What this does:

    This will add a new screen into your Network Admin area called "Pending Sites"

    It will show a list of all sites that exist in _signups table in your database that are not yet Activated. This is actually a part from WordPress Core and it's not that much related to Pro Sites, since Core itself doesn't show the non-active sites either so think of it as a WP extension as well in general.

    This will allow you to manually Activate as an admin a site, to Delete the entry from the _signups table and send a customized e-mail as a reminder to the member that registered it.

    Extra notes:

    As I've said this purely handles all the non-active sites in the _signups table, so for example anything that is not automatically activated means that it would be from a Manual Payment within Pro Sites. You'll have to be careful and double-check the payments etc as if you're using PayPal/Stripe etc as payment methods and the payment didn't go through the site might still show as 'inactive' and if you remove it the entries from Pro Sites won't be deleted as well and might occur again in the future. This is a plugin to get you started and I've already talked with our Developer to add a more robust and fully compatible version that handles all payment types etc in the future within Pro Sites as well.

    The e-mail that is sent to the user as a reminder can be edited within the plugin file on line 239, I've added a default test for now but you can alter it to anything you like. All the basic information is already there ( username / site title / activation link ) for you to use within the email itself.

    Tell me if this helps!

    Regards,
    Konstantinos

    Code preview:

    <?php // phpcs:ignore
    
    /**
     * Plugin Name: [Pro Sites] - Show Pending Sites on Admin
     * Plugin URI: https://premium.wpmudev.org/
     * Description: Adds a new menu button to show Pending sites for the Super Admin.
     * Author: Konstantinos Xenos @ WPMUDEV
     * Author URI: https://premium.wpmudev.org/
     * License: GPLv2 or later
     */
    
    if ( ! defined( 'ABSPATH' ) ) {
    	exit;
    }
    
    if ( ! class_exists( 'WPMUDEV_PS_PENDING_SITES' ) ) {
    	/**
    	 * WPMUDEV_PS_PENDING_SITES Class.
    	 */
    	class WPMUDEV_PS_PENDING_SITES {
    
    		/**
    		 * Class instance.
    		 *
    		 * @var $instance
    		 */
    		private static $instance = null;
    
    		public static function get_instance() {
    			if ( is_null( self::$instance ) ) {
    				self::$instance = new WPMUDEV_PS_PENDING_SITES();
    			}
    			return self::$instance;
    		}
    
    		/**
    		 * Class constructor.
    		 */
    		private function __construct() {
    			add_action( 'init', array( $this, 'create_menus' ) );
    			add_action( 'post_updated', array( $this, 'check_posts_for_shortcode' ), 15, 3 );
    		}
    
    		/**
    		 * Creates the Super Admin Menus.
    		 */
    		public function create_menus() {
    			add_action( 'network_admin_menu', array( $this, 'populate_admin_menu' ) );
    		}
    
    		/**
    		 * Populate the admin menus.
    		 */
    		public static function populate_admin_menu() {
    			add_menu_page(
    				esc_html__( 'Pending Sites', 'pending-sites' ),
    				esc_html__( 'Pending Sites', 'pending-sites' ),
    				'manage_network',
    				'pending-sites',
    				array( $this, 'create_page' ),
    				'dashicons-feedback'
    			);
    		}
    
    		/**
    		 * Create the Super Admin page.
    		 */
    		public function create_page() {
    			global $wpdb;
    
    			if ( isset( $_GET['action'] ) && isset( $_GET['id'] ) && isset( $_GET['nonce'] ) && 'delete' === $_GET['action'] && intval( $_GET['id'] ) && wp_verify_nonce( $_GET['nonce'], 'delete' . $_GET['id'] ) ) {
    				$id = intval( $_GET['id'] );
    
    				$result = $wpdb->query(
    					$wpdb->prepare(
    						"DELETE
    						FROM $wpdb->signups
    						WHERE signup_id = %s",
    						intval( $id )
    					)
    				);
    
    				if ( $result ) {
    					echo '<div class="notice notice-success is-dismissible"><p>';
    					printf(
    						// translators: %1$s The site ID.
    						esc_html__( 'Pending site with ID %1$s was removed.', 'pending-sites' ),
    						intval( $id )
    					);
    					echo '</p></div>';
    				} else {
    					echo '<div class="notice notice-error is-dismissible"><p>';
    					printf(
    						// translators: %1$s The site ID.
    						esc_html__( 'Could not delete pending site with ID %1$s.', 'pending-sites' ),
    						intval( $id )
    					);
    					echo '</p></div>';
    				}
    			} elseif ( isset( $_GET['action'] ) && isset( $_GET['id'] ) && isset( $_GET['nonce'] ) && 'reminder' === $_GET['action'] && intval( $_GET['id'] ) && wp_verify_nonce( $_GET['nonce'], 'reminder' . $_GET['id'] ) ) {
    
    				$id = intval( $_GET['id'] );
    
    				$result = $this->send_mail( $id );
    
    				if ( 'success' === $result['status'] ) {
    					echo '<div class="notice notice-success is-dismissible"><p>';
    					printf(
    						// translators: %1$s The site ID. %2$s The users e-mail.
    						esc_html__( 'E-mail for pending site with ID %1$s was sent to %2$s.', 'pending-sites' ),
    						intval( $id ),
    						esc_attr( $result['email'] )
    					);
    					echo '</p></div>';
    				} elseif ( 'error' === $result['status'] ) {
    					echo '<div class="notice notice-error is-dismissible"><p>';
    					printf(
    						// translators: %1$s The site ID.
    						esc_html__( 'Could not send e-mail to pending site with ID %1$s.', 'pending-sites' ),
    						intval( $id )
    					);
    					echo '</p></div>';
    				}
    			}
    			?>
    			<div class="wrap">
    				<h1><?php esc_attr_e( 'Pending Sites', 'pending-sites' ); ?></h1>
    				<br class="clear" />
    				<table class="widefat">
    				<thead>
    				<tr>
    					<th><?php esc_attr_e( 'ID', 'pending-sites' ); ?></th>
    					<th><?php esc_attr_e( 'Domain', 'pending-sites' ); ?></th>
    					<th><?php esc_attr_e( 'Path', 'pending-sites' ); ?></th>
    					<th><?php esc_attr_e( 'Title', 'pending-sites' ); ?></th>
    					<th><?php esc_attr_e( 'Username', 'pending-sites' ); ?></th>
    					<th><?php esc_attr_e( 'E-mail', 'pending-sites' ); ?></th>
    					<th><?php esc_attr_e( 'Registered Date', 'pending-sites' ); ?></th>
    					<th><?php esc_attr_e( 'Activation Key', 'pending-sites' ); ?></th>
    					<th></th>
    					<th></th>
    					<th></th>
    				</tr>
    				</thead>
    				<tbody>
    				<?php
    				$sites = $wpdb->get_results(
    					"SELECT signup_id, domain, path, title, user_login, user_email, registered, activation_key
    					FROM {$wpdb->base_prefix}signups
    					WHERE active = 0",
    					OBJECT
    				);
    
    				if ( $sites ) {
    					foreach ( $sites as $site ) {
    						?>
    						<tr>
    							<td><?php echo esc_attr( $site->signup_id ); ?></td>
    							<td><?php echo esc_attr( $site->domain ); ?></td>
    							<td><?php echo esc_attr( $site->path ); ?></td>
    							<td><?php echo esc_attr( $site->title ); ?></td>
    							<td><?php echo esc_attr( $site->user_login ); ?></td>
    							<td><?php echo esc_attr( $site->user_email ); ?></td>
    							<td><?php echo esc_attr( $site->registered ); ?></td>
    							<td><?php echo esc_attr( $site->activation_key ); ?></td>
    							<td><a href="<?php echo esc_url( get_site_url() ); ?>/wp-activate.php?key=<?php echo esc_attr( $site->activation_key ); ?>" target="_blank" rel="nofollow">Activate</a></td>
    							<td><a href="<?php echo esc_url( network_admin_url() ); ?>admin.php?page=pending-sites&action=delete&id=<?php echo esc_attr( $site->signup_id ); ?>&nonce=<?php echo wp_create_nonce( 'delete' . esc_attr( $site->signup_id ) ); ?>" style="color:#dc3232;">Delete</a></td>
    							<td><a href="<?php echo esc_url( network_admin_url() ); ?>admin.php?page=pending-sites&action=reminder&id=<?php echo esc_attr( $site->signup_id ); ?>&nonce=<?php echo wp_create_nonce( 'reminder' . esc_attr( $site->signup_id ) ); ?>" >E-mail</a></td>
    						</tr>
    						<?php
    					}
    				} else {
    					?>
    					<tr>
    						<td colspan="9"><?php esc_attr_e( 'There are no pending sites to show.', 'pending-sites' ); ?></td>
    					</tr>
    					<?php
    				}
    				?>
    				</tbody>
    				<tfoot>
    				<tr>
    					<th><?php esc_attr_e( 'ID', 'pending-sites' ); ?></th>
    					<th><?php esc_attr_e( 'Domain', 'pending-sites' ); ?></th>
    					<th><?php esc_attr_e( 'Path', 'pending-sites' ); ?></th>
    					<th><?php esc_attr_e( 'Title', 'pending-sites' ); ?></th>
    					<th><?php esc_attr_e( 'Username', 'pending-sites' ); ?></th>
    					<th><?php esc_attr_e( 'E-mail', 'pending-sites' ); ?></th>
    					<th><?php esc_attr_e( 'Registered Date', 'pending-sites' ); ?></th>
    					<th><?php esc_attr_e( 'Activation Key', 'pending-sites' ); ?></th>
    					<th></th>
    					<th></th>
    					<th></th>
    				</tr>
    				</tfoot>
    			</table>
    			</div>
    			<?php
    		}
    
    		/**
    		 * Sends the e-mail.
    		 *
    		 * @param int $id The id of the entry.
    		 *
    		 * @return array $result The details of the email.
    		 */
    		public function send_mail( $id ) {
    			global $wpdb;
    
    			$result = array(
    				'status' => 'error',
    				'id'     => $id,
    			);
    
    			$sites = $wpdb->get_results(
    				$wpdb->prepare(
    					"SELECT signup_id, domain, path, title, user_login, user_email, registered, activation_key
    					FROM {$wpdb->base_prefix}signups
    					WHERE active = 0
    					AND signup_id = %s",
    					$id
    				),
    				OBJECT
    			);
    
    			if ( $sites ) {
    				foreach ( $sites as $site ) {
    					$user_email      = $site->user_email;
    					$user_name       = $site->user_login;
    					$activation_link = get_site_url() . '/wp-activate.php?key=' . $site->activation_key;
    					$website_title   = $site->title;
    					$headers         = array( 'Content-Type: text/html; charset=UTF-8' );
    
    					$subject = __( 'Pending Site Activation', 'pending-sites' );
    
    					$message = sprintf(
    						// translators: %1$s The username. %2$s The website title. %3$s The activation url.
    						__( 'Hi %1$s!<br><br>You\'re receiving this e-mail as a reminder to activate your site <strong>"%2$s</strong> at <a href="%3$s\">%3$s</a>. Regards,<br>the team!', 'pending-sites' ),
    						esc_attr( $user_name ),
    						esc_attr( $website_title ),
    						esc_url( $activation_link )
    					);
    
    					$mail = wp_mail( $user_email, $subject, $message, $headers );
    
    					if ( $mail ) {
    						$result = array(
    							'status' => 'success',
    							'id'     => $id,
    							'email'  => $user_email,
    						);
    					}
    				}
    			}
    
    			return $result;
    		}
    
    	}
    
    	if ( ! function_exists( 'wpmudev_ps_pending_sites' ) ) {
    		add_action(
    			'plugins_loaded',
    			function() {
    				return WPMUDEV_PS_PENDING_SITES::get_instance();
    			},
    			10
    		);
    	}
    }
  • Philippe
    • Flash Drive

    Hello.

    Works like a charm. Thank you for taking the time to do this, it has everything it needs for admin to provide real support should there be a user problem which makes us look more professional.

    Very much appreciated
    Thank You

Thank NAME, for their help.

Let NAME know exactly why they deserved these points.

Gift a custom amount of points.