/** * convertCacheMapDataToSchema() -- protected method * * this method takes an input array of payload data and checks to see if the current-loaded class has cacheMapping * set (the cacheMap element has to be an array) and uses the map to convert the data from the public (cachemap) * to private (schema) format. * * method requires two input parameters: * * - the payload data - which is a indexed array of associative array tuples * - boolean toggle indicating if ALL fields are required to pass validation * * If the current class has cacheMapping, then we're going to spin through each tuple in the $_data parameter * and look at each $key in the tuple -- if the $key exists as a member in the cacheMap, pull the key from cacheMap * and store the new key and the old value in a temp array. If the key does not exist in the cacheMap then * use the current (old) key/value pair. * * After each tuple is processed,copy the new vector in to a temporary matrix which will eventually be returned * to the calling client. * * in all other (fail) cases, a null is returned. * * NOTE: * ----- * This method is not to be confused with gasCache->buildMappedDataArray() which converts schema to cacheMap. * * @author mike@givingassistant.org * @version 1.0 * * @param array $_data * @param bool $_allFields * @return null|array * * HISTORY: * ======== * 07-13-17 mks CORE-464: original coding * 02-06-18 mks _INF-139: support for disabled caching + no cache map * 02-22-18 mks _INF-139: when cache is disabled, need to verify that submitted data included the class * extension - if not, replace the old key with the old key + class extension * 12-12-18 mks DB-77: fixed error in processing: when we have a journal recovery event, the restore * query uses column literals instead of cache-mapped values. Added conditional code * to check if the literal appears in the field list and, if so, validate that field */ protected function convertCacheMapDataToSchema(array $_data, bool $_allFields = false): ?array { $this->state = STATE_VALIDATION_ERROR; $this->status = false; $data = false; $badData = false; $loggerAvailable = (isset($this->logger) and $this->logger->available); if (!is_array($_data)) { $msg = basename(__METHOD__) . AT . __LINE__ . COLON . ERROR_DATA_INVALID_FORMAT; if ($loggerAvailable) $this->logger->data($msg); else consoleLog($this->res, CON_ERROR, $msg); $this->eventMessages[] = $msg; } elseif ($this->useCache and empty($this->cacheMap)) { $msg = ERROR_CACHE_MAP_404 . COLON . $this->class; if ($loggerAvailable) $this->logger->data($msg); else consoleLog($this->res, CON_ERROR, $msg); $this->eventMessages[] = $msg; } elseif (!$this->useCache and (!isset($this->cacheMap) or empty($this->cacheMap))) { $data = $_data[0]; foreach ($data as $key => $value) { try { $newKey = $this->addExtension($key); } catch (TypeError $t) { $msg = ERROR_TYPE_EXCEPTION . COLON . $t->getMessage(); if ($loggerAvailable) $this->logger->error($msg); else consoleLog($this->res, CON_ERROR, $msg); $this->eventMessages[] = $msg; return null; } if (is_null($newKey)) return null; if ($newKey != $key) { $data[$newKey] = $value; unset($data[$key]); } } $this->state = STATE_SUCCESS; $this->status = true; return [$data]; } else { $counter = 0; for ($index = 0, $last = count($_data); $index < $last; $index++) { $row = null; foreach ($_data[$index] as $key => $value) { $ck = array_search($key, $this->cacheMap); if (false === $ck) { $ck = array_key_exists($key, $this->cacheMap); /* * edge case - this case will be encountered in situations where we're using non-cache-mapped * keys (e.g.: column literals) in a cached-class query where there exists a cache-map. * Journaling saves the recovery query in literal (as opposed to cache-mapped) format... so, we * need to accommodate the possibility where the data keys exist only in the $fieldList member * and, if so, treat the keys as valid values once we've exhausted cache-map processing */ if (false === $ck) { // check to see if key is member of $fieldList // first - see if we have an extension appended to the key - if not, add one $newKey = $this->addExtension($key); // then, check if the qualified key exists in the fieldList - if so, update the value of $ck $ck = (in_array($newKey, $this->fieldList)) ? $newKey : false; } if (false === $ck) { $msg = ERROR_DATA_INVALID_KEY . $key; $this->eventMessages[] = $msg; if ($loggerAvailable) $this->logger->data($msg); else consoleLog($this->res, CON_ERROR, $msg); if ($_allFields) $badData = true; $ck = $key; } } if (is_array($value) and !empty($this->subCollections) and array_key_exists($ck, $this->subCollections)) { try { $value = $this->convertCacheMapDataToSchema($value); } catch (TypeError $t) { $msg = ERROR_TYPE_EXCEPTION . COLON . $t->getMessage(); if ($loggerAvailable) $this->logger->error($msg); else consoleLog($this->res, CON_ERROR, $msg); return null; } if (false === $value) { $msg = sprintf(ERROR_SUB_C_V_NULL, $ck); $this->logger->warn($msg); $this->eventMessages[] = $msg; } } if (false !== $ck) $row[$ck] = $value; } if (!empty($row)) $data[$counter++] = $row; } if (($_allFields and !$badData and is_array($data)) or (!$_allFields and is_array($data))) { $this->state = STATE_SUCCESS; $this->status = true; } } return( ($this->status) ? $data : null ); } NOTE: dataScrub() wasn't deprecated, just eviscerated... /** * dataScrub() -- private method * * this method parses all of the data stored in the protected $data member and replaces keys with cleaned values * (extensions stripped from keys) and critical values removed entirely. * * $_data -- call-by-reference variable that's the implicitly returned * * While processing the data rows, we make a recursive call back to this method if we encounter sub-arrays so * that the sub-array keys can be stripped (method 1 only!) also. * * When generating the return data, for every row of data, we check each column to ensure it's not listed in the * $hiddenColumns member array and, if it is, we remove it. * * For nosql-based collections, if we specify that we want the meta data, then we'll return the history * sub-collection (aka meta data) so if meta isn't specified, the meta is dropped from the return set. * * There are no errors raised in this method. The success is implicitly defined in the $_data return structure. * * NOTE: * ===== * Cache-Key Mapping is located in the private static method gasCache::buildMappedDataArray(). * * * @author mikegivingassistant.org * @version 1.0 * * @param $_data * * HISTORY: * ======== * 06-22-17 mks original coding * 08-14-17 mks CORE-493: removing meta param support (DB_HISTORY no longer supported) * */ private function dataScrub(array &$_data): void { if (empty($_data)) { $msg = ERROR_DATA_MISSING_ARRAY . STRING_DATA; $this->eventMessages[] = $msg; if (isset($this->logger) and $this->logger->available) $this->logger->error($msg); else consoleLog($this->res, CON_ERROR, $msg); return; } /* * if we're requesting a clean data set, and we've not requested a key-mapping, then * clean the data "old-school" style, stripping off extensions, pulling the mongo ID * fields, in the return data set. */ for ($index = 0, $last = count($_data); $index < $last; $index++) { if (!empty($_data[$index]) and is_array($_data[$index])) { foreach ($_data[$index] as $key => $value) { $newKey = str_replace($this->ext, '', $key); if (is_array($value)) { try { $this->dataScrub($value); } catch (TypeError $t) { $msg = basename(__METHOD__) . AT . __LINE__ . COLON . ERROR_TYPE_EXCEPTION . COLON . $t->getMessage(); $this->eventMessages[] = $msg; if (isset($this->logger) and $this->logger->available) $this->logger->error($msg); else consoleLog($this->res, CON_ERROR, $msg); } return; } if ($newKey != $key and !in_array($newKey, $this->hiddenColumns)) { $_data[$index][$newKey] = $value; unset($_data[$index][$key]); } elseif (in_array($newKey, $this->hiddenColumns)) { unset($_data[$index][$key]); } } } } } /** * cmData() -- public function * * This public function is a dirty little way to stuff whatever data is defined in $_payload to replace whatever * is stored in the protected member: $data. * * The only requirement is that the input parameter be an array. * * The purpose of this method is to store the cacheMap key(s) into the $data payload right before the broker * event, that generated the data payload, finished processing an releases the class memory assigned to the object. * * * @author mike@givingassistant.org * @version 1.0 * * @param array $_payload * * * HISTORY: * ======== * 03-04-19 mks DB-116: original coding * */ public function cmData(array $_payload): void { $this->data = $_payload; } /** * dumpRecord() -- public core method * * Sometimes, you need to know what's in the $data payload and, since it's protected, you can't access it directly * without going through one of the other methods that filters the payload. * * This method allows you to dump a row of data from the $data array to stdout. If you don't specify a row (as * the only input parameter, then you will dump the first (0th) row in the array. However, if the array is empty, * we'll out a message to that effect. * * * @author mike@givingassistant.org * @version 1.0 * * @param int $_row * * * HISTORY: * ======== * 10-24-18 mks DB-67: original coding * * */ public function dumpRecord(int $_row = 0): void { if (empty($this->data)) echo INFO_NO_DATA_IN_DATA; else var_export($this->data[$_row]); } /** * validateStatus() -- public method * * Simple method that takes a single input parameter, a string, and returns a boolean value corresponding to * whether or not the string-value is present in the validStatus member array. * * * @author mike@givingassistant.org * @version 1.0 * * @param string $_status * @return bool * * * HISTORY: * ======== * 02-12-18 mks _INF-139: original coding * */ public function validateStatus(string $_status): bool { return (in_array($_status, $this->validStatus)); }