• Hi,

    I have a vexing problem I cannot seem to resolve. I created a plugin that allows a musician who has purchased embed slots to post their videos.

    System:
    Server: Apache
    PHP: 7.1.20 (The latest version available on the server)

    WordPress: 4.9.7
    WooCommerce: 3.4.3
    BuddyPress: 3.1.0

    I created a plugin, “WC Pay To Embed”, that integrates with WooCommerce and BuddyPress. When logged in as a member, a musician can purchase a video slot package. Once purchased, the musician is then able to click on ‘Account’ which takes that person to the Order page. From there, the member clicks the “View Order” button, which takes the member to the ‘view-order’ WooCommerce endpoint. It is in this endpoint where the embed slot form is displayed.

    The embed form includes fields for the video name, the embed URL, and some other information.

    I have tried several ways to get this to work, but have had no success. Some of the things I tried:
    — Set form action to an external file with the create_post() function, which included the wp_insert_post() method
    — Set form action to call the create_post() function from within the plugin’s class-wc-pay-to-embed.php file
    — Removed action from form to self-call the function.

    I spent hours looking through documentation and research, but found nothing helpful. The rudimentary examples I found involved a simple PHP form with an external file called for automated post creation.

    Here is the class-wc-pay-to-embed.php file code:

    
    <?php
    /**
     * WC_Pay_To_Embed class.
     * 
     * @extends Airy_Framework
     */
    
    class WC_Pay_To_Embed extends Airy_Framework {
    	/**
    	 * __construct function.
    	 * 
    	 * @access public
    	 * @return void
    	 */
    
    	// fields in the constructor are for PTE settings in WP-Admin for users with the Administrator role
    	function __construct() {
    		
    		//Pay To Embed Variables
    		$this->shortname = 'wc_pay_to_embed';
    		$this->plugin_name = __('WC Pay to embed', 'wc_pay_to_embed' );
    		$this->desc = __('Let WooCommerce customers pay to embed files when purchasing specific products.', 'wc_pay_to_embed' );
    		$this->version = '1.0.0';
    		$this->menu_location = 'woocommerce';
    		// $embeds = wp_embed_dir();
    		$this->defaultLimit = (get_option('wc_pte_default_limit') ? get_option('wc_pte_default_limit') : 1);
    		$this->defaultStatus = (get_option('wc_pte_order_statuses') ? get_option('wc_pte_order_statuses') : 'wc-completed');
    
    		// Pay To Embed fields
    		$this->fields = array(
    			array(
    				'name'		=> 'wc_pte_default_limit',
    				'title'		=> __( 'Default Embed Limit', 'wc_pay_to_embed' ),
    				'type'		=> 'text',
    				'desc'		=> __( 'Default embed limit when activating feature for products.', 'wc_pay_to_embed' ),
    				'default'	=> $this->defaultLimit,
    			),
    		);
    		
    		add_action( 'add_meta_boxes', array( &$this, 'add_meta_boxes' ) );
    		add_action( 'woocommerce_init', array( &$this, 'woocommerce_init' ) );
    		add_action( 'save_post', array( &$this, 'save_meta_box' ) );
    		add_action( 'woocommerce_view_order', array( &$this, 'embedder' ) );
    	}
    	
    	/**
    	 * add_meta_boxes function.
    	 * 
    	 * @access public
    	 * @return void
    	 */
    	function add_meta_boxes() {
    		add_meta_box( 'wc_pte_enable', __( 'WC Pay to embed', 'wc_pay_to_embed' ), array( &$this, 'product_embed_options'), 'product', 'side' );
    		add_meta_box( 'wc_pte_files', __( 'Embedded Files', 'wc_pay_to_embed' ), array( &$this, 'order_embedded_files'), 'shop_order', 'side' );
    	}
    	
    	/**
    	 * woocommerce_init function.
    	 * 
    	 * @access public
    	 * @return void
    	 */
    	function woocommerce_init() {
    			
    		$order_status = wc_get_order_statuses();
    
    		$statuses = $order_status;
    
    		$values = array();
    
    		foreach( $statuses as $status => $key ) {
    
    			$values[ $status ] = $key;
    
    		}
    
    		$this->fields[] = array(
    			'name'		=> 'wc_pte_order_statuses',
    			'title'		=> __('Required Status(es)', 'wc_pay_to_embed' ),
    			'type'		=> 'select',
    			'desc'		=> __('The required order status to allow customers to embed files.', 'wc_pay_to_embed' ),
    			'values'	=> $values,
    			'default'	=> $this->defaultStatus,
    		);
    		parent::__construct();
    	}
    	
    	/**
    	 * order_embedded_files function.
    	 * 
    	 * @access public
    	 * @param mixed $post
    	 * @return void
    	 */
    	function order_embedded_files( $post ) {
    		$order = new WC_Order( $post->ID );
    		
    		$items = $order->get_items();
    		$limit = $this->check_for_embeddables( $post->ID );
    		echo '<table style="border-collapse:collapse;" border="1" cellpadding="5" cellspacing="0">';
    		foreach( $items as $item ) {
    						echo '<tr><th colspan="3">embedded Files for '.$item['name'].'</th></tr>';
    								echo '<tr><th>S.No.</th><th>File Name</th><th>Extra Info</th></tr>';
    
    				$limit = (int) get_post_meta( $item['product_id'], '_wc_pte_limit', true ); //Changed $item['item_id'] to $item['product_id'] for wordpress version 3.5.1 Ashok G
    				if( get_post_meta( $item['product_id'], '_wc_pte_enable', true ) == 1 && $limit > 0 ) {
    					$limits = $limit;
    				}
    		for ($i = 1; $i <= $limit; $i++) {
    			$item_id = $item['product_id'].$i;
    			$url =  get_post_meta( $post->ID, '_wc_embedded_file_path_' . $item_id, true );
    			$name = get_post_meta( $post->ID, '_wc_embedded_file_name_' . $item_id, true );
    			$ef = get_post_meta( $post->ID, '_wc_embedded_file_name_extra_info_' . $item_id, true );
    			if( !empty( $url ) && !empty( $name ) ) {
    				printf( __('<tr><td>%s</td><td> <a href="%s" target="_blank">%s</a></td><td>%s</td></tr>', 'wc_pay_to_embed'),$i,  $url, $name,$ef);
    			} else {
    				printf( __('<tr><td> %s</td><td> has not been embedded.</td><td></td></tr>', 'wc_pay_to_embed'), $i );
    			}
    			
    		}
    	}
    	echo '</table>';
    	}
    	
    	/**
    	 * product_embed_options function.
    	 * 
    	 * @access public
    	 * @param mixed $post
    	 * @return void
    	 */
    	function product_embed_options( $post ) {
    		wp_nonce_field( 'wc_pte_nonce', 'wc_pte_nonce' );
    		echo '<p>';
    			echo '<label for="_wc_pte_enable" style="float:left; width:50px;">' . __('Enable', 'wc_pay_to_embed' ) . '</label>';
    			echo '<input type="hidden" name="_wc_pte_enable" value="0" />';
    			/* Individual product checks Auto enable primarily. */ 
    			$upStats = get_post_meta( $post->ID, '_wc_pte_enable', true );
    			if($upStats !=0 || $upStats =='' || $upStats == Null) { $chked = 'checked="true"'; }			
    			echo '<input type="checkbox" id="_wc_pte_enable" '.$chked.' class="checkbox" name="_wc_pte_enable" value="1" ' . checked( get_post_meta( $post->ID, '_wc_pte_enable', true ), 1, false ) . ' />';
    		echo '</p>';
    		echo '<p>';
    			$value = get_post_meta( $post->ID, '_wc_pte_limit', true );
    			$value = ( !empty( $value ) ) ? $value : $this->defaultLimit;
    			echo '<label for="_wc_pte_limit" style="float:left; width:50px;">' . __('Limit', 'wc_pay_to_embed' ) . '</label>';
    			echo '<input type="text" id="_wc_pte_limit" class="short" name="_wc_pte_limit" value="' . $value . '" />';
    		echo '</p>';
    	}
    	
    	/**
    	 * save_meta_box function.
    	 * 
    	 * @access public
    	 * @param mixed $post_id
    	 * @return void
    	 */
    	function save_meta_box( $post_id ) {
    		if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
    		if ( !isset( $_POST['wc_pte_nonce'] ) || !wp_verify_nonce( $_POST['wc_pte_nonce'], 'wc_pte_nonce' ) ) return;
    		update_post_meta( $post_id, '_wc_pte_enable', (int) $_POST['_wc_pte_enable'] );
    		update_post_meta( $post_id, '_wc_pte_limit', (int) $_POST['_wc_pte_limit'] );		
    	}
    	
    	/**
    	 * check_for_embeddables function.
    	 * 
    	 * @access public
    	 * @param mixed $order_id
    	 * @return void
    	 */
    	function check_for_embeddables( $order_id ) {
    	//Changed the Previous parameters to existing parameters for wordpress Version 3.5.1 Ashok G
    	global $woocommerce;
    	$order = new WC_Order( $order_id );
    	$items = get_post_meta( $order_id ,'_order_items', true);
    	$new_items = $order->get_items();
    		
    
    $limits = 0;		
    		if( is_array( $new_items ) ) {
    			foreach( $new_items as $item ) {
    				$limit = (int) get_post_meta( $item['product_id'], '_wc_pte_limit', true ); //Changed $item['item_id'] to $item['product_id'] for wordpress version 3.5.1 Ashok G
    				if( get_post_meta( $item['product_id'], '_wc_pte_enable', true ) == 1 && $limit > 0 ) {
    					$limits += $limit;
    				}
    			}
    		} else {
    			echo wpautop( __( 'Sorry, no files have been embedded yet.', 'wc_pay_to_embed' ) );
    			
    		}
    		return $limits;
    		
    	}
    	
    	/**
    	 * Embedder function.
    	 * 
    	 * @access public
    	 * @param mixed $order_id
    	 * @return void
    	 */
    	function embedder( $order_id ) {
    		$x = new WC_Order( $order_id );
    
    		// Assign variable for compatibility with WooCommerce 3.0+
    		$norder = wc_get_order( $order_id );
    
    		if(isset($_GET['delete']) && isset($_GET['item']))
    		{
    			echo $this->delete_file($order_id,$_GET['item']);
    			
    			
    		}
    		if(!defined("PHP_EOL")){define("PHP_EOL", strtoupper(substr(PHP_OS,0,3) == "WIN") ? "\r\n" : "\n");}
    		$order = new WC_Order( $order_id );
    		 $items = $order->get_items();
    		$limits = $this->check_for_embeddables( $order_id );
    		
    		
     	 	$admin_email = get_option('admin_email'); 
    		echo '<h2>' . __( 'Embed Files', 'wc_pay_to_embed' ) . '</h2>';
    		global $current_user;
         	 wp_get_current_user();
    		 $from =  $current_user->user_email;
    		 $to = $admin_email;
    		if( isset( $_FILES ) ) {
    			$path = trailingslashit( trailingslashit( $this->defaultPath ) . $order_id );
    			foreach( $_FILES as $key => $file ) {
    				if( empty( $file['name'] ) ) continue;
    				wp_mkdir_p( $path );
    				$filepath = $path . $file['name'];
    				$ext = strtolower( pathinfo( $filepath, PATHINFO_EXTENSION ) );
    				$types = explode( ',', $this->defaultFileTypes );
    				foreach( $types as $k => $v ) { $types[$k] = strtolower( trim( $v ) ); }
    				switch( $this->defaultListType ) {
    					case 'all':
    						$allow = true;
    						break;
    					case 'white':
    						if( in_array( $ext, $types ) ) $allow = true;
    						else $allow = false;
    						break;
    					case 'black':
    						if( in_array( $ext, $types ) ) $allow = false;
    						else $allow = true;
    						break;
    				}
    				if( $allow == true ) {
    					$headers = '';
    					$dburl = $this->fileurl.'/'.$order_id.'/'.$file['name'];
    					if( copy( $file['tmp_name'], $filepath ) ) {
    						
    						$subject = 'File Embed Notification OrderId - '.$order_id;
    						$message = "Dear Admin, <br><br>User Has embedded files for order - ".$order_id."<br><br> Please logon to your Admin Panel to review the files.";
    						$headers .= 'From:'. $from.PHP_EOL;
    						$headers .= 'Content-type: text/html; charset=iso-8859-1'.PHP_EOL;
    						if (wp_mail( $to, $subject, $message, $headers ))
    						{
    						echo '<p class="success">' . __( 'Your file(s) were embedded successfully.', 'wc_pay_to_embed') . '</p>';
    							//echo 'Mail Success';
    						}
    						else
    						{
    							//echo 'Mail Error';
    						}
    						
    						update_post_meta( $order_id, '_wc_embedded_file_name_' . $key, $file['name'] );
    						update_post_meta( $order_id, '_wc_embedded_file_path_' . $key, $dburl );
    						update_post_meta( $order_id, '_wc_embedded_file_name_extra_info_' . $key, sanitize_text_field($_POST['wc_embed_extra_info_'.$key]) );
    					} else {
    						echo '<p class="error">' . __( 'There was an error in embedding your file(s).', 'wc_pay_to_embed') . '</p>';
    					}
    				} else {
    					echo '<p class="error">' . sprintf( __( 'The %s filetype is not allowed.', 'wc_pay_to_embed'), $ext ) . '</p>';
    				}
    			}
    		}
    		
    		// may not need one or more oof these
    		$max_embed = (int)(ini_get('embed_max_filesize'));
    		$max_post = (int)(ini_get('post_max_size'));
    		$memory_limit = (int)(ini_get('memory_limit'));
    		$embed_mb = min($max_embed, $max_post, $memory_limit);
    
    		/** 
    		 * Customer purchase form
    		 *
    		 */
    
    		?>
    		
    		<form enctype="multipart/form-data" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>" method="POST">';
    
    		<?php
    
    			if ($_GET['twms_create_post']) {twms_create_post();}
    			$embed = false;
    			if( is_array( $items ) ) {
    			foreach( $items as $item ) {
    				/* Individual product checks,whether item is enabled for embed. */
    				if(get_post_meta( $item['product_id'], '_wc_pte_enable', true ) == 1)
    				{
    				echo '<h3> embed Files for '.$item['name'].'</h3>';
    				$limit = (int) get_post_meta( $item['product_id'], '_wc_pte_limit', true ); //Changed $item['item_id'] to $item['product_id'] for wordpress version 3.5.1 
    				if( get_post_meta( $item['product_id'], '_wc_pte_enable', true ) == 1 && $limit > 0 ) {
    					$limits = $limit;
    				}
    			echo '<table border="1" style="border-collapse:collapse;" cellpadding="5"><tr><th>Video Embed Slot</th><th>Video Name</th><th>Your Username</th><th>Embed Video URL</th><th>Music Genre</th><th>Save Video</th><th>Video Status</th><th>Published Date and Time</th><tr>';	
    			for ($i = 1; $i <= $limits; $i++) {
    				echo '<tr><td>';
    				$item_id = $item['product_id'].$i;
    				$embedded_video_name = get_post_meta( $order_id, '_wc_embedded_video_name', true );  
    				$member_name = get_post_meta( $order_id, '_wc_embedded_member_name', true ); 
    				$embedded_video_url = get_post_meta( $order_id, '_wc_embedded_video_url', true ); 
    				$video_content = 'content';
    				echo '<label for="' . $i . '">Slot #' . $i . ': </label></td>'; // numbers each purchased video embed slot
    				// $file_name_append = $item['product_id'].$i; // appends product id and video slot number to file name (may not need this)
    		
    				$current_date_time = date('F j, Y, g:i a');
    
    				
    				$embedded_video_name = get_post_meta( $order_id, '_wc_embedded_video_name', true );
    				if( empty( $embedded_video_name ) ) {
    					?>
    					<td><input type="text" name="_wc_embedded_video_name" value="<?php echo $name; ?>"></td>
    				<?php
    				}
    				
    				$embed = true;
    				// } else {
    				// 	echo '<td><input type="text" name="_wc_embedded_video_name" value=' . '"<?php if (isset($_POST['_wc_embedded_video_name'])) { echo $_POST['_wc_embedded_video_name']}
    				// 	</td>';
    				// }
    
    				$member_name = get_post_meta( $order_id, '_wc_embedded_member_name', true );
    				if( empty( $member_name ) ) {
    					echo '<td><input type="text" name="_wc_embedded_member_name"/></td>';
    					$embed = true;
    				} 
    				else {	
    					?>
    						<td><input type="text" name="_wc_embedded_video_name" value="<?php echo $_POST['_wc_embedded_member_name']; ?>" /></td>
    					<?php
    				}
    
    				/* Maybe add member ID as hidden input? */
    				// $member_id = get_post_meta( $order_id, '_wc_embedded_member_id', true );
    				// if( empty( $member_id) ) {
    				// 	echo '<td><input type="text" name="_wc_embedded_member_id"/></td>';
    				// 	$embed = true;
    				// } else {
    				// 	echo '<td>'.$this->file_type_icons($url_embed,$order_id,$name,$item_id_embed,$norder->get_status()).'</td>';
    				// }
    
    				$embedded_video_url = get_post_meta( $order_id, '_wc_embedded_video_url', true );
    				if( empty( $embedded_video_url ) ) {
    					echo '<td><input type="text" name="_wc_embedded_video_url" /></td>';
    					$embed = true;
    				} 
    				else {	
    					?>
    						<td><input type="text" name="_wc_embedded_video_name" value="<?php echo $_POST['_wc_embedded_video_url']; ?>" /></td>
    					<?php
    				}
    
    				$embedded_video_genre = get_post_meta( $order_id, '', true );
    				if( empty( $embedded_video_url ) ) {
    					echo '<td><select name="_wc_embedded_video_genre">';
    					echo '<option value="1" selected disabled>Choose Music Genre</option>';
    					echo '<option value="2">Classical</option>';
    					echo '<option value="3">Country</option>';
    					echo '<option value="4">Gospel</option>';
    					echo '<option value="5">Pop</option>';
    					echo '<option value="6">Rap/Soul/R&B</option>';
    					echo '<option value="7">Rock</option>';
    					echo '<option value="8">Somethin\' Else</option>';
    					echo '</select></td>';
    					$embed = true;
    				} 
    				else {	
    					?>
    						<td><input type="text" name="_wc_embedded_video_name" value="<?php echo $_POST['_wc_embedded_video_genre']; ?>" /></td>
    					<?php
    				}
    
    				$embedded_video_post_type = 'post';
    
    				// use $save_video to create a post from the information in this form. May need to use JavaScript to trigger the twms_create_post function
    				$save_embedded_video = get_post_status( $order_id, '_wc_embedded_video_save', true );
    				echo '<td><input type="submit" class="twms-input" name="_wc_embedded_video_save" value="Save Video"></td>';
    
    				$publish_status = get_post_status( $order_id, '', true );
    					echo '<td>' . $publish_status . '</td>';
    
    				$published_date_time = get_post_meta( $order_id, '', true );
    					echo '<td>';
    					echo $current_date_time;
    					echo '</td></tr>';
    
    			}
    			}
    			}
    		}
    			/**
    			 * Need to figure out a way to: 
    			 * -- Programmatically create a post for every embedded video
    			 * -- organize it by username and music video name
    			 * -- make post name the same as video name
    			 * -- make author the same as userame
    			 *
    			 */
    
    			if ( $this->defaultStatus == 'wc-processing' ) {
    
    				$this->defaultStatus = 'processing';
    
    			}
    			if ( $this->defaultStatus == 'wc-completed' ) {
    				$this->defaultStatus = 'completed';
    			}
    
    			if( $embed && $norder->get_status() == $this->defaultStatus) {
    
    				echo '<tr><td colspan="3"><input type="submit" class="button" value="' . __( 'embed', 'wc_pay_to_embed' ) . '" /><tr/>';
    			}
    			else
    			{
    				echo $embed;
    				
    				echo '<p>' . sprintf( __( 'The order status has been changed so you cannot embed files. Please contact Site Admin.', 'wc_pay_to_embed' )). ' </p>';
    			}
    		echo '</form>';
    
    		function twms_create_post() {
    
    			global $user_ID;
    
    			$new_post = array(
    
    				'post_title'    => $embedded_video_name,
    				'post_content'  => $video_content,
    				'post_status'   => $publish_status,
    				'post_date'     => $published_date_time,
    				'post_author'   => $user_ID,
    				'post_type'     => $embedded_video_post_type,
    				'post_category' => array( $embedded_video_genre )
    			);
    
    		}
    
    		$post_id = wp_insert_post( $new_post );
    
    	
    }
    }
    
    

    Also, I cannot for the life of me to get the input field data to persist. When I click on ‘Save Video’, the fields go blank and nothing is stored, even thought I am echoing the input value.

    Any help would be greatly appreciated!

    Thanks in advance:)

    The page I need help with: [log in to see the link]

