*/
public $fieldPrefix = '';
/**
- * Field processing for various field types
+ * Pseudo-Random Order Key Array - Used for Pseudo-Random database result lists
*
- * @var $f is field data
+ * @access private
+ */
+ public $pseudoRandArray = false;
+ /**
+ * Pseudo-Random Order flag
*
- * @return void
- * @access public
+ * @access private
+ */
+ public $pseudoRand = false;
+
+
+ /*
+ * Field processing for various types of fields
*/
// Integer Field Processing
- function integerField($f)
+ private function integerField($f)
{
return 'T.'.$f['field'];
}
- function integerOptions($f)
+ private function integerOptions($f)
{
return false;
}
- function integerOutput($f, $d)
+ private function integerOutput($f, $d)
{
return $d;
}
- function integerInput($as, $f, $id, $idfield, $op)
+ private function integerInput($as, $f, $id, $idfield, $op)
{
// If this is setup for a new entry, then just return default value
if ($op == 'n') {
return $in;
}
- function integerStore($in, $f)
+ private function integerStore($in, $f)
{
return $in;
}
/*
* Float Field Processing
*/
- function floatField($f)
+ private function floatField($f)
{
return 'T.'.$f['field'];
}
- function floatOptions($f)
+ private function floatOptions($f)
{
return false;
}
- function floatOutput($f, $d)
+ private function floatOutput($f, $d)
{
// if a format is specified
if (isset($f['output_format']) && $f['output_format']) {
return $d;
}
- function floatInput($as, $f, $id, $idfield, $op)
+ private function floatInput($as, $f, $id, $idfield, $op)
{
// If this is setup for a new entry, then just return default value
if ($op == 'n') {
return $in;
}
- function floatStore($in, $f)
+ private function floatStore($in, $f)
{
return $in;
}
/*
* Money Field Processing
*/
- function moneyField($f)
+ private function moneyField($f)
{
return 'T.'.$f['field'];
}
- function moneyOptions($f)
+ private function moneyOptions($f)
{
return false;
}
- function moneyOutput($f, $d)
+ private function moneyOutput($f, $d)
{
return "$".sprintf("%01.2f", $d);
;
}
- function moneyInput($as, $f, $id, $idfield, $op)
+ private function moneyInput($as, $f, $id, $idfield, $op)
{
// If this is setup for a new entry, then just return default value
if ($op == 'n') {
return $in;
}
- function moneyStore($in, $f)
+ private function moneyStore($in, $f)
{
return $in;
}
/*
* Percent Field Processing
*/
- function percentField($f)
+ private function percentField($f)
{
return 'T.'.$f['field'];
}
- function percentOptions($f)
+ private function percentOptions($f)
{
return false;
}
- function percentOutput($f, $d)
+ private function percentOutput($f, $d)
{
return $d;
}
- function percentInput($as, $f, $id, $idfield, $op)
+ private function percentInput($as, $f, $id, $idfield, $op)
{
// If this is setup for a new entry, then just return default value
if ($op == 'n') {
return $in;
}
- function percentStore($in, $f)
+ private function percentStore($in, $f)
{
return $in;
}
/*
* Pointer Field Processing
*/
- function pointerField($f)
+ private function pointerField($f)
{
return 'T.'.$f['field'];
}
- function pointerOptions($f)
+ private function pointerOptions($f)
{
// Get ID field of other table - default to 'id'
return $options;
}
- function pointerOutput($f, $d, $forEdit = false, $id = false, $idfield = 'id')
+ private function pointerOutput($f, $d, $forEdit = false, $id = false, $idfield = 'id')
{
/*
return $d;
}
- function pointerInput($as, $f, $id, $idfield, $op)
+ private function pointerInput($as, $f, $id, $idfield, $op)
{
$this->inputFieldStatus = true;
return $r;
}
- function pointerStore($in, $f)
+ private function pointerStore($in, $f)
{
return $in['value'];
}
/*
* List Field Processing
*/
- function listField($f)
+ private function listField($f)
{
return 'T.'.$f['field'];
}
- function listOptions($f)
+ private function listOptions($f)
{
return false;
}
- function listOutput($f, $d, $forEdit, $id, $idfield, $op)
+ private function listOutput($f, $d, $forEdit, $id, $idfield, $op)
{
// Check for a list data
return $r;
}
- function listInput($as, $f, $id, $idField, $op)
+ private function listInput($as, $f, $id, $idField, $op)
{
// Check for a list data
return $r;
}
- function listStore($in, $f)
+ private function listStore($in, $f)
{
$keytype = 'text';
/*\r
* Bitmap List Field Processing\r
*/\r
- function bitmapField($f)\r
+ private function bitmapField($f)\r
{\r
return 'T.'.$f['field'];\r
}\r
- function bitmapOptions($f)\r
+ private function bitmapOptions($f)\r
{\r
return false;\r
}\r
- function bitmapOutput($f, $d)\r
+ private function bitmapOutput($f, $d)\r
{\r
// Check for a bitmap data\r
if (!isset($f['bitmap']) || !is_array($f['bitmap'])) {\r
return $r;\r
\r
}\r
- function bitmapInput($as, $f, $id, $idField, $op)\r
+ private function bitmapInput($as, $f, $id, $idField, $op)\r
{\r
// Check for a bitmap data
\r
return $r;\r
}\r
- function bitmapStore($in, $f)\r
+ private function bitmapStore($in, $f)\r
{\r
$keytype = 'text';\r
\r
/*
* Text Field Processing
*/
- function textField($f)
+ private function textField($f)
{
return 'T.'.$f['field'];
}
- function textOptions($f)
+ private function textOptions($f)
{
return false;
}
- function textOutput($f, $d)
+ private function textOutput($f, $d)
{
return $d;
}
- function textInput($as, $f, $id, $idField, $op)
+ private function textInput($as, $f, $id, $idField, $op)
{
// If this is setup for a new entry, then just return default value
return $in;
}
- function textStore($in, $f)
+ private function textStore($in, $f)
{
$r = "'".addslashes($in)."'";
return $r;
/*\r
* Password Field Processing\r
*/\r
- function passwordField($f)\r
+ private function passwordField($f)\r
{\r
return 'T.'.$f['field'];\r
}\r
- function passwordOptions($f)\r
+ private function passwordOptions($f)\r
{\r
return false;\r
}\r
- function passwordOutput($f, $d)\r
+ private function passwordOutput($f, $d)\r
{
// No output for a password field\r
return '';\r
}\r
- function passwordInput($as, $f, $id, $idField, $op)\r
+ private function passwordInput($as, $f, $id, $idField, $op)\r
{\r
// If this is setup for a new entry, then just return default value\r
if ($op == 'n') {\r
\r
return $c;\r
}\r
- function passwordStore($in, $f)\r
+ private function passwordStore($in, $f)\r
{\r
$r = "'".addslashes($in)."'";\r
return $r;\r
/*
* Checkbox Field Processing
*/
- function checkboxField($f)
+ private function checkboxField($f)
{
return 'T.'.$f['field'];
}
- function checkboxOptions($f)
+ private function checkboxOptions($f)
{
return false;
}
- function checkboxOutput($f, $d)
+ private function checkboxOutput($f, $d)
{
$list = array(
0 => array(
return $r;
}
- function checkboxInput($as, $f, $x, $y, $op)
+ private function checkboxInput($as, $f, $x, $y, $op)
{
$list = array(
0 => array(
return $r;
}
- function checkboxStore($in, $f)
+ private function checkboxStore($in, $f)
{
if ($in['value']) {
return "true";
/*
* E-Mail Field Procesing
*/
- function emailField($f)
+ private function emailField($f)
{
return 'T.'.$f['field'];
}
- function emailOptions($f)
+ private function emailOptions($f)
{
return false;
}
- function emailOutput($f, $d)
+ private function emailOutput($f, $d)
{
return $d;
}
- function emailInput($as, $f, $id, $idfield, $op)
+ private function emailInput($as, $f, $id, $idfield, $op)
{
// If this is setup for a new entry, then just return default value
if ($op == 'n') {
return $in;
}
- function emailStore($in, $f)
+ private function emailStore($in, $f)
{
return "'".addslashes($in)."'";
}
/*
* Date Field Processing
*/
- function dateField($f)
+ private function dateField($f)
{
return 'T.'.$f['field'];
}
- function dateOptions($f)
+ private function dateOptions($f)
{
return false;
}
- function dateOutput($f, $d, $forEdit)
+ private function dateOutput($f, $d, $forEdit)
{
// Check for min/max date values
\r
return $out;
}
- function dateInput($as, $f, $id, $idfield, $op)
+ private function dateInput($as, $f, $id, $idfield, $op)
{
$this->inputFieldStatus = true;
return $v;
}
- function dateStore($in, $f)
+ private function dateStore($in, $f)
{
// Check if there's no date then supply null
* Time Field Processing
*/
// Support function to build picklists for Time field
- function buildTimeFieldLists()
+ private function buildTimeFieldLists()
{
// Setup hour and minute pick lists
$hour_list = array();
return $time_list;
}
- function timeField($f)
+ private function timeField($f)
{
return 'T.'.$f['field'];
}
- function timeOptions($f)
+ private function timeOptions($f)
{
return false;
}
- function timeOutput($f, $d)
+ private function timeOutput($f, $d)
{
// Default values if no time returned
$hour = 12;
return $r;
}
- function timeInput($as, $f, $id, $idfield, $op)
+ private function timeInput($as, $f, $id, $idfield, $op)
{
$this->inputFieldStatus = true;
$hour = 12;
return $r;
}
- function timeStore($in, $f)
+ private function timeStore($in, $f)
{
return "'".$in['time_store']."'";
}
/*
* datetime (date and time) Field Processing
*/
- function datetimeField($f)
+ private function datetimeField($f)
{
return 'T.'.$f['field'];
}
- function datetimeOptions($f)
+ private function datetimeOptions($f)
{
return false;
}
- function datetimeOutput($f, $d, $forEdit)
+ private function datetimeOutput($f, $d, $forEdit)
{
// Check for min/max date values
return $out;
}
- function datetimeInput($as, $f, $id, $idfield, $op)
+ private function datetimeInput($as, $f, $id, $idfield, $op)
{
$this->inputFieldStatus = true;
return $v;
}
- function datetimeStore($in, $f)
+ private function datetimeStore($in, $f)
{
// Check if there's no date then supply null
/*
* Phone Field Processing
*/
- function phoneField($f)
+ private function phoneField($f)
{
return 'T.'.$f['field'];
}
- function phoneOptions($f)
+ private function phoneOptions($f)
{
return false;
}
- function phoneOutput($f, $d)
+ private function phoneOutput($f, $d)
{
return $d;
}
- function phoneInput($as, $f, $id, $idfield, $op)
+ private function phoneInput($as, $f, $id, $idfield, $op)
{
// If this is setup for a new entry, then just return default value
if ($op == 'n') {
$in = $_REQUEST[$as];
return $in;
}
- function phoneStore($in, $f)
+ private function phoneStore($in, $f)
{
return "'".addslashes($in)."'";
}
/*
* Image Field Processing
*/
- function imageField($f)
+ private function imageField($f)
{
return 'T.'.$f['field'];
}
- function imageOptions($f)
+ private function imageOptions($f)
{
return false;
}
- function imageOutput($f, $d)
+ private function imageOutput($f, $d)
{
return $d;
}
- function imageInput($as, $f, $id, $idfield, $op)
+ private function imageInput($as, $f, $id, $idfield, $op)
{
$new = false;
return $current_img;
}
- function imageStore($in, $f)
+ private function imageStore($in, $f)
{
return "'".addslashes($in)."'";
}
/*
* Base64 Image Field Processing (for inline images)
*/
- function b64imageField($f)
+ private function b64imageField($f)
{
return 'T.'.$f['field'];
}
- function b64imageOptions($f)
+ private function b64imageOptions($f)
{
return false;
}
- function b64imageOutput($f, $d)
+ private function b64imageOutput($f, $d)
{
return $d;
}
- function b64imageInput($as, $f, $id, $idfield, $op)
+ private function b64imageInput($as, $f, $id, $idfield, $op)
{
$new = false;
return $b64image;
}
- function b64imageStore($in, $f)
+ private function b64imageStore($in, $f)
{
return "'".$in."'";
}
/*
* File Field Processing
*/
- function fileField($f)
+ private function fileField($f)
{
return 'T.'.$f['field'];
}
- function fileOptions($f)
+ private function fileOptions($f)
{
return false;
}
- function fileOutput($f, $d)
+ private function fileOutput($f, $d)
{
return $d;
}
- function fileInput($as, $f, $id, $idfield, $op)
+ private function fileInput($as, $f, $id, $idfield, $op)
{
$new = false;
return $current_file;
}
- function fileStore($in, $f)
+ private function fileStore($in, $f)
{
return "'".addslashes($in)."'";
}
/*
* latitude Field Processing
*/
- function latitudeField($f)
+ private function latitudeField($f)
{
return 'T.'.$f['field'];
}
- function latitudeOptions($f)
+ private function latitudeOptions($f)
{
return false;
}
- function latitudeOutput($f, $d)
+ private function latitudeOutput($f, $d)
{
$type = 'DMS';
if (isset($f['latlon_type'])) {
return $lat;
}
- function latitudeInput($as, $f, $id, $idfield, $op)
+ private function latitudeInput($as, $f, $id, $idfield, $op)
{
// If this is setup for a new entry, then just return default value
if ($op == 'n') {
return $in;
}
- function latitudeStore($in, $f)
+ private function latitudeStore($in, $f)
{
// NOTE: input must be processed first.
/*
* Longitude Field Processing
*/
- function longitudeField($f)
+ private function longitudeField($f)
{
return 'T.'.$f['field'];
}
- function longitudeOptions($f)
+ private function longitudeOptions($f)
{
return false;
}
- function longitudeOutput($f, $d)
+ private function longitudeOutput($f, $d)
{
$type = 'DMS';
return $out;
}
- function longitudeInput($as, $f, $id, $idfield, $op)
+ private function longitudeInput($as, $f, $id, $idfield, $op)
{
// If this is setup for a new entry, then just return default value
if ($op == 'n') {
return $in;
}
- function longitudeStore($in, $f)
+ private function longitudeStore($in, $f)
{
// NOTE: input must be processed first.
// Need to convert to float degrees here
* @return void
* @access public
*/
- public function buildFieldsList($op = 'l', $options = false, $defaults = false)
+ private function buildFieldsList($op = 'l', $options = false, $defaults = false)
{
$this->fieldData = array();
$this->select = '';
*
* @access public
*/
- public function processOutputData($data, $op = 'l', $forEdit = false, $id = false, $idfield = 'id')
+ private function processOutputData($data, $op = 'l', $forEdit = false, $id = false, $idfield = 'id')
{
if ($forEdit) {
*
* @access public
*/
- public function processInputData($op = 'u', $id = false, $idField = false)
+ private function processInputData($op = 'u', $id = false, $idField = false)
{
// Status is good unless otherwise determined
*
* @param string $where Optional WHERE clause for selection of entries. Defaults to all.
* @param string $order Optional ORDER BY clause for sorting of results.
+ * Set to "pseudo-random" for Pseudo-Random sorting that uses a browser cookie
+ * to store a custom seed value so all results are in the same randomized order
+ * for some period of time. See genPseudoRandIdArray() and pseudoRandDataSort().
* @param boolean $fieldVals Optional flag requesting fields contain array of all possible values.
* @param string $idField Optional name of ID field (primary index) to use for result array keys.
*
// Get field specifications for this instance
$this->buildFieldsList('l');
+ // If pseudo random order is requested
+ $this->pseudoRand = false;
+ if ($order == 'pseudo-random') {
+
+ // Set pseudo random flag and clear the order string
+ $this->pseudoRand = true;
+ $order = '';
+
+ }
+
+ // If doing pseudo-random ordering, generate array of IDs in pseudo-random order
+ $idString = '';
+ if ($this->pseudoRand) {
+
+ $prSql = "SELECT $idField
+ FROM $this->table T
+ ";
+ if (trim($where) != '') {
+ $prSql .= "WHERE $where
+ ";
+ }
+
+ $idList = $this->wpdb->get_results($prSql, ARRAY_A);
+ $prList = $this->genPseudoRandIdArray($idList, $start, $limit);
+ $idString = $prList['idString'];
+
+ }
+
$sql = "SELECT $this->select
FROM $this->table T
+ WHERE true
";
if (trim($where != '')) {
- $sql .= "WHERE $where
+ $sql .= "AND $where
+ ";
+ }
+
+ // If there's a pseudo-random id list to use for results selection
+ if ($idString != '') {
+ $sql .= "AND T.$idField IN ($idString)
";
}
- if (trim($order != '')) {
+ if (!$this->pseudoRand && trim($order != '')) {
$sql .= "ORDER BY $order
";
}
- // If $start and $limit, we're doing paging
+ // If $start and $limit, we're doing paging (pseudo-random does it's own paging)
$paging = false;
if ($start !== false && $limit > 0) {
- $sql .= "limit ".($start-1).", $limit";
+
+ // If using pseudo-random, don't use the SQL limit. The pseudo-random code does it's own paging
+ if (!$this->pseudoRand) {
+ $sql .= "limit ".($start-1).", $limit";
+ }
+
$paging = true;
}
$newList[$v['id']] = $this->processOutputData($v, 'l');
}
+ // If pseudo-random, sort the list by $prList
+ if ($this->pseudoRand) {
+ $this->pseudoRandDataSort($prList, $newList);
+ }
+
if (is_admin() && GLM_MEMBERS_PLUGIN_ADMIN_DEBUG_VERBOSE && class_exists('glmMembersAdmin')) {
$this->addDataAbstractNotice($newList, 'DataBlock', "getList() data");
}
-
// If we're doing paging, return that data along with the list
if ($paging) {
$c = count($list);
}
/*
- * Convert fload degrees to N/S or E/W Lat/Lon as D, D M, or D M S
+ * Convert float degrees to N/S or E/W Lat/Lon as D, D M, or D M S
*
* @return array
* text Text output of value
* min Minutes
* sec Seconds
*/
- public function f2LatLon($d, $LatLon, $type, $precision)
+ private function f2LatLon($d, $LatLon, $type, $precision)
{
$sign = +1;
*
* @return array
*/
- public function buildDateFieldLists($min, $max, $time = false)
+ private function buildDateFieldLists($min, $max, $time = false)
{
if (!$this->optionIncludeSelectListData) {
* @return object Class object
*
*/
- public function addDataAbstractNotice ( $d1, $d2 = false, $d3 = false)
+ private function addDataAbstractNotice ( $d1, $d2 = false, $d3 = false)
{
if (is_admin() && GLM_MEMBERS_PLUGIN_ADMIN_DEBUG_VERBOSE ) {
glmMembersFront::addNotice($d1, $d2, $d3);
}
}
+
+ /**
+ * The following two functions are used to build pseudo-random list results with optional paging
+ */
+
+ /*
+ * Generate a list of ID's sorted in pseudo-random order from
+ * a supplied array of record IDs.
+ *
+ * This function checks for a browser cookie that is used to save
+ * the seed. If that seed exists and has not timed out, it is used.
+ * Otherwise a new seed is generated and stored into a browser cookie.
+ *
+ * This function is passed an array of all possible record IDs that have been
+ * retrieved by a query against some table. That query should use a specific
+ * sort order to ensure that the resulting list of IDs is sorted the same
+ * for each identical query.
+ *
+ * Optional start and page size values may be specified to have this function
+ * return a subset of the IDs for a particular page of pagenated results.
+ *
+ * The return from this function is an array of IDs for the desired pseudo-
+ * random results in the desired sequence (numerical keys in sequence).
+ *
+ * Use the PseudoRandArraysort() function to order any selected results that
+ * were generated using the ID list returned from this function.
+ *
+ * @param array $idList A simple array that's a list of record IDs
+ * in the order in which they were retrieved.
+ * @param int $start Optional start of page value for paging
+ * @param int $length Optional length of page value for paging
+ * (required if there is a $start value)
+ * @param string $idName Optional id field name to override default 'id'
+ * @param string $cookieName Optional name for seed cookie
+ * @param int $cookieTime Optional # of seconds for cookie timeout
+ * @param int $seed Optional seed value to use instead of using value from cookie
+ *
+ * @return array Array inluding the following...
+ * 'idString' A comma separated string to use for an "in" clause in
+ * a second SQL query to get the actual data.
+ * 'idArray' An array of IDs in the generated pseudo-random order
+ *
+ */
+ private function genPseudoRandIdArray ($ids, $start = false, $length = false, $idName = 'id', $cookieName = 'GLM_PR_SEED', $cookieTime = 86400, $seed = false)
+ {
+
+ $transientSeed = false; // Indicates if the function was passed a specific seed. These are not stored back into a browser cookie.
+
+ // Change $ids array to simple array of ids
+ foreach ($ids as $k => $v) {
+ $ids[$k] = $v[$idName];
+ }
+
+ // if no id list is supplied
+ if (!is_array($ids) || count($ids) == 0) {
+ return false;
+ }
+
+ // If a seed is supplied
+ if ($seed && is_int($seed)) {
+
+ // Set flag so cookie is not updated with this seed.
+ $transientSeed = true;
+
+ //Otherwise, use a browser cookie seed if available or generate a new one
+ } else {
+
+ // Get browser cookie if it exists
+ if (isset($_COOKIE[$cookieName])) {
+ $seed = ($_COOKIE[$cookieName]);
+ } else {
+
+ // Generate a new seed
+ $seed = intval(time()*1000000+microtime()*1000000);
+
+ }
+ }
+
+ // Enforce seed as positive integer
+ $seed = abs(intval($seed -0));
+
+ // If seed is somehow 0, return false
+ if ($seed == 0) {
+ return false;
+ }
+
+ // If this is not a transient seed, store or updated it into the browser cookie.
+ if (!$transientSeed) {
+ setcookie($cookieName, $seed, time() + $cookieTime);
+ }
+
+ // Use the seed to order the ID list - Note that shuffle() will produce the same results if strand() has the same seed.
+ srand($seed);
+ shuffle($ids);
+
+ // If we have a start value
+ if ($start !== false) {
+
+ // Enforce valid start
+ $start = abs(intval($start-0));
+
+ // Enforce length - Required with a $start value
+ $length = abs(intval($length-0));
+ if ($length == 0) {
+ return false;
+ }
+
+ // Get at max $length elements of the ID array starting with $start
+ $ids = array_slice($ids, $start, $length, true);
+
+
+ }
+
+ // If paging, build comma separated string of id's for use as part of a "in" clause in an SQL query.
+ $idString = '';
+ $newIdArray = array();
+ if ($start !== false) {
+ $sep = '';
+ foreach ($ids as $i) {
+ $idString .= $sep.$i;
+ $sep = ', ';
+ }
+ }
+
+ return array('idString' => $idString, 'idArray' => $ids);
+
+ }
+
+
+ /*
+ * Order a final data array by the sequence of results from genPseudoRandIdArray().
+ *
+ * To use this function...
+ *
+ * * Query the database to get a list of record IDs only matching the desired result
+ * * Retrieve an ordered list of those IDs using genPseudoRandIdArray()
+ * * Query the database again for final results matching the list of IDs
+ * * Use this function to sort the final resuts by the generated order of IDs
+ *
+ * Note that the $data parameter is used by reference so as to not duplicate the full
+ * data array. This will modify the original array.
+ *
+ * @param array $idArray An array returned by genPseudoRandIdArray()
+ * @param array &$data A data array of final results to be ordered
+ * @param string $idName Optional id field name to override default 'id'
+ *
+ * @return boolean True if successful, otherwise false
+ *
+ */
+ private function pseudoRandDataSort ($idList, &$data, $idName = 'id')
+ {
+
+ $idFlip = array_flip($idList['idArray']);
+
+ foreach($data as $k=>$v) {
+ $data[$k]['prSort'] = $idFlip[$v[$idName]];
+ }
+
+ uasort( $data, function($a, $b) {
+ if ($a['prSort'] == $b['prSort']) {
+ return 0;
+ }
+ return ($a['prSort'] < $b['prSort']) ? -1 : 1;
+ });
+
+ return true;
+ }
+
+
}
?>
\ No newline at end of file