Forum Replies Created

Viewing 10 replies - 1 through 10 (of 10 total)
  • Thread Starter Mr.Meerkat

    (@mrmeerkat)

    But I have become curious about the case that the admin is not to be trusted. If anyone knows of a detailed tutorial for this case, please let me know.

    Thread Starter Mr.Meerkat

    (@mrmeerkat)

    Many, many thanks to both of you for your answers. I will go with the options table, especially as no-one will have admin rights on the target systems but me.

    • This reply was modified 1 year ago by Mr.Meerkat.
    Forum: Plugins
    In reply to: [CMB2] Filter file types
    Thread Starter Mr.Meerkat

    (@mrmeerkat)

    Thank you for answering again. I understand that. It’s certainly not the most important feature. I also had no idea about the code of the media library so complex.

    Forum: Plugins
    In reply to: [CMB2] Filter file types
    Thread Starter Mr.Meerkat

    (@mrmeerkat)

    Thank you very much for answering. Yes, that was what I wanted to ask. I just wanted to make sure there is no easy solution. Maybe possible feature request for future versions of CMB2?

    Forum: Plugins
    In reply to: [CMB2] zip file upload
    Thread Starter Mr.Meerkat

    (@mrmeerkat)

    The Upload of zip-Files with CMB2 as suggested by Michael works fine. Thanks again! Just for the case someone likes to do the same:

    I found two solutions for the unzip problem.

    First solution: use the updated_post_meta action hook to unzip if the value and validate whenever zipfieldname_id changes (Note here that the _id suffix must be attached to the field name!)

    class Unzipper {
    
    	/**
    	 * Run all Hooks.
    	 *
    	 * @return void
    	 */
    	public function init() {
    		require_once ABSPATH . 'wp-admin/includes/file.php';
    		WP_Filesystem();
    		add_action( 'updated_post_meta', array( $this, 'unzip_and_validate' ), 10, 4 );
    	}
    
    	/**
    	 * Executed when a new zipfile is assigned to my_cpt
    	 * Unpacks the zip-file checks if its content meets the requirements.
    	 *
    	 * @param int    $meta_id ID of updated metadata entry.
    	 * @param int    $post_id ID of the object metadata is for.
    	 * @param string $meta_key Metadata key.
    	 * @param mixed  $meta_value Metadata value.
    	 *
    	 * @return void
    	 */
    	public function unzip_and_validate( $meta_id, $post_id, $meta_key, $meta_value ) {
    		if ( 'panorama_zip_id' !== $meta_key ) {
    			return;
    		}
    
    		write_log( "new panorama_zip_id: {$meta_value}" );
    
    		global $wp_filesystem;
    
    		$zip_file_path = get_attached_file( $meta_value );
    		$upload_array  = wp_upload_dir();
    		$upload_folder = $upload_array['basedir'];
    		$dest_folder   = "{$upload_folder}/my_plugin_folder/{$post_id}";
    
    		$wp_filesystem->delete( $dest_folder, true, 'd' );
    
    		wp_mkdir_p( $dest_folder );
    
    		unzip_file( $zip_file_path, $dest_folder );
    // validation
    ...

    2. Solution (More complicated but also more user friendly): Use a JS-Observer and Ajax. The advantage here is that we can give the user validation feedback as soon as he selects a new zip file.

    In your admin JavaScript file use an observer to run a function everytime the value of the hidden field zipfieldname_id (Again: Note the id suffix) changes. (A simple change event wont fire, if the value is not changed by the user but by WordPress scripts, so you have to use an observer here).

    The function called by the Observer will send an Ajax request, that sends the zipfile id. The invoked PHP-Funktion will find the zipfile by its id and unzips it, validates the unzipped folder and sends a validation message or code in response.

    Use this response in JavaScript to add a validation message to output a validation feedback to the admin page.

    If your validation prosses works fine, you can prevent the zip file to be unziped and validated more the one time, by storing a validation code in the meta table after validation and check if such a code is stored in the meta table, before you unzip and validat it.

    Admittedly: quite elaborate, but as user friendly as possible.

    Here is my JS-Code

    jQuery( function( $ ) {
    
    	if ( $( 'body.post-type-tree_panorama' ).length ) {
    
    		const url = zipAjaxObject.ajaxURL;
    		const data = {};
    		data.action = 'zip-validation';
    		data.nonce = zipAjaxObject.nonce;
    
    		// Observe if the zip file is changing
    
    		const hiddenZip         = document.getElementById( 'panorama_zip_id' );
    		const validationMessage = $( 'div.cmb2-id-panorama-zip div.validation' );
    
    		function ajaxValidationRequest() {
    			let zipId = hiddenZip.getAttribute( 'value' );
    			data.zipId = zipId;
    
    			$.ajax({
    				url: url,
    				type: 'post',
    				data: data,
    				success( response ) {
    					response = JSON.parse( response );
    					console.log( response.notice );
    
    					validationMessage.html( response.notice );
    				}
    			});
    		}
    
    		ajaxValidationRequest();
    
    		const mutationCallback = ( mutationsList ) => {
    			for ( const mutation of mutationsList ) {
    
    				if ( 'attributes' === mutation.type	&& 'value' === mutation.attributeName ) {
    					ajaxValidationRequest();
    				}
    			}
    		};
    
    		const observer = new MutationObserver( mutationCallback );
    
    		observer.observe( hiddenZip, { attributes: true });
    
    	}
    });
    

    And some of my php code:

    <?php
    /**
     * Ajax-Resopnse on panorama_zip_id change.
     *
     * @link       https://digidrom.de
     * @since      1.0.0
     *
     * @package    digipano
     * @subpackage digipano/includes
     */
    
    namespace digidrom\digipano;
    
    use digidrom\digipano\ZipError;
    
    /**
     * Handels Ajax requests that is send when ever the panorama_zip_id of a panoaram_tree changes.
     *
     * @package    Digipano
     * @author     Jan Tack <[email protected]>
     */
    class ZipAjax {
    
    	/**
    	 * Run all Hooks.
    	 *
    	 * @return void
    	 */
    	public function init() {
    		add_action( 'admin_enqueue_scripts', array( $this, 'load' ) );
    		add_action( 'wp_ajax_zip-validation', array( $this, 'response_ajax' ) );
    	}
    
    	/**
    	 * The user should get an instant feedback when selecting a zip file for a tree-panoram,
    	 * even before adas post form is submitted.
    	 *
    	 * Therefore this function is called via Ajax whenever the user selects a new zip file.
    	 * The zip file is then unpacked and validated. The response to the Ajax request then contains
    	 * a div container with a matching success or error message.
    	 *
    	 * @return void
    	 */
    	public function response_ajax() {
    		// phpcs:ignore
    		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'ajax-nonce' ) ) {
    			die( 'YOU SHALL NOT PASS!' );
    		}
    
    		if ( isset( $_POST['zipId'] ) ) {
    			$zip_id = sanitize_text_field( wp_unslash( $_POST['zipId'] ) );
    
    			// $note = get_post_meta( $zip_id, 'zip-validation', true );
    
    			$note = '';
    			if ( '' === $note ) {
    
    				$note = $this->unzip_and_validate( $zip_id );
    
    				if ( 'allright' === $note ) {
    					$upload_array  = wp_upload_dir();
    					$upload_folder = $upload_array['basedir'];
    					$source_dir    = "{$upload_folder}/unzip/{$zip_id}/";
    
    				}
    
    				update_post_meta( $zip_id, 'zip-validation', $note );
    			}
    
    			$response = array(
    				'zipId'  => $zip_id,
    				'note'   => $note,
    				'notice' => ZipError::get_notice( $note ),
    			);
    
    			echo wp_json_encode( $response );
    		}
    
    		die();
    	}
    
    	/**
    	 * Enqueue script and inject data
    	 *
    	 * @return void
    	 */
    	public function load() {
    		wp_enqueue_script( 'zip-script', plugins_url( '/js/zipvalidation.js', DIGIPANO_FILE ), array( 'jquery' ), '1.0.0', true );
    
    		$zip_ajax_object = array(
    			'ajaxURL' => admin_url( 'admin-ajax.php' ),
    			'nonce'   => wp_create_nonce( 'ajax-nonce' ),
    		);
    
    		wp_localize_script( 'zip-script', 'zipAjaxObject', $zip_ajax_object );
    	}
    
    	/**
    	 * Unzip and validate
    	 *
    	 * @param int $zip_id The id of the zip file.
    	 *
    	 * @return ZipError
    	 */
    	private function unzip_and_validate( $zip_id ) {
    		global $wp_filesystem;
    
    		$upload_array  = wp_upload_dir();
    		$upload_folder = $upload_array['basedir'];
    		$dest_folder   = "{$upload_folder}/unzip/{$zip_id}/";
    
    		if ( $wp_filesystem->exists( $dest_folder ) ) {
    			$wp_filesystem->delete( $dest_folder, true, 'd' );
    		}
    		wp_mkdir_p( $dest_folder );
    
    		$zip_file = get_attached_file( $zip_id );
    		unzip_file( $zip_file, $dest_folder );
    
    		require_once __DIR__ . '/class-unzipvalidator.php';
    
    		$validator = new UnzipValidator( $dest_folder );
    		return $validator->validate_and_sanitize();
    	}
    }
    

    Thread Starter Mr.Meerkat

    (@mrmeerkat)

    Thanks!

    Probably a bit naive to think that this callback magic that works for some fields also works for attributes as well.

    I finally found a solution by passing the options as a javaScript-Object and then using jQuery to set the attribute to the appropriate value. J ust for the case it helps someone else:

    PHP:

    Enqueue a custom admin script and transmitting the options as a JS-Object via wp_localize_script :

    class MyClass {
    
    public function init() {
      add_action(
        'admin_enqueue_scripts',
        array( $this, 'enqueue_admin' ) );
    }
    
    
    public function enqueue_admin() {
      wp_enqueue_script( 
        'my-admin-script',
        plugins_url( '/js/admin.js', MY_PLUGIN_FILE ), 
        array( 'jquery' ), 
        '1.0.0',
        true );
    
      $my_object = array(
         ... 
         'options' => get_option( 'my-settings' ),
      );
    
      wp_localize_script( 
         'my-admin-script', 
         'myObject', 
         $my_object 
      );
    
      ...
    }
    ...
    }
    
    ( new MyClass() )->init();

    JS: (plugindir/js/admin.js)

    jQuery( function( $ ) {
       if ( $( 'body.post-my-post-type' ).length ) {
    	let numbering = myObject.options.numbering;
    	let input = $( 'input#my_cmb2_id' );
    
    	if ( 'numeric' === numbering ) {
    	  input.attr( 'pattern', '[1-9][0-9]*' );
    	}
    
    	if ( 'alphanumeric' === numbering ) {
    	  input.attr( 'pattern', '[A-Z]{1}[1-9][0-9]*');
    	}
       }
    });
    
    • This reply was modified 1 year, 6 months ago by Mr.Meerkat.
    Forum: Plugins
    In reply to: [CMB2] zip file upload
    Thread Starter Mr.Meerkat

    (@mrmeerkat)

    Thanks!

    Forum: Plugins
    In reply to: [CMB2] zip file upload
    Thread Starter Mr.Meerkat

    (@mrmeerkat)

    Thanks for the answer. I didn’t think that would work for zip files. Is there a way to register a callback that is called when the upload is complete?

    Thread Starter Mr.Meerkat

    (@mrmeerkat)

    Thank you for the reply and sorry to bother you again.

    aria-hidden=”false” really seems to be a bad idea. But are you sure you want to remove the validation messages from the access tree. They might contain useful information, don’t they?

    Thread Starter Mr.Meerkat

    (@mrmeerkat)

    Thanks for your fast reply. I already removed your plugin from my site and replaced it with another one. But I will change the rating.

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