Viewing 9 reply threads
  • Author
    Posts
    • #7495
      Mehdi Salem
      Member

      Hello folks,

      I’m experiencing the following issue with a field group meta box containing a file upload field (Piklist v 0.9.9.9):
      The first time I save the post, every thing goes well and data is saved correctly in the database. If I update the post without doing any modifications, no problem. HOWEVER if I add an additional photo after the post has been saved once, the postmeta gets corrupted and thus, all the meta box data disappears from the post…

      – Here is how looks the postmeta after first save:
      a:2:{s:12:”folder_title”;s:10:”test title”;s:12:”single_photo”;a:2:{i:0;s:4:”1306″;i:1;s:4:”1305″;}}

      – And here is how it gets corrupted after adding one file and second save:
      a:2:{i:0;s:10:”test title”;i:1;a:3:{i:0;s:4:”1306″;i:1;s:4:”1305″;i:2;s:4:”1296″;}}

      Did not have time to debug so not sure if it is a JS or a PHP issue.

      Could you have a quick look at this guys and fix? I need to get my client’s site up asap…

      Many thanks in advance!

      Her is the meta box code:

      piklist('field', array(
          'type' => 'group'
      ,'field' => 'folder_content_group'
      ,'label' => __('Gallery Photo','stopping-the-world-admin')
      ,'description' => __('Add photos to this folder.', 'stopping-the-world-admin')
      ,'help' => __('Adds a new photo to this gallery folder and sets its availability on the store.','stopping-the-world-admin')
      ,'fields' => array(
              array(
                  'type' => 'text'
              ,'field' => 'folder_title'
              ,'label' => __('Title','stopping-the-world-admin')
              ,'required' => true
              ,'columns' => 12
              )
              ,array(
                  'type' => 'file'
              ,'field' => 'single_photo'
              ,'label' => __('Photo','stopping-the-world-admin')
              ,'options' => array(
                  'modal_title' => __('Add photo','stopping-the-world-admin')
              ,'button' => __('Add','stopping-the-world-admin')
              )
              ,'required' => true
              ,'columns' => 12
              ,'validate' => array(
              array(
                      'type' => 'jpeg'
                  )
              ,array(
                      'type' => 'gallery_photo'
                  )
              )
              )
          )
      ));
    • #7497
      Mehdi Salem
      Member

      Here is something weird worth noticing:
      I’m hooking into the update_post_metadata filter to correct the issue on the fly. I tested trying to grab what’s in the $prev_value variable and guess what, IT IS ALWAYS EMPTY… even if a previous value for the postmeta was already set

    • #7498
      Mehdi Salem
      Member

      Here is a temporary ugly fix I made in case somebody needs it while you guys are hopefully trying to fix this in core:

      Replace of course the value of the MY_CORRUPTED_METADATA_META constant according to your fields

      if( ! function_exists( 'hdev_filter_piklist_corrupted_metadata' ) )
      {
         /**
          * Define field group fields constant and apply filter
          */
         function hdev_filter_piklist_corrupted_metadata()
         {
            // Define all the meta keys we want to process here as an array constant [string META_KEY => array FIELDS] (make sure to include all the groups fields in the right order)
            define( 'MY_CORRUPTED_METADATA_META', array( 'folder_content_group' => array( 'folder_title', 'single_photo' ) ) );
      
            // Hook filter
            add_filter( 'update_post_metadata', 'hdev_overwrite_piklist_corrupted_metabox_fields', 10, 5 );
         }
      }
      add_action( 'init', 'hdev_filter_piklist_corrupted_metadata' );
      
      if( ! function_exists( 'hdev_overwrite_piklist_corrupted_metabox_fields' ) )
      {
         /**
          * Overwrite Piklist corrupted post metadata with correct value before it is added to the database
          *
          * @param $null
          * @param $object_id
          * @param $meta_key
          * @param $meta_value
          * @param $prev_value
          * @return bool|null
          */
         function hdev_overwrite_piklist_corrupted_metabox_fields( $null, $object_id, $meta_key, $meta_value, $prev_value ) {
      
            // Loop through meta keys associated with potential corruptible metadata
            foreach( MY_CORRUPTED_METADATA_META as $corrupted_meta_key => $corrupted_metadata_fields )
            {
               // Possible correct data if processing potential corruptible metadata
               if ( $corrupted_meta_key == $meta_key )
               {
                  // do nothing and continue normal execution if new value is empty
                  if (  empty( $meta_value ) ) {
                     return null;
                  }
      
                  // Initialize new meta value var
                  $corrected_meta_value = array();
      
                  // Initialize key count
                  $key = 0;
      
                  // Loop through all the filed group fields defined earlier in the constant
                  foreach( $corrupted_metadata_fields as $corrupted_metadata_field )
                  {
                     // Make sure the new meta value is corrupted, correct if necessary
                     if ( ! array_key_exists( $corrupted_metadata_field, $meta_value ) )
                     {
                        // Correct
                        $corrected_meta_value[$corrupted_metadata_field] = $meta_value[$key];
                        $key++;
                     }
                     else
                     {
                        // Do not correct
                        $corrected_meta_value[$corrupted_metadata_field] = $meta_value[$corrupted_metadata_field];
                        $key++;
                     }
                  }
      
                  // continue normal execution if meta value was not corrupted
                  if( $corrected_meta_value == $meta_key ) {
                     return null;
                  }
      
                  // Unhook just in case
                  remove_filter( 'update_post_metadata', 'hdev_overwrite_piklist_corrupted_metabox_fields', 10 );
      
                  update_post_meta( $object_id, $corrupted_meta_key, $corrected_meta_value );
      
                  // Reapply hook
                  add_filter( 'update_post_metadata', 'hdev_overwrite_piklist_corrupted_metabox_fields', 10, 5 );
      
                  return true; // Stop normal execution
               }
            }
      
            return null; // continue normal execution
         }
      }
    • #7504
      Mehdi Salem
      Member

      Thanks for your feedback and I respect your point of view.

      I’m not affiliated to Piklist in any way, however, I believe that Piklist coding standards are high and that it can be a great tool for developers if the community starts supporting it.

      This is just my point of view and keep in mind that Piklist is still in beta and mostly targeting developers for now 😉

      Best regards

    • #7513
      Mehdi Salem
      Member

      BIG OOOOOPS!!! What I described above is not a bug…

      In fact, I had the same meta box group set as an add_more before. Since I had issues with Javascript performance when I passing 15 add_more boxes, I changed the structure of the group, dropping the add_more feature but kept the same name and since I had some updated_post_meta action that was necessary ti fix a bug with the add_more group, I did completely forgot about it and it was messing the metadata with the new field structure because it is using the array_values php function…

      I will open a new ticket about add_more bug when I’ll have time

      My sincere apologies guys!!!

    • #7519
      Jason
      Keymaster

      @Mehdi Salem: Glad you figured it out! Can you please elaborate on the js performance issues you had?

    • #7526
      Mehdi Salem
      Member

      Thanks Jason! I will elaborate asap a little later today, I have to run to an appointment right now

    • #7529
      Mehdi Salem
      Member

      Ok, here is the issue with Piklist admin Javascript and there are 2 major issue scenarios.

      Tested on default Twenty Sixteen WP theme with default post type “Post” and also custom post types on powerful Macbook Pro (all major browsers)

      1. In first scenario we have a meta box “Gallery” containing an add_more field group with file upload and simple stuff (code bellow): First time post is created, you can add as many add_more as you want. As soon as you save the post, the more you have add_mores, the slower the browser responds. if you reach 40 add_mores then 2 issues: takes 15 seconds and more for the page to load – if a new add_more is added or removed when “minus” or “plus” buttons are clicked same thing, 15 seconds or more delay…

      2. In second scenario we have the same previous meta box “Gallery” containing add_more folder_content_group field group COUPLED with another meta box “Gallery Folder Display Setting” containing file upload field and some conditionals with NO add_more: Same behavior on first save, no problem with as many add_mores as you want but gets very slow if you pass 25 add_mores and when you reach 40 and up, browser becomes unresponsive and Firefox even prompts to kill the script. Can take 60 seconds for browser to respond on page load and same amount of time just to add an add_more or remove it… Oh, yes, and some HEATING AND SUPER HIGH CPU usage on MacBook Pro (Retina, 15-inch, Mid 2015) – 2.5 GHz Intel Core i7 – 16 GB 1600 MHz DDR3

      I’ve seen that some tickets have been opened regarding performance issues with Javascript with and field combination… I was not satisfied by the solutions offered which basically asked to simplify the fields and that it was a lot to handle by for the scripts…

      This is for me a major Javascript optimization issue (and maybe also an architectural issue in the way JS has to prepare the html form input fields for PHP handling???)

      Because Piklist is meant for developers I do think this needs to be addressed seriously and before the release of the stable version.

      Many page builders handle add_mores efficiently, on WordPress or on many many other platforms.

      Personally this is an issue because on of my future projects was to create a Bootstrap and Curb Foundation page builder for WordPress using piklist, but I see this is not an option at this time…

      Thank you Jason for looking at this. Here are the two different meta boxes. Coupling them on the same post type will certainly allow to duplicate all this.

      Let me know if you want me to transfer this to another topic.
      Cheers!

      Gallery meta box:

      <?php
      /*
      Title: <h3>Gallery</h3>
      Post Type: post
      Order: 20
      */
      
      piklist('field', array(
          'type' => 'group'
      ,'field' => 'folder_content_group'
      ,'label' => __('Gallery Photo','stopping-the-world-admin')
      ,'description' => __('Add photos to this folder.', 'stopping-the-world-admin')
      ,'help' => __('Adds a new photo to this gallery folder and sets its availability on the store.','stopping-the-world-admin')
      ,'add_more' => true
      ,'fields' => array(
              array(
                  'type' => 'file'
              ,'field' => 'single_photo'
              ,'label' => __('Photo','stopping-the-world-admin')
              ,'options' => array(
                  'modal_title' => __('Add photo','stopping-the-world-admin')
              ,'button' => __('Add','stopping-the-world-admin')
              )
              ,'required' => true
              ,'columns' => 6
              ,'validate' => array(
                  array(
                      'type' => 'limit',
                      'options' => array(
                          'min' => 1,
                          'max' => 1
                      )
                  )
              ,array(
                      'type' => 'image'
                  )
              )
              )
          ,array(
                  'type' => 'text'
              ,'field' => 'photo_title'
              ,'label' => __('Title','stopping-the-world-admin')
              ,'help' => __('Sets the photo title. This will appear bellow the photo and above the description on the Gallery Foolder post.','stopping-the-world-admin')
              ,'columns' => 6
              ,'attributes' => array(
                      'placeholder' => __('Enter photo title here...', 'stopping-the-world-admin')
                  )
              )
          ,array(
                  'type' => 'checkbox'
              ,'field' => 'store_availability'
              ,'label' => __('Store Availability','stopping-the-world-admin')
              ,'help' => __('(Leave unchecked if you do not want to sell this photo.)','stopping-the-world-admin')
              ,'columns' => 6
              ,'choices' => array(
                      'option1' => 'Stock'
                  ,'option2' => 'Print'
                  )
              )
          ,array(
                  'type' => 'textarea'
              ,'field' => 'photo_description'
              ,'label' => __('Description','stopping-the-world-admin')
              ,'help' => __('Sets the photo description. This will appear bellow the photo and its title on the Gallery Folder post.','stopping-the-world-admin')
              ,'columns' => 6
              ,'attributes' => array(
                      'rows' => 5
                  ,'cols' => 60
                  ,'placeholder' => __('Describe this photo...', 'stopping-the-world-admin')
                  ,'maxlength' => '320'
                  )
              )
          )
      ));

      Gallery Folder Display Setting meta box:

      <?php
      /*
      Title: <h3>Gallery Folder Display Setting</h3>
      Post Type: post
      Order: 10
      */
      
      piklist('field', array(
          'type' => 'file'
      ,'field' => 'folder_cover_photo'
      ,'label' => __('Folder Cover Photo','stopping-the-world-admin')
      ,'help' => __('Sets the folder folder cover photo of the folder next to the folder title & description on the Galleries Menu page.','stopping-the-world-admin')
      ,'options' => array(
              'modal_title' => __('Set folder cover photo','stopping-the-world-admin')
          ,'button' => __('Set','stopping-the-world-admin')
          )
      ,'required' => true
      ,'columns' => 12
      ,'validate' => array(
              array(
                  'type' => 'limit',
                  'options' => array(
                      'min' => 1,
                      'max' => 1
                  )
              )
          ,array(
                  'type' => 'image'
              )
          )
      ));
      
      piklist('field', array(
          'type' => 'text'
      ,'field' => 'folder_title'
      ,'label' => __('Folder Title','stopping-the-world-admin')
      ,'description' => __('(Max 60 characters.)', 'stopping-the-world-admin')
      ,'help' => __('Sets the folder title. This will appear above the folder description and next to the folder cover photo on the Gallery page.','stopping-the-world-admin')
      ,'required' => true
      ,'columns' => 12
      ,'attributes' => array(
              'rows' => 4
          ,'cols' => 20
          ,'placeholder' => 'Enter folder title here...'
          ,'maxlength' => '60'
          ,'class' => 'centered-text'
          )
      ));
      
      piklist('field', array(
          'type' => 'textarea'
      ,'field' => 'folder_description'
      ,'label' => __('Folder Description','stopping-the-world-admin')
      ,'description' => __('(Max 220 characters.)', 'stopping-the-world-admin')
      ,'help' => __('Sets the folder description. This will appear bellow the folder title and next to the folder cover photo on the Gallery page.','stopping-the-world-admin')
      ,'columns' => 12
      ,'attributes' => array(
              'rows' => 5
          ,'cols' => 50
          ,'placeholder' => __('Describe this gallery folder...', 'stopping-the-world-admin')
          ,'maxlength' => '220'
          )
      ));
      
      // Register checkbox that will control conditionally the displaying of the CSS settings options below
      piklist('field', array(
          'type' => 'radio'
      ,'field' => 'custom_css'
      ,'label' => 'Customize CSS'
      ,'help' => __('Check this box to adjust some styling parameters on the folder\'s title, description and containing box.', 'stopping-the-world-admin')
      ,'columns' => 12
      ,'attributes' => array(
              'class' => 'text custom-folder-info'
          )
      ,'choices' => array(
              'no' => __('No', 'stopping-the-world-admin')
          ,'yes' => __('Yes', 'stopping-the-world-admin')
          )
      ,'value' => 'no'
      ));
      
      // Register the folder info box field group
      piklist('field', array(
          'type' => 'group'
      ,'field' => 'folder_info_box_css'
      ,'label' => '<span class="mnl-setting-tab-inner-title">' . __('Folder Info Box CSS','stopping-the-world-admin') . '</span>'
      ,'fields' => array(
              array( // Register the info spacing field
                  'type' => 'text'
              ,'field' => 'folder_info_spacing'
              ,'label' => __('Spacing between the Title and the Description', 'stopping-the-world-admin')
              ,'help' => __('Sets the space between the Folder Title and its Description which appear next to the folder\'s Cover Photo on the Galleries Menu pages. The margin CSS unit used here will be a percentage of the width of the containing box to ensure mobile responsiveness.', 'stopping-the-world-admin')
              ,'attributes' => array(
                  'class' => 'number'
              ,'placeholder' => '1.3'
              )
              ,'validate' => array(
                  array(
                      'type' => 'range'
                  ,'options' => array(
                      'min' => 0
                  ,'max' => 25
                  )
                  )
              )
              )
          )
      ,'conditions' => array(
              array(
                  'field' => 'custom_css'
              ,'value' => 'yes'
              )
          )
      ));
      
      // Register the folder title field group
      piklist('field', array(
          'type' => 'group'
      ,'field' => 'folder_title_css'
      ,'label' => '<span class="mnl-setting-tab-inner-title">' . __('Folder Title CSS','stopping-the-world-admin') . '</span>'
      ,'fields' => array(
              array( // Register the title font size field
                  'type' => 'text'
              ,'field' => 'font_size'
              ,'label' => __('Font Size <span class="mnl-label-comment">(4 decimals max.)</span>', 'stopping-the-world-admin')
              ,'help' => 'Sets the font size of the Folder Title which appear next to the folder\'s Cover Photo on the Galleries Menu pages. The CSS unit used here will be in \'em\' and thus will depend on the parent element font size.'
              ,'columns' => 12
              ,'attributes' => array(
                  'class' => 'number'
              ,'placeholder' => '1.525'
              )
              ,'validate' => array(
                  array(
                      'type' => 'range'
                  ,'options' => array(
                      'min' => 0
                  ,'max' => 25
                  )
                  )
              )
              )
          ,array( // Register the title line height field
                  'type' => 'text'
              ,'field' => 'line_height'
              ,'label' => __('Line Height <span class="mnl-label-comment">(3 decimals max.)</span>', 'stopping-the-world-admin')
              ,'help' => 'Sets the line height of the Folder Title which appear next to the folder\'s Cover Photo on the Galleries Menu pages. No CSS unit is used here.'
              ,'columns' => 12
              ,'attributes' => array(
                      'class' => 'number'
                  ,'placeholder' => '1.5'
                  )
              ,'validate' => array(
                      array(
                          'type' => 'range'
                      ,'options' => array(
                          'min' => 0
                      ,'max' => 25
                      )
                      )
                  )
              )
          ,array( // Register the title letter spacing field
                  'type' => 'text'
              ,'field' => 'letter_spacing'
              ,'label' => __('Letter spacing <span class="mnl-label-comment">(3 decimals max.)</span>', 'stopping-the-world-admin')
              ,'help' => 'Sets the letter spacing of the Folder Title which appear next to the folder\'s Cover Photo on the Galleries Menu pages. The CSS unit used here will be in \'em\' and thus will depend on the parent element font size.'
              ,'columns' => 12
              ,'attributes' => array(
                      'class' => 'number'
                  ,'placeholder' => '.1'
                  )
              ,'validate' => array(
                      array(
                          'type' => 'range'
                      ,'options' => array(
                          'min' => 0
                      ,'max' => 10
                      )
                      )
                  )
              )
          )
      ,'conditions' => array(
              array(
                  'field' => 'custom_css'
              ,'value' => 'yes'
              )
          )
      ));
      
      // Register the folder description field group
      piklist('field', array(
          'type' => 'group'
      ,'field' => 'folder_desc_css'
      ,'label' => '<span class="mnl-setting-tab-inner-title">' . __('Folder Description CSS','stopping-the-world-admin') . '</span>'
      ,'fields' => array(
              array( // Register the description font size field
                  'type' => 'text'
              ,'field' => 'font_size'
              ,'label' => __('Font Size <span class="mnl-label-comment">(4 decimals max.)</span>', 'stopping-the-world-admin')
              ,'help' => 'Sets the font size of the Folder description which appear next to the folder\'s Cover Photo on the Galleries Menu pages. The CSS unit used here will be in \'em\' and thus will depend on the parent element font size.'
              ,'columns' => 12
              ,'attributes' => array(
                  'class' => 'number'
              ,'placeholder' => '.08'
              )
              ,'validate' => array(
                  array(
                      'type' => 'range'
                  ,'options' => array(
                      'min' => 0
                  ,'max' => 25
                  )
                  )
              )
              )
          ,array( // Register the description line height field
                  'type' => 'text'
              ,'field' => 'line_height'
              ,'label' => __('Line Height <span class="mnl-label-comment">(3 decimals max.)</span>', 'stopping-the-world-admin')
              ,'help' => 'Sets the line height of the Folder description which appear next to the folder\'s Cover Photo on the Galleries Menu pages. No CSS unit is used here.'
              ,'columns' => 12
              ,'attributes' => array(
                      'class' => 'number'
                  ,'placeholder' => '1.5'
                  )
              ,'validate' => array(
                      array(
                          'type' => 'range'
                      ,'options' => array(
                          'min' => 0
                      ,'max' => 25
                      )
                      )
                  )
              )
          ,array( // Register the description letter spacing field
                  'type' => 'text'
              ,'field' => 'letter_spacing'
              ,'label' => __('Letter spacing <span class="mnl-label-comment">(3 decimals max.)</span>', 'stopping-the-world-admin')
              ,'help' => 'Sets the letter spacing of the Folder description which appear next to the folder\'s Cover Photo on the Galleries Menu pages. The CSS unit used here will be in \'em\' and thus will depend on the parent element font size.'
              ,'columns' => 12
              ,'attributes' => array(
                      'class' => 'number'
                  ,'placeholder' => '.1'
                  )
              ,'validate' => array(
                      array(
                          'type' => 'range'
                      ,'options' => array(
                          'min' => 0
                      ,'max' => 10
                      )
                      )
                  )
              )
          )
      ,'conditions' => array(
              array(
                  'field' => 'custom_css'
              ,'value' => 'yes'
              )
          )
      ));
      
    • #7530
      Jason
      Keymaster

      Hey @Mehdi Salem!

      Thank you for taking the time to put that together! I’ve made a note to the team. We’ll probably make a ticket or something out of this. We’d definitely like to continue to make optimizations.

      To be honest, while I use Piklist on every project, I haven’t run into a scenario yet where there were mass amounts of complex fields. Not to say it isn’t possible. I did at one time but then decided it wasn’t a good user experience and so I thought of a more creative way of giving the user options. This isn’t an excuse for performance issues, but merely a suggestion that it may be worth exploring if there’s a creative way of improving the UX while cutting down on massive fields.

    • #7531
      Mehdi Salem
      Member

      Thanks @Jason for transmitting and for your prompt answer!

      Yes, I faced the user experience issue as soon as my client started adding stuff. So it pushed me to find a more creative solution, in this case, getting rid of the add_more and let the user add multiple files in the same uploader field. I had to do some more work though to hook into the media uploader ajax light box and stick my other fields in there instead… and write a conversion script for the data already saved in the database. So far it is a way nicer user experience for this particular project but it did cost me a lot to make the switch at the last minute.

      And I’m happy that we all agree it is not a valid excuse… making Piklist more efficient and match other platforms performances out there is a must. While I could figure out an alternative in this case, other more ambitious projects might suffer.

      I’ll be happy if you keep me in the loop in case this moves to another topic.

    • #7518
      Jason
      Keymaster
Viewing 9 reply threads
  • You must be logged in to reply to this topic.