/** * function SenchaModel($fileModel): * This method will create the table and fields if does not exist in the database * also this is the brain of the micro ORM. * * This method needs rework, this method has to be the brain! * * @param string $fileModel 'App.model.Example' * @param bool $force for to read the sencha model file (skip the MatchaMemory) * @return bool success * */ public static function __SenchaModel($fileModel, $force = false) { try { self::$fileModel = $fileModel; // skip this entire routine if freeze option is true if (self::$__freeze) { self::$__senchaModel = self::__getSenchaModel($fileModel); return true; } self::$__senchaModel = array(); // check the difference in dates of the Sencha model file and the stored Sencha model on the server memory, // if there are equal go ahead and load the model from memory and quit the procedure if (!$force && self::__getFileModifyDate($fileModel) == MatchaMemory::__getSenchaModelLastChange($fileModel)) { self::$__senchaModel = MatchaMemory::__getModelFromMemory($fileModel); return true; } // get the model of the table from the sencha .js file self::$__senchaModel = self::__getSenchaModel($fileModel); if (!self::$__senchaModel['fields']) { return false; } // get model fields $modelFields = (array) self::$__senchaModel['fields']; // Copy the table ID from the idProperty if the idProperty is undefined use "id" instead. self::$tableId = isset(self::$__senchaModel['idProperty']) ? self::$__senchaModel['idProperty'] : 'id'; //id properties $tableIdIndex = MatchaUtils::__recursiveArraySearch(self::$tableId, $modelFields); self::$tableIdProperties = $modelFields[$tableIdIndex]; // check if the table property is an array, if not return the array is a table string. $table = (string) (is_array(self::$__senchaModel['table']) ? self::$__senchaModel['table']['name'] : self::$__senchaModel['table']); // verify the existence of the table if it does not exist create it $recordSet = self::$__conn->query("SHOW TABLES LIKE '" . $table . "';"); if (isset($recordSet)) { self::__createTable($table); } // if id property is not set in sencha model look for propertyId. if ($modelFields[$tableIdIndex] === false) { unset($modelFields[$tableIdIndex]); } // unset the fields that will noe be store int the database foreach ($modelFields as $key => $field) { if (isset($field['store']) && $field['store'] === false || isset($field['persist']) && $field['persist'] === false) { unset($modelFields[$key]); } } // get the table column information and remove the id column $tableColumns = self::$__conn->query("SHOW FULL COLUMNS IN " . $table . ";")->fetchAll(PDO::FETCH_ASSOC); unset($tableColumns[MatchaUtils::__recursiveArraySearch(self::$tableId, $tableColumns)]); $columnsTableNames = array(); $columnsSenchaNames = array(); // get all the column names of each model (Sencha and Database-table) foreach ($tableColumns as $column) { $columnsTableNames[] = $column['Field']; } foreach ($modelFields as $column) { $columnsSenchaNames[] = isset($column['mapping']) ? $column['mapping'] : $column['name']; } // get all the column that are not present in the database-table $differentCreateColumns = array_diff($columnsSenchaNames, $columnsTableNames); $differentDropColumns = array_diff($columnsTableNames, $columnsSenchaNames); // unset the id field from both arrays unset($differentCreateColumns[MatchaUtils::__recursiveArraySearch('id', $differentCreateColumns)]); unset($modelFields[MatchaUtils::__recursiveArraySearch('id', $modelFields)]); // deal with the sencha triggers self::__diffTriggers(self::$__senchaModel); $indexArray = self::__getIndexFields(self::$__senchaModel); // check if the table has columns, if not create them. if (count($tableColumns) <= 1) { self::__createAllColumns($modelFields); // add data - if the model has data defined. if (isset(self::$__senchaModel['table']['data'])) { $rec = self::$__conn->prepare('SELECT * FROM ' . $table); $rec->execute(); if ($rec->rowCount() <= 0) { MatchaModel::__setSenchaModelData(MatchaModel::$__senchaModel['table']['data']); } } return true; } elseif (count($differentCreateColumns) || count($differentDropColumns)) { // add columns to the table foreach ($differentCreateColumns as $column) { self::__createColumn($modelFields[MatchaUtils::__recursiveArraySearch($column, $modelFields)], $table, in_array($column, $indexArray)); } // remove columns from the table foreach ($differentDropColumns as $column) { self::__dropColumn($column); } } else { // modify the table columns if is not equal to the Sencha Model foreach ($tableColumns as $column) { $change = 'false'; foreach ($modelFields as $field) { // if the field is found, start the comparison if ($field['name'] == $column['Field']) { // the following code will check if there is a dataType property if not, take the type instead // on the model and parse it too. $modelDataType = isset($field['dataType']) ? $field['dataType'] : $field['type']; if ($modelDataType == 'string') { $modelDataType = 'varchar'; } if ($modelDataType == 'bool' && $modelDataType == 'boolean') { $modelDataType = 'tinyint'; } // check for changes on the field type is a obligatory thing if (strripos($column['Type'], $modelDataType) === false) { $change = 'true'; } // Type // check if there changes on the allowNull property, // but first check if it's used on the sencha model if (isset($field['allowNull'])) { if ($column['Null'] == ($field['allowNull'] ? 'YES' : 'NO')) { $change = 'true'; } } // NULL // check the length of the field, // but first check if it's used on the sencha model. if (isset($field['len'])) { if ($field['len'] != filter_var($column['Type'], FILTER_SANITIZE_NUMBER_INT)) { $change = 'true'; } } // Length // check if the default value is changed on the model, // but first check if it's used on the sencha model if (isset($field['defaultValue'])) { if ($column['Default'] != $field['defaultValue']) { $change = 'true'; } } // Default value // check if the primary key is changed on the model, // but first check if the primary key is used on the sencha model. if (isset($field['primaryKey'])) { if ($column['Key'] != ($field['primaryKey'] ? 'PRI' : '')) { $change = 'true'; } } // Primary key // check if the auto increment is changed on the model, // but first check if the auto increment is used on the sencha model. if (isset($field['autoIncrement'])) { if ($column['Extra'] != ($field['autoIncrement'] ? 'auto_increment' : '')) { $change = 'true'; } } // auto increment // check if the comment is changed on the model, // but first check if the comment is used on the sencha model. if (isset($field['comment'])) { if ($column['Comment'] != $field['comment']) { $change = 'true'; } } // Comment if (isset($field['comment'])) { if ($column['Comment'] != $field['comment']) { $change = 'true'; } } // Comment // Index.... $sth = self::$__conn->prepare("SHOW INDEX FROM {$table} WHERE Key_name = '{$field['name']}'"); $sth->execute(); $recs = $sth->fetchAll(); $isIndex = count($recs) != 0; $toIndex = in_array($field['name'], $indexArray); $indexChange = $toIndex !== $isIndex; if ($indexChange) { $change = 'true'; } // error_log($table); // error_log($field['name']); // error_log(var_dump($toIndex)); // error_log(var_dump($indexChange)); // Modify the column on the database if ($change == 'true') { self::__modifyColumn($field, $table, $toIndex); } } } } } return true; } catch (PDOException $e) { MatchaErrorHandler::__errorProcess($e); return false; } }