• Resolved anemos2k

    (@anemos2k)


    Hi Tom,

    I am thinking of implementing your plugin on my site and I have a small question that I was hoping you could answer.

    Is there a possibility to detect a flag like active/inactive on the external database and deactivate/activate accordingly the users created on the local WordPress database? Or if I assign a specific user role in the external db, can this be used to disallow access locally in WordPress? If any of the above scenarios are not possible, any ideas how I could prevent a deactivated user on the external database to login in WordPress?

    Please let me clarify: On the external database, users never get deleted, they are only marked as deactivated and this leads me to question the fact that since a user account and a password DO EXIST in the external database how do I prevent that this user gets created and be allowed to log in locally in WordPress?

    By the way, the suggestion that you made on another user to allow adding/modifying part of the SQL query on the external database is very, very interesting!

    Thanks in advance for your input!
    Panos

Viewing 15 replies - 31 through 45 (of 50 total)
  • Tom,
    OK did this. The field reappeared in the table and the option value is “false”

    Plugin Author tbenyon

    (@tbenyon)

    I so badly wish I could sit at your machine with you to help you faster 😛

    My new theory is that because you are getting JSON data stored, in that field, and it’s not getting stored in the database that there must be some sort of validation that is blocking this within WordPress. This is the bit that WordPress handles by default and I haven’t changed a lot. I don’t know why I’m not experiencing this (I’m going to try a fresh WP build this evening when I have more time).

    Next steps:

    1. Can you double check you’re looking in the DIV tag with the classes “option-container repeater exlog-repeater-master”
    2. In there find the INPUT with the class “exlog_repeater_data_store”
    3. In the inspector, change its TYPE attribute from “hidden” to “text”
    4. You should see the red input field appear
    5. Delete what is currently in there and just write “FUNKY MONKEY”
    6. Save the form
    7. Check your database to see if “FUNKY MONKEY” has appeared in there

    If it has, we can start to guess that maybe it’s do with:

    • The input being hidden
    • The JSON data you’re seeing appear in there not being accepted
    • Setting the value of this item is setting the attribute but not it’s real value?! Seems odd but I’m running out of ideas 😛

    Thanks for being so patient. I know this will help you but it’s also really appreciated by me to have such a supportive user as it means I can have a more stable plugin for other users. Thank you!

    • This reply was modified 5 years, 3 months ago by tbenyon.

    1) yes
    2) OK
    3) done
    4) yes
    5) done
    6) done
    7) yes it is there

    Plugin Author tbenyon

    (@tbenyon)

    Brilliant news! I think we’re close to solving this one!

    Still confused why it works in mine and not in yours.

    Let’s try base64 encoding all data going to the database.

    Could you replace everything in ‘wp-content/plugins/external-login/js/exlog_repeater_field_handler.js’ with the following code:

    
    
    (function ($) {
      $(function () {
        var $parent_repeater_fields = $(".option-container.repeater.exlog-repeater-master");
        var repeater_buttons_selector = ".exlog_repeater_add_button";
        var repeater_item_selector = ".repeater_item";
        var repeater_data_attr = 'data-exlog-repeater-id';
        var master_markup_item_selector = repeater_item_selector + '[' + repeater_data_attr + '="0"]';
        var click_event_name = 'click';
        var change_events = ['keyup', 'paste'];
        var repeater_data_store_selector = '.exlog_repeater_data_store';
    
        function object_to_string_if_object(data) {
          if (typeof data === 'object') {
            try {
              data = JSON.stringify(data);
            } catch (error) {
              //  Leave data in current format
            }
          }
          return data
        }
    
        function place_data_from_db() {
          function place_specific_repeater_values($parent_element, data) {
          //  Put all data in the name value
            var $data_store = $parent_element.children(repeater_data_store_selector);
            var data_string;
            try {
              data_string = JSON.stringify(data);
            } catch(e) {
              console.log('EXLOG: Failed to parse some data from the database.\nIncorrect data:', data);
              data_string = false;
            }
            $data_store.val(data_string);
    
            // Of that data, put each value in the correct input
            if (data) {
              data.forEach(function (repeater_item, i) {
                var $repeater_item;
                if (i > 0) { // If not the first repeater item - create a new one in the DOM and store the jQuery object
                  $repeater_item = create_new_item($parent_element, i, false);
                } else { // If the first repeater item, get the one repeater jQuery object
                  $repeater_item = $parent_element.find('> .repeater_item');
                }
    
                repeater_item.forEach(function (repeater_item_option) {
    
                  var input_data = object_to_string_if_object(repeater_item_option['value']);
    
                  var input_selector = '> .repeater_item_input_container > .option-container > [name="' + repeater_item_option['name'] + '"]';
    
                  // Add DB value into the input
                  var $input_element = $repeater_item.find(input_selector).val(input_data);
    
                  //  If the input data is a repeater field, call this function again with the relevant data and $parent element
                  if (repeater_item_option['repeater_field']) {
                    place_specific_repeater_values($input_element.closest('.option-container'), repeater_item_option['value']);
                  }
                });
              });
            }
          }
    
          // Put the master data into the repeater master component and then start placing specific values
          $parent_repeater_fields.each(function () {
            var $parent_repeater_field = $(this);
            var base_64_string = $parent_repeater_field.children(repeater_data_store_selector).val();
            var parent_repeater_data;
            try {
              parent_repeater_data = JSON.parse(atob(atob(base_64_string))); // Once for storing from server, once for data store
            } catch (e) {
              parent_repeater_data = false;
            }
            place_specific_repeater_values($parent_repeater_field, parent_repeater_data)
          });
    
        }
    
        function create_new_item($repeater_option_container, item_id) {
          // Get the markup to copy from looking at first item
          var markup = $repeater_option_container.children(master_markup_item_selector).html();
    
          var $markup = $('<section class="repeater_item">' + markup + '</section>');
    
          // Clean out any repeater ids that are not the first one from the generated markup
          $(repeater_item_selector, $markup).each(function () {
            var $repeater_item = $(this);
            if ($repeater_item.attr(repeater_data_attr) !== "0") {
              $repeater_item.remove();
            }
          });
    
          // Store the new id in the attr of the repeater item
          $markup.attr('data-exlog-repeater-id', item_id);
    
          var $markup_inputs = $markup.children('.repeater_item_input_container').find('.option-container input:not([type=button])');
    
          $markup_inputs.each(function () {
            var $markup_input = $(this);
            $markup_input.val('');
          });
    
          // Place the new markup on the page
          $repeater_option_container.children('.add_more').before($markup);
          reset_watchers();
          return $markup;
        }
    
        function reselect_add_buttons() {
          $(repeater_buttons_selector).off(click_event_name).on(click_event_name, on_add_button_click);
        }
    
        function on_add_button_click() {
          var $button = $(this);
    
          var $add_more_container = $button.closest(".add_more");
    
          var used_ids = [];
          // Store all used ids
          $add_more_container.siblings(repeater_item_selector).each(function () {
            var $repeater_item = $(this);
            var repeater_item_id = $repeater_item.attr(repeater_data_attr);
            used_ids.push(repeater_item_id)
          });
    
          // Get a unique id for the new repeater item
          var new_id = 1;
          while (used_ids.indexOf(new_id.toString()) > -1 ) { // While new_id is in used_ids
            new_id += 1;
          }
    
          var $repeater_option_container = $add_more_container.closest('.option-container.repeater');
    
          create_new_item($repeater_option_container, new_id, false);
        }
        
        function monitorRepeaterInputs() {
          var change_events_string = change_events.join(' ');
          var $repeater_data_stores = $(repeater_data_store_selector);
    
          $repeater_data_stores.each(function () {
            var $repeater_data_store = $(this);
            var $inputs = $repeater_data_store.siblings('.repeater_item').children('.repeater_item_input_container').children('.option-container').children('input, textarea');
    
            // Clear previous events
            $inputs.off(change_events_string);
    
            $inputs.on(change_events_string, (function () {
              update_repeater_data($repeater_data_store, $inputs);
              $repeater_data_store.trigger(change_events[0]);
            }));
          });
        }
    
        function update_repeater_data($repeater_data_store) {
          var data_for_store = []; // Object to be populated by first child inputs of repeater
          var repeater_items = $repeater_data_store.siblings('.repeater_item');
          repeater_items.each(function () {
            var repeater_item = [];
            var $inputs = $(this).children('.repeater_item_input_container').children('.option-container').children('input, textarea');
            $inputs.each(function () {
              var $input = $(this);
              var value = $input.val();
              var repeater_field = false;
              if ($input.hasClass('exlog_repeater_data_store')) {
                repeater_field = true;
                try {
                  value = JSON.parse(atob(value)); // If the data can be interpreted as JSON convert it to an object
                } catch (error) {
                  console.log("EXLOG: Error storing repeater data for '" + $input.attr('name') + "'", "Value:", value);
                }
              }
              repeater_item.push({
                "name": $input.attr('name'),
                "repeater_field": repeater_field,
                "value": value
              });
            });
            data_for_store.push(repeater_item);
          });
    
          $repeater_data_store.val(btoa(JSON.stringify(data_for_store)));
        }
    
        function on_delete_item_click() {
          $('.delete_repeater_item').off(click_event_name).on(click_event_name, function () {
            var $delete_button = $(this);
            var $repeater_item = $delete_button.closest(repeater_item_selector);
    
            // var $repeater_item_name = $repeater_item.attr('name');
    
            var $first_item = $repeater_item.siblings(master_markup_item_selector).find('input');
    
            // Remove the repeater item from the DOM
            $repeater_item.remove();
    
            // Ensure elements no longer in the DOM are no longer selected as otherwise data is kept
            reset_watchers();
    
            // Make first repeater item trigger change to remove deleted items data
            $first_item.trigger(change_events[0]);
          })
        }
    
        // All the selectors that need updating on DOM change
        function reset_watchers() {
          monitorRepeaterInputs();
          reselect_add_buttons();
          on_delete_item_click();
        }
    
        place_data_from_db();
        reset_watchers();
      })
    }(jQuery));
    

    OK I did that. I ran it with the same results. I also went into the db and deleted exlog_exclude_users_field_name_repeater and ran it again. Same result

    Plugin Author tbenyon

    (@tbenyon)

    To clarify:

    1. You updated the JS with the code I gave you above
    2. You modified a field
    3. In there find the INPUT with the class “exlog_repeater_data_store” you can see a base 64 encoded string (a jumble of characters that ends with an equal sign = )
    4. When you click save the only thing you see in the database is “false”

    When we did this by manually modifying the “FUNKY MONKEY” string previously the data did get saved in the database. This is so weird to me. I don’t know why Funky Monkey would get saved but the base64 string wouldn’t.

    The only other differences I can think of is that:

    • The input field was not hidden
    • We manually typed it into the field

    Let’s see which one of these makes a differences.

    Firstly let’s just try making the hidden input non hidden.
    In “wp-content/plugins/external-login/views/form_elements/repeater_field.php”

    Let’s modify the below code so it no longer says hidden as the type like this:

        <input
          style="background-color: red;"
          class="exlog_repeater_data_store"
          type="hidden"
          name="<?php echo $form_field["field_slug"]; ?>"
          <?php if (!$exlog_parent_repeater_slug) : ?>
            value="<?php echo base64_encode(get_option($form_field["field_slug"])); ?>"
          <?php endif; ?>
        >

    . . . and change it to say text like this:

        <input
          style="background-color: red;"
          class="exlog_repeater_data_store"
          type="text"
          name="<?php echo $form_field["field_slug"]; ?>"
          <?php if (!$exlog_parent_repeater_slug) : ?>
            value="<?php echo base64_encode(get_option($form_field["field_slug"])); ?>"
          <?php endif; ?>
        >

    After this let’s go through the process of:

    1. Reloading the page
    2. Typing something in the input fields
    3. make sure we can see the base 64 data appearing in that red field
    4. Hit save
    5. Check if anything saved to the database (Don’t forget to refresh 😛 )

    Thanks,

    Tom

    Before we proceed, I want to (clarify) your -to-clarify item #3 – yes I updated the code in the file: exlog_repeater_field_handler.js

    However in the wp admin for external login, I do not see any base64 code string. This is what is rendered:

    <input style="background-color: red;" class="exlog_repeater_data_store" name="exlog_exclude_users_field_name_repeater" value="false" type="hidden">

    and if I change that to type="text" it is just a red box with false in it.

    Plugin Author tbenyon

    (@tbenyon)

    I expect that on page load, but when you have changed type to be text, and then typed in some boxes, do you see a base 64 encoded value, and does it save to the database when you click save?

    OK I see you are correct. So when I change that input type to text and then submit it actually works. In the wp admin I see what I typed in for the fields but in the db it is a long string of text

    Plugin Author tbenyon

    (@tbenyon)

    And just to double check, with the new JS (with the base 64 conversion) does this work without setting the input type to text?

    I’d be surprised if once you’ve updated the field on the front end then hit save that it doesn’t get stored in the database.

    no it does not work without setting it to text

    Plugin Author tbenyon

    (@tbenyon)

    Hey @xprojectsx,

    Sincere apologies for the delay.

    New thing to try.

    1) Replace all the code in options/wpconfig_options.php with the below:

    
    <?php
    
    //If a constant is defined for an option, make that take president
    function exlog_get_option($option_name) {
        $constant_option_name = strtoupper($option_name);
    
        if (defined($constant_option_name)) {
            return constant($constant_option_name);
        } else {
            $option_data = get_option($option_name);
            $decoded_option_data = json_decode(base64_decode($option_data), true);
            if ($decoded_option_data) {
                return exlog_modify_repeater_data_for_view_use($decoded_option_data); // If data was JSON return PHP array (for repeater fields)
            }
            return $option_data;
        }
    }
    
    function exlog_is_wpconfig_option_set($option_name) {
        return defined(strtoupper($option_name));
    }
    
    function exlog_modify_repeater_data_for_view_use($repeater_data) {
        $formatted_data = array();
        if (is_array($repeater_data)) {
            foreach ($repeater_data as $repeater_item_data) {
                $formatted_repeater_items_data = array();
                foreach ($repeater_item_data as $repeater_item_datum) {
                    if ($repeater_item_datum['repeater_field']) {
                        $value = exlog_modify_repeater_data_for_view_use($repeater_item_datum['value']);
                    } else {
                        $value = $repeater_item_datum['value'];
                    }
                    $formatted_repeater_items_data[$repeater_item_datum['name']] = $value;
                }
                array_push($formatted_data, $formatted_repeater_items_data);
            }
            return $formatted_data;
        } else {
            return $repeater_data;
        }
    }
    

    2) Replace all the code in js/exlog_repeater_field_handler.js with this:

    
    // Possible data structure
    
    var possible_repeater_data_master = [
      {
        "field_name": "title",
        "id": "12345678",
        "repeater_field": false,
        "field_data": "this is some text"
      },
      {
        "field_name": "Names Repeater",
        "id": "12345678",
        "repeater_field": true,
        "field_data": [ // Repeater items
          [ // Repeater Item
            {
              "field_name": "title in repeater",
              "id": "12345678",
              "repeater_field": false,
              "field_data": "this is some textoooo"
            },
            {
              "field_name": "title in repeater222",
              "id": "12345678",
              "repeater_field": false,
              "field_data": "this is some textoooo222"
            },
            {
              "field_name": "inner_repeater",
              "id": "12345678",
              "repeater_field": true,
              "field_data": [ // Repeater Items
                [ // Repater Item
                  {
                    "field_name": "title in repeater333",
                    "id": "12345678",
                    "repeater_field": false,
                    "field_data": "this is some textoooo3333"
                  },
                  {
                    "field_name": "title in repeater3331",
                    "id": "12345678",
                    "repeater_field": false,
                    "field_data": "this is some textoooo3332"
                  }
                ],
                [ // Repater Item 2
                  {
                    "field_name": "title in repeater333",
                    "id": "12345678",
                    "repeater_field": false,
                    "field_data": "this is some textoooo3333"
                  },
                  {
                    "field_name": "title in repeater3331",
                    "id": "12345678",
                    "repeater_field": false,
                    "field_data": "this is some textoooo3332"
                  }
                ]
              ]
            }
          ]
        ]
      }
    ];
    
    (function ($) {
      $(function () {
        var $parent_repeater_fields = $(".option-container.repeater.exlog-repeater-master");
        var repeater_buttons_selector = ".exlog_repeater_add_button";
        var repeater_item_selector = ".repeater_item";
        var repeater_data_attr = 'data-exlog-repeater-id';
        var master_markup_item_selector = repeater_item_selector + '[' + repeater_data_attr + '="0"]';
        var click_event_name = 'click';
        var change_events = ['keyup', 'paste', 'change'];
        var repeater_data_store_selector = '.exlog_repeater_data_store';
    
        function object_to_string_if_object(data) {
          if (typeof data === 'object') {
            try {
              data = JSON.stringify(data);
            } catch (error) {
              //  Leave data in current format
            }
          }
          return data
        }
    
        function place_data_from_db() {
          function place_specific_repeater_values($parent_element, data) {
            try {
              data = JSON.parse(data);
            } catch(e) {
              //
            }
    
          //  Put all data in the name value
            var $data_store = $parent_element.children(repeater_data_store_selector);
            var data_string;
            try {
              data_string = JSON.stringify(data);
            } catch(e) {
              console.log('EXLOG: Failed to parse some data from the database.\nIncorrect data:', data);
              data_string = false;
            }
    
            $data_store.val(btoa(data_string));
    
            // Of that data, put each value in the correct input
            if (data && data != 'false') {
              data.forEach(function (repeater_item, i) {
                var $repeater_item;
                if (i > 0) { // If not the first repeater item - create a new one in the DOM and store the jQuery object
                  $repeater_item = create_new_item($parent_element, i, false);
                } else { // If the first repeater item, get the one repeater jQuery object
                  $repeater_item = $parent_element.find('> .repeater_item');
                }
    
                repeater_item.forEach(function (repeater_item_option) {
    
                  var input_data = object_to_string_if_object(repeater_item_option['value']);
    
                  var input_selector = '> .repeater_item_input_container > .option-container > [name="' + repeater_item_option['name'] + '"]';
    
                  var $input_item = $repeater_item.find(input_selector);
    
                  // Add DB value into the input
                  if ($input_item.attr('type') === 'checkbox') {
                    $input_item.prop('checked', input_data);
                  } else {
                    $input_item.val(input_data);
                  }
    
                  //  If the input data is a repeater field, call this function again with the relevant data and $parent element
                  if (repeater_item_option['repeater_field']) {
                    var $next_repeater = $input_item.closest('.option-container');
                    place_specific_repeater_values($next_repeater, repeater_item_option['value']);
                  }
                });
              });
            }
          }
    
          // Put the master data into the repeater master component and then start placing specific values
          $parent_repeater_fields.each(function () {
            var $parent_repeater_field = $(this);
            var base_64_string = $parent_repeater_field.children(repeater_data_store_selector).val();
            var parent_repeater_data;
            try {
              parent_repeater_data = JSON.parse(atob(atob(base_64_string))); // Once for storing from server, once for data store
            } catch (e) {
              parent_repeater_data = false;
            }
            place_specific_repeater_values($parent_repeater_field, parent_repeater_data)
          });
    
        }
    
        function create_new_item($repeater_option_container, item_id) {
          // Get the markup to copy from looking at first item
          var markup = $repeater_option_container.children(master_markup_item_selector).html();
    
          var $markup = $('<section class="repeater_item">' + markup + '</section>');
    
          // Clean out any repeater ids that are not the first one from the generated markup
          $(repeater_item_selector, $markup).each(function () {
            var $repeater_item = $(this);
            if ($repeater_item.attr(repeater_data_attr) !== "0") {
              $repeater_item.remove();
            }
          });
    
          // Store the new id in the attr of the repeater item
          $markup.attr('data-exlog-repeater-id', item_id);
    
          var $markup_inputs = $markup.children('.repeater_item_input_container').find('.option-container input:not([type=button])');
    
          $markup_inputs.each(function () {
            var $markup_input = $(this);
            $markup_input.val('');
          });
    
          // Place the new markup on the page
          $repeater_option_container.children('.add_more').before($markup);
          reset_watchers();
          return $markup;
        }
    
        function reselect_add_buttons() {
          $(repeater_buttons_selector).off(click_event_name).on(click_event_name, on_add_button_click);
        }
    
        function on_add_button_click() {
          var $button = $(this);
    
          var $add_more_container = $button.closest(".add_more");
    
          var used_ids = [];
          // Store all used ids
          $add_more_container.siblings(repeater_item_selector).each(function () {
            var $repeater_item = $(this);
            var repeater_item_id = $repeater_item.attr(repeater_data_attr);
            used_ids.push(repeater_item_id)
          });
    
          // Get a unique id for the new repeater item
          var new_id = 1;
          while (used_ids.indexOf(new_id.toString()) > -1 ) { // While new_id is in used_ids
            new_id += 1;
          }
    
          var $repeater_option_container = $add_more_container.closest('.option-container.repeater');
    
          create_new_item($repeater_option_container, new_id, false);
        }
        
        function monitorRepeaterInputs() {
          var change_events_string = change_events.join(' ');
          var $repeater_data_stores = $(repeater_data_store_selector);
    
          // For every repeater data store
          $repeater_data_stores.each(function () {
            var $repeater_data_store = $(this);
    
            // Get just the inputs for that data store
            var $inputs = $repeater_data_store.siblings('.repeater_item').children('.repeater_item_input_container').children('.option-container').children('input, textarea');
    
            // Clear previous change events on inputs
            $inputs.off(change_events_string);
    
            // For each input, if there is a change in the data, update the data in the repeater data store
            $inputs.on(change_events_string, (function () {
              update_repeater_data($repeater_data_store, $inputs);
    
              // After the data store data is updated, trigger an event change on the store so that parent stores will update their data
              $repeater_data_store.trigger(change_events[0]);
            }));
          });
        }
    
        function update_repeater_data($repeater_data_store) {
          var data_for_store = []; // Object to be populated by first child inputs of repeater
          var repeater_items = $repeater_data_store.siblings('.repeater_item');
          repeater_items.each(function () {
            var repeater_item = [];
            var $inputs = $(this).children('.repeater_item_input_container').children('.option-container').children('input, textarea');
            $inputs.each(function () {
              var $input = $(this);
              var value;
    
              if ($input.attr('type') === 'text') {
                value = $input.val();
              } else if ($input.attr('type') === 'checkbox') {
                value = $input.prop('checked');
              } else {
                value = null;
              }
    
              var repeater_field = false;
              if ($input.hasClass('exlog_repeater_data_store')) {
                repeater_field = true;
                try {
                  value = JSON.parse(atob(value)); // If the data can be interpreted as JSON convert it to an object
                } catch (error) {
                  console.log("EXLOG: Error storing repeater data for '" + $input.attr('name') + "'", "Value:", value);
                }
              }
              repeater_item.push({
                "name": $input.attr('name'),
                "repeater_field": repeater_field,
                "value": value
              });
            });
            data_for_store.push(repeater_item);
          });
    
          $repeater_data_store.val(btoa(JSON.stringify(data_for_store)));
        }
    
        function on_delete_item_click() {
          $('.delete_repeater_item').off(click_event_name).on(click_event_name, function () {
            var $delete_button = $(this);
            var $repeater_item = $delete_button.closest(repeater_item_selector);
    
            // var $repeater_item_name = $repeater_item.attr('name');
    
            var $first_item = $repeater_item.siblings(master_markup_item_selector).find('input');
    
            // Remove the repeater item from the DOM
            $repeater_item.remove();
    
            // Ensure elements no longer in the DOM are no longer selected as otherwise data is kept
            reset_watchers();
    
            // Make first repeater item trigger change to remove deleted items data
            $first_item.trigger(change_events[0]);
          })
        }
    
        // All the selectors that need updating on DOM change
        function reset_watchers() {
          monitorRepeaterInputs();
          reselect_add_buttons();
          on_delete_item_click();
        }
    
        place_data_from_db();
        reset_watchers();
      })
    }(jQuery));
    

    Let me know if this works.

    Tom

    It works! You save me! Thanks.

    Plugin Author tbenyon

    (@tbenyon)

    Hey @mainpagepl,

    I’m really glad it’s working for you 🙂

    Can you please advise what you had to change to make it work so that we can help others or I can update the plugin.

    Or have more recent updates to the plugin already fixed this for you?

    Thanks,

    Tom

    I am currently working with this plugin. Maybe I will have some ideas for development, but for now it meets my requirements.

Viewing 15 replies - 31 through 45 (of 50 total)
  • The topic ‘Active/Inactive Users’ is closed to new replies.