$enabled) if (gasConfig::$settings[$service][CONFIG_IS_LOCAL] and gasConfig::$settings[$service][CONFIG_ACTIVE]) $envList[] = $service; $logFile = dirname(__DIR__) . DIR_LOGS . FILE_MONGO_CONFIG_LOG; $outFile = dirname(__DIR__) . DIR_SCRIPTS . DIR_MONGO . FILE_MONGO_INDEX_SCRIPT; if (!file_exists($logFile)) touch($logFile); if (!file_exists($outFile)) { if (!touch($outFile)) { $hdr = basename(__FILE__) . AT . __LINE__ . COLON; $msg = ERROR_OPEN_LOG_FILE . $outFile; consoleLog($res, CON_ERROR, $hdr . $msg); consoleLog($res, CON_ERROR, INFO_NO_DIR); exit; } } $pLogFile = @fopen($logFile, 'a'); $pIndexFile = @fopen($outFile, 'w'); if (false === $pLogFile) { echo ERROR_OPEN_LOG_FILE . $logFile . PHP_EOL; exit(1); } if (false === $pIndexFile) { echo ERROR_OPEN_LOG_FILE . $outFile . PHP_EOL; exit(1); } @fwrite($pLogFile, getDateTime() . CON_SUCCESS . $res . 'begin processing templates' . PHP_EOL); @fwrite($pLogFile, getDateTime() . CON_SUCCESS . $res . 'opened output file: ' . $outFile . PHP_EOL); @fwrite($pIndexFile, '#! /bin/sh' . PHP_EOL); // pull a copy of the config into memory $config = gasConfig::$settings[CONFIG_DATABASE][CONFIG_DATABASE_MONGODB]; $firstPass = true; // loop through each Namaste-supported environment... foreach ($envList as $environment) { @fwrite($pIndexFile, '# Processing Environment: ' . $environment . PHP_EOL); // reset RBAC credentials $user = ''; $password = ''; $authDB = ''; $indexText = null; // if the current env is set and if that env has enabled mongoDB then... if (array_key_exists($environment, $config) and intval($config[$environment][STRING_ENABLED]) === 1) { // derive port assignment based-off the current db configuration (shard v. replSet v. standAlone) if (intval($config[$environment][CONFIG_DATABASE_MONGODB_SHARDING][CONFIG_DATABASE_MONGODB_ENABLED]) === 1) { $port = $config[$environment][CONFIG_DATABASE_MONGODB_SHARDING][CONFIG_DATABASE_MONGODB_SHARDING_MONGOS_NODES][CONFIG_DATABASE_MONGODB_ADMIN_REPLSET_SET]; $port = intval(substr($port, -5)); } elseif (intval($config[$environment][CONFIG_DATABASE_MONGODB_REPLSET][CONFIG_DATABASE_MONGODB_REPLSET_ENABLED]) === 1) { $port = $config[$environment][CONFIG_DATABASE_MONGODB_REPLSET][CONFIG_DATABASE_MONGODB_REPLSET_DSN][CONFIG_DATABASE_MONGODB_ADMIN_REPLSET_SET][0]; $port = intval(substr($port, -5)); } else { $port = intval($config[$environment][CONFIG_DATABASE_MONGODB_PORT]); } // if RBAC is enabled, grabbed the login credentials from the current env if ($config[$environment][CONFIG_DATABASE_MONGODB_USE_AUTH] == 1) { $user = $config[$environment][CONFIG_DATABASE_MONGODB_USER]; $password = $config[$environment][CONFIG_DATABASE_MONGODB_PASSWORD]; $authDB = gasConfig::$settings[CONFIG_ID][CONFIG_ID_ENV] . UDASH . $config[$environment][CONFIG_DATABASE_MONGODB_AUTH_SOURCE]; $command = 'mongo -u ' . $user . ' -p ' . $password . ' --port ' . $port . ' --authenticationDatabase ' . $authDB; } else { $command = 'mongo --port ' . $port; } /** @noinspection PhpComposerExtensionStubsInspection */ /** @var MongoClient $mongoResource */ $mongoResource = gasResourceManager::fetchResource(RESOURCE_MONGO_MASTER, $environment); if (is_null($mongoResource)) { @fwrite($pLogFile, getDateTime() . CON_ERROR . $res . ERROR_MONGO_CONNECT . AT . $environment . PHP_EOL); fclose($pLogFile); fclose($pIndexFile); exit(1); } // STEP 1 -- for every c-type class template, load and process the template foreach(glob(dirname(getcwd()) . DIR_CLASSES . DIR_TEMPLATE . '/*' . STRING_CLASS_FILE_EXT) as $filename) { $currentClass = basename($filename); $currentClass = preg_replace("/" . STRING_CLASS_FILE_EXT . "/", "", $currentClass); // extract the $tlti from the front of the template for the factory-class instantiation $tlti = substr($currentClass, 0, 3); $currentClass = preg_replace("/" . $tlti . "/", "", $currentClass); $database = null; $collection = null; $collectionName = null; if ($currentClass == 'SystemData' and $environment == ENV_ADMIN) $x = 1; echo 'processing: ' . $currentClass . '...' . $eos; try { $e = array(); $meta = [ META_TEMPLATE => $currentClass, META_CLIENT => CLIENT_SYSTEM, META_TLTI => $tlti ]; $objFactory = new gacFactory($meta, FACTORY_EVENT_NEW_CLASS, '', $e); if (is_null($objFactory)) break; // we couldn't instantiate the factory class for this template // do not process PDO scripts if ($objFactory->template->schema == TEMPLATE_DB_PDO) { $objFactory->__destruct(); unset($objFactory); continue; } // do not process if the template is not a member of the current environment if ($objFactory->template->service != $environment) { $objFactory->__destruct(); unset($objFactory); continue; } $version = $objFactory->template->version; $ext = $objFactory->template->extension; $service = $objFactory->template->service; $collectionName = $objFactory->template->collection; /** @var gacMongoDB $tmpObj */ $tmpObj = $objFactory->widget; $collectionName = $tmpObj->getCollectionName(); $dbName = $tmpObj->getDBName(); if (is_object($objFactory)) $objFactory->__destruct(); unset($objFactory); } catch (Throwable $t) { fclose($pLogFile); fclose($pIndexFile); exit($t->getMessage() . $eos); } $indexes = array(); // this is the index payload we'll submit to the mongoDB Manager\Command $options = array(); // this is the options payload for the corresponding index $commands = array(); // this is the list of commands that comprise the final ouput // indexes $singleIndices = $tmpObj->singleIndexes; $compoundIndices = $tmpObj->compoundIndexes; $multiKeyIndices = $tmpObj->multiKey; // index properties $uniqueIndices = $tmpObj->uniqueIndexes; $partialIndices = $tmpObj->partialIndexes; $t2LiveIndices = $tmpObj->ttlIndexes; // all indexing done in the background $sysOption = [ MONGO_STRING_BACKGROUND => true ]; // order for these two variables is critical: do *NOT* add or delete from one unless you do it to the other // while maintaining identical positions for each index type in the arrays. If we ever support indexes // other than what appears in these lists, we'll have not only manually add them to the lists, but also // code the respective validation and processing bits too. $indexTypes = [ $partialIndices, $uniqueIndices, $t2LiveIndices, $singleIndices, $compoundIndices, $multiKeyIndices ]; $indexList = [ 'partialIndices' => 0, 'uniqueIndices' => 1, 't2LiveIndices' => 2, 'singleIndices' => 3, 'compoundIndices' => 4, 'multiKeyIndices' => 5 ]; // process partial index properties for the class first $count = 0; foreach ($indexList as $indexName => $indexCounter) { if (!empty($indexTypes[$indexCounter])) { $badIndexName = false; $indexText[][MONGO_COLLECTION_NAME] = $collectionName; // the first part of this is to validate the index column/label names as valid/declared indexes foreach ($indexTypes[$indexCounter] as $indexLabel => $indexContents) { // strip, if it exists, the extension of the column name so we can grep it in our index lists $modifiedField = ($indexName == STRING_PARTIAL_INDICES) ? preg_replace("/" . $ext . "/", "", key($indexContents[0])) : preg_replace("/" . $ext . "/", "", $indexLabel); if (!in_array($modifiedField, $tmpObj->indexList)) { $hdr = sprintf(INFO_LOC, basename(__FILE__), __LINE__); $msg = sprintf(ERROR_MDB_INDEX_UNDECL, array_search($indexCounter, $indexList), basename($filename), $modifiedField); echo $hdr . $msg . PHP_EOL; $badIndexName = true; } // if we have one, just one, bad index reference, we need to error-out and stop processing // (but we'll echo a list of the bad index names before exiting) if ($badIndexName) { $hdr = sprintf(INFO_LOC, basename(__FILE__), __LINE__); echo $hdr . ERROR_DATA_VALIDATION; exit(1); } /* * the $indexes and $options structure contain all elements of the current index. If an index, * or index property, does not have options, then the placeholder for that position in $options * will be set to null. * */ switch ($indexCounter) { // changed structure of $indexes/$options to down-layer the data that will be passed to // mongo so as to avoid index name collisions within the arrays using the column name. // // the goal of this section is to generate the structures that we'll convert to json- // -encoded arrays that will ultimately be written to the bash deployment script case 0 : // partial indexes (done) for ($index = 0, $max = count($indexContents[0]); $index < $max; $index++) $indexes[][key($indexContents[$index])] = $indexContents[$index][key($indexContents[$index])]; $options[][ MONGO_STRING_PARTIAL_FE ] = $indexContents[1][0]; break; case 1 : // unique index (done) $indexes[][$indexLabel] = $uniqueIndices[$indexLabel]; $options[][MONGO_STRING_UNIQUE] = true; break; case 2 : // time-to-live indexes $indexes[][$indexLabel] = 1; $options[] = [ MONGO_STRING_EXPIRE_SEC => $t2LiveIndices[$indexLabel] ]; break; case 3 : // single indexes (done) $indexes[][$indexLabel] = $singleIndices[$indexLabel]; break; case 4 : // compound indexes (done) // mongo imposes a limit of 32 fields on compound indexes // mongo does not use index labels (that's a mysql thing) but we do use the label to // distinguish/differentiate the index lists $indexes[][$indexLabel] = $indexContents; break; case 5 : // multikey indexes for ($index = 0, $max = count($multiKeyIndices); $index < $max; $index++) $indexes[][$indexLabel] = $multiKeyIndices[$indexLabel]; break; default : // unknown index type $hdr = sprintf(INFO_LOC, __FILE__, __LINE__); $msg = $hdr . ERROR_MDB_UNK_IDX_TYPE . $indexLabel; echo $msg; exit (1); break; } } // the second part of this is to generate the BSON for each index type outputting the directives // to a bash-script that will be executed (manually) after this script completes processing switch ($indexCounter) { case 0 : // partial indexes for ($index = 0, $max = count($indexes); $index < $max; $index++) $indexText[] = json_encode($indexes[$index]) . COMMA . json_encode($options[$index]); break; case 1 : // unique indexes (done) for ($index = 0, $max = count($indexes); $index < $max; $index++) $indexText[] = json_encode($indexes[$index]) . COMMA . json_encode($options[$index]); break; case 2 : // t2Live indexes for ($index = 0, $max = count($indexes); $index < $max; $index++) $indexText[] = json_encode([$indexes[$index], $options[$index]]); break; case 3 : // single indexes (done) for ($index = 0, $max = count($indexes); $index < $max; $index++) $indexText[] = json_encode($indexes[$index]); break; case 4 : // compound indexes (done) for ($index = 0, $max = count($indexes); $index < $max; $index++) $indexText[] = json_encode($indexes[$index][key($indexes[$index])]); break; case 5 : // multi-key indexes for ($index = 0, $max = count($indexes); $index < $max; $index++) $indexText[] = json_encode($indexes[$index][key($indexes[$index])]); break; default : // unknown index type $hdr = sprintf(INFO_LOC, __FILE__, __LINE__); $msg = $hdr . ERROR_MDB_UNK_IDX_TYPE . $indexLabel; echo $msg; exit (1); break; } unset($indexes, $options); // reset the processed-index/options containers } } } // close the env-enabled loop if (!empty($indexText)) { // we have generated indexing commands --- write out the command to log into mongo @fwrite($pIndexFile, $command . ' << EOF' . PHP_EOL); @fwrite($pIndexFile, 'use ' . $dbName . PHP_EOL); for ($index = 0, $max = count($indexText); $index < $max; $index++) { if (is_array($indexText[$index])) { $collectionName = $indexText[$index][MONGO_COLLECTION_NAME]; continue; } @fwrite($pIndexFile, 'db.' . $collectionName . '.createIndex(' . $indexText[$index] . ')' . PHP_EOL); } @fwrite($pIndexFile, 'EOF' . PHP_EOL); } } } @fwrite($pLogFile, getDateTime() . CON_SUCCESS . $res . basename(__FILE__) . ': script processing ends' . PHP_EOL); fclose($pLogFile); fclose($pIndexFile); chmod($outFile, 0755); echo 'processing ended successfully!' . PHP_EOL; exit(0);