952 days continuous production uptime, 40k+ tp/s single node. Original corpo Bitbucket history not included — clean archive commit.
1586 lines
73 KiB
PHP
1586 lines
73 KiB
PHP
<?php declare(strict_types=1);
|
|
|
|
/**
|
|
* gacFactory()
|
|
*
|
|
* This is the factory class which is used to instantiate all database class objects. Since Namaste supports and
|
|
* abstracts different data schemas, instantiation of those classes starts with this class.
|
|
*
|
|
* The basic algorithm is that, when this class is invoked, it analyzed the template passed to it's constructor.
|
|
* It instantiates a new data class based on the template settings and returns that object class back to the calling
|
|
* client.
|
|
*
|
|
* Some requested events, such as a schema-fetch, may not require full instantiation - instead a data-ball may be
|
|
* passed back to the calling client instead. So, it's up the calling client to understand and anticipate which data
|
|
* object will be returned back to them based on the event that's being invoked.
|
|
*
|
|
*
|
|
* @author mike@givingassistant.org
|
|
* @version 1.0
|
|
*
|
|
*
|
|
* HISTORY:
|
|
* ========
|
|
* 06-15-17 mks original coding
|
|
* 03-02-18 mks CORE-680: deprecated trace/squelch logging
|
|
* 07-31-18 mks CORE-774: PHP7.2 exception handling
|
|
* 01-07-20 mks DB-150: PHP7.4 type casting for member variables
|
|
* 06-01-20 mks ECI-108: Protecting Instantiations from SMAX API Requests
|
|
*
|
|
*/
|
|
class gacFactory
|
|
{
|
|
public ?object $template = null; // container for the template class
|
|
private string $class; // defines the current class
|
|
private gacErrorLogger $logger; // instantiation of the logger class client
|
|
private string $eventID; // the broker event ID, extracted from meta
|
|
private array $validTemplates; // array/list of the valid templates stored in the templates directory
|
|
public array $meta; // hold a copy of the meta data passed in via the constructor
|
|
public array $schema = []; // the schema data object returned from a fetchSchema event
|
|
public bool $status; // boolean indicating the current status of the class
|
|
public string $state; // string indicating the current state of the class
|
|
private gacDdb $ddbWidget;
|
|
private gacMongoDB $mongoWidget;
|
|
private gacPDO $pdoWidget;
|
|
public object $widget; // the new object we'll construct and return to the calling client
|
|
public array $eventMessages; // container for processing event messages we may want to know about
|
|
private string $res; // label for console log output
|
|
private bool $debug; // for squelching output in prod envs
|
|
|
|
/**
|
|
* gacFactory constructor.
|
|
*
|
|
* this is the constructor for the factory class - the following input parameters are supported:
|
|
*
|
|
* $_meta -- this is the array of meta data as received by the broker. Within the meta data, we must extract:
|
|
*
|
|
* $_template -- this string defines the name of the class that we're wanting to work with. it is a required
|
|
* parameter and should match the name of the template without the ".class.inc" extensions.
|
|
* $_guid -- this is an optional parameter: if supplied, it means to instantiate the class and populate it
|
|
* with the record referenced by the guid.
|
|
*
|
|
* $_event -- this is the event that the constructor will process -- it defaults to instantiating a new class.
|
|
* $_es -- this is an array which is a call-by-reference parameter and will contain an error stack of
|
|
* on or more errors that were created during processing to help the calling client understand
|
|
* why the request failed.
|
|
*
|
|
* First, we're going to set some class variables before attempting to extract the template name from the
|
|
* meta-data payload. We'll load up a dynamic list of all templates currently in the templates directory and
|
|
* see if our template is in the list, if not, then return an error.
|
|
*
|
|
* Next, we process the event - and call the appropriate method. In the called method, the member variable state
|
|
* is updated and that's what's evaluated and subsequently returned to the calling client to indicate if the
|
|
* requested event successfully processed or not.
|
|
*
|
|
* Instantiation Security:
|
|
* -----------------------
|
|
* Namaste no longer checks for the environment before instantiation a data class. In most cases, any class can
|
|
* now be instantiated on any service. This follows the common Unix pattern "ALLOW_ALL_EXCEPT...".
|
|
*
|
|
* Where the "except" part happens is within the data template. There are two member variables related to class
|
|
* instantiation security:
|
|
*
|
|
* $isGA
|
|
* -----
|
|
* boolean, indicates if the data class is a Namaste (internal) class. If set to false, then the class is a "user"
|
|
* data class. This member is provided only as a sanity check for the next member.
|
|
* $authToken
|
|
* ----------
|
|
* This member can contain the Partner's API token key which is set in the constructor of the template class. By
|
|
* default, this member is assigned a string constant: NULL_STRING which is a string of zeros in 36-character
|
|
* GUID format. The presence of an actual, non-zero, string GUID indicates that this data class is proprietary to
|
|
* the user account, indicated by the token value and found within the SMAX token collection.
|
|
*
|
|
* When we're working with a user class, and the $authToken value is set, and we're instantiating on appServer
|
|
* ONLY, then we lookup the SMAX Token value to ensure that the account (a) exists and that the record status
|
|
* is (b) valid. If so, then we compare the GUID to the string value passed in the API call by SMAX.
|
|
*
|
|
* Correspondingly, these checks will only be performed when the request is coming from SMAX, meaning that the
|
|
* class can be instantiated internally by Namaste for events such as audit, journaling, user-validation, etc.
|
|
*
|
|
* $isGA should always be set to false for proprietary user classes providing an additional check to ensure
|
|
* the instantiation is legit.
|
|
*
|
|
* In summary, we'll instantiate a proprietary data class only if the following conditions are satisfied, in the
|
|
* following order:
|
|
* -- the instantiation is happening on the appServer service in Namaste
|
|
* -- the instantiation request originated from the SMAX API
|
|
* -- the meta payload has the Partner's API Token (SMAX inserted it into the meta payload for us, how nice!)
|
|
* -- the data template has a valid GUID assigned to the $authToken member
|
|
* -- the GUID token submitted by the requester matches the value in $authToken
|
|
*
|
|
* Note: This upgraded security deprecates the constant META_SKIP_ENV_CHECK
|
|
*
|
|
*
|
|
* @author mike@givingassistant.org
|
|
* @version 1.0
|
|
*
|
|
* @param string $_event
|
|
* @param array|null $_meta
|
|
* @param string|null $_guid
|
|
* @param array|null $_es
|
|
*
|
|
*
|
|
* HISTORY:
|
|
* ========
|
|
* 06-15-17 mks original coding
|
|
* 08-03-17 mks CORE-503: qualify schema and env of template against current xml configuration
|
|
* 02-21-18 mks _INF-139: registered destructor function
|
|
* 05-04-18 mks _INF-188: embedding the meta class into the widget
|
|
* 05-09-18 mks _INF-188: adding segundo service
|
|
* 06-06-18 mks CORE-1012: revamp security for data classes following an "ALLOW_ALL" pattern.
|
|
* 06-15-20 mks ECI-164: support for partner tlti designations, instantiation security for partner
|
|
* classes with override for system requests
|
|
* 12-21-20 mks DB-180: updated exception handling
|
|
*
|
|
*/
|
|
public function __construct(array $_meta, string $_event = FACTORY_EVENT_NEW_CLASS, string $_guid = '', array &$_es = array())
|
|
{
|
|
register_shutdown_function(array($this, '__destruct'));
|
|
$this->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.
|
|
}
|
|
|
|
}
|