Viewing 2 replies - 1 through 2 (of 2 total)
  • Moderator bcworkz

    (@bcworkz)

    Posting forms to external files to handle the data is the usual process, or posting to the form’s own file. Neither of these are ideal in the WP environment. In any case, aren’t these “forms” not really forms, but meta boxes? As meta boxes, they contain form fields, but the form being submitted is the one for the entire edit screen. You cannot specify where the form submits to.

    I see how you are saving meta box data for the wc_pte_enable meta box. I don’t see any fields or code to save fields for wc_pte_files meta box. You posted a lot of code, I may have missed something. This appears to be why you are not saving data.

    To do anything from a meta box, such as creating another post, you need to hook into an action that fires when the form containing the meta box is submitted, such as “save_post” action. Just like you can save meta data in such a callback, you can create posts. The one thing to watch out for is it is not guaranteed that any action will only fire once per request. When updating data, there is little downside if the same thing is saved 2 or 3 times. Not so if creating posts. You need to take measures to ensure your callback only inserts a post the first time through, not every time. Also, creating posts from the “save_post” action will result in an infinite loop unless measures are taken. One way to do this is have your callback remove itself from the action stack before adding the post. (use remove_action())

    Next time you need to post a large amount of code, please use Pastebin or make a Gist, they make code much easier to read. Especially if you enable syntax highlighting. Do ```php in Gist, pick the language when saving in pastebin. Posting large amounts of code is against our Forum Guidelines.

    Thread Starter bfrancoeur

    (@bfrancoeur)

    Hi @bcworkz,

    Thank you for your response. This morning, I created a simplified version of what I am trying to do. Here’s the Pastebin link: https://pastebin.com/Cr0U8cbC.

    I am working with the suggestions you provided and will update this post with the results.

    Thanks!

Viewing 2 replies - 1 through 2 (of 2 total)
  • The topic ‘Programmatic Creation of Custom Post Type’ is closed to new replies.