function amr_meta_menu()
{
    /* parent, page title, menu title, access level, file, function */
    /* Note have to have different files, else wordpress runs all the functions together */
    global $amain, $amr_pluginpage;
    global $ausersadminurl, $ausersadminusersurl;
    if (is_network_admin()) {
        $ausersadminurl = network_admin_url('admin.php');
        $ausersadminusersurl = network_admin_url('users.php');
    } else {
        $ausersadminurl = admin_url('admin.php');
        $ausersadminusersurl = admin_url('users.php');
    }
    if (empty($amain)) {
        $amain = ausers_get_option('amr-users-main');
    }
    /* add the options page at admin level of access */
    $menu_title = $page_title = __('User Lists', 'amr-users');
    $parent_slug = 'amr-users';
    $function = 'amrmeta_about_page';
    $menu_slug = 'amr-users';
    $capability = 'manage_options';
    $settings_page = $ausersadminurl . '?page=amr-users';
    $amr_pluginpage = add_menu_page($page_title, $menu_title, $capability, $menu_slug, $function);
    add_action('load-' . $amr_pluginpage, 'amru_on_load_page');
    add_action('admin_init-' . $amr_pluginpage, 'amr_load_scripts');
    $parent_slug = $menu_slug;
    $amr_pluginpage = add_submenu_page($parent_slug, __('About', 'amr-users'), __('About', 'amr-users'), 'manage_options', $menu_slug, $function);
    $amr_pluginpage = add_submenu_page($parent_slug, __('User List Settings', 'amr-users'), __('General Settings', 'amr-users'), 'manage_options', 'ameta-admin-general.php', 'amr_meta_general_page');
    $amr_pluginpage = add_submenu_page($parent_slug, __('Configure a list', 'amr-users'), __('Configure a list', 'amr-users'), 'manage_options', 'ameta-admin-configure.php', 'amrmeta_configure_page');
    add_action('admin_head-' . $amr_pluginpage, 'ameta_admin_style');
    $amr_pluginpage = add_submenu_page($parent_slug, __('Cache Settings', 'amr-users'), __('Cacheing', 'amr-users'), 'manage_options', 'ameta-admin-cache-settings.php', 'amrmeta_cache_settings_page');
    add_action('admin_head-' . $amr_pluginpage, 'ameta_admin_style');
    if (empty($amain)) {
        $amain = ausers_get_option('amr-users-main');
    }
    /*  Need to get this early so we can do menus */
    if (current_user_can('list_users') or current_user_can('edit_users')) {
        if (isset($amain['names'])) {
            /* add a separate menu item for each list */
            foreach ($amain['names'] as $i => $name) {
                if (isset($amain['names'][$i])) {
                    $page = add_submenu_page('users.php', __('User lists', 'amr-users'), $amain['names'][$i], 'list_users', 'ameta-list.php?ulist=' . $i, 'amr_list_user_meta');
                    // function
                    /* Using registered $page handle to hook stylesheet loading */
                    add_action('admin_print_styles-' . $page, 'add_ameta_stylesheet');
                    add_action('admin_head-' . $page, 'ameta_admin_style');
                }
            }
        }
    }
}
function amr_meta_overview_page()
{
    /* the main setting spage  - num of lists and names of lists */
    global $amain;
    global $aopt;
    if (empty($amain)) {
        $amain = ausers_get_option('amr-users-main');
    }
    //amr_meta_main_admin_header('Overview of configured user lists'.' '.AUSERS_VERSION);
    amr_meta_admin_headings($plugin_page = '');
    // does the nonce check etc
    if (isset($_POST['import-list'])) {
        amr_meta_handle_import();
    } elseif (isset($_POST['action']) and $_POST['action'] == "save") {
        if (!empty($_POST['reset'])) {
            amr_meta_reset();
            return;
        } elseif (isset($_POST['export-list'])) {
            amr_meta_handle_export();
        } else {
            amrmeta_validate_overview();
        }
    } else {
        amr_handle_copy_delete();
    }
    if (!ameta_cache_enable() or !ameta_cachelogging_enable()) {
        echo '<h2>' . __('Problem creating DB tables', 'amr-users') . '</h2>';
    }
    if (!isset($amain['checkedpublic'])) {
        echo '<input type="hidden" name="checkedpublic" value="true"/>';
    }
    echo '<h2>' . __('Overview &amp; tools', 'amr-users') . '</h2>';
    echo PHP_EOL . '<div class="wrap"><!-- one wrap -->' . PHP_EOL;
    if (!isset($amain['names'])) {
        echo '<h2>' . __('There is a problem - Some overview list settings got lost somehow.  Try reset options.', 'amr-users') . '</h2>';
    } else {
        amr_meta_overview_onelist_headings();
        amr_meta_overview_onelist_headings_middle();
        foreach ($amain['names'] as $i => $name) {
            //for ($i = 1; $i <= $amain['no-lists']; $i++)	{
            amr_meta_overview_onelist_settings($i);
            echo '</tr>';
        }
        amr_meta_overview_onelist_headings_end();
    }
    echo '</div><!-- end of one wrap --> <br />' . PHP_EOL;
    //echo '<div style="clear: both; float:right; padding-right:100px;" class="submit">';
    echo ausers_submit();
    echo '<input class="button-primary" type="submit" name="addnew" value="' . __('Add new', 'amr-users') . '" />';
    amr_list_export_form();
    echo ausers_form_end();
    amr_list_import_form();
    // different form
}
 function cache_status()
 {
     /* show the cache status and offer to rebuild */
     global $wpdb;
     global $amain;
     $problem = false;
     $now = time();
     $dt = new DateTime('now', $this->tz);
     $nowtxt = date_format($dt, 'D, j M Y G:i e');
     if (is_admin()) {
         if (!($amain = ausers_get_option('amr-users-main'))) {
             $amain = ameta_default_main();
         }
         $wpdb->show_errors();
         $sql = 'SELECT DISTINCT reportid AS "rid", COUNT(reportid) AS "lines" FROM ' . $this->table_name . ' GROUP BY reportid';
         $results = $wpdb->get_results($sql, ARRAY_A);
         /* Now e have a summary of what isin the cache table - rid, lines */
         if (is_wp_error($results)) {
             echo '<h2>' . $results->get_error_message() . '</h2>';
             return false;
         } else {
             if (!empty($results)) {
                 //var_dump($results);  var_dump($amain);
                 foreach ($results as $i => $rpt) {
                     $r = intval(substr($rpt['rid'], 5));
                     /* *** skip the 'users' and take the rest */
                     $summary[$r]['rid'] = $rpt['rid'];
                     $summary[$r]['lines'] = $rpt['lines'] - 2;
                     /* as first two liens are headers anyway*/
                     $summary[$r]['name'] = $amain['names'][intval($r)];
                 }
             } else {
                 echo adb_cache::get_error('nocacheany');
                 // attempt a realtime run  NO!!! Don't do this - for large databases that are failing anyway will be no good.
                 //foreach ($amain['names'] as $i => $name) {
                 //	amr_build_user_data_maybe_cache($i);
                 //}
             }
             $status = ausers_get_option('amr-users-cache-status');
             /* Now pickup the record of starts etc reportid, start   and reportid end*/
             if (!empty($status)) {
                 foreach ($status as $rd => $se) {
                     $r = intval(substr($rd, 5));
                     /* *** skip the 'users' and take the rest */
                     if (empty($se['end'])) {
                         $now = time();
                         $diff = $now - $se['start'];
                         if ($diff > 60 * 5) {
                             $problem = true;
                             $summary[$r]['end'] = __('Taking too long, may have been aborted... delete cache status, try again, check server logs and/or memory limit', 'amr-users');
                             delete_transient('amr_users_cache_' . $r);
                             // so another can run
                         } else {
                             $summary[$r]['end'] = sprintf(__('Started %s', 'amr-users'), human_time_diff($now, $se['start']));
                         }
                         $summary[$r]['time_since'] = __('?', 'amr-users');
                         $summary[$r]['time_taken'] = __('?', 'amr-users');
                         $summary[$r]['peakmem'] = __('?', 'amr-users');
                         $summary[$r]['rid'] = $rd;
                         $r = intval(substr($rd, 5));
                         /* *** skip the 'users' and take the rest */
                         $summary[$r]['name'] = $amain['names'][intval($r)];
                     } else {
                         if (empty($se['end'])) {
                             $summary[$r]['end'] = 'In progress';
                         } else {
                             $datetime = new datetime(date('Y-m-d H:i:s', $se['end']));
                             if (empty($tzobj)) {
                                 $tzobj = amr_getset_timezone();
                             }
                             $datetime->setTimezone($tzobj);
                             $summary[$r]['end'] = $datetime->format('D, j M G:i');
                         }
                         //$summary[$r]['end'] = empty($se['end']) ? 'In progress' : date_i18n('D, j M H:i:s',$se['end']);  /* this is in unix timestamp not "our time" , so just say how long ago */
                         $summary[$r]['start'] = date_i18n('D, j M Y H:i:s', $se['start']);
                         /* this is in unix timestamp not "our time" , so just say how long ago */
                         $dt = new DateTime('now', $this->tz);
                         $nowtxt = date_format($dt, 'D, j M Y G:i e');
                         $summary[$r]['time_since'] = human_time_diff($se['end'], time());
                         /* the time that the last cache ended */
                         $summary[$r]['time_taken'] = $se['end'] - $se['start'];
                         /* the time that the last cache ended */
                         $summary[$r]['peakmem'] = $se['peakmem'];
                         $summary[$r]['headings'] = $se['headings'];
                     }
                 }
             } else {
                 if (!empty($summary)) {
                     foreach ($summary as $rd => $rpt) {
                         $summary[$rd]['time_since'] = $summary[$rd]['time_taken'] = $summary[$rd]['end'] = $summary[$rd]['peakmem'] = '';
                     }
                 }
             }
             if (!empty($summary)) {
                 echo PHP_EOL . '<div class="wrap" style="padding-top: 20px;">' . '<h3>' . $nowtxt . '</h3>' . PHP_EOL . '<table class="widefat" style="width:auto; ">' . '<thead><tr><th>' . __('Report Id', 'amr-users') . '</th><th>' . __('Name', 'amr-users') . '</th><th>' . __('Lines', 'amr-users') . '</th><th style="text-align: right;">' . __('Ended?', 'amr-users') . '</th><th style="text-align: right;">' . __('How long ago?', 'amr-users') . '</th><th style="text-align: right;">' . __('Seconds taken', 'amr-users') . '</th><th style="text-align: right;">' . __('Peak Memory', 'amr-users') . '</th><th style="text-align: right;">' . __('Details', 'amr-users') . '</th></tr></thead>';
                 foreach ($summary as $rd => $rpt) {
                     if (!isset($rpt['headings'])) {
                         $rpt['headings'] = ' ';
                     }
                     if (!isset($rpt['lines'])) {
                         $rpt['lines'] = ' ';
                     }
                     if (isset($rpt['rid'])) {
                         echo '<tr>' . '<td>' . $rpt['rid'] . '</td>' . '<td>' . au_view_link($rpt['name'], $rd, '') . '</td>' . '<td align="right">' . $rpt['lines'] . '</td>' . '<td align="right">' . $rpt['end'] . '</td>' . '<td align="right">' . $rpt['time_since'] . '</td>' . '<td align="right">' . $rpt['time_taken'] . '</td>' . '<td align="right">' . $rpt['peakmem'] . '</td>' . '<td align="right">' . $rpt['headings'] . '</td>' . '</tr>';
                     }
                 }
                 echo PHP_EOL . '</table>' . PHP_EOL . '</div><!-- end wrap -->' . PHP_EOL;
             }
         }
     } else {
         echo '<h3>not admin?</h3>';
     }
     if ($problem) {
         $fun = '<a target="_blank" title="' . __('Link to audio file of the astronauts of Apollo 13 reporting a problem.', 'amr-users') . '" href="http://upload.wikimedia.org/wikipedia/commons/1/12/Apollo13-wehaveaproblem_edit_1.ogg" >' . __('Houston, we have a problem', 'amr-users') . '</a>';
         $text = __('The background job\'s may be having problems.', 'amr-users');
         $text .= '<br />' . __('Delete all the cache records and try again', 'amr-users');
         $text .= '<br />' . __('Check the server logs and your php wordpress memory limit.', 'amr-users');
         $text .= '<br />' . __('The TPC memory usage plugin may be useful to assess whether the problem is memory.', 'amr-users');
         $text = $fun . '<br/>' . $text;
         amr_users_message($text);
     }
 }
