class = get_class($this); $this->res = 'FACT: '; $this->widget = new stdClass(); $this->eventMessages = []; $this->status = false; $this->debug = boolval(gasConfig::$settings[CONFIG_DEBUG]); $file = basename(__FILE__); // using __FILE__ instead of __METHOD__ b/c constructor $this->state = STATE_PENDING; $this->eventID = (array_key_exists(META_EVENT_GUID, $_meta)) ? $_meta[META_EVENT_GUID] : ''; $tlti = STRING_CLASS_GAT; $templateKey = null; try { $this->logger = new gacErrorLogger(); } catch (Throwable | TypeError $t) { $hdr = sprintf(INFO_LOC, basename(__FILE__), __LINE__); @handleExceptionMessaging($hdr, $t->getMessage(), $_es, true); return; } // PROCESS THE TEMPLATE if (!array_key_exists(META_TEMPLATE, $_meta)) { $msg = ERROR_CONFIG_RESOURCE_404 . STRING_TEMPLATE; $_es[] = $msg; $this->logger->error($msg); return; } // get a list of the current templates $this->validTemplates = gasStatic::loadValidTemplateNames(); if (!is_array($this->validTemplates)) { $_es[] = ERROR_TEMPLATE_DIR_404; $this->logger->error(ERROR_TEMPLATE_DIR_404); return; } // if this is a SMAX request, fetch and replace the TLTI based on the auth code if (isset($_meta[CLIENT_AUTH_TOKEN]) and $_meta[CLIENT_AUTH_TOKEN] != NULL_TOKEN) { // ensure a valid token... if (!validateGUID($_meta[CLIENT_AUTH_TOKEN])) { $_es[] = ERROR_CLIENT_AUTH_TOKEN_BAD; $this->state = STATE_DATA_ERROR; return; } if (!isset($_meta[META_TLTI]) or empty($_meta[META_TLTI])) { $tlti = gasStatic::getTLTI($_meta[CLIENT_AUTH_TOKEN], $_meta[META_EVENT_GUID], $response); if ($response[PAYLOAD_STATUS] and $response[PAYLOAD_STATE] == STATE_NOT_FOUND) { $_es[] = ERROR_CLIENT_AUTH_TOKEN_BAD; $this->logger->warn(sprintf(INFO_LOC, $file, __LINE__) . ERROR_CLIENT_AUTH_TOKEN_SEARCH . $_meta[CLIENT_AUTH_TOKEN]); $this->state = STATE_REQUEST_REJECTED; return; } elseif (!$response[PAYLOAD_STATUS] or is_null($tlti)) { $_es[] = ERROR_SOUR_PICKLE; $this->logger->fatal(sprintf(INFO_LOC, $file, __LINE__) . ERROR_ARRAY_KEY_404 . SMAX_TLTI); $this->state = STATE_FRAMEWORK_FAIL; return; } // inject the tlti into the meta-payload for use later by the instantiation classes $_meta[META_TLTI] = $tlti; $templateKey = $response[PAYLOAD_RESULTS][STRING_QUERY_RESULTS][0][STRING_KEY]; } else { $templateKey = $_meta[CLIENT_AUTH_TOKEN]; } } elseif (!isset($_meta[META_TLTI]) or empty($_meta[META_TLTI])) { $_meta[META_TLTI] = $tlti; } // is the requested template in the list of valid templates? if (!in_array(($_meta[META_TLTI] . $_meta[META_TEMPLATE]), $this->validTemplates)) { $msg = ERROR_TEMPLATE_FILE_404 . $_meta[META_TLTI] . $_meta[META_TEMPLATE]; $_es[] = $msg; $this->logger->error($msg); return; } // instantiate a copy of the template $tc = $_meta[META_TLTI] . $_meta[META_TEMPLATE]; try { $this->template = new $tc(); } catch (Throwable | TypeError $t) { $hdr = sprintf(INFO_LOC, basename(__METHOD__), __LINE__); @handleExceptionMessaging($hdr, $t->getMessage(), $_es, true); $this->state = STATE_NOT_FOUND; return; } $env = $this->template->service; $dbConfig = gasConfig::$settings[CONFIG_DATABASE]; // In this block, we're validating the current environment against the schema because not all of the schema's // exist for every environment... this is a weak check just to ensure we don't try to instantiate a class, // internal, or external, for a schema that's non-existent in the current env. // ------------------------------------------------------------------------------------------------------------- $msg = ''; switch ($this->template->schema) { case TEMPLATE_DB_MONGO : if ($dbConfig[CONFIG_DATABASE_MONGODB][CONFIG_DATABASE_MONGODB_ENABLED] != 1) { $msg = sprintf(CONFIG_DB_NOT_ENABLED, TEMPLATE_DB_MONGO); $_es[] = $msg; $this->logger->warn($msg); } // we can have mongo running on all services if (($env == CONFIG_DATABASE_SERVICE_APPSERVER and $dbConfig[CONFIG_DATABASE_MONGODB][CONFIG_DATABASE_MONGODB_APPSERVER][CONFIG_DATABASE_MONGODB_ENABLED] != 1) or ($env == CONFIG_DATABASE_SERVICE_ADMIN and $dbConfig[CONFIG_DATABASE_MONGODB][CONFIG_DATABASE_MONGODB_ADMIN][CONFIG_DATABASE_MONGODB_ENABLED] != 1) or ($env == CONFIG_DATABASE_SERVICE_SEGUNDO and $dbConfig[CONFIG_DATABASE_MONGODB][CONFIG_DATABASE_SERVICE_SEGUNDO][CONFIG_DATABASE_MONGODB_ENABLED] != 1) or ($env == CONFIG_DATABASE_SERVICE_TERCERO and $dbConfig[CONFIG_DATABASE_MONGODB][CONFIG_DATABASE_SERVICE_TERCERO][CONFIG_DATABASE_MONGODB_ENABLED] != 1)) { $msg = sprintf(CONFIG_DB_ENV_NOT_ENABLED, TEMPLATE_DB_MONGO, $env, $_meta[META_TEMPLATE]); $_es[] = $msg; $this->logger->warn($msg); } break; case TEMPLATE_DB_DDB : if ($dbConfig[CONFIG_DATABASE_DDB][CONFIG_DATABASE_DDB_ENABLED] != 1) { $msg = sprintf(CONFIG_DB_NOT_ENABLED, TEMPLATE_DB_MONGO); $_es[] = $msg; $this->logger->warn($msg); } // DynamoDB can be running on appServer or Admin if (($env == CONFIG_DATABASE_SERVICE_APPSERVER and $dbConfig[CONFIG_DATABASE_DDB][CONFIG_DATABASE_DDB_APPSERVER][CONFIG_DATABASE_DDB_ENABLED] != 1) or ($env == CONFIG_DATABASE_SERVICE_ADMIN and $dbConfig[CONFIG_DATABASE_DDB][CONFIG_DATABASE_DDB_ADMIN][CONFIG_DATABASE_DDB_ENABLED] != 1)) { $msg = sprintf(CONFIG_DB_ENV_NOT_ENABLED, TEMPLATE_DB_MONGO, $env, $_meta[META_TEMPLATE]); $_es[] = $msg; $this->logger->warn($msg); } break; case TEMPLATE_DB_PDO : if ($dbConfig[CONFIG_DATABASE_PDO][CONFIG_DATABASE_PDO_ENABLED] != 1) { $msg = sprintf(CONFIG_DB_NOT_ENABLED, TEMPLATE_DB_MONGO); $_es[] = $msg; $this->logger->warn($msg); } // PDO (mariaDB) can be running on appServer and Segundo if (($env == CONFIG_DATABASE_SERVICE_APPSERVER and $dbConfig[CONFIG_DATABASE_PDO][CONFIG_DATABASE_PDO_APPSERVER][CONFIG_DATABASE_PDO_ENABLED] != 1) or ($env == CONFIG_DATABASE_SERVICE_SEGUNDO and $dbConfig[CONFIG_DATABASE_PDO][CONFIG_DATABASE_SERVICE_SEGUNDO][CONFIG_DATABASE_PDO_ENABLED] != 1)) { $msg = sprintf(CONFIG_DB_ENV_NOT_ENABLED, TEMPLATE_DB_PDO, $env, $_meta[META_TEMPLATE]); $_es[] = $msg; $this->logger->warn($msg); } break; } if (!empty($msg)) return; // ------------------------------------------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------------------------- // instantiation security begins... if (gasConfig::$settings[CONFIG_REGISTERED_SERVICES][CONFIG_BROKER_APPSERVER] == 1 and $env == ENV_APPSERVER) { // ^^^ if we're on appServer... if (isset($_meta[META_CLIENT]) and $_meta[META_CLIENT] == CLIENT_API_USER) { // ^^^ if the request originated from SMAX-User... if (isset($_meta[CLIENT_AUTH_TOKEN])) { // ^^^ if the request has the Partner API token... if (isset($this->template->authToken) and $this->template->authToken != NULL_TOKEN) { // ^^^ if we have a non-zero auth token set in the template class // we need to validate the client-auth-token in the template against the SMAX record // which we already fetched in real-time (above) when deriving the tlti... if ($this->template->authToken != $templateKey) { $_es[] = ERROR_CLIENT_AUTH_TOKEN_MISMATCH; $this->state = STATE_AUTH_ERROR; return; } } // END: check for presence of auth token } else { // error: we got a SMAX Client request but the meta payload is missing the auth token $_es[] = ERROR_CLIENT_AUTH_TOKEN_404; $this->state = STATE_META_ERROR; return; } // END: check for client Auth Token in meta payload } // END: check for SMAX user } // END: check for appServer env // ------------------------------------------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------------------------- // instantiate a meta-data class try { $tmpMeta = new gacMeta(true); // this is NOT the functions.php::validateMetaPayload() function! if (!$tmpMeta->validateMetaPayload($_meta)) { if (empty($_es) and !empty($tmpMeta->eventMessages)) { $_es = $tmpMeta->eventMessages; } elseif (!empty($_es) and !empty($tmpMeta->eventMessages)) { $_es = array_merge($_es, $tmpMeta->eventMessages); } return; } } catch (Throwable | TypeError $t) { $hdr = sprintf(INFO_LOC, basename(__METHOD__), __LINE__); @handleExceptionMessaging($hdr, $t->getMessage(), $_es, true); return; } // ------------------------------------------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------------------------- // normally, for an instantiation class (widget) this would be a copy of the instantiated meta class and the // meta data would go into metaPayload. However, remember this is the ephemeral factory class... $this->meta = $_meta; // PROCESS THE EVENT switch ($_event) { case FACTORY_EVENT_SCHEMA_REQUEST: case FACTORY_EVENT_NEW_CLASS: try { $this->instantiateClass($_guid); $this->fetchSchema($this->eventMessages); $this->widget->addMetaTemplate($tmpMeta); $this->widget->templateReport = $this->schema; $this->status = true; $this->state = STATE_SUCCESS; } catch (Throwable | TypeError $t) { $hdr = sprintf(INFO_LOC, basename(__METHOD__), __LINE__); @handleExceptionMessaging($hdr, $t->getMessage(), $_es, true); } break; default: $_es[] = (empty($_event)) ? ERROR_NO_EVENT : ERROR_UNKNOWN_EVENT; break; } $tmpMeta->__destruct(); unset($tmpMeta); // ------------------------------------------------------------------------------------------------------------- } /** * instantiateClass() -- private method * * this method is called from the constructor whenever someone wants to instantiate a new class. The parameter * passed to the method is a guid -- which is optional -- and, if provided, indicates that the instantiation of * the class include loading the record (singular) referenced by the guid. * * There are no explicit returns -- the new object is created under the class property "widget" (because all * factories make widgets, yah?) and that widget object (which also has the standard state/status properties) * contains the success/fail indicators. * * As more schemas are added to the framework, this method will expand to accommodate each schema type. * * * @author mike@givingassistant.org * @version 1.0 * * @param string $_guid * * * HISTORY: * ======== * 06-22-17 mks initial coding * 07-06-17 mks CORE-463: logging/metrics in mongodb * 09-18-17 mks CORE-562: PDO class coding * 01-07-20 mks DB-150: refactored making $widget a reference-assignment to another db-class resource * */ private function instantiateClass(string $_guid) { try { switch ($this->template->schema) { case TEMPLATE_DB_DDB : $this->ddbWidget = new gacDdb($this->meta, $_guid); $this->widget =& $this->ddbWidget; break; case TEMPLATE_DB_MONGO : $this->mongoWidget = new gacMongoDB($this->meta, $_guid); $this->widget =& $this->mongoWidget; break; case TEMPLATE_DB_PDO : $this->pdoWidget = new gacPDO($this->meta, $_guid); $this->widget =& $this->pdoWidget; break; default : $msg = ERROR_CLASS_SCHEMA_404 . COLON . $this->template->schema; $this->logger->error($msg); $this->eventMessages[] = $msg; $this->state = STATE_SCHEMA_ERROR; $this->status = false; $this->widget = new stdClass(); break; } } catch (Throwable $t) { $msg = ERROR_THROWABLE_EXCEPTION . COLON . $t->getMessage(); $this->eventMessages[] = $msg; if ($this->logger->available) { $this->logger->error($msg); } else { consoleLog($this->res, CON_ERROR, $msg); } } } /** * fetchSchema() -- private class method * * the fetchSchema() event instantiates the template passed implicitly as a class member and creates an * array of data describing the data template - the array has been homogenized to work with all schemas. * * On success, we'll return the template report (array) otherwise, we'll just return a null value. Also, * on success, we'll update the class $status member to Boolean(true) so that the constructor realizes that * the operation was successful. * * Programmer Notes: * ----------------- * While there exists only one explicitly coded point of failure, this processing will work unless there's * something missing, or something wrong, in the template file. So, if you're not getting the expected * results in the template report, check the template file first. * * * @author mike@givingassistant.org * @version 1.0 * * @param array $_es * * * HISTORY: * ======== * 06-15-17 mks original coding * 07-07-17 mks updated: each schema type has their own indexing strategy - the template report now * evaluates the schema and generates the appropriate index report. * 09-20-17 mks CORE-562: added PDO processing, refactored code segments to reduce footprint * 10-18-17 mks CORE-584: added PDO dataObjects processing, system-variables section * 06-08-18 mks CORE-1035: adding migration and warehouse to schema report * 11-01-19 mks DB-136: added the indexList to processing, fixed some switch-break syntax * */ private function fetchSchema(array &$_es): void { $templateReport = null; $templateReport[TEMPLATE_NAMASTE_INFO] = null; // ensure this is the first element in the array if (empty($this->template)) { $_es[] = ERROR_TEMPLATE_FILE_404; $this->logger->warn(ERROR_TEMPLATE_FILE_404); return; } $templateReport[TEMPLATE_FEATURE_TITLE] = $this->template->collection; $templateReport[TEMPLATE_FEATURE_WH_TITLE] = (isset($this->template->whTemplate)) ? $this->template->whTemplate : STRING_NOT_DEFINED; $templateReport[TEMPLATE_FEATURE_USES_CACHE_MAPS] = ($this->template->setCache and !empty($this->template->cacheMap)) ? YES : NO; $templateReport[TEMPLATE_FEATURE_USES_LOCKS] = ($this->template->setLocking) ? YES : NO; $templateReport[TEMPLATE_FEATURE_USES_TIMER] = ($this->template->setTimers) ? YES : NO; $templateReport[TEMPLATE_FEATURE_USES_TOKENS] = ($this->template->setTokens) ? YES : NO; $templateReport[TEMPLATE_FEATURE_USES_HISTORY] = ($this->template->setHistory) ? YES : NO; $templateReport[TEMPLATE_FEATURE_ALLOWS_AUDITS] = ($this->template->setAuditing) ? YES : NO; $templateReport[TEMPLATE_FEATURE_ALLOWS_JOURNALING] = ($this->template->setJournaling) ? YES : NO; $templateReport[TEMPLATE_FEATURE_ALLOWS_DELETES] = ($this->template->setDeletes) ? YES : NO; $templateReport[TEMPLATE_FEATURE_ALLOWS_UPDATES] = ($this->template->setUpdates) ? YES : NO; $templateReport[TEMPLATE_FEATURE_CACHE_EXPIRES] = $this->template->cacheTimer; try { switch ($this->template->schema) { case TEMPLATE_DB_DDB : // get the field lists and data types $this->getFieldList($templateReport); // if Binary fields are declared, grab them but filter through the cache map and exposed field lists $templateReport = $this->getBinaryFields($templateReport); // process the primary, global and local indexes foreach ($this->template->indexes as $key => $value) $templateReport[DDB_INDEX_TYPE_PRIMARY][$value] = $key; foreach ($this->template->globalIndexes as $key => $value) { if ($key == STRING_INDEXES) foreach ($key as $k => $v) $templateReport[DDB_INDEX_TYPE_GLOBAL][$v] = $k; else $templateReport[$key] = $value; } foreach ($this->template->localIndexes as $key => $value) { if ($key == STRING_INDEXES) foreach ($key as $k => $v) $templateReport[DDB_INDEX_TYPE_LOCAL][$v] = $k; else $templateReport[$key] = $value; } break; case TEMPLATE_DB_MONGO : $this->processTemplateIndexes($templateReport); break; case TEMPLATE_DB_PDO : // generate the mySQL/mariaDB template report // populate the field lists and data types $this->getFieldList($templateReport); // if Binary fields are declared, grab them but filter through the cache map and exposed field lists $templateReport = $this->getBinaryFields($templateReport); // process the indexes $this->processTemplateIndexes($templateReport); // get the database objects $templateReport = $this->processDBObjects($templateReport); break; } if (isset($this->widget->migrationConfig) and !empty($this->widget->migrationConfig)) { $templateReport[TEMPLATE_FEATURE_MIG_CONFIG] = var_export($this->widget->migrationConfig, true); } else { $templateReport[TEMPLATE_FEATURE_MIG_CONFIG] = STRING_NOT_DEFINED; } if (isset($this->widget->warehouseConfig) and !empty($this->widget->warehouseConfig)) { $templateReport[TEMPLATE_FEATURE_WH_CONFIG] = var_export($this->widget->warehouseConfig, true); } else { $templateReport[TEMPLATE_FEATURE_WH_CONFIG] = STRING_NOT_DEFINED; } $templateReport = $this->getTemplateReportSystemHeader($templateReport); } catch (Throwable $t) { $msg = ERROR_THROWABLE_EXCEPTION . COLON . $t->getMessage(); $_es[] = $msg; if ($this->logger->available) { $this->logger->error($msg); } else { consoleLog($this->res, CON_ERROR, $msg); } return; } $this->status = true; $this->schema = $templateReport; } /** * getTemplateReportSystemHeader() -- private method * * This method requires one input parameter - an array containing the current template report. * * This method returns the update template report back to the calling client once the namaste server information * has been copied from the configuration (static) class. * * * @author mike@givingassistant.org * @version 1.0 * * @param array $_templateReport * @return array * * * HISTORY: * ======== * 10-18-17 mks CORE-584: original coding * */ private function getTemplateReportSystemHeader(array $_templateReport): array { $_templateReport[TEMPLATE_NAMASTE_INFO] = [ TEMPLATE_NAMASTE_ENV => gasConfig::$settings[CONFIG_ID][CONFIG_ID_ENV], TEMPLATE_NAMASTE_VER => gasConfig::$settings[CONFIG_ID][CONFIG_ID_VER], TEMPLATE_NAMASTE_DB => (gasConfig::$settings[CONFIG_DEBUG]) ? STRING_ENABLED : STRING_DISABLED, TEMPLATE_NAMASTE_AUDIT => (gasConfig::$settings[CONFIG_AUDIT_ON]) ? STRING_ENABLED : STRING_DISABLED, TEMPLATE_NAMASTE_JOURNAL => (gasConfig::$settings[CONFIG_JOURNAL_ON]) ? STRING_ENABLED : STRING_DISABLED ]; return($_templateReport); } /** * processDBObjects() -- private method * * This method is part of the template report-generation process. * * The input parameter is the array containing the templateReport in it's current state. * The return is the templateReport with the DB-Objects inserted into the report. * * The only validation check we make is to ensure we're working with a current PDO instantiation class. * * * @author mike@givingassistant.org * @version 1.0 * * @param array $_templateReport * @return array * * HISTORY: * ======== * 10-18-17 mks CORE-584: original coding * */ private function processDBObjects(array $_templateReport): array { $schema = $this->widget->schema; if ($schema != TEMPLATE_DB_PDO) { $msg = sprintf(ERROR_SCHEMA_NOT_SUPPORTED, $schema); $this->eventMessages[] = $msg; if (gasConfig::$settings[CONFIG_DEBUG]) $this->logger->debug($msg); return ($_templateReport); } if (!isset($this->template->dbObjects)) { $_templateReport[TEMPLATE_DB_OBJECTS] = STRING_NOT_DEFINED; } else { $_templateReport[TEMPLATE_DB_OBJECTS] = $this->template->dbObjects; } return($_templateReport); } /** * processTemplateIndexes() -- private method * * This method is invoked by the fetchSchema (above) method and requires a single input parameter which is a * call-by-reference parameter: * * $_template: container that will eventually be assigned to the the schema property for the class * * This method was pulled from fetchSchema() and updated to check that a field has been set before we evaluate * if the field is empty - because the index fields change between the mongoDB and PDO schemas. * * * @author mike@givingassistant.org * @version 1.0 * * @param array $_templateReport * @return bool * * * HISTORY: * ======== * 09-20-18 mks CORE-562: original coding * */ private function processTemplateIndexes(array &$_templateReport): bool { $schema = $this->widget->schema; if ($schema != TEMPLATE_DB_PDO and $schema != TEMPLATE_DB_MONGO) { $msg = sprintf(ERROR_SCHEMA_NOT_SUPPORTED, $schema); $this->eventMessages[] = $msg; if (gasConfig::$settings[CONFIG_DEBUG]) $this->logger->debug($msg); return false; } try { switch ($schema) { case TEMPLATE_DB_MONGO : if ($this->template->setCache and !empty($this->template->cacheMap)) { $_templateReport = $this->mongoCacheMappedIndexes($_templateReport); } elseif (empty($this->template->cacheMap) and !empty($this->template->exposedFields)) { $_templateReport = $this->mongoExposedFieldsIndexes($_templateReport); } else { $_templateReport = $this->mongoFieldIndexes($_templateReport); } break; case TEMPLATE_DB_PDO : if ($this->template->setCache and !empty($this->template->cacheMap)) { $_templateReport = $this->pdoCacheMappedIndexes($_templateReport); } elseif (empty($this->template->cacheMap and !empty($this->template->exposedFields))) { $_templateReport = $this->pdoExposedFieldIndexes($_templateReport); } else { $_templateReport = $this->pdoFieldIndexes($_templateReport); } break; default: $msg = sprintf(ERROR_SCHEMA_NOT_SUPPORTED, $schema); $this->eventMessages[] = $msg; if (gasConfig::$settings[CONFIG_DEBUG]) $this->logger->debug($msg); return false; break; } } catch (Throwable $t) { $msg = ERROR_THROWABLE_EXCEPTION . COLON . $t->getMessage(); $this->eventMessages[] = $msg; if ($this->logger->available) { $this->logger->error($msg); } else { consoleLog($this->res, CON_ERROR, $msg); } return false; } return true; } /** * pdoFieldIndexes() -- private method * * This method is called from the processTemplateIndexes() method which passes a single input parameter to the * method -- the template report which is in-progress of being build. This method will add the fieldList * and process and add the template indexes to the report. * * * @author mike@givingassistant.org * @version 1.0 * * @param array $_templateReport * @return array * * * HISTORY: * ======== * 09-22-17 mks CORE-562: original coding * 06-15-20 mks ECI-164: fixed warning in index processing b/c not all indexes in $indexList are k->v arrays * */ private function pdoFieldIndexes(array $_templateReport): array { // build the template field list first foreach ($this->template->fields as $key => $value) { if ($key != PDO_ID) { $_templateReport[TEMPLATE_FIELD_LIST][$key] = $value; } } // build the index loop-control variants... $indexList = [ 'indexFields', 'singleFields', 'uniqueIndexes', 'binFields' ]; $indexLabels = [ TEMPLATE_FIELD_INDEX_LIST, TEMPLATE_SINGLE_INDEXES, TEMPLATE_UNIQUE_INDEX_PROPERTY, TEMPLATE_BINARY_FIELD_LIST ]; $counter = 0; foreach ($indexList as $currentIndex) { if (!is_null($this->template->$currentIndex)) { if (isset($this->template->$currentIndex) and !empty($this->template->$currentIndex) and is_array($currentIndex)) { foreach ($this->template->$currentIndex as $key => $value) { if ($key != PDO_ID) { $_templateReport[$indexLabels[$counter]][] = $key; } } } elseif (isset($this->template->$currentIndex) and !empty($this->template->$currentIndex)) { foreach ($this->template->$currentIndex as $key) { if ($key != PDO_ID) { $_templateReport[$indexLabels[$counter]][] = $key; } } } $counter++; } } if (isset($this->template->compoundIndexes) and !empty($this->template->compoundIndexes)) { foreach ($this->template->compoundIndexes as $key => $subArray) { foreach ($subArray as $indexKey => $value) { if ($indexKey != PDO_ID) { if (!isset($_templateReport[TEMPLATE_COMPOUND_INDEXES]) or !in_array($indexKey, $_templateReport[TEMPLATE_COMPOUND_INDEXES])) { $_templateReport[TEMPLATE_COMPOUND_INDEXES][] = $indexKey; } } } } } return($_templateReport); } /** * mongoFieldIndexes() -- private method * * This method is called from processTemplateIndexes() when it's been determined that the current instantiation * is a mongoDB class and that both cacheMapping and ExposedFields limitations do not exist. (System collections * would be a good example...) * * Based on the index architecture, we're able to group all the indexes into three processing loops -- each loop * processes the index fields in the template and adds them to the template report as long as the current field * isn't the MONGO_ID which is never exposed to the client. * * The input parameter to the method is the partially completed template report, which will eventually be * assigned as the class schema once this method processes and assigns the field and index field lists. * * The return value, an array, is the updated template report. * * * @author mike@givingassistant.org * @version 1.0 * * @param array $_templateReport * @return array * * * HISTORY: * ======== * 09-22-17 mks CORE-562: original coding * 10-19-17 mks CORE-610: added not-defined placeholders for not-defined indexes * 01-31-18 mks _INF-139: support for non-caching classes when building index list * */ private function mongoFieldIndexes(array $_templateReport): array { foreach ($this->template->fields as $key => $value) { if ($key != MONGO_ID) { $_templateReport[TEMPLATE_FIELD_LIST][$key] = $value; } } // set-up the index lists and process $indexList = [ 'singleFields', 'uniqueIndexes', 'ttlIndexes', 'subC' ]; $indexLabels = [ TEMPLATE_SINGLE_INDEXES, TEMPLATE_UNIQUE_INDEX_PROPERTY, TEMPLATE_TTL_INDEX_PROPERTY, TEMPLATE_SUB_COLLECTION_FIELDS ]; $counter = 0; foreach ($indexList as $currentIndex) { if (isset($this->template->$currentIndex) and !empty($this->template->$currentIndex)) { foreach ($this->template->$currentIndex as $key => $value) { if ($value != MONGO_ID) { $_templateReport[$indexLabels[$counter]][] = $key; } } } else { $_templateReport[$indexLabels[$counter]] = STRING_NOT_DEFINED; } $counter++; } // set-up the index lists and process $indexList = [ 'compoundIndexes', 'multiKey', 'partialIndexes' ]; $indexLabels = [ TEMPLATE_COMPOUND_INDEXES, TEMPLATE_MULTIKEY_INDEXES, TEMPLATE_PARTIAL_INDEX_PROPERTY ]; // nested-array (sub-key) indexes // example: 'cIdx1Test' => [TEST_FIELD_TEST_INT => 1, TEST_FIELD_TEST_DOUBLE => -1 ] $counter = 0; foreach ($indexList as $currentIndex) { if (isset($this->template->$currentIndex) and !empty($this->template->$currentIndex)) { foreach ($this->template->$currentIndex as $key => $subArray) { foreach ($subArray as $indexKey => $value) { if ($indexKey != MONGO_ID and !isset($_templateReport[$indexLabels[$counter]])) { $_templateReport[$indexLabels[$counter]][] = $indexKey; } } } } else { $_templateReport[$indexLabels[$counter]] = STRING_NOT_DEFINED; } $counter++; } // set-up the index lists and process (these are all indexed arrays) $indexList = [ 'indexFields', 'regexFields', 'binFields' ]; $indexLabels = [ TEMPLATE_FIELD_INDEX_LIST, TEMPLATE_REGEX_INDEXES, TEMPLATE_BINARY_FIELD_LIST ]; $counter = 0; foreach ($indexList as $currentIndex) { if (isset($this->template->$currentIndex) and !empty($this->template->$currentIndex)) { foreach ($this->template->$currentIndex as $key) { if ($this->template->setCache) { if (array_key_exists($key, $this->template->cacheMap)) { $_templateReport[$indexLabels[$counter]][] = $key; } } else { $_templateReport[$indexLabels[$counter]][] = $key; } } } else { $_templateReport[$indexLabels[$counter]] = STRING_NOT_DEFINED; } $counter++; } return($_templateReport); } /** * pdoCacheMappedIndexes() -- private method * * This method is called from processTemplateIndexes() and is responsible for processing PDO class indexes * in a template file when said class has caching enabled and a cacheMap built in the template. * * The input parameter to the method is the in-progress template array from the calling client. During processing * of the template indices, we'll continue to build the template report which will be the array passed back * to the calling client. * * * @author mike@givingassistant.org * @version 1.0 * * @param array $_templateReport * @return array * * * HISTORY: * ======== * 09-22-17 mks CORE-562: original coding * 10-18-17 mks CORE-584: bug fixing, added protectedFields to report * 10-19-17 mks CORE-610: added event messages for when a key is not in cacheMap * 03-01-18 mks CORE-689: filtering identical error messages out of the eventMessage container, * filtering 'id' out of comparisons b/c we never expose this key * */ private function pdoCacheMappedIndexes(array $_templateReport): array { // build the template field list first foreach ($this->template->fields as $key => $value) { if ($key != PDO_ID) { if (array_key_exists($key, $this->template->cacheMap)) { $_templateReport[TEMPLATE_FIELD_LIST][$this->template->cacheMap[$key]] = $value; } else { $msg = sprintf(ERROR_MDB_FIELD_NOT_CACHED, $key, $this->template->collection); if (!in_array($msg, $this->eventMessages)) { $this->eventMessages[] = $msg; if (gasConfig::$settings[CONFIG_DEBUG]) $this->logger->debug($msg); } } } } $indexList = [ 'indexFields', 'singleFields', 'uniqueIndexes', 'binFields', 'protectedFields' ]; $indexLabels = [ TEMPLATE_FIELD_INDEX_LIST, TEMPLATE_SINGLE_INDEXES, TEMPLATE_UNIQUE_INDEX_PROPERTY, TEMPLATE_BINARY_FIELD_LIST, TEMPLATE_PROTECTED_FIELDS ]; $counter = 0; foreach ($indexList as $currentIndex) { if (isset($this->template->$currentIndex) and !empty($this->template->$currentIndex)) { foreach ($this->template->$currentIndex as $key) { if ($key != PDO_ID) { if (array_key_exists($key, $this->template->cacheMap)) { $_templateReport[$indexLabels[$counter]][] = $this->template->cacheMap[$key]; } else { $msg = sprintf(ERROR_MDB_FIELD_NOT_CACHED, $key, $this->template->collection); if (!in_array($msg, $this->eventMessages)) { $this->eventMessages[] = $msg; if (gasConfig::$settings[CONFIG_DEBUG]) $this->logger->debug($msg); } } } } } else { $_templateReport[$indexLabels[$counter]] = STRING_NOT_DEFINED; } $counter++; } if (isset($this->template->compoundIndexes) and !empty($this->template->compoundIndexes)) { foreach ($this->template->compoundIndexes as $key => $subArray) { if ($key != PDO_ID) { foreach ($subArray as $indexKey => $value) { if (array_key_exists($value, $this->template->cacheMap)) { $_templateReport[TEMPLATE_COMPOUND_INDEXES][$key][] = $this->template->cacheMap[$value]; } else { $msg = sprintf(ERROR_MDB_FIELD_NOT_CACHED, $key, $this->template->collection); if (!in_array($msg, $this->eventMessages)) { $this->eventMessages[] = $msg; if (gasConfig::$settings[CONFIG_DEBUG]) $this->logger->debug($msg); } } } } } } else { $_templateReport[TEMPLATE_COMPOUND_INDEXES] = STRING_NOT_DEFINED; } return($_templateReport); } /** * mongoCacheMappedIndexes() -- private method * * This method is called from the processTemplateIndexes() method - we pass the templateReport from that method * as the only input parameter to which we'll add the indexes... said report is returned to the calling program * and will eventually become the schema's template report. * * The method processes the different types of indexes (in terms of their internal format), maps the field names * against the current cache-map, and stores those into the appropriate index containers. * * * @author mike@givingassistant.org * @version 1.0 * * @param array $_templateReport * @return array * * * HISTORY: * ======== * 09-21-17 mks CORE-562: original coding * 10-19-17 mks CORE-610: refactored the processing for the new index formats, including sort-direction, * explicitly enumerating not-defined indexes as part of the report, and adding * error messages when a column is not found in the cache-map * 10-25-19 mks DB-136: error message improvements which also necessitated type-error handling * */ private function mongoCacheMappedIndexes(array $_templateReport): array { $consoleMessages = []; // build the template field list first foreach ($this->template->fields as $key => $value) { if (array_key_exists($key, $this->template->cacheMap)) { $_templateReport[TEMPLATE_FIELD_LIST][$this->template->cacheMap[$key]] = $value; } else { try { $this->processCacheMapSearchErrors((string) $key, $consoleMessages); } catch (TypeError $t) { $msg = sprintf(INFO_LOC, __METHOD__, __LINE__) . ERROR_TYPE_EXCEPTION; $this->logger->error($msg); consoleLog($this->res, CON_ERROR, $msg); $this->state = STATE_DATA_ERROR; $this->status = false; return []; } } } // set-up the like-formatted index lists and process (col -> sortDir) $indexList = [ 'singleFields', 'uniqueIndexes' ]; $indexLabels = [ TEMPLATE_SINGLE_INDEXES, TEMPLATE_UNIQUE_INDEX_PROPERTY ]; // associative array (key) indexes $counter = 0; foreach ($indexList as $currentIndex) { if (isset($this->template->$currentIndex) and !empty($this->template->$currentIndex)) { foreach ($this->template->$currentIndex as $key => $value) { if (array_key_exists($key, $this->template->cacheMap)) { $_templateReport[$indexLabels[$counter]][$this->template->cacheMap[$key]] = ($value == 1) ? STRING_SORT_ASC : STRING_SORT_DESC; } else { try { $this->processCacheMapSearchErrors((string)$key, $consoleMessages); } catch (TypeError $t) { $msg = sprintf(INFO_LOC, __METHOD__, __LINE__) . ERROR_TYPE_EXCEPTION; $this->logger->error($msg); consoleLog($this->res, CON_ERROR, $msg); $this->state = STATE_DATA_ERROR; $this->status = false; return []; } } } } else { $_templateReport[$indexLabels[$counter]] = STRING_NOT_DEFINED; } $counter++; } // set-up the index lists and process $indexList = [ 'compoundIndexes', 'multiKey' ]; $indexLabels = [ TEMPLATE_COMPOUND_INDEXES, TEMPLATE_MULTIKEY_INDEXES ]; // nested-array (sub-key) indexes // example: 'cIdx1Test' => [TEST_FIELD_TEST_INT => 1, TEST_FIELD_TEST_DOUBLE => -1 ] $counter = 0; foreach ($indexList as $currentIndex) { if (isset($this->template->$currentIndex) and !empty($this->template->$currentIndex)) { foreach ($this->template->$currentIndex as $key => $subArray) { foreach ($subArray as $indexKey => $value) { if (array_key_exists($indexKey, $this->template->cacheMap)) { if (!isset($_templateReport[$indexLabels[$counter]]) or !in_array($this->template->cacheMap[$indexKey], $_templateReport[$indexLabels[$counter]])) { $_templateReport[$indexLabels[$counter]][$key][] = [$this->template->cacheMap[$indexKey] => ($value == 1) ? STRING_SORT_ASC : STRING_SORT_DESC]; } else { try { $this->processCacheMapSearchErrors((string)$indexKey, $consoleMessages); } catch (TypeError $t) { $msg = sprintf(INFO_LOC, __METHOD__, __LINE__) . ERROR_TYPE_EXCEPTION; $this->logger->error($msg); consoleLog($this->res, CON_ERROR, $msg); $this->state = STATE_DATA_ERROR; $this->status = false; return []; } } } } } } else { $_templateReport[$indexLabels[$counter]] = STRING_NOT_DEFINED; } $counter++; } // set-up the index lists and process (these are all indexed arrays) $indexList = [ 'indexFields', 'regexFields', 'binFields', 'protectedFields', 'exposedFields' ]; $indexLabels = [ TEMPLATE_FIELD_INDEX_LIST, TEMPLATE_REGEX_INDEXES, TEMPLATE_BINARY_FIELD_LIST, TEMPLATE_PROTECTED_FIELDS, TEMPLATE_EXPOSED_FIELDS ]; $counter = 0; foreach ($indexList as $currentIndex) { if (isset($this->template->$currentIndex) and !empty($this->template->$currentIndex)) { foreach ($this->template->$currentIndex as $key) { if (array_key_exists($key, $this->template->cacheMap)) { $_templateReport[$indexLabels[$counter]][] = $this->template->cacheMap[$key]; } else { try { $this->processCacheMapSearchErrors((string)$key, $consoleMessages); } catch (TypeError $t) { $msg = sprintf(INFO_LOC, __METHOD__, __LINE__) . ERROR_TYPE_EXCEPTION; $this->logger->error($msg); consoleLog($this->res, CON_ERROR, $msg); $this->state = STATE_DATA_ERROR; $this->status = false; return []; } } } } else { $_templateReport[$indexLabels[$counter]] = STRING_NOT_DEFINED; } $counter++; } // the remaining indexes have to be processed individually owing to their uniqueness... // partial indexes ( indexName => column => operand => bool) if (isset($this->template->partialIndexes) and !is_null($this->template->partialIndexes)) { foreach ($this->template->partialIndexes as $indexName => $index) { foreach ($index as $column => $subArray) { if (array_key_exists($column, $this->template->cacheMap)) { $_templateReport[TEMPLATE_PARTIAL_INDEX_PROPERTY][$indexName] = [$this->template->cacheMap[$column] => $subArray]; } else { try { $this->processCacheMapSearchErrors((string)$column, $consoleMessages); } catch (TypeError $t) { $msg = sprintf(INFO_LOC, __METHOD__, __LINE__) . ERROR_TYPE_EXCEPTION; $this->logger->error($msg); consoleLog($this->res, CON_ERROR, $msg); $this->state = STATE_DATA_ERROR; $this->status = false; return []; } } } } } else { $_templateReport[TEMPLATE_PARTIAL_INDEX_PROPERTY] = STRING_NOT_DEFINED; } // ttl indexes: (col => value) if (isset($this->template->ttlIndexes) and !is_null($this->template->ttlIndexes)) { foreach ($this->template->ttlIndexes as $column => $value) { if (array_key_exists($column, $this->template->cacheMap)) { $_templateReport[TEMPLATE_TTL_INDEX_PROPERTY][$column] = $value; } else { try { $this->processCacheMapSearchErrors((string)$column, $consoleMessages); } catch (TypeError $t) { $msg = sprintf(INFO_LOC, __METHOD__, __LINE__) . ERROR_TYPE_EXCEPTION; $this->logger->error($msg); consoleLog($this->res, CON_ERROR, $msg); $this->state = STATE_DATA_ERROR; $this->status = false; return []; } } } } else { $_templateReport[TEMPLATE_TTL_INDEX_PROPERTY] = STRING_NOT_DEFINED; } // sub-collections: (subCName => [ cols ]) if (isset($this->template->subC) and !is_null($this->template->subC)) { foreach ($this->template->subC as $indexName => $fieldList) { foreach ($fieldList as $column) { if (array_key_exists($column, $this->template->cacheMap)) { $_templateReport[TEMPLATE_SUB_COLLECTION_FIELDS][$indexName][] = $this->template->cacheMap[$column]; } else { try { $this->processCacheMapSearchErrors((string)$column, $consoleMessages); } catch (TypeError $t) { $msg = sprintf(INFO_LOC, __METHOD__, __LINE__) . ERROR_TYPE_EXCEPTION; $this->logger->error($msg); consoleLog($this->res, CON_ERROR, $msg); $this->state = STATE_DATA_ERROR; $this->status = false; return []; } } } } } else { $_templateReport[TEMPLATE_SUB_COLLECTION_FIELDS] = STRING_NOT_DEFINED; } return($_templateReport); } /** * pdoExposedFieldIndexes() -- private method * * This method is called from the processTemplateIndexes() method once it's been determined that the current class * is PDO and that the cacheMapping is disabled but exposed-fields are enabled. * * The input parameter to the method is the in-progress template report which we'll add to during processing and * that template report will eventually be assigned to the $widget->schema member. * * * @author mike@givingassistant.org * @version 1.0 * * @param array $_templateReport * @return array * * * HISTORY: * ======== * 09-22-17 mks CORE-562: original coding * */ private function pdoExposedFieldIndexes(array $_templateReport): array { // build the template field list first foreach ($this->template->fields as $key => $value) { if (array_key_exists($key, $this->template->exposedFields)) { $_templateReport[TEMPLATE_FIELD_LIST][$this->template->exposedFields[$key]] = $value; } } $indexList = [ 'indexFields', 'singleFields', 'uniqueIndexes', 'binFields' ]; $indexLabels = [ TEMPLATE_FIELD_INDEX_LIST, TEMPLATE_SINGLE_INDEXES, TEMPLATE_UNIQUE_INDEX_PROPERTY, TEMPLATE_BINARY_FIELD_LIST ]; $counter = 0; foreach ($indexList as $currentIndex) { if (isset($this->template->$currentIndex) and !empty($this->template->$currentIndex)) { foreach ($this->template->$currentIndex as $key => $value) { if (array_key_exists($key, $this->template->exposedFields) and $key != PDO_ID) { $_templateReport[$indexLabels[$counter]][] = $key; } } } $counter++; } if (isset($this->template->compoundIndexes) and !empty($this->template->compoundIndexes)) { foreach ($this->template->compoundIndexes as $key => $subArray) { foreach ($subArray as $indexKey => $value) { if (array_key_exists($indexKey, $this->template->exposedFields)) { if (!isset($_templateReport[TEMPLATE_COMPOUND_INDEXES]) or !in_array($this->template->exposedFields[$indexKey], $_templateReport[TEMPLATE_COMPOUND_INDEXES])) { $_templateReport[TEMPLATE_COMPOUND_INDEXES][] = $this->template->exposedFields[$indexKey]; } } } } } return($_templateReport); } /** * mongoExposedFieldsIndexes() -- private method * * This method is called from the processTemplateIndexes() method once it's been determined that we're going to be * building the template report for a mongo class where we have cacheMapping disabled but exposed fields enabled. * * In which case, the general rule is that for a class member (field) to be exposed to the client, it must be * explicitly listed in the exposed fields array. Exposed field arrays are indexed-arrays who's keys, like * the cacheMap array, are the "real" column names minus the three-letter table extension. * * The method requires one input parameter and that's the template report that will eventually become the widget * schema member. As such, this array is returned to the calling client. * * We're going to build the bulk of the index containers using the array member as the loop controller - this * has been set in the constructor for this class. * * * @author mike@givingassistant.org * @version 1.0 * * @param array $_templateReport * @return array * * * HISTORY: * ======== * 09-21-17 mks CORE-562: original coding * */ private function mongoExposedFieldsIndexes(array $_templateReport): array { // build the template field list first foreach ($this->template->exposedFields as $key) { $_templateReport[TEMPLATE_FIELD_LIST][$key] = $this->template->fields[$key]; } // generate the index lists... // set-up the index lists and process $indexList = [ 'singleFields', 'uniqueIndexes', 'ttlIndexes', 'subC' ]; $indexLabels = [ TEMPLATE_SINGLE_INDEXES, TEMPLATE_UNIQUE_INDEX_PROPERTY, TEMPLATE_TTL_INDEX_PROPERTY, TEMPLATE_SUB_COLLECTION_FIELDS ]; $counter = 0; foreach ($indexList as $currentIndex) { if (isset($this->template->$currentIndex) and !empty($this->template->$currentIndex)) { foreach ($this->template->$currentIndex as $key => $value) { if (array_key_exists($key, $this->template->exposedFields) and $key != MONGO_ID) { $_templateReport[$indexLabels[$counter]][] = $key; } } } $counter++; } // set-up the index lists and process (these are all indexed arrays) $indexList = [ 'indexFields', 'regexFields', 'binFields' ]; $indexLabels = [ TEMPLATE_FIELD_INDEX_LIST, TEMPLATE_REGEX_INDEXES, TEMPLATE_BINARY_FIELD_LIST ]; $counter = 0; foreach ($indexList as $currentIndex) { if (isset($this->template->$currentIndex) and !empty($this->template->$currentIndex)) { foreach ($this->template->$currentIndex as $key => $subArray) { foreach ($subArray as $indexKey => $value) { if (in_array($indexKey, $this->template->exposedFields) and $key != MONGO_ID) { if (!isset($_templateReport[$indexLabels[$counter]]) or !in_array($this->template->exposedFields[$indexKey], $_templateReport[$indexLabels[$counter]])) { $_templateReport[$indexLabels[$counter]][] = $indexKey; } } } } } $counter++; } // set-up the index lists and process (these are all indexed arrays) $indexList = [ 'indexFields', 'regexFields', 'binFields' ]; $indexLabels = [ TEMPLATE_FIELD_INDEX_LIST, TEMPLATE_REGEX_INDEXES, TEMPLATE_BINARY_FIELD_LIST ]; $counter = 0; foreach ($indexList as $currentIndex) { if (isset($this->template->$currentIndex) and !empty($this->template->$currentIndex)) { foreach ($this->template->$currentIndex as $key) { if (in_array($key, $this->template->exposedFields) and $key != MONGO_ID) { $_templateReport[$indexLabels[$counter]][] = $key; } } } $counter++; } return ($_templateReport); } /** * getPrivateFields() -- private method * * this method was scraped from the fetchSchema() method in order to reduce the code footprint. * * the method checks for the declaration/existence of binary fields declared in the template file and, if set, * will then processes those fields through the cacheMap or the exposed fields member. * * The parameter to the method is the in-progress template report which is explicitly returned back to the * calling client upon completion. * * * @author mike@givingassistant.org * @version 1.0 * * @param array $_templateReport * @return array $_templateReport * * HISTORY: * ======== * 09-20-17 mks CORE-562: original coding * */ private function getBinaryFields(array $_templateReport): array { if (!empty($this->template->binFields)) { if (empty($this->template->cacheMap) and empty($this->template->exposedFields)) { // case 1: no cacheMap and no exposedFields list $_templateReport[TEMPLATE_BINARY_FIELD_LIST] = $this->template->binFields; } elseif (!empty($this->template->cacheMap)) { // case 2: cachemap and maybe an exposedFields list foreach ($this->template->binFields as $key) { if (!empty($this->template->exposedFields)) { if (in_array($key, $this->template->exposedFields)) { $_templateReport[TEMPLATE_BINARY_FIELD_LIST][] = $key; } } elseif (in_array($key, $this->template->cacheMap)) { $_templateReport[TEMPLATE_BINARY_FIELD_LIST][] = $this->template->cacheMap[$key]; } } } elseif (!empty($this->template->exposedFields)) { foreach ($this->template->binFields as $key) { if (in_array($key, $this->template->exposedFields)) { $_templateReport[TEMPLATE_BINARY_FIELD_LIST][] = $key; } } } } else { $_templateReport[TEMPLATE_BINARY_FIELD_LIST] = STRING_NOT_DEFINED; } return($_templateReport); } /** * getFieldList() -- private method * * this method is called from the template-report builder method and is responsible for parsing the * template cachemap and exposedFields containers to build the class field list. * * at this stage of the instantiation process, all relevant error-checking has already previously happened so * we can rip through this processing. * * Note: method created to avoid code redundancy. * Note: this builds the field list for the TEMPLATE REPORT -- not for the class member of the same name * * * @author mike@givingassistant.org * @version 1.0 * * @param array $_templateReport -- call by reference parameter to continue assembling the template report * * * HISTORY: * ======== * 09-20-17 mks CORE-562: original coding (import from fetchSchema()) * 10-02-17 mks CORE-572: refactored and removed all the weird * 03-26-18 mks CORE-852: fixed bug in exposed-field list processing * */ private function getFieldList(array &$_templateReport): void { // get the field lists and data types if (!isset($_templateReport[TEMPLATE_FIELD_LIST])) $_templateReport[TEMPLATE_FIELD_LIST] = array(); // if this class uses cache and we have a cacheMap, then populate the field list using the cachemap if ($this->widget->useCache and !empty($this->widget->cacheMap)) { // case 1: no cachemap and no exposed field list => all fields are listed foreach ($this->widget->fieldTypes as $key => $value) { if (array_key_exists($key, $this->widget->cacheMap)) { $_templateReport[TEMPLATE_FIELD_LIST][$this->widget->cacheMap[$key]] = $value; } } } elseif (!empty($this->widget->exposedFields)) { // case 2: we have an exposed fields list foreach ($this->widget->fieldTypes as $key => $value) { if (in_array($key, $this->widget->exposedFields)) { $_templateReport[TEMPLATE_FIELD_LIST][$key] = $value; // $_templateReport[TEMPLATE_FIELD_LIST][$this->widget->exposedFields[$key]] = $value; } } } else { // case 3: no cache map and no exposed fields foreach ($this->widget->fieldTypes as $key => $value) { if ($key != (MONGO_ID . $this->widget->ext) and $key != (PDO_ID . $this->widget->ext)) { $_templateReport[TEMPLATE_FIELD_LIST][$key] = $value; } } } } /** * processCacheMapSearchErrors() -- private method * * This method requires two input parameters: * * $_key -- this is the string value containing the key that was being searched-for in the cache map * $_savedMessages -- call-by-reference parameter that maintains the current array of errors to eliminate duplicates * * This method takes the incoming $key value and checks to see if the value contains the mongo primary key or an * integer value. An integer value would indicate that the key is referencing a sub-array container and is not * necessarily an error. If either of these values are stored in key, we'll output a console message but, before * doing so, we'll check the $_savedMessages variable to see if the value has already been stored in this current * run of data. If so, skip adding and outputting the error message. * * If the error is legit, then we'll add the error message to the event messages stack. We'll only output the * error to the logger log if the global debug switch is enabled. * * The method does not return a value so is declared as type void. * * * @author mike@givingassistant.org * @version 1.0 * * @param string $_key * @param array $_savedMessages * * * HISTORY: * ======== * 10-25-19 mks DB-136: original coding * */ private function processCacheMapSearchErrors(string $_key, array &$_savedMessages): void { if ($_key == MONGO_ID) { // having a pkey in payload data isn't necessarily an error $hdr = sprintf(INFO_LOC, __METHOD__, __LINE__); $msg = $hdr . ERROR_MDB_CACHE_NO_PKEYS; if (!in_array($msg, $_savedMessages)) { if ($this->debug) consoleLog($this->res, CON_SYSTEM, $msg); $_savedMessages[] = $msg; } } elseif (is_numeric($_key)) { // having an integer value means we're processing a sub-array so is not error $hdr = sprintf(INFO_LOC, __METHOD__, __LINE__); $msg = $hdr . ERROR_MDB_CACHE_INTVAL; if (!in_array($msg, $_savedMessages)) { if ($this->debug) consoleLog($this->res, CON_SYSTEM, $msg); $_savedMessages[] = $msg; } } else { // this is definitely an error and should be returned in the error stack $hdr = sprintf(INFO_LOC, __METHOD__, __LINE__); $msg = $hdr . sprintf(ERROR_MDB_FIELD_NOT_CACHED, $_key, $this->template->collection); if (!in_array($msg, $this->eventMessages)) $this->eventMessages[] = $msg; // this line reduces a LOT of log spam: if (gasConfig::$settings[CONFIG_DEBUG]) $this->logger->debug($msg); } } /** * __destruct() -- public function * * class destructor * * * @author mike@givingassistant.org * @version 1.0 * * * HISTORY: * ======== * 06-15-17 mks original coding * */ public function __destruct() { // As of PHP 5.3.10 destructors are not run on shutdown caused by fatal errors. // // destructor is registered shut-down function in constructor -- so any recovery // efforts should go in this method. } }