Title: Shortcodes patch
Last modified: September 1, 2016

---

# Shortcodes patch

 *  ResolvedPlugin Contributor [mattsenate](https://wordpress.org/support/users/mattsenate/)
 * (@mattsenate)
 * [9 years, 11 months ago](https://wordpress.org/support/topic/shortcodes-patch/)
 * Hi,
 * I saw some additional shortcodes were started by the original author(s), but 
   not finished. I finished and added some more. I believe this should allow users
   to correctly display confirmed users, unconfirmed users, a tally of each, and
   a total number of signatories all with shortcodes. I think the functions I called
   are fast and scoped to the minimum data, but let me know if you see any other
   optimizations. Below is an `svn diff` to be applied as a patch:
 *     ```
       Index: lh-signing.php
       ===================================================================
       --- lh-signing.php	(revision 1443169)
       +++ lh-signing.php	(working copy)
       @@ -656,8 +656,9 @@
        public function list_attached_users($id, $list, $fields)  {
   
        $users = get_users( array(
       -  'connected_type' => array($list,'foobar'),
       -  'connected_items' => $id
       +  'connected_type' => array($list),
       +  'connected_items' => get_queried_object_id(),
       +  'fields' => array($fields)
        ) );
   
        $return_string = "<ul>";
       @@ -664,7 +665,7 @@
   
        foreach ( $users as $user ) {
   
       -$return_string .= '<li>'.get_the_author_meta( 'display_name', $user->ID ).'</li>';
       +$return_string .= '<li>'. $user->{'display_name'} .'</li>';
   
        }
   
       @@ -674,7 +675,30 @@
   
        }
   
       +public function count_attached_users($id, $list, $fields) {
   
       +$users = get_users( array(
       +  'connected_type' => array($list),
       +  'connected_items' => get_queried_object_id(),
       +  'fields' => array($fields)
       +) );
       +
       +
       +$user_count = 0;
       +
       +foreach ( $users as $user ) {
       +
       +$user_count++;
       +
       +}
       +
       +$return_string = $user_count;
       +
       +return $return_string;
       +
       +}
       +
       +
        public function the_content_filter( $content ) {
   
        global $post;
       @@ -910,6 +934,7 @@
        add_shortcode($this->namespace.'_form', array($this,"form_shortcode_output"));
        add_shortcode($this->namespace.'_unconfirmed_count', array($this,"unconfirmed_count_shortcode_output"));
        add_shortcode($this->namespace.'_confirmed_count', array($this,"confirmed_count_shortcode_output"));
       +add_shortcode($this->namespace.'_total_count', array($this,"total_count_shortcode_output"));
        add_shortcode($this->namespace.'_unconfirmed_list', array($this,"unconfirmed_list_shortcode_output"));
        add_shortcode($this->namespace.'_confirmed_list', array($this,"confirmed_list_shortcode_output"));
   
       @@ -961,10 +986,10 @@
   
        extract( shortcode_atts( array (
        'id' => false,
       -'fields' => 'display_name' ), $atts )
       +'fields' => 'display_name' ), $atts )
        );
   
       -$return_string = $this_>list_attached_users($id, 'signing_sign_unconfirmed', $fields);
       +$return_string = $this->list_attached_users($id, 'signing_sign_unconfirmed', $fields);
   
       @@ -972,6 +997,66 @@
   
        }
   
       +public function confirmed_list_shortcode_output($atts,$content = null)  {
       +
       +extract( shortcode_atts( array (
       +'id' => false,
       +'fields' => 'display_name' ), $atts )
       +);
       +
       +$return_string = $this->list_attached_users($id, 'signing_sign_confirmed', $fields);
       +
       +
       +
       +return $return_string;
       +
       +}
       +
       +
       +public function confirmed_count_shortcode_output($atts,$content = null) {
       +
       +extract( shortcode_atts( array (
       +'id' => false,
       +'fields' => 'display_name' ), $atts )
       +);
       +
       +$return_string = '<span class="confirmed_count">' . $this->count_attached_users($id, 'signing_sign_confirmed', $fields) . '</span>';
       +
       +
       +return $return_string;
       +
       +}
       +
       +public function unconfirmed_count_shortcode_output($atts,$content = null) {
       +
       +extract( shortcode_atts( array (
       +'id' => false,
       +'fields' => 'display_name' ), $atts )
       +);
       +
       +$return_string = '<span class="confirmed_count">' . $this->count_attached_users($id, 'signing_sign_unconfirmed', $fields) . '</span>';
       +
       +
       +return $return_string;
       +
       +}
       +
       +public function total_count_shortcode_output($atts,$content = null) {
       +
       +extract( shortcode_atts( array (
       +'id' => false,
       +'fields' => 'display_name' ), $atts )
       +);
       +
       +$return_string = '<span class="confirmed_count">';
       +$return_string .= $this->count_attached_users($id, 'signing_sign_unconfirmed', $fields) + $this->count_attached_users($id, 'signing_sign_confirmed', $fields);
       +$return_string .= '</span>';
       +
       +
       +return $return_string;
       +
       +}
       +
        public function add_meta_boxes($post_type, $post) {
   
        if (has_shortcode( $post->post_content, 'lh_signing_form' )){
       @@ -1576,4 +1661,4 @@
   
       -?>
       \ No newline at end of file
       +?>
       Index: readme.txt
       ===================================================================
       --- readme.txt	(revision 1443169)
       +++ readme.txt	(working copy)
       @@ -16,6 +16,20 @@
   
        Creating a petition/list/signup is as easy as adding a shortcode to a post or page (or CPT). From there additional editors are available to configure easch aspect of the sign up. Everything is completely self hosted and all list members become users of your site (not a third parties).
   
       +Available shortcodes:
       +
       +[lh_signing_form] (enable signatories on any post, page, or custom post type)
       +
       +Unconfirmed signatories: [lh_signing_unconfirmed_count]
       +
       +Confirmed signatories: [lh_signing_confirmed_count]
       +
       +Total signatories: [lh_signing_total_count]
       +
       +[lh_signing_unconfirmed_list] (unformated list)
       +
       +[lh_signing_confirmed_list] (unformated list)
       +
        == Installation ==
   
        1. Upload the <code>lh-signing</code> folder to the <code>/wp-content/plugins/</code> directory
       @@ -97,4 +111,4 @@
        * Conditionally show admin boxes
   
        **2.61 June 22, 2016**
       -* Update links
       \ No newline at end of file
       +* Update links
       ```
   
 * [https://wordpress.org/plugins/lh-signing/](https://wordpress.org/plugins/lh-signing/)

Viewing 5 replies - 1 through 5 (of 5 total)

 *  Plugin Author [shawfactor](https://wordpress.org/support/users/shawfactor/)
 * (@shawfactor)
 * [9 years, 11 months ago](https://wordpress.org/support/topic/shortcodes-patch/#post-7517275)
 * Thankyou I have incorporated your changes in version 2.62. Do you want to be 
   made a contributor?
 *  Plugin Contributor [mattsenate](https://wordpress.org/support/users/mattsenate/)
 * (@mattsenate)
 * [9 years, 11 months ago](https://wordpress.org/support/topic/shortcodes-patch/#post-7517386)
 * Great, thanks!
 * Sure, sounds good, add me as a contributor.
 * I was thinking I would also like if lh-signing could support custom form fields
   for signatories. Say, for example, I would like the user to share an optional“
   affiliation” or values for general wordpress user profile fields.
 * Beyond that, how goes the LocalHero project? I’m curious about this since you
   have a handful of plugins in development here.
 * Cheers,
    Matt
 *  Plugin Contributor [mattsenate](https://wordpress.org/support/users/mattsenate/)
 * (@mattsenate)
 * [9 years, 10 months ago](https://wordpress.org/support/topic/shortcodes-patch/#post-7517482)
 * Hi,
 * Either you weren’t able to incorporate my full patch, or there was a regression
   introduced, but it seems that version `2.63` does not contain the necessary code
   to use the shortcode features…
 * I’ve had to patch on a live site given my development version, let me know when
   I can test your updated version so all the features work as expected.
 * Thanks, here are the two files in question
 * `lh-signing.php v2.63`:
 *     ```
       <?php
       /*
        Plugin Name: LH Signing
        Plugin URI: https://lhero.org/portfolio/lh-signing/
        Description: Adds signing functionality, create petitions, validated lists etc
        Author: Peter Shaw
        Author URI: https://shawfactor.com
        Version: 2.63
        License: GPL v3 (http://www.gnu.org/licenses/gpl.html)
       */
   
       class LH_Signing_plugin {
   
       var $opt_name = 'lh_signing-options';
       var $hidden_field_name = 'lh_signing-submit_hidden';
       var $login_link_field_name = '_lh_signing-login_link';
       var $email_title_field_name = 'lh_signing-email_title';
       var $email_bcc_field_name = 'lh_signing-email_bcc';
       var $message_field_name = 'lh_signing-message';
       var $page_id_field = 'lh_signing-page_id';
       var $namespace = 'lh_signing';
       var $signing_states = array('signing_sign_confirmed','signing_sign_unconfirmed');
   
       var $filename;
       var $options;
   
       private function arrayToCsv( $fields, $delimiter = ';', $enclosure = '"', $encloseAll = false, $nullToMysqlNull = false ) {
           $delimiter_esc = preg_quote($delimiter, '/');
           $enclosure_esc = preg_quote($enclosure, '/');
   
           $output = array();
           foreach ( $fields as $field ) {
               if ($field === null && $nullToMysqlNull) {
                   $output[] = 'NULL';
                   continue;
               }
   
               // Enclose fields containing $delimiter, $enclosure or whitespace
               if ( $encloseAll || preg_match( "/(?:${delimiter_esc}|${enclosure_esc}|\s)/", $field ) ) {
                   $output[] = $enclosure . str_replace($enclosure, $enclosure . $enclosure, $field) . $enclosure;
               }
               else {
                   $output[] = $field;
               }
           }
   
           return implode( $delimiter, $output );
       }
   
       private function generate_csv_string($vararray){
   
       $csvString = '';
   
       $bar = array_flip((array)$vararray[0]);
   
       $csvString .= $this->arrayToCsv($bar,",")."\n";
   
       foreach ($vararray as $fields) {
   
       $csvString .= $this->arrayToCsv($fields,",")."\n";
   
        }
   
       return $csvString;
   
       }
   
       private function domain_exists($email, $record = 'MX'){
       $pieces = explode("@", $email);
   
       return checkdnsrr($pieces[1], $record);
   
       }
   
       private function maybe_upgrade_user($user){
   
       //only run this process if the current user has an unclaimed role
       if ($user->roles[0] == 'unclaimed'){
   
       $default_role = get_option( 'default_role' );
   
       wp_update_user(array(
           'ID' => $user->ID,
           'role' => $default_role
       ));
   
       }
   
       }
   
       private function return_signing_button($user, $post){
   
       $button .= '<table width="100%" border="0" cellspacing="0" cellpadding="0">
         <tr>
           <td>
             <table border="0" cellspacing="0" cellpadding="0">
               <tr>
       <td><a class="confirm_button" href="'.$this->generate_url( $user, $post ).'">'.$this->return_email_button_text($post).'</a></td>
               </tr>
             </table>
           </td>
         </tr>
       </table>';
   
       return $button;
   
       }
   
       private function get_connection_type_by_id($id){
   
       global $wpdb;
   
       $sql = "SELECT p2p_type FROM ".$wpdb->prefix."p2p WHERE p2p_id = '" .$id. "'";
   
       $type = $wpdb->get_var($sql);
   
       return $type;
   
       }
   
       private function get_connection_from_by_id($id){
   
       global $wpdb;
   
       $sql = "SELECT p2p_from FROM ".$wpdb->prefix."p2p WHERE p2p_id = '" .$id. "'";
   
       $from = $wpdb->get_var($sql);
   
       return $from;
   
       }
   
       private function personalise_message($message,$post,$user){
   
       $message = str_replace('%post_title%', $post->post_title, $message);
       $message = str_replace('%first_name%', $user->first_name, $message);
       $message = str_replace('%last_name%', $user->last_name, $message);
       $message = str_replace('%user_email%', $user->user_email, $message);
       $message = str_replace('%user_login%', $user->user_login, $message);
       $message = str_replace('%bloginfo_name%',get_bloginfo('name','display'), $message);
   
       return $message;
   
       }
   
       private function list_users($users){
   
       echo "<ul>";
   
       foreach ( $users as $user ) { 
   
       echo '<li><a href="'.get_edit_user_link( $user->ID ).'">'.get_the_author_meta( 'display_name', $user->ID ).'</a></li>';
   
       }
   
       echo "</ul>";
   
       }
   
       private function return_approved_posttypes() {
   
       $posttypes = array('post','page');
   
       $posttypes = apply_filters('lh_signing_posttypes_filter', $posttypes);
   
       return $posttypes;
   
       }
   
       private function use_email_template( $message ) {
   
       if (file_exists(get_stylesheet_directory().'/'.$this->namespace.'-template.php')){
   
       ob_start();
   
       include( get_stylesheet_directory().'/'.$this->namespace.'-template.php');
   
       $message = ob_get_contents();
   
       ob_end_clean();
   
       } else {
   
       ob_start();
   
       include( plugin_dir_path( __FILE__ ).'/'.$this->namespace.'-template.php');
   
       $message = ob_get_contents();
   
       ob_end_clean();
   
       }
   
       if (!class_exists('CssToInlineStyles')) {
   
       require_once('csstoinlinestyles/CssToInlineStyles.php');
   
       }
   
       $doc = new DOMDocument();
   
       $doc->loadHTML($message);
   
       // create instance
       $cssToInlineStyles = new CssToInlineStyles();
   
       $cssToInlineStyles->setHTML($message);
   
       $cssToInlineStyles->setCSS($doc->getElementsByTagName('style')->item(0)->nodeValue);
   
       // output
   
       $message = $cssToInlineStyles->convert(); 
   
       return $message;
   
       }
   
       private function create_token( $user, $post ) {
   
       // random salt
       $token = wp_generate_password( 20, false );
   
       // we're sending this to the user
       $hash  = wp_hash($token);
   
       update_user_meta( $user->ID, $this->namespace."_".$post->ID."-confirmation_token" , $hash );
   
       return $token;
   
       }
   
       private function curpageurl() {
       	$pageURL = 'http';
   
       	if ((isset($_SERVER["HTTPS"])) && ($_SERVER["HTTPS"] == "on")){
       		$pageURL .= "s";
       }
   
       	$pageURL .= "://";
   
       	if (($_SERVER["SERVER_PORT"] != "80") and ($_SERVER["SERVER_PORT"] != "443")){
       		$pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
   
       	} else {
       		$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
   
       }
   
       	return $pageURL;
       }
   
       private function generate_url( $user, $post ) {
   
       	$token = $this->create_token( $user, $post );
   
       	$url =  ' '.preg_replace('/\?.*/', '', $this->curpageurl());
       	$url .= "?".$this->namespace."-action=sign&".$this->namespace."-uid=".$user->ID."&".$this->namespace."-token=".$token;
   
       if (get_post_meta($post->ID, $this->login_link_field_name, true )){
   
       $url = add_query_arg( $this->namespace.'-action', 'login', $url);
   
       $url = wp_logout_url( $url );
   
       }
   
       return $url;
   
       }
   
       private function send_email( $user, $post ) {
   
       $title = get_post_meta( $post->ID, $this->namespace."-email_title", true );
   
       $title = $this->personalise_message($title,$post,$user);
   
       $message = wpautop(do_shortcode(get_post_meta( $post->ID, $this->namespace."-email_message", true )));
   
       $message = apply_filters( 'lh_signing_email_message_filter', $message, $user, $post );
   
       $message = $this->personalise_message($message,$post,$user);
   
       $headers = array('Content-Type: text/html; charset=UTF-8');
   
       $headers = apply_filters( 'lh_signing_headers_filter', $headers, $user, $post );
   
       //default add_url is true
       $add_url = true;
       $add_url = apply_filters( 'lh_signing_add_url_filter', $add_url, $user, $post );
   
       if ($add_url){
   
       //ensure the email contains the signing url
       if (strpos($message, '%lh_signing_sign_url%') !== false) {
   
       $message = str_replace('%lh_signing_sign_url%', $this->return_signing_button($user, $post), $message);
   
       } else {
   
       $message .= $this->return_signing_button($user, $post);
   
       }
   
       }
   
       $message = $this->use_email_template( $message );
   
       wp_mail( $user->user_email, $title, $message, $headers);
   
       }
   
       private function handle_new_user( $email, $first_name, $last_name ) {
   
       global $wpdb;
   
       $random_password = wp_generate_password( $length=12, $include_standard_special_chars=false );
   
       $userdata = array(
           'user_login'  =>  $email,
           'user_email' => $email,
           'role' => 'unclaimed',
           'user_pass'   =>  $random_password
       );
   
       $user_id = wp_insert_user( $userdata ) ;
   
       $sql = "update ".$wpdb->users." set user_login = user_email where ID = '".$user_id."'";
   
       $result = $wpdb->get_results($sql);
   
       wp_update_user( array( 'ID' => $user_id, 'first_name' => $first_name, 'last_name' => $last_name, 'display_name' => $first_name." ".$last_name ));
   
       apply_filters( 'lh_signing_http_post_filter', $user_id);
   
       return $user_id;
   
       }
   
       private function format_results($post){
   
       if( is_wp_error( $GLOBALS[$this->namespace.'-insert_result']) ) {
   
       $error = $GLOBALS[$this->namespace.'-insert_result'];
   
       $message = '<p>There was an error</p><p><strong>'.$error->get_error_code() .'</strong>: '.$error->get_error_message() .'</p>';
   
       } else {
   
       $type = $this->get_connection_type_by_id($GLOBALS[$this->namespace.'-insert_result']);
   
       $from = $this->get_connection_from_by_id($GLOBALS[$this->namespace.'-insert_result']);
   
       $user = get_user_by( 'ID', $from);
   
       if ($type == "signing_sign_unconfirmed"){
   
       $message = get_post_meta( $post->ID, $this->namespace."-unconfirmed_message", true );
   
       } elseif ($type == "signing_sign_confirmed"){
   
       $message = get_post_meta( $post->ID, $this->namespace."-confirmed_message", true );
   
       } else {
   
       $message = "something went wrong";
   
       }
   
       $message = $this->personalise_message(wpautop(do_shortcode($message)),$post,$user);
   
       }
   
       return $message;
   
       }
   
       private function return_submit_text($post) {
   
       if (($submit_text = get_post_meta( $post->ID, $this->namespace."-submit_text", true )) == ""){
   
       $submit_text = "Add your Signature";
   
       }
   
       return $submit_text;
   
       }
   
       private function return_email_button_text($post) {
   
       if (($email_button_text = get_post_meta( $post->ID, $this->namespace."-email_button_text", true )) == ""){
   
       $email_button_text = "Sign me Up!";
   
       }
   
       return $email_button_text;
   
       }
   
       private function logged_out_form($atts, $post) {
   
       wp_enqueue_script('lh_signing-script', plugins_url( '/scripts/lh-signing.js' , __FILE__ ), array(), '1.0', true  );
   
       $content .= "\n<form name=\"lh_signing-form\" id=\"lh_signing-form\" action=\"".get_permalink($post)."\" method=\"post\" data-".$this->namespace."-nonce=\"".wp_create_nonce($this->namespace."-nonce")."\"  >";
   
       $content .= "\n<noscript>Please switch on Javascript to enable this registration</noscript>\n\n";
   
       $content .= "\n<p><input name=\"".$this->namespace."-first_name\" id=\"".$this->namespace."-first_name\" value=\"\" type=\"text\" placeholder=\"Your First Name\" required=\"required\" /></p>";
       $content .= "\n<p><input name=\"".$this->namespace."-last_name\" id=\"".$this->namespace."-last_name\" value=\"\" type=\"text\" placeholder=\"Your Second Name\" required=\"required\" /></p>";
       $content .= "\n<p><input name=\"".$this->namespace."-email\" id=\"".$this->namespace."-email\" value=\"\" type=\"email\" placeholder=\"Your Email\" required=\"required\" /></p>";
   
       $content = apply_filters( 'lh_signing_intermediate_logged_out_form_filter',$content, $atts, $post);
   
       //do_action( 'register_form' );
   
       $content .= "\n<input id=\"".$this->namespace."-nonce\" name=\"".$this->namespace."-nonce\" value=\"\" type=\"hidden\" />";
   
       $content .= "\n<p><input type=\"submit\" id=\"".$this->namespace."-submit\" name=\"".$this->namespace."-submit\" value=\"".$this->return_submit_text($post)."\"/></p>";
   
       $content .= "\n</form>";
   
       $content = apply_filters( 'lh_signing_final_logged_out_form_filter',$content, $atts, $post);
   
       return $content;
   
       }
   
       private function logged_in_form($atts, $post) {
   
       $user = wp_get_current_user();
   
       if (p2p_connection_exists( 'signing_sign_unconfirmed', array( 'from' => $user->ID, 'to' => $post->ID ) )){
   
       $content .= "\n<p>You have already registered but you have yet to confirm, please check your email to confirm your signature</p>";
   
       } elseif  (p2p_connection_exists( 'signing_sign_confirmed', array( 'from' => $user->ID, 'to' => $post->ID ) )){
   
       $content .= "\n<p>You have already added your signature</p>";
   
       } else {
   
       $content .= "\n<form name=\"lh_signing-form\" id=\"lh_signing-form\" action=\"".get_permalink($post)."\" method=\"post\" >";
   
       $content .= "\n<input id=\"".$this->namespace."-nonce\" name=\"".$this->namespace."-nonce\" value=\"".wp_create_nonce($this->namespace."-nonce")."\" type=\"hidden\" />";
   
       $content .= "\n<p><input type=\"submit\" id=\"".$this->namespace."-submit\" name=\"".$this->namespace."-submit\" value=\"".$this->return_submit_text($post)."\"/></p>";
   
       $content .= "\n</form>";
   
       }
   
       return $content;
   
       }
   
       private function action_signing( $user, $post, $type) {
   
       if (p2p_connection_exists( $type, array( 'from' => $user->ID, 'to' => $post->ID ) )){
   
       //the post already has this state
   
       $error = new WP_Error( 'error', __( "You already have this state on this ".$post->post_type, $this->namespace ) );
   
       return $error;
   
       } else {
   
       if ($result = p2p_type( $type )->connect( $user->ID, $post->ID, array(
           'date' => current_time('mysql')
       ) )){
   
       $array_to_remove = array($type);
   
       $states = array_diff($this->signing_states,$array_to_remove);
   
       foreach ($states as $state){
   
       $foo = p2p_type( $state )->disconnect( $user->ID, $post->ID );
   
       }
   
       if ($type == 'signing_sign_unconfirmed'){
   
       $this->send_email( $user, $post );
   
       }
   
       if ($type == 'signing_sign_confirmed'){
   
       $this->maybe_upgrade_user($user);
   
       }
   
       return $result;
   
       } else {
   
       $error = new WP_Error( 'error', __( "Something went wrong on this ".$post->post_type, $this->namespace ) );
   
       return $error;
   
       }
   
       }
   
       }
   
       private function validate_token($user,$post,$token) {
   
       if (($meta = get_user_meta($user->ID, $this->namespace."_".$post->ID."-confirmation_token", true)) != ""){
   
       $hash  = wp_hash($token);
   
       if ($meta == $hash){
   
       return true;
   
       } else {
   
       return false;
   
       }
   
       } else {
   
       return false;
   
       }
   
       }
   
       public function autologin_via_url(){
   
       if (($_GET[$this->namespace.'-action'] == "login") and ($user = get_user_by('ID', $_GET[$this->namespace.'-uid']))){
   
       $postdata = get_post(url_to_postid(strtok($this->curpageurl(), '?')));
   
       $token = $_GET[$this->namespace.'-token'];
   
       if ($this->validate_token($user,$postdata,$token)){
   
       wp_set_auth_cookie( $user->ID );
       do_action( 'wp_login', $user->user_login);
   
       } 
   
       wp_redirect( add_query_arg( $this->namespace.'-action', 'sign', $this->curpageurl() ) );
       exit;
   
       }
   
       }
   
       public function list_attached_users($id, $list, $fields)  {
   
       $users = get_users( array(
         'connected_type' => array($list),
         'connected_items' => get_queried_object_id(),
         'fields' => array($fields)
       ) );
   
       $return_string = "<ul>";
   
       foreach ( $users as $user ) {
   
       $return_string .= '<li>'. $user->{'display_name'} .'</li>';
   
       }
   
       $return_string .= "</ul>";
   
       return $return_string;
   
       }
   
       public function count_attached_users($id, $list, $fields) {
   
       $users = get_users( array(
         'connected_type' => array($list),
         'connected_items' => get_queried_object_id(),
         'fields' => array($fields)
       ) );
   
       $user_count = 0;
   
       foreach ( $users as $user ) {
   
       $user_count++;
   
       }
   
       $return_string = $user_count;
   
       return $return_string;
   
       }
   
       public function the_content_filter( $content ) {
   
       global $post;
   
       if (has_shortcode( $post->post_content, 'lh_signing_form' )){
   
       if ($GLOBALS[$this->namespace.'-insert_result']){
   
       $content = $this->format_results($post);
   
       } 
   
       }
   
       // Returns the content.
   
       return $content;
   
       }
   
       public function register_p2p_connection_types() {
   
       if ( current_user_can( 'edit_users' ) ) {
           /* A user with admin privileges */
       $admin_box = true;
   
       } else {
           /* A user without admin privileges */
       $admin_box = false;
       }
   
         p2p_register_connection_type( array(
       	'title' => 'Confirmed Signature',
               'name' => 'signing_sign_confirmed',
               'from' => 'user',
               'to' => $this->return_approved_posttypes(),
       'admin_column' => 'from',
               'admin_box' => $admin_box,
       'admin_dropdown' => 'from'
           ) );
   
         p2p_register_connection_type( array(
       	'title' => 'Unconfirmed Signature',
               'name' => 'signing_sign_unconfirmed',
               'from' => 'user',
               'to' => $this->return_approved_posttypes(),
       'admin_column' => 'from',
              'admin_box' => $admin_box,
       'admin_dropdown' => 'from'
           ) );
   
       }
   
       public function save_data(){
   
       if (!is_admin()){
   
       global $post;
   
       if (($_GET[$this->namespace.'-action'] == "sign") and ($user = get_user_by('ID', $_GET[$this->namespace.'-uid']))){
   
       $token = $_GET[$this->namespace.'-token'];
   
       if ($this->validate_token($user,$post,$token)){
   
       //hashes match so the documents can be signed
       $GLOBALS[$this->namespace.'-insert_result'] = $this->action_signing( $user, $post, 'signing_sign_confirmed');
   
       }
   
       } elseif ($_POST[$this->namespace.'-submit']) {
   
       if ( wp_verify_nonce( $_POST[$this->namespace.'-nonce'], $this->namespace.'-nonce') ) {
   
       if ( is_user_logged_in() ){
   
       $user = wp_get_current_user();
   
       $GLOBALS[$this->namespace.'-insert_result'] = $this->action_signing( $user, $post, 'signing_sign_confirmed');
   
       } else {
   
       $test = trim(sanitize_user($_POST[$this->namespace.'-email']));
   
       if (is_email($test) and ($this->domain_exists($test))){
   
       $email = trim(wp_filter_nohtml_kses($_POST[$this->namespace.'-email']));
   
       } else {
   
       $error = new WP_Error( 'error', __( "Invalid email", $this->namespace ) );
   
       }
   
       if ( isset( $_POST[$this->namespace.'-full_name'])){
   
       $full_name = sanitize_text_field($_POST[$this->namespace.'-full_name']);
   
       $pieces = explode(" ", $full_name);
   
       $first_name = $pieces[0];
   
       if ($pieces[1]){
   
       $last_name = $pieces[1];
   
       } else {
   
       $last_name = " ";
   
       }
   
       } elseif ( isset( $_POST[$this->namespace.'-first_name']) &&  isset( $_POST[$this->namespace.'-last_name']) ){
   
       $first_name = sanitize_text_field($_POST[$this->namespace.'-first_name']);
   
       $last_name = sanitize_text_field($_POST[$this->namespace.'-last_name']);
   
       } else {
   
       $error = new WP_Error( 'error', __( "Please add a first and last name", $this->namespace ) );
   
       }
   
       if( is_wp_error( $error) ) {
   
       $GLOBALS[$this->namespace.'-insert_result'] = $error;
   
       return $error;
   
       } else {
   
       $user = get_user_by( 'email', $email );
   
       if ($user){
   
       //Only send email etc if the user has not already signed
   
       if (!p2p_connection_exists( 'signing_sign_confirmed', array( 'from' => $user->ID, 'to' => $post->ID ) )){
   
       $GLOBALS[$this->namespace.'-insert_result'] = $this->action_signing( $user, $post, 'signing_sign_unconfirmed');
   
       }
       } else {
   
       $user_id = $this->handle_new_user( $email, $first_name, $last_name );
   
       $user = get_user_by( 'id', $user_id );
   
       $GLOBALS[$this->namespace.'-insert_result'] = $this->action_signing( $user, $post, 'signing_sign_unconfirmed');
   
       }
   
       }
   
       }
   
       }
   
       } elseif (($this->options[ $this->page_id_field ] == $post->ID) and is_user_logged_in() and $this->options[ $this->page_id_field ]){
   
       //They are registered, logged in and this si the registration page so redirect them to home
       wp_redirect( home_url() );
       exit;
   
       }
   
       }
   
       }
   
       public function add_unclaimed_role(){
   
       if (!get_role('unclaimed')){
               add_role('unclaimed', 'Unclaimed User', array(
                   'read' => true, // True allows that capability, False specifically removes it.
               ));
   
       }
   
       }
   
       public function register_shortcodes(){
   
       add_shortcode($this->namespace.'_form', array($this,"form_shortcode_output"));
       add_shortcode($this->namespace.'_unconfirmed_count', array($this,"unconfirmed_count_shortcode_output"));
       add_shortcode($this->namespace.'_confirmed_count', array($this,"confirmed_count_shortcode_output"));
       add_shortcode($this->namespace.'_total_count', array($this,"total_count_shortcode_output"));
       add_shortcode($this->namespace.'_unconfirmed_list', array($this,"unconfirmed_list_shortcode_output"));
       add_shortcode($this->namespace.'_confirmed_list', array($this,"confirmed_list_shortcode_output"));
   
       }
   
       public function return_html_form($atts, $post)  {
   
       if ( is_user_logged_in() ){
   
       $return_string = $this->logged_in_form($atts, $post);
   
       } else {
   
       $return_string = $this->logged_out_form($atts, $post);
   
       }
   
       return $return_string;
   
       }
   
       public function form_shortcode_output($atts,$content = null)  {
   
       global $post;
   
       if (in_array ( $post->post_type , $this->return_approved_posttypes() )){
   
       $return_string = $this->return_html_form($atts, $post);
   
       }
   
       return $return_string;
   
       }
   
       public function unconfirmed_list_shortcode_output($atts,$content = null)  {
   
       extract( shortcode_atts( array (
       'id' => false,
       'fields' => 'display_name' ), $atts )
       );
   
       $return_string = $this->list_attached_users($id, 'signing_sign_unconfirmed', $fields);
   
       return $return_string;
   
       }
   
       public function add_meta_boxes($post_type, $post) {
   
       if (has_shortcode( $post->post_content, 'lh_signing_form' )){
   
       add_meta_box($this->namespace."-initial_form-div", "Initial Form Configuration", array($this,"initial_form_metabox_content"), $post_type, "normal", "high");
   
       add_meta_box($this->namespace."-unconfirmed_message-div", "Unconfirmed Message", array($this,"unconfirmed_message_metabox_content"), $post_type, "normal", "high");
       add_meta_box($this->namespace."-email_message-div", "Email Message", array($this,"email_message_metabox_content"), $post_type, "normal", "high");
   
       add_meta_box($this->namespace."-confirmed_message-div", "Confirmed Message", array($this,"confirmed_message_metabox_content"), $post_type, "normal", "high");
   
       add_meta_box($this->namespace."-unconfirmed_users-div", "Unconfirmed Users", array($this,"unconfirmed_users_metabox_content"), $post_type, "normal", "high");
   
       add_meta_box($this->namespace."-confirmed_users-div", "Confirmed Users", array($this,"confirmed_users_metabox_content"), $post_type, "normal", "high");
   
       } else {
   
       }
   
       }
   
       public function initial_form_metabox_content(){
   
       $signing_type = get_post_meta( get_the_ID(), $this->namespace."-signing_type", true );
   
       $submit_text = get_post_meta( get_the_ID(), $this->namespace."-submit_text", true );
   
       $login_link = get_post_meta( get_the_ID(), $this->login_link_field_name, true );
   
       ?>
       <table>
       <tbody>
       <tr>
       <td>
       <label id="<?php  echo $this->namespace."-signing_type-prompt-text";  ?>" for="<?php  echo $this->namespace."-signing_type";  ?>">Enter document type here</label></td>
       <td>
       <input type="text" name="<?php  echo $this->namespace."-signing_type";  ?>" id="<?php  echo $this->namespace."-signing_type";  ?>"  size="50" value="<?php echo $signing_type;  ?>" placeholder="Document type e.g. petition, mailing list, etc" />
       </td>
       </tr>
       <tr>
       <td>
       <label id="<?php  echo $this->namespace."-submit_text-prompt-text";  ?>" for="<?php  echo $this->namespace."-submit_text";  ?>">Enter the text you want on the submit button</label>
       </td>
       <td>
       <input type="text" name="<?php  echo $this->namespace."-submit_text";  ?>" id="<?php  echo $this->namespace."-submit_text";  ?>"  size="50" value="<?php echo $submit_text;  ?>" placeholder="e.g. Add your Signature" />
       </td>
       </tr>
       <tr>
       <td>
       <label id="<?php  echo $this->login_link_field_name;  ?>" for="<?php  echo $this->login_link_field_name;  ?>">Logged the confirmed User in:</label>
       </td>
       <td>
       <select name="<?php echo $this->login_link_field_name; ?>" id="<?php echo $this->login_link_field_name; ?>">
       <option value="1" <?php  if ($login_link == 1){ echo 'selected="selected"'; }  ?>>Yes</option>
       <option value="0" <?php  if ($login_link == 0){ echo 'selected="selected"';}  ?>>No</option>
       </select>
       (<a href="https://lhero.org/portfolio/lh-signing/#<?php echo $this->login_link_field_name; ?>">What does this mean?</a>)
       </td>
       </tr>
       </tbody>
       </table>
   
       <?php
   
       }
   
       public function unconfirmed_message_metabox_content(){
   
       $content = get_post_meta( get_the_ID(), $this->namespace."-unconfirmed_message", true );
   
       $settings = array( 'media_buttons' => false );
   
       wp_editor( $content, $this->namespace."-unconfirmed_message");
   
       }
   
       public function email_message_metabox_content(){
   
       $title = get_post_meta( get_the_ID(), $this->namespace."-email_title", true );
   
       $content = get_post_meta( get_the_ID(), $this->namespace."-email_message", true );
   
       $email_button_text = get_post_meta( get_the_ID(), $this->namespace."-email_button_text", true );
   
       ?>
   
       <label class="screen-reader-text" id="<?php  echo $this->namespace."-email_title-prompt-text";  ?>" for="<?php  echo $this->namespace."-email_title";  ?>">Enter title here</label>
       <input type="text" name="<?php  echo $this->namespace."-email_title";  ?>" id="<?php  echo $this->namespace."-email_title";  ?>"  size="50" value="<?php echo $title;  ?>" placeholder="Enter Email title here" />
   
       <?php
   
       $settings = array( 'media_buttons' => false );
   
       wp_editor( $content, $this->namespace."-email_message");
   
       ?>
   
       <label id="<?php  echo $this->namespace."-email_button_text-prompt-text";  ?>" for="<?php  echo $this->namespace."-email_button_text";  ?>">Email confirmation button text:</label>
       <input type="text" name="<?php  echo $this->namespace."-email_button_text";  ?>" id="<?php  echo $this->namespace."-email_button_text";  ?>"  size="50" value="<?php echo $email_button_text;  ?>" placeholder="e.g Sign me up or Join the list" />
   
       <?php
   
       }
   
       public function confirmed_message_metabox_content(){
   
       $content = get_post_meta( get_the_ID(), $this->namespace."-confirmed_message", true );
   
       $settings = array( 'media_buttons' => false );
   
       wp_editor( $content, $this->namespace."-confirmed_message");
   
       }
   
       public function unconfirmed_users_metabox_content(){
   
       global $post;
   
       $users = get_users( array(
         'connected_type' => array('signing_sign_unconfirmed','foobar'),
         'connected_items' => $post->ID
       ) );
   
       $this->list_users($users);
   
       if ($users){
       ?>
   
       <strong><a href="<?php echo add_query_arg( 'lh_signing-export_users', 'signing_sign_unconfirmed'); ?>">Export these Users</a></strong>
   
       <?php
       }
   
       }
   
       public function confirmed_users_metabox_content(){
   
       global $post;
   
       $users = get_users( array(
         'connected_type' => array('signing_sign_confirmed','foobar'),
         'connected_items' => $post->ID
       ) );
   
       $this->list_users($users);
   
       if ($users){
       ?>
   
       <strong><a href="<?php echo add_query_arg( 'lh_signing-export_users', 'signing_sign_confirmed'); ?>">Export these Users</a></strong>
   
       <?php
       }
   
       }
   
       public function update_post_meta(){
   
       global $post;
   
       if (has_shortcode( $post->post_content, 'lh_signing_form' )){
   
       if ($_POST[$this->namespace."-signing_type"]){
   
       $signing_type = sanitize_text_field($_POST[$this->namespace."-signing_type"]);
   
       update_post_meta($post->ID, $this->namespace."-signing_type", $signing_type);
   
       $submit_text = sanitize_text_field($_POST[$this->namespace."-submit_text"]);
   
       update_post_meta($post->ID, $this->namespace."-submit_text", $submit_text);
   
       }
   
       if (($_POST[$this->login_link_field_name] == "0") || ($_POST[$this->login_link_field_name] == "1")){
   
       update_post_meta($post->ID, $this->login_link_field_name, $_POST[$this->login_link_field_name]);
   
       }
   
       if ($_POST[$this->namespace."-unconfirmed_message"]){
   
       $content = wp_kses_post($_POST[$this->namespace."-unconfirmed_message"]);
   
       update_post_meta($post->ID, $this->namespace."-unconfirmed_message", $content);
   
       }
   
       if ($_POST[$this->namespace."-email_message"]){
   
       $content = wp_kses_post($_POST[$this->namespace."-email_message"]);
   
       update_post_meta($post->ID, $this->namespace."-email_message", $content);
   
       }
   
       if ($_POST[$this->namespace."-email_title"]){
   
       $title = sanitize_text_field($_POST[$this->namespace."-email_title"]);
   
       update_post_meta($post->ID, $this->namespace."-email_title", $title);
   
       }
   
       if ($_POST[$this->namespace."-email_button_text"]){
   
       $email_button_text = sanitize_text_field($_POST[$this->namespace."-email_button_text"]);
   
       update_post_meta($post->ID, $this->namespace."-email_button_text", $email_button_text);
   
       }
   
       if ($_POST[$this->namespace."-confirmed_message"]){
   
       $content = wp_kses_post($_POST[$this->namespace."-confirmed_message"]);
   
       update_post_meta($post->ID, $this->namespace."-confirmed_message", $content);
   
       }
   
       }
   
       }
   
       function plugin_menu() {
   
       add_options_page('Signing Options', 'Signing Options', 'manage_options', $this->filename, array($this,"plugin_options")); 
   
       }
   
       function plugin_options() {
   
       if (!current_user_can('manage_options')){
   
       wp_die( __('You do not have sufficient permissions to access this page.') );
   
       }
   
       if( isset($_POST[ $this->hidden_field_name ]) && $_POST[ $this->hidden_field_name ] == 'Y' ) {
   
       if (($_POST[ $this->page_id_field ] != "") and ($page = get_page(sanitize_text_field($_POST[ $this->page_id_field ])))){
   
       if ( has_shortcode( $page->post_content, 'lh_signing_form' ) ) {
   
       $options[ $this->page_id_field ] = sanitize_text_field($_POST[ $this->page_id_field ]);
   
       } else {
   
       echo "shortcode not found";
   
       }
   
       }
   
       if (update_option( $this->opt_name, $options )){
   
       $this->options = get_option($this->opt_name);
   
       ?>
       <div class="updated"><p><strong><?php _e('Values saved', $this->namespace ); ?></strong></p></div>
       <?php
   
           } 
   
       }
   
       // Now display the settings editing screen
   
           echo '<div class="wrap">';
   
           // header
   
           echo "<h1>" . __('LH Signing Settings', 'menu-test' ) . "</h21>";
   
           // settings form
   
           ?>
   
       <form name="lh_signing-settings_form" method="post" action="">
       <input type="hidden" name="<?php echo $this->hidden_field_name; ?>" id="<?php echo $this->hidden_field_name; ?>" value="Y" />
   
       <p><label for="<?php echo $this->page_id_field; ?>"><?php _e("Registration Page ID;", 'menu-test' ); ?></label>
       <input type="number" name="<?php echo $this->page_id_field; ?>" id="<?php echo $this->page_id_field; ?>" value="<?php echo $this->options[ $this->page_id_field ]; ?>" size="10" /><a href="<?php echo get_permalink($this->options[ $this->page_id_field ]); ?>">Link</a>
       </p>
   
       <p class="submit">
       <input type="submit" name="lh_signing-settings_form-submit" class="button-primary" value="<?php esc_attr_e('Save Changes') ?>" />
       </p>
   
       </form>
   
       <?php
   
       }
   
       function register_url( $register_url ) {
   
       if ($page = get_page($this->options[ $this->page_id_field ])){
   
       return get_permalink($page);
   
       } else {
   
       return $register_url;
   
       }
   
       }
   
       public function export_users(){
           global $pagenow;
   
       if( is_admin() && ('post.php' == $pagenow) && $_GET['lh_signing-export_users'] ) {
   
       do_action("p2p_init");
   
       $users = get_users( array(
         'connected_type' => array('signing_sign_unconfirmed'),
         'connected_items' => $_GET['post']
       ) );
   
       $i = 0;
       foreach ($users as $user){
   
       $var[$i]['display_name'] = get_the_author_meta( 'display_name', $user->ID );
       $var[$i]['user_email'] = $user->user_email;
   
       $i++; 
   
       }
   
       header("Content-Type: text/csv");
       header("Content-Disposition: attachment; filename=file.csv");
   
       echo $this->generate_csv_string($var);
   
       die;
   
       }
   
       }
   
       public function restrict_p2p_box_display( $show, $ctype, $post ) {
   
       if (in_array($ctype->name, $this->signing_states)) {
   
       if (has_shortcode( $post->post_content, 'lh_signing_form' )){
   
       return $show;
   
       } else {
   
       return false;
   
       }
   
       } else {
   
       return $show;
   
       }
   
       }
   
       public function __construct() {
   
       $this->options = get_option($this->opt_name);
       $this->filename = plugin_basename( __FILE__ );
   
       add_action('add_meta_boxes', array($this,"add_meta_boxes"),10,2);
       add_action('save_post', array($this,"update_post_meta"));
       add_action('init', array($this,"register_shortcodes"));
       add_action('init', array($this,"autologin_via_url"));
       add_action('init', array($this,"export_users"));
       add_filter('the_content', array($this,"the_content_filter"),100);
       add_action('p2p_init', array($this,"register_p2p_connection_types"));
       add_filter( 'p2p_admin_box_show', array($this,"restrict_p2p_box_display"), 10, 3 );
       add_action('wp', array($this,"save_data"));
       add_action('after_setup_theme',array($this,"add_unclaimed_role"));
       add_action('admin_menu', array($this,"plugin_menu"));
       add_filter('register_url', array($this,"plugin_menu"),10,1);
   
       }
   
       }
   
       $lh_signing_instance = new LH_Signing_plugin();
   
       add_action( 'widgets_init', 'lh_signing_widget_init' );
   
       function lh_signing_widget_init() {
           register_widget( 'lh_signing_widget' );
       }
   
       class lh_signing_widget extends WP_Widget {
   
           public function __construct()    {
               $widget_details = array(
                   'classname' => 'lh_signing_widget',
                   'description' => 'My plugin description'
               );
   
               parent::__construct( 'lh_signing_widget', 'LH Signing Widget', $widget_details );
   
           }
   
           public function form( $instance ) {
               // Backend Form
   
       $title = '';
           if( !empty( $instance['title'] ) ) {
               $title = $instance['title'];
           }
   
          $text = '';
           if( !empty( $instance['text'] ) ) {
               $text = $instance['text'];
           }
   
           $postid = '';
           if( !empty( $instance['postid'] ) ) {
               $postid = $instance['postid'];
           }
   
           ?>
   
           <p>
               <label for="<?php echo $this->get_field_name( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
               <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
           </p>
   
           <p>
               <label for="<?php echo $this->get_field_name( 'text' ); ?>"><?php _e( 'Text:' ); ?></label>
               <textarea class="widefat" id="<?php echo $this->get_field_id( 'text' ); ?>" name="<?php echo $this->get_field_name( 'text' ); ?>" type="text" ><?php echo esc_attr( $text ); ?></textarea>
           </p>
   
       <p>
       <?php  echo "the post id is ".$postid; ?>
   
       <label for="<?php  echo $this->get_field_name( 'postid' );  ?>"><?php _e( 'Post:' ); ?></label>
   
       <select name="<?php echo $this->get_field_name( 'postid' ); ?>" id="<?php echo $this->get_field_id( 'postid' ); ?>" >
   
       <?php
   
       global $wpdb;
   
       $sql = "SELECT * FROM ".$wpdb->prefix."posts WHERE post_content LIKE '%[lh_signing_form%'";
   
       $result = $wpdb->get_results($sql);
         if ($result){
           foreach($result as $pageThing){
   
       ?><option value="<?php echo $pageThing->ID; ?>" <?php  if ($postid == $pageThing->ID){ echo 'selected="selected"'; } ?> ><?php echo $pageThing->post_title; ?></option><?php
   
       	}
         }
   
       ?>
   
        </select>
           <div class='mfc-text'>
   
           </div>
   
           <?php
   
           echo $args['after_widget'];
   
           }
   
           public function update( $new_instance, $old_instance ) {
               return $new_instance;
           }
   
           public function widget( $args, $instance ) {
               // Frontend display HTML
   
       $title = apply_filters( 'widget_title', $instance['title'] );
   
       	// before and after widget arguments are defined by themes
   
       	echo $args['before_widget'];
   
       	if ( ! empty( $title ) ){
   
       	echo $args['before_title'] . $title . $args['after_title'];
   
       }
   
       $text = $instance['text'];
   
       	// This is where you run the code and display the output
   
       	echo __( $text, 'wpb_widget_domain' );
   
       if ($instance['postid']){
   
       $postobject = get_post($instance['postid']);
   
       $atts = null;
   
       $foo = new LH_Signing_plugin();
   
       echo $foo->return_html_form($atts, $postobject);
   
       }
   
       	echo $args['after_widget'];
   
       }
   
       }
   
       ?>
       ```
   
 * `lh-sgning.php` with my changes:
 *     ```
       <?php
       /*
        Plugin Name: LH Signing
        Plugin URI: https://lhero.org/portfolio/lh-signing/
        Description: Adds signing functionality, create petitions, validated lists etc
        Author: Peter Shaw
        Author URI: https://shawfactor.com
        Version: 2.61
        License: GPL v3 (http://www.gnu.org/licenses/gpl.html)
       */
   
       class LH_Signing_plugin {
   
       var $opt_name = 'lh_signing-options';
       var $hidden_field_name = 'lh_signing-submit_hidden';
       var $login_link_field_name = '_lh_signing-login_link';
       var $email_title_field_name = 'lh_signing-email_title';
       var $email_bcc_field_name = 'lh_signing-email_bcc';
       var $message_field_name = 'lh_signing-message';
       var $page_id_field = 'lh_signing-page_id';
       var $namespace = 'lh_signing';
       var $signing_states = array('signing_sign_confirmed','signing_sign_unconfirmed');
   
       var $filename;
       var $options;
   
       private function arrayToCsv( $fields, $delimiter = ';', $enclosure = '"', $encloseAll = false, $nullToMysqlNull = false ) {
           $delimiter_esc = preg_quote($delimiter, '/');
           $enclosure_esc = preg_quote($enclosure, '/');
   
           $output = array();
           foreach ( $fields as $field ) {
               if ($field === null && $nullToMysqlNull) {
                   $output[] = 'NULL';
                   continue;
               }
   
               // Enclose fields containing $delimiter, $enclosure or whitespace
               if ( $encloseAll || preg_match( "/(?:${delimiter_esc}|${enclosure_esc}|\s)/", $field ) ) {
                   $output[] = $enclosure . str_replace($enclosure, $enclosure . $enclosure, $field) . $enclosure;
               }
               else {
                   $output[] = $field;
               }
           }
   
           return implode( $delimiter, $output );
       }
   
       private function generate_csv_string($vararray){
   
       $csvString = '';
   
       $bar = array_flip((array)$vararray[0]);
   
       $csvString .= $this->arrayToCsv($bar,",")."\n";
   
       foreach ($vararray as $fields) {
   
       $csvString .= $this->arrayToCsv($fields,",")."\n";
   
        }
   
       return $csvString;
   
       }
   
       private function domain_exists($email, $record = 'MX'){
       $pieces = explode("@", $email);
   
       return checkdnsrr($pieces[1], $record);
   
       }
   
       private function maybe_upgrade_user($user){
   
       //only run this process if the current user has an unclaimed role
       if ($user->roles[0] == 'unclaimed'){
   
       $default_role = get_option( 'default_role' );
   
       wp_update_user(array(
           'ID' => $user->ID,
           'role' => $default_role
       ));
   
       }
   
       }
   
       private function return_signing_button($user, $post){
   
       $button .= '<table width="100%" border="0" cellspacing="0" cellpadding="0">
         <tr>
           <td>
             <table border="0" cellspacing="0" cellpadding="0">
               <tr>
       <td><a class="confirm_button" href="'.$this->generate_url( $user, $post ).'">'.$this->return_email_button_text($post).'</a></td>
               </tr>
             </table>
           </td>
         </tr>
       </table>';
   
       return $button;
   
       }
   
       private function get_connection_type_by_id($id){
   
       global $wpdb;
   
       $sql = "SELECT p2p_type FROM ".$wpdb->prefix."p2p WHERE p2p_id = '" .$id. "'";
   
       $type = $wpdb->get_var($sql);
   
       return $type;
   
       }
   
       private function get_connection_from_by_id($id){
   
       global $wpdb;
   
       $sql = "SELECT p2p_from FROM ".$wpdb->prefix."p2p WHERE p2p_id = '" .$id. "'";
   
       $from = $wpdb->get_var($sql);
   
       return $from;
   
       }
   
       private function personalise_message($message,$post,$user){
   
       $message = str_replace('%post_title%', $post->post_title, $message);
       $message = str_replace('%first_name%', $user->first_name, $message);
       $message = str_replace('%last_name%', $user->last_name, $message);
       $message = str_replace('%user_email%', $user->user_email, $message);
       $message = str_replace('%user_login%', $user->user_login, $message);
       $message = str_replace('%bloginfo_name%',get_bloginfo('name','display'), $message);
   
       return $message;
   
       }
   
       private function list_users($users){
   
       echo "<ul>";
   
       foreach ( $users as $user ) { 
   
       echo '<li><a href="'.get_edit_user_link( $user->ID ).'">'.get_the_author_meta( 'display_name', $user->ID ).'</a></li>';
   
       }
   
       echo "</ul>";
   
       }
   
       private function return_approved_posttypes() {
   
       $posttypes = array('post','page');
   
       $posttypes = apply_filters('lh_signing_posttypes_filter', $posttypes);
   
       return $posttypes;
   
       }
   
       private function use_email_template( $message ) {
   
       if (file_exists(get_stylesheet_directory().'/'.$this->namespace.'-template.php')){
   
       ob_start();
   
       include( get_stylesheet_directory().'/'.$this->namespace.'-template.php');
   
       $message = ob_get_contents();
   
       ob_end_clean();
   
       } else {
   
       ob_start();
   
       include( plugin_dir_path( __FILE__ ).'/'.$this->namespace.'-template.php');
   
       $message = ob_get_contents();
   
       ob_end_clean();
   
       }
   
       if (!class_exists('CssToInlineStyles')) {
   
       require_once('csstoinlinestyles/CssToInlineStyles.php');
   
       }
   
       $doc = new DOMDocument();
   
       $doc->loadHTML($message);
   
       // create instance
       $cssToInlineStyles = new CssToInlineStyles();
   
       $cssToInlineStyles->setHTML($message);
   
       $cssToInlineStyles->setCSS($doc->getElementsByTagName('style')->item(0)->nodeValue);
   
       // output
   
       $message = $cssToInlineStyles->convert(); 
   
       return $message;
   
       }
   
       private function create_token( $user, $post ) {
   
       // random salt
       $token = wp_generate_password( 20, false );
   
       // we're sending this to the user
       $hash  = wp_hash($token);
   
       update_user_meta( $user->ID, $this->namespace."_".$post->ID."-confirmation_token" , $hash );
   
       return $token;
   
       }
   
       private function curpageurl() {
       	$pageURL = 'http';
   
       	if ((isset($_SERVER["HTTPS"])) && ($_SERVER["HTTPS"] == "on")){
       		$pageURL .= "s";
       }
   
       	$pageURL .= "://";
   
       	if (($_SERVER["SERVER_PORT"] != "80") and ($_SERVER["SERVER_PORT"] != "443")){
       		$pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
   
       	} else {
       		$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
   
       }
   
       	return $pageURL;
       }
   
       private function generate_url( $user, $post ) {
   
       	$token = $this->create_token( $user, $post );
   
       	$url =  ' '.preg_replace('/\?.*/', '', $this->curpageurl());
       	$url .= "?".$this->namespace."-action=sign&".$this->namespace."-uid=".$user->ID."&".$this->namespace."-token=".$token;
   
       if (get_post_meta($post->ID, $this->login_link_field_name, true )){
   
       $url = add_query_arg( $this->namespace.'-action', 'login', $url);
   
       $url = wp_logout_url( $url );
   
       }
   
       return $url;
   
       }
   
       private function send_email( $user, $post ) {
   
       $title = get_post_meta( $post->ID, $this->namespace."-email_title", true );
   
       $title = $this->personalise_message($title,$post,$user);
   
       $message = wpautop(do_shortcode(get_post_meta( $post->ID, $this->namespace."-email_message", true )));
   
       $message = apply_filters( 'lh_signing_email_message_filter', $message, $user, $post );
   
       $message = $this->personalise_message($message,$post,$user);
   
       $headers = array('Content-Type: text/html; charset=UTF-8');
   
       $headers = apply_filters( 'lh_signing_headers_filter', $headers, $user, $post );
   
       //default add_url is true
       $add_url = true;
       $add_url = apply_filters( 'lh_signing_add_url_filter', $add_url, $user, $post );
   
       if ($add_url){
   
       //ensure the email contains the signing url
       if (strpos($message, '%lh_signing_sign_url%') !== false) {
   
       $message = str_replace('%lh_signing_sign_url%', $this->return_signing_button($user, $post), $message);
   
       } else {
   
       $message .= $this->return_signing_button($user, $post);
   
       }
   
       }
   
       $message = $this->use_email_template( $message );
   
       wp_mail( $user->user_email, $title, $message, $headers);
   
       }
   
       private function handle_new_user( $email, $first_name, $last_name ) {
   
       global $wpdb;
   
       $random_password = wp_generate_password( $length=12, $include_standard_special_chars=false );
   
       $userdata = array(
           'user_login'  =>  $email,
           'user_email' => $email,
           'role' => 'unclaimed',
           'user_pass'   =>  $random_password
       );
   
       $user_id = wp_insert_user( $userdata ) ;
   
       $sql = "update ".$wpdb->users." set user_login = user_email where ID = '".$user_id."'";
   
       $result = $wpdb->get_results($sql);
   
       wp_update_user( array( 'ID' => $user_id, 'first_name' => $first_name, 'last_name' => $last_name, 'display_name' => $first_name." ".$last_name ));
   
       apply_filters( 'lh_signing_http_post_filter', $user_id);
   
       return $user_id;
   
       }
   
       private function format_results($post){
   
       if( is_wp_error( $GLOBALS[$this->namespace.'-insert_result']) ) {
   
       $error = $GLOBALS[$this->namespace.'-insert_result'];
   
       $message = '<p>There was an error</p><p><strong>'.$error->get_error_code() .'</strong>: '.$error->get_error_message() .'</p>';
   
       } else {
   
       $type = $this->get_connection_type_by_id($GLOBALS[$this->namespace.'-insert_result']);
   
       $from = $this->get_connection_from_by_id($GLOBALS[$this->namespace.'-insert_result']);
   
       $user = get_user_by( 'ID', $from);
   
       if ($type == "signing_sign_unconfirmed"){
   
       $message = get_post_meta( $post->ID, $this->namespace."-unconfirmed_message", true );
   
       } elseif ($type == "signing_sign_confirmed"){
   
       $message = get_post_meta( $post->ID, $this->namespace."-confirmed_message", true );
   
       } else {
   
       $message = "something went wrong";
   
       }
   
       $message = $this->personalise_message(wpautop(do_shortcode($message)),$post,$user);
   
       }
   
       return $message;
   
       }
   
       private function return_submit_text($post) {
   
       if (($submit_text = get_post_meta( $post->ID, $this->namespace."-submit_text", true )) == ""){
   
       $submit_text = "Add your Signature";
   
       }
   
       return $submit_text;
   
       }
   
       private function return_email_button_text($post) {
   
       if (($email_button_text = get_post_meta( $post->ID, $this->namespace."-email_button_text", true )) == ""){
   
       $email_button_text = "Sign me Up!";
   
       }
   
       return $email_button_text;
   
       }
   
       private function logged_out_form($atts, $post) {
   
       wp_enqueue_script('lh_signing-script', plugins_url( '/scripts/lh-signing.js' , __FILE__ ), array(), '1.0', true  );
   
       $content .= "\n<form name=\"lh_signing-form\" id=\"lh_signing-form\" action=\"".get_permalink($post)."\" method=\"post\" data-".$this->namespace."-nonce=\"".wp_create_nonce($this->namespace."-nonce")."\"  >";
   
       $content .= "\n<noscript>Please switch on Javascript to enable this registration</noscript>\n\n";
   
       $content .= "\n<p><input name=\"".$this->namespace."-first_name\" id=\"".$this->namespace."-first_name\" value=\"\" type=\"text\" placeholder=\"Your First Name\" required=\"required\" /></p>";
       $content .= "\n<p><input name=\"".$this->namespace."-last_name\" id=\"".$this->namespace."-last_name\" value=\"\" type=\"text\" placeholder=\"Your Second Name\" required=\"required\" /></p>";
       $content .= "\n<p><input name=\"".$this->namespace."-email\" id=\"".$this->namespace."-email\" value=\"\" type=\"email\" placeholder=\"Your Email\" required=\"required\" /></p>";
   
       $content = apply_filters( 'lh_signing_intermediate_logged_out_form_filter',$content, $atts, $post);
   
       //do_action( 'register_form' );
   
       $content .= "\n<input id=\"".$this->namespace."-nonce\" name=\"".$this->namespace."-nonce\" value=\"\" type=\"hidden\" />";
   
       $content .= "\n<p><input type=\"submit\" id=\"".$this->namespace."-submit\" name=\"".$this->namespace."-submit\" value=\"".$this->return_submit_text($post)."\"/></p>";
   
       $content .= "\n</form>";
   
       $content = apply_filters( 'lh_signing_final_logged_out_form_filter',$content, $atts, $post);
   
       return $content;
   
       }
   
       private function logged_in_form($atts, $post) {
   
       $user = wp_get_current_user();
   
       if (p2p_connection_exists( 'signing_sign_unconfirmed', array( 'from' => $user->ID, 'to' => $post->ID ) )){
   
       $content .= "\n<p>You have already registered but you have yet to confirm, please check your email to confirm your signature</p>";
   
       } elseif  (p2p_connection_exists( 'signing_sign_confirmed', array( 'from' => $user->ID, 'to' => $post->ID ) )){
   
       $content .= "\n<p>You have already added your signature</p>";
   
       } else {
   
       $content .= "\n<form name=\"lh_signing-form\" id=\"lh_signing-form\" action=\"".get_permalink($post)."\" method=\"post\" >";
   
       $content .= "\n<input id=\"".$this->namespace."-nonce\" name=\"".$this->namespace."-nonce\" value=\"".wp_create_nonce($this->namespace."-nonce")."\" type=\"hidden\" />";
   
       $content .= "\n<p><input type=\"submit\" id=\"".$this->namespace."-submit\" name=\"".$this->namespace."-submit\" value=\"".$this->return_submit_text($post)."\"/></p>";
   
       $content .= "\n</form>";
   
       }
   
       return $content;
   
       }
   
       private function action_signing( $user, $post, $type) {
   
       if (p2p_connection_exists( $type, array( 'from' => $user->ID, 'to' => $post->ID ) )){
   
       //the post already has this state
   
       $error = new WP_Error( 'error', __( "You already have this state on this ".$post->post_type, $this->namespace ) );
   
       return $error;
   
       } else {
   
       if ($result = p2p_type( $type )->connect( $user->ID, $post->ID, array(
           'date' => current_time('mysql')
       ) )){
   
       $array_to_remove = array($type);
   
       $states = array_diff($this->signing_states,$array_to_remove);
   
       foreach ($states as $state){
   
       $foo = p2p_type( $state )->disconnect( $user->ID, $post->ID );
   
       }
   
       if ($type == 'signing_sign_unconfirmed'){
   
       $this->send_email( $user, $post );
   
       }
   
       if ($type == 'signing_sign_confirmed'){
   
       $this->maybe_upgrade_user($user);
   
       }
   
       return $result;
   
       } else {
   
       $error = new WP_Error( 'error', __( "Something went wrong on this ".$post->post_type, $this->namespace ) );
   
       return $error;
   
       }
   
       }
   
       }
   
       private function validate_token($user,$post,$token) {
   
       if (($meta = get_user_meta($user->ID, $this->namespace."_".$post->ID."-confirmation_token", true)) != ""){
   
       $hash  = wp_hash($token);
   
       if ($meta == $hash){
   
       return true;
   
       } else {
   
       return false;
   
       }
   
       } else {
   
       return false;
   
       }
   
       }
   
       public function autologin_via_url(){
   
       if (($_GET[$this->namespace.'-action'] == "login") and ($user = get_user_by('ID', $_GET[$this->namespace.'-uid']))){
   
       $postdata = get_post(url_to_postid(strtok($this->curpageurl(), '?')));
   
       $token = $_GET[$this->namespace.'-token'];
   
       if ($this->validate_token($user,$postdata,$token)){
   
       wp_set_auth_cookie( $user->ID );
       do_action( 'wp_login', $user->user_login);
   
       } 
   
       wp_redirect( add_query_arg( $this->namespace.'-action', 'sign', $this->curpageurl() ) );
       exit;
   
       }
   
       }
   
       public function list_attached_users($id, $list, $fields)  {
   
       $users = get_users( array(
         'connected_type' => array($list),
         'connected_items' => get_queried_object_id(),
         'fields' => array($fields)
       ) );
   
       $return_string = "<ul>";
   
       foreach ( $users as $user ) { 
   
       $return_string .= '<li>'. $user->{'display_name'} .'</li>';
   
       }
   
       $return_string .= "</ul>";
   
       return $return_string;
   
       }
   
       public function count_attached_users($id, $list, $fields) {
   
       $users = get_users( array(
         'connected_type' => array($list),
         'connected_items' => get_queried_object_id(),
         'fields' => array($fields)
       ) );
   
       $user_count = 0;
   
       foreach ( $users as $user ) { 
   
       $user_count++;
   
       }
   
       $return_string = $user_count;
   
       return $return_string;
   
       }
   
       public function the_content_filter( $content ) {
   
       global $post;
   
       if (has_shortcode( $post->post_content, 'lh_signing_form' )){
   
       if ($GLOBALS[$this->namespace.'-insert_result']){
   
       $content = $this->format_results($post);
   
       } 
   
       }
   
       // Returns the content.
   
       return $content;
   
       }
   
       public function register_p2p_connection_types() {
   
       if ( current_user_can( 'edit_users' ) ) {
           /* A user with admin privileges */
       $admin_box = true;
   
       } else {
           /* A user without admin privileges */
       $admin_box = false;
       }
   
         p2p_register_connection_type( array(
       	'title' => 'Confirmed Signature',
               'name' => 'signing_sign_confirmed',
               'from' => 'user',
               'to' => $this->return_approved_posttypes(),
       'admin_column' => 'from',
               'admin_box' => $admin_box,
       'admin_dropdown' => 'from'
           ) );
   
         p2p_register_connection_type( array(
       	'title' => 'Unconfirmed Signature',
               'name' => 'signing_sign_unconfirmed',
               'from' => 'user',
               'to' => $this->return_approved_posttypes(),
       'admin_column' => 'from',
              'admin_box' => $admin_box,
       'admin_dropdown' => 'from'
           ) );
   
       }
   
       public function save_data(){
   
       if (!is_admin()){
   
       global $post;
   
       if (($_GET[$this->namespace.'-action'] == "sign") and ($user = get_user_by('ID', $_GET[$this->namespace.'-uid']))){
   
       $token = $_GET[$this->namespace.'-token'];
   
       if ($this->validate_token($user,$post,$token)){
   
       //hashes match so the documents can be signed
       $GLOBALS[$this->namespace.'-insert_result'] = $this->action_signing( $user, $post, 'signing_sign_confirmed');
   
       }
   
       } elseif ($_POST[$this->namespace.'-submit']) {
   
       if ( wp_verify_nonce( $_POST[$this->namespace.'-nonce'], $this->namespace.'-nonce') ) {
   
       if ( is_user_logged_in() ){
   
       $user = wp_get_current_user();
   
       $GLOBALS[$this->namespace.'-insert_result'] = $this->action_signing( $user, $post, 'signing_sign_confirmed');
   
       } else {
   
       $test = trim(sanitize_user($_POST[$this->namespace.'-email']));
   
       if (is_email($test) and ($this->domain_exists($test))){
   
       $email = trim(wp_filter_nohtml_kses($_POST[$this->namespace.'-email']));
   
       } else {
   
       $error = new WP_Error( 'error', __( "Invalid email", $this->namespace ) );
   
       }
   
       if ( isset( $_POST[$this->namespace.'-full_name'])){
   
       $full_name = sanitize_text_field($_POST[$this->namespace.'-full_name']);
   
       $pieces = explode(" ", $full_name);
   
       $first_name = $pieces[0];
   
       if ($pieces[1]){
   
       $last_name = $pieces[1];
   
       } else {
   
       $last_name = " ";
   
       }
   
       } elseif ( isset( $_POST[$this->namespace.'-first_name']) &&  isset( $_POST[$this->namespace.'-last_name']) ){
   
       $first_name = sanitize_text_field($_POST[$this->namespace.'-first_name']);
   
       $last_name = sanitize_text_field($_POST[$this->namespace.'-last_name']);
   
       } else {
   
       $error = new WP_Error( 'error', __( "Please add a first and last name", $this->namespace ) );
   
       }
   
       if( is_wp_error( $error) ) {
   
       $GLOBALS[$this->namespace.'-insert_result'] = $error;
   
       return $error;
   
       } else {
   
       $user = get_user_by( 'email', $email );
   
       if ($user){
   
       //Only send email etc if the user has not already signed
   
       if (!p2p_connection_exists( 'signing_sign_confirmed', array( 'from' => $user->ID, 'to' => $post->ID ) )){
   
       $GLOBALS[$this->namespace.'-insert_result'] = $this->action_signing( $user, $post, 'signing_sign_unconfirmed');
   
       }
       } else {
   
       $user_id = $this->handle_new_user( $email, $first_name, $last_name );
   
       $user = get_user_by( 'id', $user_id );
   
       $GLOBALS[$this->namespace.'-insert_result'] = $this->action_signing( $user, $post, 'signing_sign_unconfirmed');
   
       }
   
       }
   
       }
   
       }
   
       } elseif (($this->options[ $this->page_id_field ] == $post->ID) and is_user_logged_in() and $this->options[ $this->page_id_field ]){
   
       //They are registered, logged in and this si the registration page so redirect them to home
       wp_redirect( home_url() );
       exit;
   
       }
   
       }
   
       }
   
       public function add_unclaimed_role(){
   
       if (!get_role('unclaimed')){
               add_role('uncla
       ```
   
 *  Plugin Author [shawfactor](https://wordpress.org/support/users/shawfactor/)
 * (@shawfactor)
 * [9 years, 10 months ago](https://wordpress.org/support/topic/shortcodes-patch/#post-7517486)
 * Hey I am, not sure what happpened but instead of working out what I have missed
   I have added you as a contributor.
 * Pete
 *  Plugin Author [shawfactor](https://wordpress.org/support/users/shawfactor/)
 * (@shawfactor)
 * [9 years, 10 months ago](https://wordpress.org/support/topic/shortcodes-patch/#post-7517491)
 * For some reason the diff file doesn’t incorporate all changes buyt I have put
   them in manually in version 2.64

Viewing 5 replies - 1 through 5 (of 5 total)

The topic ‘Shortcodes patch’ is closed to new replies.

 * ![](https://s.w.org/plugins/geopattern-icon/lh-signing_928f98.svg)
 * [LH Signing](https://wordpress.org/plugins/lh-signing/)
 * [Frequently Asked Questions](https://wordpress.org/plugins/lh-signing/#faq)
 * [Support Threads](https://wordpress.org/support/plugin/lh-signing/)
 * [Active Topics](https://wordpress.org/support/plugin/lh-signing/active/)
 * [Unresolved Topics](https://wordpress.org/support/plugin/lh-signing/unresolved/)
 * [Reviews](https://wordpress.org/support/plugin/lh-signing/reviews/)

 * 5 replies
 * 2 participants
 * Last reply from: [shawfactor](https://wordpress.org/support/users/shawfactor/)
 * Last activity: [9 years, 10 months ago](https://wordpress.org/support/topic/shortcodes-patch/#post-7517491)
 * Status: resolved