function amrmeta_cache_settings_page()
{
    global $aopt;
    global $amr_nicenames;
    global $pluginpage;
    global $amain;
    if (empty($amain)) {
        $amain = ausers_get_option('amr-users-main');
    }
    $tabs['settings'] = __('Cache Settings', 'amr-users');
    $tabs['logs'] = __('Cache Logs', 'amr-users');
    $tabs['status'] = __('Cache Status', 'amr-users');
    if (isset($_GET['tab'])) {
        if ($_GET['tab'] == 'logs') {
            amr_users_do_tabs($tabs, 'logs');
            amrmeta_cache_logs_page();
            return;
        } elseif ($_GET['tab'] == 'status') {
            amr_users_do_tabs($tabs, 'status');
            amrmeta_cachestatus_page();
            return;
        }
    }
    amr_users_do_tabs($tabs, 'settings');
    //amr_meta_main_admin_header('Cache Settings');
    amr_meta_admin_headings($plugin_page = '');
    // does the nonce check etc
    if (!ameta_cache_enable() or !ameta_cachelogging_enable()) {
        echo '<h2>Problem creating DB tables</h2>';
    }
    if (isset($_POST['action']) and $_POST['action'] == "save") {
        amrmeta_validate_cache_settings();
    }
    if (isset($_REQUEST['rebuildback'])) {
        echo '<p>' . __('Background cache request received', 'amr-users') . '</p>';
        if (isset($_REQUEST['rebuildreal'])) {
            $ulist = (int) $_REQUEST['rebuildreal'];
            amr_request_cache_with_feedback($ulist);
        } else {
            amr_request_cache_with_feedback();
        }
        return;
    } elseif (isset($_REQUEST['rebuildreal'])) {
        /* can only do one list at a time in realtime */
        $ulist = (int) $_REQUEST['rebuildreal'];
        amr_rebuild_in_realtime_with_info($ulist);
        //echo amr_build_cache_for_one($_REQUEST['rebuildreal']);
        //echo '<h2>'.sprintf(__('Cache rebuilt for %s ','amr-users'),$_REQUEST['rebuildreal']).'</h2>'; /* check that allowed */
        //echo au_view_link(__('View Report','amr-users'), $_REQUEST['rebuildreal'], __('View the recently cached report','amr-users'));
        return;
    } else {
        /* validation will have been done */
        $freq = array('notauto' => __('No scheduled auto cacheing', 'amr-users'), 'hourly' => __('Hourly', 'amr-users'), 'twicedaily' => __('Twice daily', 'amr-users'), 'daily' => __('Daily', 'amr-users'));
        if (!isset($amain['cache_frequency'])) {
            $freqchosen = 'notauto';
        } else {
            $freqchosen = $amain['cache_frequency'];
        }
        echo '<h3>';
        _e('Activate regular cache rebuild ? ', 'amr-users');
        echo '</h3><span><em>';
        echo '<p>';
        _e('This cacheing grabs all the raw data it can find and does some preprocessing. ', 'amr-users');
        echo '<br />';
        _e('The data is stored in a flat db table for later formatting and reporting. ', 'amr-users');
        echo '</p>';
        echo '<p>';
        _e('The cache log will tell you the last few times that the cache was rebuilt and why. ', 'amr-users');
        echo '<a href="' . admin_url('admin.php?page=ameta-admin-cache-settings.php&tab=logs') . '">' . __('Go to cache log', 'amr-users') . '</a>';
        echo '<br />';
        _e('A cron plugin may also be useful.', 'amr-users');
        echo ' <a href="http://wpusersplugin.com/related-plugins/amr-cron-manager/">amr cron manager</a>';
        echo '</p>';
        echo '<p><a target="_blank" href="http://wpusersplugin.com/3458/cacheing-amr-users/">' . __('More information', 'amr-users') . '</a></p>';
        echo '</em>	</span>	<p>';
        /*		echo '<label for="notonuserupdate">
        			<input type="checkbox" size="2" id="notonuserupdate" 
        				name="notonuserupdate" ';
        		echo (empty($amain['notonuserupdate'])) ? '' :' checked="checked" '; 
        		echo '/>';
        		_e('Do NOT re-cache on user update', 'amr-users'); 
        		echo '</label>';
        */
        echo '<ul><li>';
        echo '<label for="notonuserupdate">
			<input type="radio" size="2" id="notonuserupdate" 
				name="notonuserupdate" value="true"';
        echo empty($amain['notonuserupdate']) ? '' : ' checked="checked" ';
        echo '/>';
        _e('Do NOT re-cache on user update', 'amr-users');
        echo '</label>';
        echo '</li><li>';
        //echo '<br />';
        echo '<label for="doonuserupdate">
			<input type="radio" size="2" id="doonuserupdate" 
				name="notonuserupdate" value="false"';
        echo $amain['notonuserupdate'] ? '' : ' checked="checked" ';
        echo '/>';
        _e('Do re-cache on user update', 'amr-users');
        echo '</label>';
        echo '</li></ul>';
        echo '</p><br />';
        echo '<br />';
        echo '<p><em><b>';
        _e('If you have very frequent user updates consider only cacheing at regular intervals', 'amr-users');
        echo '</b> ';
        _e('This will help prevent excessive database activity', 'amr-users');
        echo '<br />';
        _e('EG: Are you tracking every page ? every login.. you do not want it recaching all the time?!', 'amr-users');
        _e('Rather cache hourly only.  A refresh can be requested.', 'amr-users');
        echo '<br />';
        _e('Wordpress transients are also used to cache the html in public lists and front end', 'amr-users');
        echo '</em></p>';
        echo '<p><em><b>';
        _e('To switch off all auto cacheing, select "Do not.." above AND "No..." below.', 'amr-users');
        echo '</b><br />';
        _e('Lists will then be re-generated on manual refresh request only.', 'amr-users');
        echo '</em></p>';
        foreach ($freq as $i => $f) {
            echo '<label><input type="radio" name="cache_frequency" value="' . $i . '" ';
            if ($i == $freqchosen) {
                echo ' checked="checked" ';
            }
            echo '/>';
            echo $f;
            echo '</label><br />';
        }
        echo alist_update();
        echo alist_rebuild();
    }
    echo ausers_form_end();
}
function amr_check_for_upgrades()
{
    // NB must be in order of the oldest changes first // called from ausers_get_option
    // should already have values then - and will not be new ?
    global $amain, $aopt;
    if (empty($amain)) {
        $amain = ausers_get_option('amr-users-main');
    }
    //if (WP_DEBUG) echo '<div class="message">Debug mode: check doing upgrade check </div>';
    // must be in admin and be admin
    if (!is_admin() or !current_user_can('manage_options')) {
        return;
    }
    // handle a series of updates in order
    if (!isset($amain['version'])) {
        $amain['version'] = '0';
    }
    // really old?
    if (version_compare($amain['version'], AUSERS_VERSION, '=')) {
        return;
    }
    // if same version, don't repeat check
    $prev = $amain['version'];
    echo PHP_EOL . '<div class="updated"><p>';
    // closing div at end
    printf(__('Previous version was %s. ', 'amr-users'), $prev);
    _e('New version activated. ', 'amr-users');
    _e('We may need to process some updates.... checking now... ', 'amr-users');
    // do old changes first - user may not have updated for a while....
    if (!isset($amain['version']) or version_compare($amain['version'], '3.1', '<')) {
        // convert old options from before 3.1
        echo '<br />';
        printf(__('Prev version less than %s', 'amr-users'), '3.1.');
        if (!isset($amain['csv_text'])) {
            $amain['csv_text'] = '<img src="' . plugins_url('amr-users/images/file_export.png') . '" alt="' . __('Csv', 'amr-users') . '"/>';
        }
        if (!isset($amain['refresh_text'])) {
            $amain['refresh_text'] = '<img src="' . plugins_url('amr-users/images/rebuild.png') . '" alt="' . __('Refresh user list cache', 'amr-users') . '"/>';
        }
        ausers_update_option('amr-users-main', $amain);
        echo '<br />' . __('Image links updated.', 'amr-users');
        echo '</p>';
    }
    //
    if (!isset($amain['version']) or version_compare($amain['version'], '3.3.1', '<')) {
        // check for before 3.3.1
        echo '<br />';
        printf(__('Prev version less than %s', 'amr-users'), '3.3.1.');
        $c = new adb_cache();
        $c->deactivate();
        if (!ameta_cache_enable() or !ameta_cachelogging_enable()) {
            echo '<h2>' . __('Problem creating amr user DB tables', 'amr-users') . '</h2>';
        }
        echo '<br />';
        _e('Cacheing tables recreated.', 'amr-users');
    }
    //
    if (!isset($amain['version']) or version_compare($amain['version'], '3.3.6', '<')) {
        // check for before 3.3.6,
        echo '<br />';
        printf(__('Prev version less than %s', 'amr-users'), '3.3.6. ');
        echo '</p>' . __('Minor sub option name change for avatar size', 'amr-users') . '</p>';
        if (!empty($amain['avatar-size'])) {
            $amain['avatar_size'] = $amain['avatar-size'];
        } else {
            $amain['avatar_size'] = '16';
        }
        unset($amain['avatar-size']);
        ausers_update_option('amr-users-main', $amain);
    }
    // 3.4.4  July 2012
    if (!isset($amain['version']) or version_compare($amain['version'], '3.4.4', '<')) {
        // check for before 3.3.,
        echo '<br />';
        printf(__('Prev version less than %s', 'amr-users'), '3.4.4 ');
        echo '<p><b>' . __('New Pagination option default to yes for all lists.', 'amr-users') . '</b></p>';
        if (!isset($amain['show_pagination'])) {
            foreach ($amain['names'] as $i => $n) {
                $amain['show_pagination'][$i] = true;
            }
        }
    }
    $amain['version'] = AUSERS_VERSION;
    ausers_update_option('amr-users-main', $amain);
    // was 'amr-users-no-lists'
    echo '<p>' . __('Finished Update Checks', 'amr-users') . ' ';
    echo ' <a href="http://wordpress.org/extend/plugins/amr-users/changelog/">' . __('Please read the changelog', 'amr-users') . '</a>';
    echo '</p>' . PHP_EOL;
    echo '<br />' . __('As a precaution we will now rebuild the nice names.', 'amr-users');
    echo '<br />' . __('Relax .... you won\'t lose anything.', 'amr-users');
    ameta_rebuildnicenames();
    echo '</div><!-- end updated -->' . PHP_EOL;
}
function amr_get_alluserdata($list)
{
    /*  get all user data and attempt to extract out any object values into arrays for listing  */
    global $excluded_nicenames, $amain, $aopt, $orig_mk, $amr_current_list;
    $amr_current_list = $list;
    $main_fields = amr_get_usermasterfields();
    // mainwpuser fields less any excluded in nice names
    // 	maybe use, but no major improvement for normal usage add_filter( 'pre_user_query', 'amr_add_where');
    if (!($orig_mk = ausers_get_option('amr-users-original-keys'))) {
        $orig_mk = array();
    }
    //
    //	track_progress ('Meta fields we could use to improve selection: '.print_r($orig_mk, true));
    $combofields = amr_get_combo_fields($list);
    $role = '';
    $mkeys = array();
    if (!empty($aopt['list'][$list]['included'])) {
        // if we have fields that are in main user table, we could add - but unliket as selection criteria - more in search
        foreach ($aopt['list'][$list]['included'] as $newk => $choose) {
            if (isset($orig_mk[$newk])) {
                $keys[$orig_mk[$newk]] = true;
            }
            if ($newk == 'first_role') {
                if (is_array($choose)) {
                    $role = array_pop($choose);
                } else {
                    $role = $choose;
                }
            }
            if (isset($orig_mk[$newk]) and $newk == $orig_mk[$newk]) {
                // ie it is an original meta field
                if (is_array($choose)) {
                    if (count($choose) == 1) {
                        $choose = array_pop($choose);
                        $compare = '=';
                    } else {
                        $compare = 'IN';
                    }
                } else {
                    $compare = '=';
                }
                $meta_query[] = array('key' => $newk, 'value' => $choose, 'compare' => $compare);
            }
        }
    }
    // now try for exclusions
    if (!empty($aopt['list'][$list]['excluded'])) {
        foreach ($aopt['list'][$list]['excluded'] as $newk => $choose) {
            if (isset($orig_mk[$newk])) {
                $keys[$orig_mk[$newk]] = true;
                // we need to fetch a meta value
                if ($newk == $orig_mk[$newk]) {
                    // ie it is an original meta field 1 to 1
                    if (is_array($choose)) {
                        if (count($choose) == 1) {
                            $choose = array_pop($choose);
                            $compare = '!=';
                        } else {
                            $compare = 'NOT IN';
                        }
                    } else {
                        $compare = '!=';
                    }
                    $meta_query[] = array('key' => $newk, 'value' => $choose, 'compare' => $compare);
                }
            }
        }
        // end for each
    }
    // now need to make sure we find all the meta keys we need
    foreach (array('selected', 'excludeifblank', 'includeonlyifblank', 'sortby') as $v) {
        if (!empty($aopt['list'][$list][$v])) {
            foreach ($aopt['list'][$list][$v] as $newk => $choose) {
                if (isset($orig_mk[$newk])) {
                    // ie it is FROM an original meta field
                    $keys[$orig_mk[$newk]] = true;
                }
            }
        }
    }
    if (!empty($aopt['list'][$list]['grouping'])) {
        foreach ($aopt['list'][$list]['grouping'] as $i => $newk) {
            if (isset($orig_mk[$newk])) {
                // ie it is FROM an original meta field
                $keys[$orig_mk[$newk]] = true;
            }
        }
    }
    $args = array();
    $users = array();
    // to handle in weird situation of no users - eg if db corrupt!
    if (!empty($role)) {
        $args['role'] = $role;
    }
    if (!empty($meta_query)) {
        $args['meta_query'] = $meta_query;
    }
    //if (!empty ($fields) ) $args['fields'] = $fields;
    //$args['fields'] = 'all_with_meta'; //might be too huge , but fast - DOES NOT GET META DATA ?? and/or only gets single values
    //track_progress ('Simple meta selections to pass to query: '.print_r($args, true));
    if (is_network_admin() or amr_is_network_admin()) {
        //if (WP_DEBUG) {echo '<br/>';if (is_network_admin()) echo 'network admin'; else echo 'NOT network admin but treating as is';}
        $args['blog_id'] = '0';
    }
    if (isset($amain['use_wp_query'])) {
        //hmm always doing this
        $all = get_users($args);
        // later - add selection if possible here to reduce memory requirements
        //if (WP_DEBUG) {echo '<br/>Fetched with wordpress query.  No. of records found: <b>'.count($all).'</b><br /> using args: '; var_dump($args); }
    } else {
        //if (WP_DEBUG) echo '<br/>if WP_DEBUG: Fetching with own query ';
        $all = amru_get_users($args);
        // later - add selection if possible here to reduce memory requirements
        //if (WP_DEBUG) {echo '<br/>Fetched with own query.  No. of records found: <b>'.count($all).'</b><br /> using args: '; var_dump($args); }
    }
    //track_progress('after get wp users, we have '.count($all));
    foreach ($all as $i => $userobj) {
        // build our user array and add any missing meta
        // save the main data, toss the rest
        foreach ($main_fields as $i2 => $v2) {
            //$users[$i][$v2] = $userobj->$v2;
            if (!empty($userobj->{$v2})) {
                $users[$userobj->ID][$v2] = $userobj->{$v2};
            }
            //OBJECT_K does not always seem to key the array correctly
        }
        // -------------------------------------------------------------------
        // we just need to expand the meta data
        if (!empty($keys)) {
            // - the list of metadata keys.  If we have some meta data requested, and most of the time we will
            foreach ($keys as $i2 => $v2) {
                //if (!isset($userobj->$i2)) {  // in some versions the overloading does not work - only fetches 1
                //$userobj->$i2 = get_user_meta($userobj->ID, $i2, false);
                //wordpress does some kind of overloading to fetch meta data  BUT above only fetches single
                $test = get_user_meta($userobj->ID, $i2, false);
                // get as array in case there are multiple values
                if (!empty($test)) {
                    //if (WP_DEBUG) echo 'i2='.$i2;var_dump($test);
                    if (is_array($test)) {
                        // because we are now checking for multiple values so it returns an array
                        if (count($test) == 1) {
                            // one record, single value returned
                            $temp = current($test);
                            // there is only one - get it without taking it out of array
                            //$temp = array_pop($test);  // get that one record
                            //if (WP_DEBUG) {var_dump($temp);}
                            // oh dear next code broke those nasty complex s2membercustom fields
                            // but it's the way to deal with non associative arrays
                            if (is_array($temp)) {
                                // if that one record is an array - hope to hell that's the end of the nested arrays, but now it wont be
                                if (!amr_is_assoc($temp)) {
                                    // if it is a numeric keyed array, cannot handle as per associative array
                                    // ideally no spaces here BUT if there is no custom formatting routine to explode and re-implode, then folks complain about lack of space between.   NB Check impact on filter values.  (explode with spaces perhaps?)
                                    //$temp = implode (',',$temp);  // 20140305 space sinformatting only - not here
                                    $temp = implode(', ', $temp);
                                    // must be a list of values ? implode here or later?
                                    // or should we force it into a mulit meta array ?
                                }
                                // else	leave as is for further processing
                                //else var_dump($temp);
                            }
                            $userobj->{$i2} = $temp;
                            // save it as our value
                            //$userobj->$i2 = array_pop($test); // cannot indirectly update an overloaded value
                            //if (WP_DEBUG) {echo '<br />save obj: ';var_dump($userobj->$i2);}
                        } else {
                            // we got multple meta records - ASSUME for now it is a good implementation and the values are 'simple'
                            // otherwise they really should create their meta data a better way. Can't solve everyones problems.
                            $userobj->{$i2} = implode(', ', $test);
                        }
                    } else {
                        $userobj->{$i2} = $test;
                    }
                    $temp = maybe_unserialize($userobj->{$i2});
                    // in case anyone done anything weird
                    //gravity forms has weird serialised nested array - argghh
                    $temp = objectToArray($temp);
                    /* must do all so can cope with incomplete objects  eg: if the creating plugin has been uninstalled*/
                    $key = str_replace(' ', '_', $i2);
                    /* html does not like spaces in the names*/
                    if (is_array($temp)) {
                        if (count($temp) == 1) {
                            // one record, single value returned - will fix that annoying gravity form emergency contact thing
                            // oh dear but broke the single capability thing
                            if (!current($temp) == true and !current($temp) == '1') {
                                // ie not a capability thing
                                $temp = array_pop($temp);
                            }
                            // its a usable value and
                        }
                    }
                    if (is_array($temp)) {
                        // if it is still an array inside
                        //if (WP_DEBUG) {echo '<br/>Got an array'; var_dump($temp);}
                        foreach ($temp as $i3 => $v3) {
                            $key = $i2 . '-' . str_replace(' ', '_', $i3);
                            /* html does not like spaces in the names*/
                            //if (WP_DEBUG) {echo '<br/>Got an array - key'; var_dump($key);}
                            if (is_array($v3)) {
                                //if (WP_DEBUG) {echo '<br/>Got an nested array'; }
                                // code just in case another plugin nests deeper, until we know tehre is one, let us be more efficient
                                if (amr_is_assoc($v3)) {
                                    // does not yet handle, just dump values for now
                                    // really shouldn't be nested this deep associativey - bad
                                    $users[$i][$key] = implode(", ", $v3);
                                    //if (WP_DEBUG) {echo '<br/>Got associative array:'.$i2.' '.$i3; var_dump($users[$i][$key]);}
                                } else {
                                    // is numeric array eg s2member custom multi choice
                                    $users[$userobj->ID][$key] = implode(", ", $v3);
                                }
                            } else {
                                $users[$userobj->ID][$key] = $v3;
                            }
                        }
                    } else {
                        $users[$userobj->ID][$key] = $temp;
                        //if (WP_DEBUG) {echo '<br/>Not an array'; var_dump($temp);}
                    }
                    unset($temp);
                    // we could add some include / exclude checking here?
                    //if (WP_DEBUG) var_dump($users[$userobj->ID]);
                }
            }
            /// end for each keys
        }
        //
        unset($all[$i]);
    }
    // end for each all
    unset($all);
    $users = apply_filters('amr_get_users', $users);
    // allow addition or removal of normal wp users who will have userid, and /or any other data
    //track_progress('after get users meta check '.(count($users)));
    $post_types = get_post_types();
    /* get the extra count data */
    if (amr_need_the_field($list, 'comment_count')) {
        $c = get_commentnumbers_by_author();
    } else {
        $c = array();
    }
    //track_progress('after get comments check');
    if (!empty($users)) {
        foreach ($users as $iu => $u) {
            // do the comments
            if (isset($u['ID']) and isset($c[$u['ID']])) {
                $users[$iu]['comment_count'] = $c[$u['ID']]++;
                /*** would like to cope with situation of no userid, but awkward here */
            }
            // do the post counts
            foreach ($post_types as $post_type) {
                if (amr_need_the_field($list, $post_type . '_count')) {
                    $users[$iu][$post_type . '_count'] = amr_count_user_posts($u['ID'], $post_type);
                    //					if ()WP_DEBUG) echo '<br />**'.$post_type.' '.$list[$iu][$post_type.'_count'];
                    //					$list[$iu]['post_count'] = get_usernumposts($u['ID']); /* wordpress function */
                    if ($users[$iu][$post_type . '_count'] == 0) {
                        unset($users[$iu][$post_type . '_count']);
                    }
                }
            }
            if (amr_need_the_field($list, 'first_role')) {
                $user_object = new WP_User($u['ID']);
                if (!empty($user_object->roles)) {
                    $users[$iu]['first_role'] = amr_which_role($user_object);
                }
                if (empty($users[$iu]['first_role'])) {
                    unset($users[$iu]['first_role']);
                }
            }
        }
    }
    //track_progress('after post types and roles:'.count($users));
    unset($c);
    $users = apply_filters('amr_get_users_with_meta', $users);
    // allow addition of users from other tables with own meta data
    //track_progress('after user filter, have'.count($users));
    if (empty($users)) {
        return false;
    }
    return $users;
}
function ameta_list_excluded_keys()
{
    global $wpdb;
    //we need to allow manual exclusion of metakeys becuase of s2members strange time keys on access_cap_limits and who knows there might be others.
    if (!($excluded_meta_keys = ausers_get_option('amr-users-excluded-meta-keys'))) {
        $excluded_meta_keys = amr_default_excluded_metakeys();
    }
    // check if we have any new keys since last time, no need to fetch
    $q = "SELECT meta_key, COUNT(umeta_id) AS Count FROM {$wpdb->usermeta} GROUP BY meta_key";
    $allkeys = $wpdb->get_results($q, ARRAY_A);
    $num_keys = count($allkeys);
    $exc_keys = 0;
    foreach ($allkeys as $i => $row) {
        if (!isset($excluded_meta_keys[$row['meta_key']])) {
            $excluded_meta_keys[$row['meta_key']] = false;
            //echo '<br />'.__('Added meta to report DB: ','amr-users').$row['meta_key'];
        }
        if ($excluded_meta_keys[$row['meta_key']]) {
            $exc_keys = $exc_keys + 1;
        }
        $totals[$row['meta_key']] = $allkeys[$i]['Count'];
    }
    ksort($excluded_meta_keys);
    echo PHP_EOL . '<div class="clear"> </div>' . PHP_EOL;
    echo '<div><!-- excluded keys list-->';
    echo '<h2>' . __('User meta keys in this site today', 'amr-users') . ' (' . $num_keys . ') - ' . sprintf(__('%s excluded', 'amr-users'), $exc_keys) . '</h2>';
    echo '<ul>' . '<li>' . __('Extracts the current distinct user meta keys used', 'amr-users') . ' - <strong>' . __('Sample data MUST exist!', 'amr-users') . '</strong>' . '</li>' . '</ul>';
    echo ameta_keys_update_buttons();
    // the buttons
    echo '<table class="widefat">';
    echo '<tr><th>' . __('Meta Key', 'amr-users') . '</th>' . '<th>' . __('Exclude?', 'amr-users') . '</th>' . '<th>' . __('Delete meta records?', 'amr-users') . '</th>' . '</tr>';
    foreach ($excluded_meta_keys as $i => $v) {
        if (empty($totals[$i])) {
            continue;
        }
        //ie it has not been deleted since we saved
        echo "\n\t" . '<tr>' . '<td>' . $i . '</td><td>';
        if ($i === 'ID') {
            echo ' ';
        } else {
            echo '<input type="checkbox" id="mex' . $i . '"  name="mex[' . $i . ']"';
            if (!empty($excluded_meta_keys[$i])) {
                echo ' value=true checked="checked" ';
            }
            echo ' />';
        }
        echo '</td><td>';
        if ($i === 'ID') {
            echo ' ';
        } else {
            echo '<input type="checkbox" id="del' . $i . '"  name="del[' . $i . ']"';
            echo ' />';
            echo ' (' . $totals[$i] . ')';
        }
        echo '</td></tr>';
    }
    echo "\n\t" . '</table>' . PHP_EOL . '</div><!-- excluded keys list-->' . PHP_EOL;
    return;
}
function add_amr_stylesheet()
{
    global $amain;
    if (empty($amain)) {
        $amain = ausers_get_option('amr-users-main');
    }
    if (isset($amain['do_not_use_css']) and $amain['do_not_use_css']) {
        return;
    }
    if (!empty($amain['use_css_on_pages'])) {
        $do_css = false;
        $csspages = explode(',', $amain['use_css_on_pages']);
        foreach ($csspages as $csspage) {
            if ($do_css = is_page($csspage)) {
                break;
            }
        }
        if (!$do_css) {
            return;
        }
    }
    $myStyleUrl = AUSERS_URL . 'css/amrusersfront.css';
    $myStyleFile = AUSERS_DIR . 'css/amrusersfront.css';
    if (file_exists($myStyleFile)) {
        wp_register_style('amrusers', $myStyleUrl);
        wp_enqueue_style('amrusers');
    }
}
function amrmeta_listfields($listindex = 1)
{
    global $aopt;
    global $amain;
    global $amr_nicenames, $excluded_nicenames, $ausersadminurl;
    $linktypes = amr_linktypes();
    /* check if we have some options already in Database. - use their names, if not, use default, else overwrite .*/
    if (!($checkifusingdefault = ausers_get_option('amr-users-nicenames')) or empty($amr_nicenames)) {
        //$text = __('Possible fields not configured! default list being used. Please build complete nicenames list.','amr-users');
        amrmeta_check_find_fields();
        exit;
    }
    $config =& $aopt['list'][$listindex];
    $sel =& $config['selected'];
    /* sort our controlling index by the selected display order for ease of viewing */
    foreach ($amr_nicenames as $i => $n) {
        if (isset($config['selected'][$i]) or isset($config['sortby'][$i]) or isset($config['included'][$i]) or isset($config['includeonlyifblank'][$i]) or isset($config['excluded'][$i]) or isset($config['excludeifblank'][$i]) or isset($config['sortdir'][$i])) {
            $keyfields[$i] = $i;
        }
    }
    if (isset($keyfields)) {
        $nicenames = auser_sortbyother($amr_nicenames, $keyfields);
    } else {
        $nicenames = $amr_nicenames;
    }
    if (count($sel) > 0) {
        uasort($sel, 'amr_usort');
        $nicenames = auser_sortbyother($nicenames, $sel);
        /* sort for display with the selected fields first */
    }
    echo '<br /><p class="clear"><input id="submit" class="button-primary" type="submit" name="updateoverview" value="';
    _e('Update overview settings', 'amr-users');
    echo '" />' . '&nbsp;<a href="' . wp_nonce_url($ausersadminurl . '?page=ameta-admin-general.php&tab=overview', 'amr-meta') . '" title="' . __('Go to overview of all lists', 'amr-users') . '" >' . __('Manage lists', 'amr-users') . '</a>' . '&nbsp;|&nbsp;<a href="' . wp_nonce_url($ausersadminurl . '?page=ameta-admin-general.php&tab=fields', 'amr-meta') . '" title="' . __('Find Fields (must have sample data in them)', 'amr-users') . '" >' . __('Find Fields', 'amr-users') . '</a>' . '</p>';
    amr_meta_overview_onelist_headings();
    amr_meta_overview_onelist_headings_middle();
    amr_meta_overview_onelist_settings($listindex);
    amr_meta_overview_onelist_headings_end();
    echo '<br /><br />';
    echo PHP_EOL . '<div class="wrap">' . PHP_EOL . '<input id="submit" class="button-primary" type="submit" name="update" value="';
    _e('Update field settings', 'amr-users');
    echo '" />&nbsp;';
    amr_userlist_submenu($listindex);
    echo '<br />';
    echo PHP_EOL . '<div class="clear userlistfields">';
    echo '<table class="widefat" style="padding-right: 2px;"><thead  style="text-align:center;"><tr>' . PHP_EOL . '<th style="text-align:right;">' . __('Field name', 'amr-users') . '</th>' . PHP_EOL . '<th style="width:1em;"><a href="#" title="' . __('Blank to hide, Enter a number to select and specify column order.  Eg: 1 2 6 8', 'amr-users') . '"> ' . __('Display order', 'amr-users') . '</a></th>' . PHP_EOL . '<th><a href="#" title="' . __('Html to appear before if there is a value', 'amr-users') . '"> ' . __('Before:', 'amr-users') . '</a></th>' . PHP_EOL . '<th><a href="#" title="' . __('Html to appear after if there is a value', 'amr-users') . '"> ' . __('After:', 'amr-users') . '</a></th>' . PHP_EOL . '<th style="width:2em;"><a href="#" title="' . __('Type of link to be generated on the field value', 'amr-users') . '"> ' . __('Link Type:', 'amr-users') . '</a></th>' . PHP_EOL . '<th><a href="#" title="' . __('Eg: value1,value2', 'amr-users') . '"> ' . __('Include:', 'amr-users') . '</a></th>' . PHP_EOL . '<th><a href="#" title="' . __('Tick to include a user ONLY if there is no value', 'amr-users') . '"> ' . __('Include ONLY if Blank:', 'amr-users') . '</a></th>' . PHP_EOL . '<th><a href="#" title="' . __('Eg: value1,value2.', 'amr-users') . ' ' . __('Display the field to set up the exclusion, then you can undisplay it afterwards.', 'amr-users') . '"> ' . __('But Exclude:', 'amr-users') . '</a></th>' . PHP_EOL . '<th><a href="#" title="' . __('Tick to exclude a user if there is no value', 'amr-users') . '"> ' . __('Exclude if Blank:', 'amr-users') . '</a></th>' . PHP_EOL . '<th style="width:1em;"><a href="#" title="' . __('Enter integers, need not be contiguous', 'amr-users') . ' ' . __('Maximum 2 sort level. Can switch off display.', 'amr-users') . '"> ' . __('Sort Order:', 'amr-users') . '</a></th>' . PHP_EOL . '<th style="width:2em;"><a href="#" title="' . __('For sort order.  Default is ascending', 'amr-users') . '"> ' . __('Sort Descending:', 'amr-users') . '</a></th>' . PHP_EOL . '</tr></thead><tbody>';
    foreach ($nicenames as $i => $f) {
        /* list through all the possible fields*/
        echo PHP_EOL . '<tr>';
        $l = 'l' . $listindex . '-' . $i;
        if ($i === 'comment_count') {
            $f .= '<a title="' . __('Explanation of comment total functionality', 'amr-users') . '" href="http://wpusersplugin.com/comment-totals-by-authors/">**</a>';
        }
        echo '<td style="text-align:right;">' . $f . '</td>';
        echo '<td><input type="text" size="1" id="' . $l . '" name="list[' . $listindex . '][selected][' . $i . ']"' . ' value="';
        if (isset($sel[$i]) or !empty($config['included'][$i]) or !empty($config['excluded'][$i]) or !empty($config['excludeifblank'][$i]) or !empty($config['includeonlyifblank'][$i]) or !empty($config['sortby'][$i]) or !empty($config['sortdir'][$i])) {
            if (isset($sel[$i])) {
                echo $sel[$i];
            }
            echo '" /></td>';
            if (!empty($sel[$i])) {
                /* don't need label - use previous lable*/
                echo '<td><input type="text" size="10"  name="list[' . $listindex . '][before][' . $i . ']"';
                if (isset($config['before'][$i])) {
                    echo ' value="' . stripslashes($config['before'][$i]) . '"';
                }
                //handle slashes returned by quotes
                echo ' /></td>';
                // do not use htmlentities2 here - break foreigh chars
                echo '<td><input type="text" size="10"  name="list[' . $listindex . '][after][' . $i . ']"';
                if (isset($config['after'][$i])) {
                    echo ' value="' . stripslashes($config['after'][$i]) . '"';
                }
                echo ' /></td>';
            } else {
                echo '<td>-</td><td>-</td>';
            }
            if (isset($sel[$i]) and !strpos($sel[$i], '.')) {
                // if not a partial cell, then can have link type
                //if (isset($sel[$i]) and !strpos($sel[$i],'.')) {
                echo '<td><select id="links' . $l . '" ' . ' name="list[' . $listindex . '][links][' . $i . ']" >';
                foreach ($linktypes as $lti => $linktype) {
                    echo ' <option value="' . $lti . '" ';
                    if (!empty($config['links'][$i]) and $config['links'][$i] === $lti) {
                        echo ' selected = "selected" ';
                    }
                    echo ' >' . $linktype . '</option>';
                }
                echo '</select></td>';
            } else {
                echo '<td>-</td>';
            }
            //	echo '<td><select name="list['.$listindex.'][included]['.$i.']"';
            //	echo amr_users_dropdown ($choices, $config['included'][$i]);
            //	echo '</select>';
            echo '<td><input type="text" size="20"  name="list[' . $listindex . '][included][' . $i . ']"';
            if (isset($config['included'][$i])) {
                echo ' value="' . implode(',', $config['included'][$i]) . '"';
            }
            echo ' /></td>';
            $l = 'c' . $listindex . '-' . $i;
            echo '<td><input type="checkbox"  name="list[' . $listindex . '][includeonlyifblank][' . $i . ']"';
            if (isset($config['includeonlyifblank'][$i])) {
                echo ' checked="checked" />';
                if (isset($config['excludeifblank'][$i])) {
                    /* check for inconsistency and flag */
                    echo '<span style="color:#D54E21; font-size:larger;">*</span>';
                }
            } else {
                echo '/>';
            }
            echo '</td>';
            $l = 'x' . $listindex . '-' . $i;
            echo '<td><input type="text" size="20" id="' . $l . '" name="list[' . $listindex . '][excluded][' . $i . ']"';
            if (isset($config['excluded'][$i])) {
                if (is_array($config['excluded'][$i])) {
                    $val = implode(',', $config['excluded'][$i]);
                } else {
                    $val = $config['excluded'][$i];
                }
                echo ' value="' . $val . '"';
            }
            echo ' /></td>';
            $l = 'b' . $listindex . '-' . $i;
            echo '<td><input type="checkbox" id="' . $l . '" name="list[' . $listindex . '][excludeifblank][' . $i . ']"';
            if (isset($config['excludeifblank'][$i])) {
                echo ' checked="checked" />';
                if (isset($config['includeonlyifblank'][$i])) {
                    /* check for inconsistency and flag */
                    echo '<span style="color:#D54E21; font-size:larger;">*</span>';
                }
            } else {
                echo '/>';
            }
            echo '</td>';
            $l = 's' . $listindex . '-' . $i;
            echo '<td>' . '<input type="text" size="2" id="' . $l . '" name="list[' . $listindex . '][sortby][' . $i . ']"';
            if (isset($config['sortby'][$i])) {
                echo ' value="' . $config['sortby'][$i] . '"';
            }
            echo ' /></td>' . '<td><input type="checkbox" id="sd' . $l . '" name="list[' . $listindex . '][sortdir][' . $i . ']"';
            echo ' value="SORT_DESC"';
            if (isset($config['sortdir'][$i])) {
                echo ' checked="checked"';
            }
            echo ' />' . '</td>';
        } else {
            echo '" /></td>';
            echo '<td>&nbsp;-&nbsp;</td>' . '<td>&nbsp;-&nbsp;</td>' . '<td>&nbsp;-&nbsp;</td>' . '<td>&nbsp;-&nbsp;</td>' . '<td>&nbsp;-&nbsp;</td>' . '<td>&nbsp;-&nbsp;</td>' . '<td>&nbsp;-&nbsp;</td>' . '<td>&nbsp;-&nbsp;</td>' . '<td>&nbsp;-&nbsp;</td>';
        }
        echo '</tr>';
    }
    echo PHP_EOL . '</tbody></table>';
    echo PHP_EOL . '</div><!-- end userlistfield -->';
    echo PHP_EOL . '</div><!-- end wrap -->';
    return;
}
function ameta_rebuildnicenames()
{
    global $wpdb, $amr_nicenames;
    /*  */
    //	amr_users_message (__('Rebuilding List of possible fields.  This could take a while - I have to query evey meta record, of which there can be multiple for each main record.  Please be patient...', 'amr-users'));
    /* check if we have some options already in Database. - use their names, if not, use default, else overwrite .*/
    flush();
    /* try does not always work */
    $oldnn = ausers_get_option('amr-users-nicenames');
    $nn = ameta_defaultnicenames();
    /* get the default list names required */
    /*	Add any new fields in */
    unset($list);
    $list = amr_get_alluserkeys();
    /* maybe only do this if a refresh is required ? No only happens on admin anyway ? */
    echo '<h3>' . __('Try to make some nicer names.', 'amr-users') . '</h3>';
    /**** wp has changed - need to alllow for prefix now on fields.  Actually due to wpmu - keep the prefix, let the user remove it!  */
    foreach ($list as $i => $v) {
        if (empty($nn[$v])) {
            /* set a reasonable default nice name */
            if (!empty($oldnn[$v])) {
                $nn[$v] = $oldnn[$v];
                //echo '<br />'. sprintf(__('Use existing name %s for %s', 'amr-users'),$nn[$v],$v);
            } else {
                // take the last part of the field only - no not nice too unpredictable
                //$lastdash = strripos($v,'-');
                //$nn[$v] = substr($v, $lastdash);
                $nn[$v] = str_replace('s2member_custom_fields', 's2m', $v);
                // if it is a s2member field - reduce length of name
                $nn[$v] = str_replace('s2member', 's2m', $nn[$v]);
                $nn[$v] = str_replace('capabilities', 'Cap', $nn[$v]);
                $nn[$v] = str_replace('-', ' ', $nn[$v]);
                //		if (isset ($wpdb->prefix)) {$nn[$v] = str_replace ($wpdb->prefix, '', $nn[$v]);}
                /* Note prefix has underscore*/
                $nn[$v] = ucwords(str_replace('_', ' ', $nn[$v]));
                if (function_exists('amr_check_ym_custom_nicenames')) {
                    // look and fix ym custom fields
                    $nn[$v] = amr_check_ym_custom_nicenames($v);
                }
                echo '<br />' . sprintf(__('Created name %s for %s', 'amr-users'), $nn[$v], $v);
            }
        }
    }
    unset($list);
    amr_check_for_table_prefixes($nn);
    ausers_update_option('amr-users-nicenames', $nn);
    $amr_nicenames = $nn;
    return $nn;
}
function amr_meta_general_page_display()
{
    global $amain;
    //amr_mimic_meta_box('related', 'Related plugins','amru_related', true);
    if (empty($amain)) {
        $amain = ausers_get_option('amr-users-main');
    }
    if (empty($amain['csv_text'])) {
        $amain['csv_text'] = '<img src="' . plugins_url('amr-users/images/file_export.png') . '" alt="' . __('Csv', 'amr-users') . '"/>';
    }
    if (empty($amain['refresh_text'])) {
        $amain['refresh_text'] = '<img src="' . plugins_url('amr-users/images/rebuild.png') . '" alt="' . __('Refresh user list cache', 'amr-users') . '"/>';
    }
    if (empty($amain['noaccess_text'])) {
        $amain['noaccess_text'] = __('You do not have access to this list, or are not logged in.', 'amr-users');
    }
    if (!isset($amain['checkedpublic'])) {
        echo '<input type="hidden" name="checkedpublic" value="true"/>';
    }
    if (isset($amain['do_not_use_css']) and $amain['do_not_use_css']) {
        $do_not_use_css = ' checked="checked" ';
    } else {
        $do_not_use_css = '';
    }
    echo PHP_EOL . '<div class="clear wrap">';
    amr_users_say_thanks_opportunity_form();
    echo '<br />';
    echo '<h3>';
    _e('How to fetch data?', 'amr-users');
    echo '</h3><input type="radio"  name="use_wp_query" value="1" ';
    if (!empty($amain['use_wp_query'])) {
        echo ' checked="checked" ';
    }
    echo '> ';
    _e('Fetch user data with wp_query? &nbsp; ', 'amr-users');
    echo ' <em>';
    _e('WordPress does some extra work which requires more memory', 'amr-users');
    echo '</em>';
    echo '<br />';
    //	echo '</label>';
    //	echo '<label for="use_wp_query">';
    echo '<input type="radio"  name="use_wp_query" value="0" ';
    if (empty($amain['use_wp_query'])) {
        echo ' checked="checked" ';
    }
    echo '> ';
    _e('Fetch user data directly? &nbsp; ', 'amr-users');
    echo ' <em>';
    _e('This seems to use less memory, better for very large databases.', 'amr-users');
    echo '</em>';
    echo '<br /><br />';
    //echo '</label>';
    echo '<h3 id="general">' . __('General & Styling', 'amr-users') . '</h3>';
    echo '<label for="do_not_use_css">';
    _e('No css ', 'amr-users');
    echo '</label>
			<input type="checkbox" size="2" id="do_not_use_css" 
					name="do_not_use_css" ';
    echo empty($amain['do_not_use_css']) ? '' : ' checked="checked" ';
    echo '/>';
    echo '<em> ';
    _e('Do not use css provided, my theme css is good enough', 'amr-users');
    echo '</em>';
    echo '<br /><br />';
    if (!empty($amain['do_not_use_css'])) {
        $disabled = ' disabled="disabled" ';
    } else {
        $disabled = '';
    }
    echo '<label for="use_css_on_pages">';
    _e('Use css on these pages only ', 'amr-users');
    echo ' <em>';
    _e('(Else all if using css)', 'amr-users');
    _e('(comma separated integers)', 'amr-users');
    echo ' </em>';
    echo '</label><br />
			<input ' . ' type="text" size="130" id="use_css_on_pages" 
					name="use_css_on_pages" ';
    echo empty($amain['use_css_on_pages']) ? '' : ' value="' . $amain['use_css_on_pages'] . '" ';
    echo '/><br /><br />';
    echo PHP_EOL . '<label for="csv_text">';
    _e('Text for csv link', 'amr-users');
    echo ' <em>';
    _e('(May be plain text or an icon link)', 'amr-users');
    echo ' </em>';
    echo '</label><br />' . PHP_EOL . '<input type="text" size="130" id="csv_text" 
					name="csv_text" value="';
    echo esc_attr($amain['csv_text']);
    echo '"/>' . ' ' . __('Preview:', 'amr-users') . ' ' . '<a href="#" title="' . __('This will be a link', 'amr-users') . '" >' . $amain['csv_text'] . '</a>';
    echo '<br /><br />' . PHP_EOL . '<label for="refresh_text">';
    _e('Text for cache refresh link', 'amr-users');
    echo '</label><br />' . PHP_EOL . '<input type="text" size="130" id="refresh_text" 
					name="refresh_text" value="';
    echo esc_attr($amain['refresh_text']);
    echo '"/>' . ' ' . __('Preview:', 'amr-users') . ' ' . '<a href="#" title="' . __('This will be a link', 'amr-users') . '" >' . $amain['refresh_text'] . '</a>';
    echo '<br /><br />' . PHP_EOL . '<label for="noaccess_text">';
    _e('Message when user does not have access or not logged in.', 'amr-users');
    echo '</label><br />';
    echo '<textarea rows="5" cols="130" id="noaccess_text" 
					name="noaccess_text" />';
    echo esc_attr($amain['noaccess_text']);
    echo '</textarea>';
    echo '<br /><br />
			<label for="rows_per_page">';
    _e('Default rows per page:', 'amr-users');
    echo '</label><br />
			<input type="text" size="2" id="rows_per_page" 
					name="rows_per_page" value="';
    echo empty($amain['rows_per_page']) ? 50 : $amain['rows_per_page'];
    echo '"/><br /><br />
			<label for="avatar_size">';
    _e('Avatar size:', 'amr-users');
    echo ' 20,40, 80, 160, 200 </label>' . '<a title="gravatar size info" href="http://en.gravatar.com/site/implement/images/">' . __('Info', 'amr-users') . '</a>' . '<br />
			<input type="text" size="2" id="avatar_size" 
					name="avatar_size" value="';
    echo empty($amain['avatar_size']) ? '' : $amain['avatar_size'];
    // because it is new and I hate notices
    echo '"/>';
    echo ausers_submit();
    echo '<br />' . PHP_EOL . '</div><!-- end of clear wrap -->	' . PHP_EOL . '<div class="clear"> </div>' . PHP_EOL;
}
function amr_meta_nice_names_page()
{
    /* may be able to work generically */
    global $amr_nicenames;
    global $ausersadminurl;
    //amr_meta_main_admin_header('Find fields, make nice names' );
    amr_meta_admin_headings($plugin_page = '');
    // does the nonce check etc
    if (isset($_POST['action']) and !($_POST['action'] === "save")) {
        return;
    }
    echo PHP_EOL . '<div class="clear" style="clear:both;">&nbsp;</div>' . PHP_EOL;
    if (isset($_POST['update']) and $_POST['update'] === "Update") {
        /* Validate the input and save */
        if (amrmeta_validate_nicenames()) {
            // updates inside the function now
        } else {
            echo '<h2>' . __('Validation failed', 'amr-users') . '</h2>';
        }
    }
    if (isset($_POST['resetnice'])) {
        if (ausers_delete_option('amr-users-nicenames')) {
            echo '<h2>' . __('Deleting all nice name settings in database', 'amr-users') . '</h2>';
        }
        if (ausers_delete_option('amr-users-nicenames-excluded')) {
            echo '<h2>' . __('Deleting all nice name exclusion settings in database', 'amr-users') . '</h2>';
        }
        if (ausers_delete_option('amr-users-original-keys')) {
            echo '<h2>' . __('Deleting original keys mapping in database', 'amr-users') . '</h2>';
        }
    }
    if (isset($_POST['rebuild']) or isset($_POST['resetnice'])) {
        /* Rebuild the nicenames - could take a while */
        $amr_nicenames = ameta_rebuildnicenames();
        echo '<h3>' . __('Rebuild Complete.', 'amr-users') . '</h3>';
        return;
    } else {
        amrmeta_check_find_fields();
    }
    $amr_nicenames = ausers_get_option('amr-users-nicenames');
    ameta_list_nicenames_for_input($amr_nicenames);
}
function amr_get_alluserdata($list)
{
    /*  get all user data and attempt to extract out any object values into arrays for listing  */
    global $excluded_nicenames, $amain, $aopt, $orig_mk, $amr_current_list;
    $amr_current_list = $list;
    $main_fields = amr_get_usermasterfields();
    // mainwpuser fields less any excluded in nice names
    // 	maybe use, but no major improvement for normal usage add_filter( 'pre_user_query', 'amr_add_where');
    if (!($orig_mk = ausers_get_option('amr-users-original-keys'))) {
        $orig_mk = array();
    }
    //
    //	track_progress ('Meta fields we could use to improve selection: '.print_r($orig_mk, true));
    $combofields = amr_get_combo_fields($list);
    $role = '';
    $mkeys = array();
    if (!empty($aopt['list'][$list]['included'])) {
        // if we have fields that are in main user table, we could add - but unliket as selection criateria - more in search
        foreach ($aopt['list'][$list]['included'] as $newk => $choose) {
            if (isset($orig_mk[$newk])) {
                $keys[$orig_mk[$newk]] = true;
            }
            if ($newk == 'first_role') {
                if (is_array($choose)) {
                    $role = array_pop($choose);
                } else {
                    $role = $choose;
                }
            }
            if (isset($orig_mk[$newk]) and $newk == $orig_mk[$newk]) {
                // ie it is an original meta field
                if (is_array($choose)) {
                    if (count($choose) == 1) {
                        $choose = array_pop($choose);
                        $compare = '=';
                    } else {
                        $compare = 'IN';
                    }
                } else {
                    $compare = '=';
                }
                $meta_query[] = array('key' => $newk, 'value' => $choose, 'compare' => $compare);
            }
        }
    }
    // now try for exclusions
    if (!empty($aopt['list'][$list]['excluded'])) {
        foreach ($aopt['list'][$list]['excluded'] as $newk => $choose) {
            if (isset($orig_mk[$newk])) {
                $keys[$orig_mk[$newk]] = true;
                // we need to fetch a meta value
                if ($newk == $orig_mk[$newk]) {
                    // ie it is an original meta field 1 to 1
                    if (is_array($choose)) {
                        if (count($choose) == 1) {
                            $choose = array_pop($choose);
                            $compare = '!=';
                        } else {
                            $compare = 'NOT IN';
                        }
                    } else {
                        $compare = '!=';
                    }
                    $meta_query[] = array('key' => $newk, 'value' => $choose, 'compare' => $compare);
                }
            }
        }
        // end for each
    }
    // now need to make sure we find all the meta keys we need
    foreach (array('selected', 'excludeifblank', 'includeifblank', 'sortby') as $v) {
        if (!empty($aopt['list'][$list][$v])) {
            foreach ($aopt['list'][$list][$v] as $newk => $choose) {
                if (isset($orig_mk[$newk])) {
                    // ie it is FROM an original meta field
                    $keys[$orig_mk[$newk]] = true;
                }
            }
        }
    }
    if (!empty($aopt['list'][$list]['grouping'])) {
        foreach ($aopt['list'][$list]['grouping'] as $i => $newk) {
            if (isset($orig_mk[$newk])) {
                // ie it is FROM an original meta field
                $keys[$orig_mk[$newk]] = true;
            }
        }
    }
    $args = array();
    if (!empty($role)) {
        $args['role'] = $role;
    }
    if (!empty($meta_query)) {
        $args['meta_query'] = $meta_query;
    }
    //if (!empty ($fields) ) $args['fields'] = $fields;
    //$args['fields'] = 'all_with_meta'; //might be too huge , but fast - DOES NOT GET META DATA ?? and/or only gets single values
    //track_progress ('Simple meta selections to pass to query: '.print_r($args, true));
    if (is_network_admin() or amr_is_network_admin()) {
        //if (WP_DEBUG) {echo '<br/>';if (is_network_admin()) echo 'network admin'; else echo 'NOT network admin but treating as is';}
        $args['blog_id'] = '0';
    }
    if (isset($amain['use_wp_query'])) {
        $all = get_users($args);
        // later - add selection if possible here to reduce memory requirements
        if (WP_DEBUG) {
            echo '<br/>Fetched with wordpress query ';
        }
    } else {
        if (WP_DEBUG) {
            echo '<br/>if WP_DEBUG: Fetching with own query ';
        }
        $all = amru_get_users($args);
        // later - add selection if possible here to reduce memory requirements
    }
    //track_progress('after get wp users, we have '.count($all));
    foreach ($all as $i => $userobj) {
        // build our user array and add any missing meta
        // save the main data, toss the rest
        foreach ($main_fields as $i2 => $v2) {
            //$users[$i][$v2] = $userobj->$v2;
            if (!empty($userobj->{$v2})) {
                $users[$userobj->ID][$v2] = $userobj->{$v2};
            }
            //OBJECT_K does not always seem to key the array correctly
        }
        // we just need to expand the meta data
        if (!empty($keys)) {
            // if some meta request
            foreach ($keys as $i2 => $v2) {
                //if (WP_DEBUG) {echo '<br /> Key:'.$i2;}
                //if (!isset($userobj->$i2)) {  // in some versions the overloading does not work - only fetches 1
                //$userobj->$i2 = get_user_meta($userobj->ID, $i2, false);
                //wordpress does some kind of overloading to fetch meta data  BUT above only fetches single
                //				$userobj->$i2  = get_user_meta($userobj->ID, $i2, false); // get as array in case there are multiple values
                $test = get_user_meta($userobj->ID, $i2, false);
                // get as array in case there are multiple values
                if (!empty($test)) {
                    if (is_array($test)) {
                        if (count($test) == 1) {
                            // single value returned
                            $userobj->{$i2} = array_pop($test);
                            // cannot indirectly update an overloaded value
                            //if (WP_DEBUG) {echo '<br /> convert array to 1 value '.$i2.'  ='; var_dump($userobj->$i2);}
                        } else {
                            // we got multple meta records - ASSUME for now it is a good implementation and the values are 'simple'
                            $userobj->{$i2} = implode(',', $test);
                            //if (WP_DEBUG) {echo '<br /> convert array to strings for display '.$i2.'  ='; var_dump($userobj->$i2);}
                        }
                    } else {
                        $userobj->{$i2} = $test;
                    }
                    $temp = maybe_unserialize($userobj->{$i2});
                    // in case anyone done anything weird
                    $temp = objectToArray($temp);
                    /* must do all so can cope with incomplete objects  eg: if creatingplugin has been uninstalled*/
                    $key = str_replace(' ', '_', $i2);
                    /* html does not like spaces in the names*/
                    if (is_array($temp)) {
                        //if (WP_DEBUG) echo '<br/>It is an array now - maybe was object';
                        foreach ($temp as $i3 => $v3) {
                            $key = $i2 . '-' . str_replace(' ', '_', $i3);
                            /* html does not like spaces in the names*/
                            if (is_array($v3)) {
                                // code just in case another plugin nests deeper, until we know tehre is one, let us be more efficient
                                //								if (amr_is_assoc($v3)) { // does not yet handle, just dump values for now
                                //									$users[$i][$key] = implode(", ", $v3);
                                //								}
                                //								else { // is numeric array eg s2member custom multi choice
                                $users[$userobj->ID][$key] = implode(", ", $v3);
                                //								}
                            } else {
                                $users[$userobj->ID][$key] = $v3;
                            }
                        }
                    } else {
                        $users[$userobj->ID][$key] = $temp;
                        //if (WP_DEBUG) {echo '<br/>Not an array'; var_dump($temp);}
                    }
                    unset($temp);
                    // we could add some include / exclude checking here?
                }
            }
            /// end for each keys
        }
        //
        unset($all[$i]);
    }
    // end for each all
    unset($all);
    $users = apply_filters('amr_get_users', $users);
    // allow addition or removal of normal wp users who will have userid, and /or any other data
    //track_progress('after get users meta check '.(count($users)));
    $post_types = get_post_types();
    /* get the extra count data */
    if (amr_need_the_field($list, 'comment_count')) {
        $c = get_commentnumbers_by_author();
    } else {
        $c = array();
    }
    //track_progress('after get comments check');
    if (!empty($users)) {
        foreach ($users as $iu => $u) {
            // do the comments
            //if (WP_DEBUG) {echo '<br />user='******'ID']])) {
                $users[$iu]['comment_count'] = $c[$u['ID']];
                /*** would like to cope with situation of no userid */
            }
            // do the post counts
            foreach ($post_types as $post_type) {
                if (amr_need_the_field($list, $post_type . '_count')) {
                    $users[$iu][$post_type . '_count'] = amr_count_user_posts($u['ID'], $post_type);
                    //					if ()WP_DEBUG) echo '<br />**'.$post_type.' '.$list[$iu][$post_type.'_count'];
                    //					$list[$iu]['post_count'] = get_usernumposts($u['ID']); /* wordpress function */
                    if ($users[$iu][$post_type . '_count'] == 0) {
                        unset($users[$iu][$post_type . '_count']);
                    }
                }
            }
            if (amr_need_the_field($list, 'first_role')) {
                $user_object = new WP_User($u['ID']);
                if (!empty($user_object->roles)) {
                    $users[$iu]['first_role'] = amr_which_role($user_object);
                }
                if (empty($users[$iu]['first_role'])) {
                    unset($users[$iu]['first_role']);
                }
            }
        }
    }
    //track_progress('after post types and roles:'.count($users));
    unset($c);
    $users = apply_filters('amr_get_users_with_meta', $users);
    // allow addition of users from other tables with own meta data
    //track_progress('after user filter, have'.count($users));
    if (empty($users)) {
        return false;
    }
    return $users;
}
 function amr_get_href_link($field, $v, $u, $linktype)
 {
     switch ($linktype) {
         case 'none':
             return '';
         case 'mailto':
             if (!empty($u->user_email)) {
                 return 'mailto:' . $u->user_email;
             } else {
                 return '';
             }
         case 'postsbyauthor':
             // figure out which post type ?
             if (empty($v) or !current_user_can('edit_others_posts')) {
                 return '';
             } else {
                 $href = network_admin_url('edit.php?author=' . $u->ID);
                 if (stristr($field, '_count')) {
                     // it is a item count thing, but not a post count
                     if (is_object($u) and isset($u->ID)) {
                         $ctype = str_replace('_count', '', $field);
                         $href = add_query_arg(array('post_type' => $ctype), $href);
                     }
                     // end if
                 }
                 // end if stristr
                 return $href;
             }
             return '';
         case 'edituser':
             if (current_user_can('edit_users') and is_object($u) and isset($u->ID)) {
                 return network_admin_url('user-edit.php?user_id=' . $u->ID);
             } else {
                 return '';
             }
         case 'authorarchive':
             // should do on a post count only
             if (is_object($u) and isset($u->ID)) {
                 return add_query_arg('author', $u->ID, home_url());
             } else {
                 return '';
             }
         case 'commentsbyauthor':
             if (empty($v) or !($stats_url = ausers_get_option('stats_url'))) {
                 return '';
             } else {
                 return add_query_arg('stats_author', $u->user_login, $stats_url);
             }
         case 'url':
             if (!empty($u->user_url)) {
                 return $u->user_url;
             }
         case 'wplist':
             // for multisite
             if (current_user_can('edit_users') and is_object($u) and isset($u->user_login)) {
                 return network_admin_url('users.php?s=' . $u->user_login);
             }
         case 'bbpressprofile':
             $slug = get_option('_bbp_user_slug');
             $forums = get_option('_bbp_root_slug');
             return home_url('/' . __($forums, 'bbpress') . '/' . __($slug, 'bbpress') . '/' . $u->user_login);
         default:
             return apply_filters('amr-users-linktype-function', $linktype, $u, $field);
             // all the user values
     }
 }
function ameta_options()
{
    // set up all  the options
    global $aopt, $amain, $amr_nicenames, $amr_your_prefixes, $excluded_nicenames, $ausersadminurl, $wpdb;
    if (empty($amain)) {
        $amain = ausers_get_option('amr-users-main');
    }
    $amr_your_prefixes = ausers_get_option('amr-users-prefixes-in-use');
    $amr_nicenames = ausers_get_option('amr-users-nicenames');
    $excluded_nicenames = ausers_get_option('amr-users-nicenames-excluded');
    foreach ($excluded_nicenames as $i => $v) {
        if ($v) {
            unset($amr_nicenames[$i]);
        }
    }
    $aopt = ausers_get_option('amr-users');
    return;
}
function amr_users_get_column_headings($ulist, $cols, $icols)
{
    global $amr_users_column_headings;
    if ($amr_users_column_headings = ausers_get_option('amr-users-custom-headings')) {
        if (!empty($amr_users_column_headings[$ulist])) {
            $customcols = $amr_users_column_headings[$ulist];
            foreach ($icols as $ic => $cv) {
                if (isset($customcols[$cv])) {
                    $cols[$ic] = $customcols[$cv];
                }
            }
            return $cols;
        }
    }
    return $cols;
}