    /**
     * cacheByTokenList() -- private method
     *
     * This method requires a single input parameter -- that's an array of tokens in the following format:
     *
     * array (
     *   0 =>
     *   array (
     *     'token_tst' => '2DB9636A-C14D-F2C9-7CDA-E7808C1EA600',
     *   ),
     * )
     *
     * This method is used from the update event -- when we've already completed the update successfully and the
     * current class has been populated with the successful update-query results, which we wish to preserve.
     *
     * The updated records, represented by the token list, has to be re-cached.  So this method is going to exec
     * a SELECT query to fetch the updated records for caching.  This is a prepared query.
     *
     * Since we don't want to overwrite the results of the update query in the current class object, we're going to
     * clone the object, execute the select query from that object, and transfer the results over to the original
     * class before releasing the cloned object.
     *
     * Prior to said release, we're going to call the method to process the data members and cache the records and,
     * on return, transfer the cache keys (if caching is enabled for the class) or the data.
     *
     * The method returns a boolean indicating success or failure for all of the operation.
     *
     *
     * @author  mike@givingassistant.org
     * @version 1.0
     *
     * @param array $_tList
     * @return bool
     *
     * HISTORY:
     * ========
     * 10-31-17     mks     CORE-586: original coding
     *
     */
    private function cacheByTokenList(array $_tList): bool
    {
        if (!is_array($_tList)) {
            $this->eventMessages[] = ERROR_DATA_ARRAY_NOT_ARRAY . STRING_TOKEN;
            return false;
        }
        // clone the current object so we don't overwrite any of the current class members & zero-out the important bits
        $tObj = clone $this;
        $tObj->queryVariables = null;
        $tObj->strQuery = '';
        $tObj->queryResults = '';
        $tObj->count = 0;
        $tObj->dbEvent = DB_EVENT_SELECT;

        /*
         * build the query to fetch the record based on the token list which looks like:
         *
         * array (
         *   0 =>
         *   array (
         *     'token_xxx' => '2DB9636A-C14D-F2C9-7CDA-E7808C1EA600',
         *   ),
         * )
         */
        $query = 'SELECT /* ' . basename(__FILE__) . COLON . __METHOD__ . AT . __LINE__ . ' */ ';
        $query .= '* FROM ';
        if (!isset($tObj->template->dbObjects[PDO_VIEWS][PDO_VIEW_BASIC . $tObj->collectionName])) {
            $query .= $tObj->collectionName;
        } else {
            $query .= PDO_VIEW_BASIC . $tObj->collectionName;
        }
        $query .= ' ';
        $query .= 'WHERE ' . STRING_TOKEN . $tObj->ext . ' IN (';
        foreach ($_tList as $record) {
            $query .= '?, ';
            $tObj->queryVariables[] = $record[(STRING_TOKEN . $tObj->ext)];
        }
        $query = rtrim($query, ', ');
        $query .= ') ';
        if (!$tObj->useDeletes) {
            $query .= 'AND status' . $tObj->ext . ' != ?';
            $tObj->queryVariables[] = STATUS_DELETED;
        }
        $tObj->strQuery = $query;

        try {
            $tObj->executePreparedQuery();
            if (!$tObj->status) {
                $this->eventMessages = array_merge($this->eventMessages, $tObj->eventMessages);
                return false;
            }

            $tObj->data = $tObj->queryResults;
            if (!$tObj->returnFilteredData()) {
                $this->eventMessages = array_merge($this->eventMessages, $tObj->eventMessages);
                $this->eventMessages[] = ERROR_RFD_CORE_FAIL;
                return false;
            }
        } catch (Throwable $t) {
            $msg = ERROR_THROWABLE_EXCEPTION . COLON . $t->getMessage();
            $this->eventMessages[] = $msg;
            if (isset($this->logger) and $this->logger->available)
                $this->logger->error($msg);
            else
                consoleLog($this->res, CON_ERROR, $msg);
            $this->state = STATE_FRAMEWORK_WARNING;
            return false;
        }
        // copy data from the clone to the original
        $this->eventMessages = array_merge($this->eventMessages, $tObj->eventMessages);
        $this->cacheKeys = $tObj->cacheKeys;
        $this->data = $tObj->data;
        $tObj->__destruct();
        unset($tObj);
        return true;
    }


    /**
     * getCacheTokenListQuery() -- private method
     *
     * This method is called from the update and delete methods for when we need to generate a list of affected tokens
     * for these operations.  We need to generate this list b/c the operation will modify the records and, if the
     * records exist in cache, they should be removed.
     *
     * The method requires one input parameter which is the list of tokens we're going to build as a result of the
     * query.  As such, all of the query elements must have been built prior to invoking this method as those member
     * elements are used to build this SELECT query...
     *
     * We'll execute the prepared select query and store the results in an array which is implicitly returned to the
     * calling client.
     *
     * The method proper returns a boolean to indicate success or fail in processing as a null value returned for
     * the token list is permissible.
     *
     *
     * @author  mike@givingassistant.org
     * @version 1.0
     *
     * @param array|null $_tokenList
     * @return boolean
     *
     * HISTORY:
     * ========
     * 10-26-17     mks     CORE-586: original coding
     *
     */
    private function getCacheTokenListQuery(array &$_tokenList = null): bool
    {
        $rc = false;

        $cq = 'SELECT /* ' . basename(__FILE__) . COLON . __METHOD__ . AT . __LINE__ . ' */ ';
        $cq .= DB_TOKEN . $this->ext . ' ';
        $cq .= 'FROM ' . $this->collectionName . ' ';
        $cq .= 'WHERE ' . $this->where . ' ';
        if (!is_null($this->queryOrderBy)) {
            $cq .= 'ORDER BY ' . $this->queryOrderBy . ' ';
        }
        if (!is_null($this->queryLimit)) {
            $cq .= 'LIMIT ' . $this->queryLimit;
        }
        try {
            $this->dbEvent = DB_EVENT_NAMASTE_READ;
            $this->strQuery = $cq;
            $this->executePreparedQuery();
            if ($this->status) {
                $_tokenList = $this->queryResults;
//            foreach ($this->queryResults as $key ) {
//                $_tokenList[] = $key;
//            }
                if (empty($_tokenList)) $_tokenList = null;
                $rc = true;
            } else {
                $this->eventMessages[] = ERROR_PDO_CQ_QUERY;
                $this->state = STATE_DB_ERROR;
            }
            return $rc;
        } catch (Throwable $t) {
            $msg = sprintf(ERROR_EXCEPTION . COLON . $this->strQuery[0]);
            consoleLog(RES_PDO, CON_ERROR, $msg);
            $this->eventMessages[] = $msg;
            $this->eventMessages[] = $t->getMessage();
            if (isset($this->logger) and $this->logger->available) {
                $this->logger->warn($msg);
                $this->logger->warn($t->getMessage());
            } else {
                consoleLog($this->res, CON_ERROR, $msg);
                consoleLog($this->res, CON_ERROR, $t->getMessage());
            }
            $this->status = false;
            $this->state = STATE_DB_ERROR;
        }
        return false;
    }
