/** * DatabaseModel->genStmt private Method * * Create a dynamically generated preparable statement. This allows emulated * parameterized identifiers, sets, and conditions. Identifiers are santized * by checking if they exist in the actual context. Sets are santized as * normal prepared statement parameters. Conditions are sanitized by being * generated with DatabaseCondition class from an array structure only. * * @param string $stmt Unpreparable statement string with extra parameter placeholders. * @param array $tables Array of table values to insert. * @param array $columns Array of column values to insert. * @param array $sets Array of set values to insert. * @param array $tablesets Array of table set values to insert. * @param array $columnsets Array of column set values to insert. * @param array $conditions Array of DatabaseCondition objects to insert. * @param string $table (optional if defined in constructor) Default context table. * @return string Preparable statement. (Note that values of sets will still need to be given at execution time) * @throws DatabaseException If someone dun goofed. */ private function genStmt($stmt, $tables = [], $columns = [], $sets = [], $tablesets = [], $columnsets = [], $conditions = [], $table = null) { if (isset($stmt)) { //validate types if (is_string($stmt) && is_array($tables) && is_array($columns) && is_array($sets) && is_array($tablesets) && is_array($columnsets) && is_array($conditions) && (is_string($table) || $table == null)) { $validTables = $this->getTables(); $columnsTable = []; // -- TABLES -- // foreach ($tables as $table) { if (in_array($table, $validTables)) { } else { throw new DatabaseException(__METHOD__ . '(): table "' . $table . '" does not exist.', DatabaseException::EXCEPTION_INPUT_NOT_VALID, $this); $stmt = DatabaseUtils::replaceOnce(self::PARAM_TABLE, '', $stmt); //delete this placeholder (in case exception is caught) array_shift($table); //shift out the table (in case exception is caught) } } // -- COLUMNS -- // foreach ($columns as $column) { $typeof_column = gettype($column); if (isset($this->table)) { if (!in_array($this->table, $validTables)) { throw new DatabaseException(__METHOD__ . '(): default table "' . $this->table . '" does not exist.', DatabaseException::EXCEPTION_CORRUPTED_OBJECT, $this); } } $columnsTable[$this->table] = $this->getColumns($this->table); if ($typeof_column == 'string') { //TODO: check $table, then $this->table, then exception. do the replacement if any are found. if ((!isset($table) || $table == null) && (isset($this->table) && $this->table != null)) { $table = $this->table; } else { throw new DatabaseException(__METHOD__ . '(): no table defined.', DatabaseException::EXCEPTION_MISSING_DEFINITION, $this); continue; //skip this iteration (in case exception was caught) } //TODO: Do replacement here } elseif ($typeof_column == 'array') { if (array_key_exists('table', $column) && array_key_exists('column', $column)) { if (!array_key_exists($column['table'], $columnsTable)) { $columnsTable[$column['table']] = $this->getColumns($column['table']); } if (in_array($column['column'], $columnTable[$column['table']])) { $stmt = DatabaseUtils::replaceOnce(self::PARAM_COLUMN, $this->quoteColumn($column['column']), $stmt); } else { throw new DatabaseException(__METHOD__ . '(): column "' . $column['column'] . '" does not exist in table "' . $column['table'] . '".', DatabaseException::EXCEPTION_INPUT_NOT_VALID, $this); } } else { throw new DatabaseException(__METHOD__ . '(): encountered invalid [\'table\',\'column\'] array structure.', DatabaseException::EXCEPTION_INPUT_NOT_VALID, $this); $stmt = DatabaseUtils::replaceOnce(self::PARAM_COLUMN, '', $stmt); //delete this placeholder (in case exception is caught) array_shift($table); //shift out the table (in case exception is caught) } } else { throw new DatabaseException(__METHOD__ . '(): encountered column parameter of invalid type.', DatabaseException::EXCEPTION_INPUT_INVALID_TYPE, $this); } } // -- SETS -- // foreach ($sets as $set) { $typeof_set = gettype($set); $count = count($set); $pseudoArray = []; for ($i = 0; $i < $count; $i++) { $pseudoArray[] = '?'; } $pseudoSet = implode(',', $pseudoArray); $stmt = DatabaseUtils::replaceOnce(self::PARAM_SET, $pseudoSet, $stmt); //NOTE: This will only create a preparable statement. //You'll still have to bind the parameters for basic sets. } // -- TABLE SETS -- // foreach ($tablesets as $set) { $typeof_set = gettype($set); if (in_array($table, $validTables)) { } else { throw new DatabaseException(__METHOD__ . '(): table "' . $table . '" does not exist.', DatabaseException::EXCEPTION_INPUT_NOT_VALID, $this); $stmt = DatabaseUtils::replaceOnce(self::PARAM_TABLE, '', $stmt); //delete this placeholder (in case exception is caught) array_shift($table); //shift out the table (in case exception is caught) } } // -- COLUMN SETS -- // foreach ($columnsets as $set) { $typeof_set = gettype($set); if (isset($this->table)) { if (!in_array($this->table, $validTables)) { throw new DatabaseException(__METHOD__ . '(): default table "' . $this->table . '" does not exist.', DatabaseException::EXCEPTION_CORRUPTED_OBJECT, $this); } } $columnsTable[$this->table] = $this->getColumns($this->table); if ($typeof_column == 'string') { //TODO: check $table, then $this->table, then exception. do the replacement if any are found. if ((!isset($table) || $table == null) && (isset($this->table) && $this->table != null)) { $table = $this->table; } else { throw new DatabaseException(__METHOD__ . '(): no table defined.', DatabaseException::EXCEPTION_MISSING_DEFINITION, $this); continue; //skip this iteration (in case exception was caught) } //TODO: Do replacement here } elseif ($typeof_column == 'array') { if (array_key_exists('table', $column) && array_key_exists('column', $column)) { if (!array_key_exists($column['table'], $columnsTable)) { $columnsTable[$column['table']] = $this->getColumns($column['table']); } if (in_array($column['column'], $columnTable[$column['table']])) { $stmt = DatabaseUtils::replaceOnce(self::PARAM_COLUMN, $this->quoteColumn($column['column']), $stmt); } else { throw new DatabaseException(__METHOD__ . '(): column "' . $column['column'] . '" does not exist in table "' . $column['table'] . '".', DatabaseException::EXCEPTION_INPUT_NOT_VALID, $this); continue; //skip this iteration (if exception is caught) } } else { throw new DatabaseException(__METHOD__ . '(): encountered invalid [\'table\',\'column\'] array structure.', DatabaseException::EXCEPTION_INPUT_NOT_VALID, $this); $stmt = DatabaseUtils::replaceOnce(self::PARAM_COLUMN, '', $stmt); //delete this placeholder (in case exception is caught) continue; //skip this iteration (if exception is caught) } } else { throw new DatabaseException(__METHOD__ . '(): encountered column parameter of invalid type.', DatabaseException::EXCEPTION_INPUT_INVALID_TYPE, $this); continue; //skip this iteration (if exception is caught) } } // -- CONDITIONS -- // foreach ($conditions as $condition) { $typeof_condition = gettype($condition); if ($typeof_condition == 'object') { if (is_subclass_of($condition, 'DatabaseConditionModel')) { $strCond = $condition->getStatement(); $stmt = DatabaseUtils::replaceOnce(self::PARAM_CONDITION, $strCond, $stmt); } else { throw new DatabaseException(__METHOD__ . '(): encountered condition parameter not descended from DatabaseConditionModel.', DatabaseException::EXCEPTION_INPUT_INVALID_TYPE, $this); $stmt = DatabaseUtils::replaceOnce(self::PARAM_CONDITION, '', $stmt); continue; //skip this iteration (in case exception is caught) } } else { throw new DatabaseException(__METHOD__ . '(): encountered condition parameter of invalid type.', DatabaseException::EXCEPTION_INPUT_INVALID_TYPE, $this); } } } else { //$stmt type violation if (!is_string($stmt)) { throw new DatabaseException(__METHOD__ . '(): encountered statement of non-string type.', DatabaseException::EXCEPTION_INPUT_INVALID_TYPE, $this); } //$tables type violation if (!is_array($tables)) { throw new DatabaseException(__METHOD__ . '(): encountered table array of non-array type.', DatabaseException::EXCEPTION_INPUT_INVALID_TYPE, $this); } //$columns type violation if (!is_array($columns)) { throw new DatabaseException(__METHOD__ . '(): encountered column array of non-array type.', DatabaseException::EXCEPTION_INPUT_INVALID_TYPE, $this); } //$sets type violation if (!is_array($sets)) { throw new DatabaseException(__METHOD__ . '(): encountered set array of non-array type.', DatabaseException::EXCEPTION_INPUT_INVALID_TYPE, $this); } //$tablesets type violation if (!is_array($tablesets)) { throw new DatabaseException(__METHOD__ . '(): encountered table-set array of non-array type.', DatabaseException::EXCEPTION_INPUT_INVALID_TYPE, $this); } //$columnsets type violation if (!is_array($columnsets)) { throw new DatabaseException(__METHOD__ . '(): encountered column-set array of non-array type.', DatabaseException::EXCEPTION_INPUT_INVALID_TYPE, $this); } //$table type violation if (!is_string($table) && $table != null) { throw new DatabaseException(__METHOD__ . '(): encountered table argument of invalid type.', DatabaseException::EXCEPTION_INPUT_INVALID_TYPE, $this); } } } else { throw new DatabaseException(__METHOD__ . '(): missing required statement string argument.', DatabaseException::EXCEPTION_MISSING_REQUIRED_ARGUMENT, $this); } return $stmt; }