diff --git a/gulliver/system/class.database_mysql.php b/gulliver/system/class.database_mysql.php index 53888a4ae..d40d36a3b 100644 --- a/gulliver/system/class.database_mysql.php +++ b/gulliver/system/class.database_mysql.php @@ -393,19 +393,20 @@ class database extends database_base } /** - * generate a sentence to add indexes or primary keys + * Generate a sentence to add indexes or primary keys * * @param string $table table name * @param string $indexName index name * @param array $keys array of keys + * @param string $indexType the index type + * * @return string sql sentence * @throws Exception */ - public function generateAddKeysSQL($table, $indexName, $keys) + public function generateAddKeysSQL($table, $indexName, $keys, $indexType = 'INDEX') { try { - $indexType = 'INDEX'; if ($indexName === 'primaryKey' || $indexName === 'PRIMARY') { $indexType = 'PRIMARY'; $indexName = 'KEY'; @@ -1037,10 +1038,11 @@ class database extends database_base * @param string $tableName * @param array $columns * @param array $indexes + * @param array $fulltextIndexes * * @return string */ - public function generateAddColumnsSql($tableName, $columns, $indexes = []) + public function generateAddColumnsSql($tableName, $columns, $indexes = [], $fulltextIndexes = []) { $indexesAlreadyAdded = []; $sql = 'ALTER TABLE ' . $this->sQuoteCharacter . $tableName . $this->sQuoteCharacter . ' '; @@ -1080,6 +1082,7 @@ class database extends database_base } $sql .= ', '; } + // Add the normal indexes if are not "primaryKeys" already added foreach ($indexes as $indexName => $indexColumns) { $indexType = 'INDEX'; if ($indexName === 'primaryKey' || $indexName === 'PRIMARY') { @@ -1097,6 +1100,15 @@ class database extends database_base $sql = substr($sql, 0, -2); $sql .= '), '; } + // Add the "fulltext" indexes always + foreach ($fulltextIndexes as $indexName => $indexColumns) { + $sql .= 'ADD FULLTEXT ' . $indexName . ' ('; + foreach ($indexColumns as $column) { + $sql .= $this->sQuoteCharacter . $column . $this->sQuoteCharacter . ', '; + } + $sql = substr($sql, 0, -2); + $sql .= '), '; + } $sql = rtrim($sql, ', '); return $sql; diff --git a/workflow/engine/bin/tasks/cliUpgrade.php b/workflow/engine/bin/tasks/cliUpgrade.php index 36aa2e37d..677a9acff 100644 --- a/workflow/engine/bin/tasks/cliUpgrade.php +++ b/workflow/engine/bin/tasks/cliUpgrade.php @@ -147,11 +147,13 @@ function run_upgrade($parameters, $args) // The previous actions should be executed only the first time $mainThread = false; + + if ($numberOfWorkspaces === 1) { + // Displaying information of the unique workspace to upgrade + CLI::logging("UPGRADING DATABASE AND FILES OF WORKSPACE '{$workspace->name}' (1/1)\n"); + } } if ($numberOfWorkspaces === 1) { - // Displaying information of the current workspace to upgrade - CLI::logging("UPGRADING DATABASE AND FILES OF WORKSPACE '{$workspace->name}' ($countWorkspace/$numberOfWorkspaces)\n"); - // Build parameters $arrayOptTranslation = [ 'updateXml' => $updateXmlForms, @@ -165,6 +167,9 @@ function run_upgrade($parameters, $args) $workspace->upgrade($workspace->name, SYS_LANG, $arrayOptTranslation, $optionMigrateHistoryData); $workspace->close(); } else { + // Displaying information of the current workspace to upgrade + CLI::logging("UPGRADING DATABASE AND FILES OF WORKSPACE '{$workspace->name}' ($countWorkspace/$numberOfWorkspaces)\n"); + // Build arguments $args = '--child'; $args .= $updateXmlForms ? '' : ' --no-xml'; diff --git a/workflow/engine/bin/tasks/cliWorkspaces.php b/workflow/engine/bin/tasks/cliWorkspaces.php index 9ad7247f8..d44c1c7d5 100644 --- a/workflow/engine/bin/tasks/cliWorkspaces.php +++ b/workflow/engine/bin/tasks/cliWorkspaces.php @@ -566,15 +566,14 @@ function run_database_import($args, $opts) * Check if we need to execute an external program for each workspace * If we apply the command for all workspaces we will need to execute one by one by redefining the constants * @param string $args, workspaceName that we need to apply the database-upgrade - * @param string $opts * * @return void */ -function run_database_upgrade($args, $opts) +function run_database_upgrade($args) { //Check if the command is executed by a specific workspace if (count($args) === 1) { - database_upgrade('upgrade', $args); + database_upgrade($args); } else { $workspaces = get_workspaces_from_args($args); foreach ($workspaces as $workspace) { @@ -583,11 +582,6 @@ function run_database_upgrade($args, $opts) } } -function run_database_check($args, $opts) -{ - database_upgrade("check", $args); -} - function run_migrate_new_cases_lists($args, $opts) { migrate_new_cases_lists("migrate", $args, $opts); @@ -605,44 +599,32 @@ function run_migrate_list_unassigned($args, $opts) /** * This function is executed only by one workspace - * @param string $command, the specific actions must be: upgrade|check * @param array $args, workspaceName for to apply the database-upgrade * * @return void */ -function database_upgrade($command, $args) +function database_upgrade($args) { + // Sanitize parameters sent $filter = new InputFilter(); - $command = $filter->xssFilterHard($command); $args = $filter->xssFilterHard($args); - //Load the attributes for the workspace - $workspaces = get_workspaces_from_args($args); - $checkOnly = (strcmp($command, "check") == 0); - //Loop, read all the attributes related to the one workspace - $wsName = $workspaces[key($workspaces)]->name; - Bootstrap::setConstantsRelatedWs($wsName); - if ($checkOnly) { - print_r("Checking database in " . pakeColor::colorize($wsName, "INFO") . "\n"); - } else { - print_r("Upgrading database in " . pakeColor::colorize($wsName, "INFO") . "\n"); - } + // Load the attributes for the workspace + $workspaces = get_workspaces_from_args($args); + + // Get the name of the first workspace + $wsName = $workspaces[key($workspaces)]->name; + + // Initialize workspace values + Bootstrap::setConstantsRelatedWs($wsName); + + // Print a informative message + print_r("Upgrading database in " . pakeColor::colorize($wsName, "INFO") . "\n"); + + // Loop to update the databases of all workspaces foreach ($workspaces as $workspace) { try { - $changes = $workspace->upgradeDatabase($checkOnly); - if ($changes != false) { - if ($checkOnly) { - echo "> " . pakeColor::colorize("Run upgrade", "INFO") . "\n"; - echo " Tables (add = " . count($changes['tablesToAdd']); - echo ", alter = " . count($changes['tablesToAlter']) . ") "; - echo "- Indexes (add = " . count($changes['tablesWithNewIndex']) . ""; - echo ", alter = " . count($changes['tablesToAlterIndex']) . ")\n"; - } else { - echo "-> Schema fixed\n"; - } - } else { - echo "> OK\n"; - } + $workspace->upgradeDatabase(); } catch (Exception $e) { G::outRes("> Error: " . CLI::error($e->getMessage()) . "\n"); } diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index f4badbba6..4400f8da9 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -252,7 +252,7 @@ class WorkspaceTools CLI::logging("* Start updating database schema...\n"); $start = microtime(true); - $this->upgradeDatabase(); + $this->upgradeDatabase(false); CLI::logging("* End updating database schema...(Completed on " . (microtime(true) - $start) . " seconds)\n"); CLI::logging("* Start updating translations...\n"); @@ -807,16 +807,17 @@ class WorkspaceTools $oldSchema[$table][$field['Field']]['Default'] = $field['Default']; } - //get indexes of each table SHOW INDEX FROM `ADDITIONAL_TABLES`; -- WHERE Key_name <> 'PRIMARY' + // Get indexes of each table SHOW INDEX FROM `ADDITIONAL_TABLES`; $description = $database->executeQuery($database->generateTableIndexSQL($table)); foreach ($description as $field) { - if (!isset($oldSchema[$table]['INDEXES'])) { - $oldSchema[$table]['INDEXES'] = []; + $type = $field['Index_type'] != 'FULLTEXT' ? 'INDEXES' : 'FULLTEXT'; + if (!isset($oldSchema[$table][$type])) { + $oldSchema[$table][$type] = []; } - if (!isset($oldSchema[$table]['INDEXES'][$field['Key_name']])) { - $oldSchema[$table]['INDEXES'][$field['Key_name']] = []; + if (!isset($oldSchema[$table][$type][$field['Key_name']])) { + $oldSchema[$table][$type][$field['Key_name']] = []; } - $oldSchema[$table]['INDEXES'][$field['Key_name']][] = $field['Column_name']; + $oldSchema[$table][$type][$field['Key_name']][] = $field['Column_name']; } } @@ -1050,8 +1051,10 @@ class WorkspaceTools /** * Upgrade the workspace database to the latest system schema + * + * @param bool $includeIndexes */ - public function upgradeDatabase() + public function upgradeDatabase($includeIndexes = true) { $this->initPropel(true); P11835::$dbAdapter = $this->dbAdapter; @@ -1059,7 +1062,7 @@ class WorkspaceTools $systemSchema = System::getSystemSchema($this->dbAdapter); $systemSchemaRbac = System::getSystemSchemaRbac($this->dbAdapter);// Get the RBAC Schema $this->registerSystemTables(array_merge($systemSchema, $systemSchemaRbac)); - $this->upgradeSchema($systemSchema, false, false, false); // Without add indexes + $this->upgradeSchema($systemSchema, false, false, $includeIndexes); $this->upgradeSchema($systemSchemaRbac, false, true); // Perform upgrade to RBAC $this->upgradeData(); $this->checkRbacPermissions();//check or add new permissions @@ -1195,7 +1198,9 @@ class WorkspaceTools $changes = System::compareSchema($workspaceSchema, $schema); - $changed = (count($changes['tablesToAdd']) > 0 || count($changes['tablesToAlter']) > 0 || count($changes['tablesWithNewIndex']) > 0 || count($changes['tablesToAlterIndex']) > 0); + $changed = (count($changes['tablesToAdd']) > 0 || count($changes['tablesToAlter']) > 0 || + count($changes['tablesWithNewIndex']) > 0 || count($changes['tablesToAlterIndex']) > 0 || + count($changes['tablesWithNewFulltext']) > 0 || count($changes['tablesToAlterFulltext']) > 0); if ($checkOnly || (!$changed)) { if ($changed) { @@ -1229,6 +1234,7 @@ class WorkspaceTools $tablesToAddColumns = []; + // Drop or change columns foreach ($changes['tablesToAlter'] as $tableName => $actions) { foreach ($actions as $action => $actionData) { if ($action == 'ADD') { @@ -1255,17 +1261,27 @@ class WorkspaceTools } } + // Add columns if (!empty($tablesToAddColumns)) { $upgradeQueries = []; foreach ($tablesToAddColumns as $tableName => $tableColumn) { + // Normal indexes to add $indexes = []; if (!empty($changes['tablesWithNewIndex'][$tableName]) && $includeIndexes) { $indexes = $changes['tablesWithNewIndex'][$tableName]; unset($changes['tablesWithNewIndex'][$tableName]); } + // "fulltext" indexes to add + $fulltextIndexes = []; + if (!empty($changes['tablesWithNewFulltext'][$tableName]) && $includeIndexes) { + $fulltextIndexes = $changes['tablesWithNewFulltext'][$tableName]; + unset($changes['tablesWithNewFulltext'][$tableName]); + } + // Instantiate the class to execute the query in background - $upgradeQueries[] = new RunProcessUpgradeQuery($this->name, $database->generateAddColumnsSql($tableName, $tableColumn, $indexes), $rbac); + $upgradeQueries[] = new RunProcessUpgradeQuery($this->name, $database->generateAddColumnsSql($tableName, + $tableColumn, $indexes, $fulltextIndexes), $rbac); } // Run queries in multiple threads @@ -1282,14 +1298,24 @@ class WorkspaceTools } } - if (!empty($changes['tablesWithNewIndex']) && $includeIndexes) { - CLI::logging("-> " . count($changes['tablesWithNewIndex']) . " tables with indexes to add\n"); + // Add indexes + if ((!empty($changes['tablesWithNewIndex']) || !empty($changes['tablesWithNewFulltext'])) && $includeIndexes) { + CLI::logging("-> " . (count($changes['tablesWithNewIndex']) + count($changes['tablesWithNewFulltext'])) . + " tables with indexes to add\n"); $upgradeQueries = []; + + // Add normal indexes foreach ($changes['tablesWithNewIndex'] as $tableName => $indexes) { // Instantiate the class to execute the query in background $upgradeQueries[] = new RunProcessUpgradeQuery($this->name, $database->generateAddColumnsSql($tableName, [], $indexes), $rbac); } + // Add "fulltext" indexes + foreach ($changes['tablesWithNewFulltext'] as $tableName => $fulltextIndexes) { + // Instantiate the class to execute the query in background + $upgradeQueries[] = new RunProcessUpgradeQuery($this->name, $database->generateAddColumnsSql($tableName, [], [], $fulltextIndexes), $rbac); + } + // Run queries in multiple threads $processesManager = new ProcessesManager($upgradeQueries); $processesManager->run(); @@ -1304,16 +1330,30 @@ class WorkspaceTools } } - if (!empty($changes['tablesToAlterIndex']) && $includeIndexes) { - CLI::logging("-> " . count($changes['tablesToAlterIndex']) . " tables with indexes to alter\n"); + // Change indexes + if ((!empty($changes['tablesToAlterIndex']) || !empty($changes['tablesToAlterFulltext'])) && $includeIndexes) { + CLI::logging("-> " . (count($changes['tablesToAlterIndex']) + count($changes['tablesToAlterFulltext'])) . + " tables with indexes to alter\n"); + + // Change normal indexes foreach ($changes['tablesToAlterIndex'] as $tableName => $indexes) { foreach ($indexes as $indexName => $indexFields) { $database->executeQuery($database->generateDropKeySQL($tableName, $indexName)); $database->executeQuery($database->generateAddKeysSQL($tableName, $indexName, $indexFields)); } } + + // Change "fulltext" indexes + foreach ($changes['tablesToAlterFulltext'] as $tableName => $fulltextIndexes) { + foreach ($fulltextIndexes as $indexName => $indexFields) { + $database->executeQuery($database->generateDropKeySQL($tableName, $indexName)); + $database->executeQuery($database->generateAddKeysSQL($tableName, $indexName, $indexFields, 'FULLTEXT')); + } + } } + // Ending the schema update + CLI::logging("-> Schema Updated\n"); $this->closeDatabase(); return true; } @@ -2064,7 +2104,7 @@ class WorkspaceTools // Upgrade the database schema and data CLI::logging("* Start updating database schema...\n"); $start = microtime(true); - $workspace->upgradeDatabase(); + $workspace->upgradeDatabase(false); CLI::logging("* End updating database schema...(Completed on " . (microtime(true) - $start) . " seconds)\n"); CLI::logging("* Start checking MAFE requirements...\n"); diff --git a/workflow/engine/config/schema.xml b/workflow/engine/config/schema.xml index a71a5e6cb..943d3deb7 100644 --- a/workflow/engine/config/schema.xml +++ b/workflow/engine/config/schema.xml @@ -94,6 +94,15 @@ + + + + + + + + + diff --git a/workflow/engine/data/mysql/schema.sql b/workflow/engine/data/mysql/schema.sql index c648e4202..e94cd7b69 100644 --- a/workflow/engine/data/mysql/schema.sql +++ b/workflow/engine/data/mysql/schema.sql @@ -40,7 +40,8 @@ CREATE TABLE `APPLICATION` KEY `indexApp`(`PRO_UID`, `APP_STATUS`, `APP_UID`), KEY `indexAppNumber`(`APP_NUMBER`), KEY `indexAppStatus`(`APP_STATUS`), - KEY `indexAppCreateDate`(`APP_CREATE_DATE`) + KEY `indexAppCreateDate`(`APP_CREATE_DATE`), + FULLTEXT `indexAppTitle`(`APP_TITLE`) )ENGINE=InnoDB DEFAULT CHARSET='utf8' COMMENT='The application'; #----------------------------------------------------------------------------- #-- APP_SEQUENCE diff --git a/workflow/engine/src/ProcessMaker/Core/System.php b/workflow/engine/src/ProcessMaker/Core/System.php index cb63ccf0f..ca81160a9 100644 --- a/workflow/engine/src/ProcessMaker/Core/System.php +++ b/workflow/engine/src/ProcessMaker/Core/System.php @@ -712,12 +712,13 @@ class System /** * Retrieves a schema array from a file. * - * @param string $sSchemaFile schema filename - * @return string $sContent + * @param string $schemaFile schema filename + * + * @return array */ - public static function getSchema($sSchemaFile) + public static function getSchema($schemaFile) { - /* This is the MySQL mapping that Propel uses (from MysqlPlatform.php) */ + // This is the MySQL mapping that Propel uses (from MysqlPlatform.php) $mysqlTypes = [ 'NUMERIC' => 'DECIMAL', 'LONGVARCHAR' => 'MEDIUMTEXT', @@ -728,32 +729,38 @@ class System 'LONGVARBINARY' => 'LONGBLOB', 'BLOB' => 'LONGBLOB', 'CLOB' => 'LONGTEXT', - /* This is not from Propel, but is required to get INT right */ + // This is not from Propel, but is required to get INT right 'INTEGER' => 'INT' ]; - $aSchema = []; - $oXml = new DomDocument(); - $oXml->load($sSchemaFile); - $aTables = $oXml->getElementsByTagName('table'); - foreach ($aTables as $oTable) { - $aPrimaryKeys = []; - $sTableName = $oTable->getAttribute('name'); - $aSchema[$sTableName] = []; - $aColumns = $oTable->getElementsByTagName('column'); - foreach ($aColumns as $oColumn) { - $sColumName = $oColumn->getAttribute('name'); + $schema = []; - /* Get the field type. Propel uses VARCHAR if nothing else is specified */ - $type = $oColumn->hasAttribute('type') ? strtoupper($oColumn->getAttribute('type')) : "VARCHAR"; + // Parse schema + $xml = new DomDocument(); + $xml->load($schemaFile); - /* Convert type to MySQL type according to Propel */ + // Build the schema array + $tablesNodes = $xml->getElementsByTagName('table'); + foreach ($tablesNodes as $tableNode) { + $primaryKeys = []; + $tableName = $tableNode->getAttribute('name'); + $schema[$tableName] = []; + $columnsNodes = $tableNode->getElementsByTagName('column'); + foreach ($columnsNodes as $columnNode) { + $columnName = $columnNode->getAttribute('name'); + + // Get the field type. Propel uses VARCHAR if nothing else is specified + $type = $columnNode->hasAttribute('type') ? strtoupper($columnNode->getAttribute('type')) : "VARCHAR"; + + // Convert type to MySQL type according to Propel if (array_key_exists($type, $mysqlTypes)) { $type = $mysqlTypes[$type]; } - $size = $oColumn->hasAttribute('size') ? $oColumn->getAttribute('size') : null; - /* Add default sizes from MySQL */ + // Get "size" attribute + $size = $columnNode->hasAttribute('size') ? $columnNode->getAttribute('size') : null; + + // Add default sizes from MySQL if ($type == "TINYINT" && !$size) { $size = "4"; } @@ -765,46 +772,64 @@ class System $type = "$type($size)"; } - $required = $oColumn->hasAttribute('required') ? $oColumn->getAttribute('required') : null; - /* Convert $required to a bool */ - $required = (in_array(strtolower($required), array('1', 'true' - ))); - $autoIncrement = $oColumn->hasAttribute('autoIncrement') ? $oColumn->hasAttribute('autoIncrement') : false; - $unique = $oColumn->hasAttribute('unique') ? $oColumn->hasAttribute('unique') : false; - $default = $oColumn->hasAttribute('default') ? $oColumn->getAttribute('default') : null; + // Get "required" attribute + $required = $columnNode->hasAttribute('required') ? $columnNode->getAttribute('required') : null; - $primaryKey = $oColumn->hasAttribute('primaryKey') ? $oColumn->getAttribute('primaryKey') : null; - /* Convert $primaryKey to a bool */ - $primaryKey = (in_array(strtolower($primaryKey), array('1', 'true' - ))); + // Convert $required to a bool + $required = (in_array(strtolower($required), ['1', 'true'])); + $autoIncrement = $columnNode->hasAttribute('autoIncrement') ? $columnNode->hasAttribute('autoIncrement') : false; + $unique = $columnNode->hasAttribute('unique') ? $columnNode->hasAttribute('unique') : false; + $default = $columnNode->hasAttribute('default') ? $columnNode->getAttribute('default') : null; + + $primaryKey = $columnNode->hasAttribute('primaryKey') ? $columnNode->getAttribute('primaryKey') : null; + + // Convert $primaryKey to a bool + $primaryKey = (in_array(strtolower($primaryKey), ['1', 'true'])); if ($primaryKey) { - $aPrimaryKeys[] = $sColumName; + $primaryKeys[] = $columnName; } - $aSchema[$sTableName][$sColumName] = array( - 'Field' => $sColumName, + + // Add the metadata from the column + $schema[$tableName][$columnName] = [ + 'Field' => $columnName, 'Type' => $type, 'Null' => $required ? "NO" : "YES", 'Default' => $default, 'AutoIncrement' => $autoIncrement, 'Unique' => $unique, 'PrimaryKey' => $primaryKey - ); + ]; } - if (is_array($aPrimaryKeys) && count($aPrimaryKeys) > 0) { - $aSchema[$sTableName]['INDEXES']['PRIMARY'] = $aPrimaryKeys; + // Add primary keys to "indexes" list + if (is_array($primaryKeys) && count($primaryKeys) > 0) { + $schema[$tableName]['INDEXES']['PRIMARY'] = $primaryKeys; } - $aIndexes = $oTable->getElementsByTagName('index'); - foreach ($aIndexes as $oIndex) { - $aIndex = []; - $aIndexesColumns = $oIndex->getElementsByTagName('index-column'); - foreach ($aIndexesColumns as $oIndexColumn) { - $aIndex[] = $oIndexColumn->getAttribute('name'); + + // Search normal indexes + $indexesNodes = $tableNode->getElementsByTagName('index'); + foreach ($indexesNodes as $indexNode) { + $indexes = []; + $indexesColumnsNodes = $indexNode->getElementsByTagName('index-column'); + foreach ($indexesColumnsNodes as $indexColumnNode) { + $indexes[] = $indexColumnNode->getAttribute('name'); } - $aSchema[$sTableName]['INDEXES'][$oIndex->getAttribute('name')] = $aIndex; + $schema[$tableName]['INDEXES'][$indexNode->getAttribute('name')] = $indexes; + } + + // Search fulltext indexes + $fulltextNodes = $tableNode->getElementsByTagName('fulltext'); + foreach ($fulltextNodes as $fulltextNode) { + $fulltextIndexes = []; + $indexColumnsNodes = $fulltextNode->getElementsByTagName('index-column'); + foreach ($indexColumnsNodes as $indexColumnsNode) { + $fulltextIndexes[] = $indexColumnsNode->getAttribute('name'); + } + $schema[$tableName]['FULLTEXT'][$fulltextNode->getAttribute('name')] = $fulltextIndexes; } } - return $aSchema; + + return $schema; } /** @@ -827,63 +852,63 @@ class System } /** - * Returns the difference between two schema arrays + * Returns the difference between two schemas * - * @param array $aOldSchema original schema array - * @param array $aNewSchema new schema array - * @return array with tablesToAdd, tablesToAlter, tablesWithNewIndex and tablesToAlterIndex + * @param array $oldSchema original schema + * @param array $newSchema new schema + * + * @return array with tablesToAdd, tablesToAlter, tablesWithNewIndex, tablesToAlterIndex, tablesWithNewFulltext and tablesToAlterFulltext */ - public static function compareSchema($aOldSchema, $aNewSchema) + public static function compareSchema($oldSchema, $newSchema) { - $aChanges = array( - 'tablesToAdd' => array(), - 'tablesToAlter' => array(), - 'tablesWithNewIndex' => array(), - 'tablesToAlterIndex' => array() - ); + $changes = [ + 'tablesToAdd' => [], + 'tablesToAlter' => [], + 'tablesWithNewIndex' => [], + 'tablesToAlterIndex' => [], + 'tablesWithNewFulltext' => [], + 'tablesToAlterFulltext' => [] + ]; - //new tables to create and alter - foreach ($aNewSchema as $sTableName => $aColumns) { - if (!isset($aOldSchema[$sTableName])) { - $aChanges['tablesToAdd'][$sTableName] = $aColumns; + // New tables to create and alter + foreach ($newSchema as $tableName => $columns) { + if (!isset($oldSchema[$tableName])) { + $changes['tablesToAdd'][$tableName] = $columns; } else { - //drop old columns - foreach ($aOldSchema[$sTableName] as $sColumName => $aParameters) { - if (!isset($aNewSchema[$sTableName][$sColumName])) { - if (!isset($aChanges['tablesToAlter'][$sTableName])) { - $aChanges['tablesToAlter'][$sTableName] = array('DROP' => array(), 'ADD' => array(), 'CHANGE' => array() - ); + // Drop old columns + foreach ($oldSchema[$tableName] as $columnName => $parameters) { + if (!isset($newSchema[$tableName][$columnName])) { + if (!isset($changes['tablesToAlter'][$tableName])) { + $changes['tablesToAlter'][$tableName] = ['DROP' => [], 'ADD' => [], 'CHANGE' => []]; } - $aChanges['tablesToAlter'][$sTableName]['DROP'][$sColumName] = $sColumName; + $changes['tablesToAlter'][$tableName]['DROP'][$columnName] = $columnName; } } - //create new columns - //foreach ($aNewSchema[$sTableName] as $sColumName => $aParameters) { - foreach ($aColumns as $sColumName => $aParameters) { - if ($sColumName != 'INDEXES') { - if (!isset($aOldSchema[$sTableName][$sColumName])) { - //this column doesnt exist in oldschema - if (!isset($aChanges['tablesToAlter'][$sTableName])) { - $aChanges['tablesToAlter'][$sTableName] = array('DROP' => array(), 'ADD' => array(), 'CHANGE' => array() - ); + // Create new columns + foreach ($columns as $columnName => $parameters) { + if ($columnName != 'INDEXES' && $columnName != 'FULLTEXT') { + if (!isset($oldSchema[$tableName][$columnName])) { + // This column doesn't exist in old schema + if (!isset($changes['tablesToAlter'][$tableName])) { + $changes['tablesToAlter'][$tableName] = ['DROP' => [], 'ADD' => [], 'CHANGE' => []]; } - $aChanges['tablesToAlter'][$sTableName]['ADD'][$sColumName] = $aParameters; + $changes['tablesToAlter'][$tableName]['ADD'][$columnName] = $parameters; } else { - //the column exists - $newField = $aNewSchema[$sTableName][$sColumName]; - $oldField = $aOldSchema[$sTableName][$sColumName]; - //both are null, no change is required + // The column exists + $newField = $newSchema[$tableName][$columnName]; + $oldField = $oldSchema[$tableName][$columnName]; + // Both are null, no change is required if (!isset($newField['Default']) && !isset($oldField['Default'])) { $changeDefaultAttr = false; - //one of them is null, change IS required + // One of them is null, change is required } if (!isset($newField['Default']) && isset($oldField['Default']) && $oldField['Default'] != '') { $changeDefaultAttr = true; } if (isset($newField['Default']) && !isset($oldField['Default'])) { $changeDefaultAttr = true; - //both are defined and they are different. + // Both are defined and they are different. } if (isset($newField['Default']) && isset($oldField['Default'])) { if ($newField['Default'] != $oldField['Default']) { @@ -892,63 +917,78 @@ class System $changeDefaultAttr = false; } } - //special cases - // BLOB and TEXT columns cannot have DEFAULT values. http://dev.mysql.com/doc/refman/5.0/en/blob.html - if (in_array(strtolower($newField['Type']), array('text', 'mediumtext'))) { + // Special cases, BLOB and TEXT columns cannot have DEFAULT values. http://dev.mysql.com/doc/refman/5.0/en/blob.html + if (in_array(strtolower($newField['Type']), ['text', 'mediumtext'])) { $changeDefaultAttr = false; } - //#1067 - Invalid default value for datetime field - if (in_array($newField['Type'], array('datetime')) && isset($newField['Default']) && $newField['Default'] == '') { + // #1067 - Invalid default value for datetime field + if (in_array($newField['Type'], ['datetime']) && isset($newField['Default']) && $newField['Default'] == '') { $changeDefaultAttr = false; } - //#1067 - Invalid default value for int field + // #1067 - Invalid default value for int field if (substr($newField['Type'], 0, 3) == "INT" && isset($newField['Default']) && $newField['Default'] == '') { $changeDefaultAttr = false; } - //if any difference exists, then insert the difference in aChanges + // If any difference exists, then insert the difference in "changes" variable if (strcasecmp($newField['Field'], $oldField['Field']) !== 0 || strcasecmp($newField['Type'], $oldField['Type']) !== 0 || strcasecmp($newField['Null'], $oldField['Null']) !== 0 || $changeDefaultAttr) { - if (!isset($aChanges['tablesToAlter'][$sTableName])) { - $aChanges['tablesToAlter'][$sTableName] = array('DROP' => array(), 'ADD' => array(), 'CHANGE' => array()); + if (!isset($changes['tablesToAlter'][$tableName])) { + $changes['tablesToAlter'][$tableName] = ['DROP' => [], 'ADD' => [], 'CHANGE' => []]; } - $aChanges['tablesToAlter'][$sTableName]['CHANGE'][$sColumName]['Field'] = $newField['Field']; - $aChanges['tablesToAlter'][$sTableName]['CHANGE'][$sColumName]['Type'] = $newField['Type']; - $aChanges['tablesToAlter'][$sTableName]['CHANGE'][$sColumName]['Null'] = $newField['Null']; + $changes['tablesToAlter'][$tableName]['CHANGE'][$columnName]['Field'] = $newField['Field']; + $changes['tablesToAlter'][$tableName]['CHANGE'][$columnName]['Type'] = $newField['Type']; + $changes['tablesToAlter'][$tableName]['CHANGE'][$columnName]['Null'] = $newField['Null']; if (isset($newField['Default'])) { - $aChanges['tablesToAlter'][$sTableName]['CHANGE'][$sColumName]['Default'] = $newField['Default']; + $changes['tablesToAlter'][$tableName]['CHANGE'][$columnName]['Default'] = $newField['Default']; } else { - $aChanges['tablesToAlter'][$sTableName]['CHANGE'][$sColumName]['Default'] = null; + $changes['tablesToAlter'][$tableName]['CHANGE'][$columnName]['Default'] = null; } } } } - //only columns, no the indexes column + // Only columns, no the indexes column } - //foreach $aColumns - //now check the indexes of table - if (isset($aNewSchema[$sTableName]['INDEXES'])) { - foreach ($aNewSchema[$sTableName]['INDEXES'] as $indexName => $indexFields) { - if (!isset($aOldSchema[$sTableName]['INDEXES'][$indexName])) { - if (!isset($aChanges['tablesWithNewIndex'][$sTableName])) { - $aChanges['tablesWithNewIndex'][$sTableName] = []; + // Now check the normal indexes of the table + if (isset($newSchema[$tableName]['INDEXES'])) { + foreach ($newSchema[$tableName]['INDEXES'] as $indexName => $indexFields) { + if (!isset($oldSchema[$tableName]['INDEXES'][$indexName])) { + if (!isset($changes['tablesWithNewIndex'][$tableName])) { + $changes['tablesWithNewIndex'][$tableName] = []; } - $aChanges['tablesWithNewIndex'][$sTableName][$indexName] = $indexFields; + $changes['tablesWithNewIndex'][$tableName][$indexName] = $indexFields; } else { - if ($aOldSchema[$sTableName]['INDEXES'][$indexName] != $indexFields) { - if (!isset($aChanges['tablesToAlterIndex'][$sTableName])) { - $aChanges['tablesToAlterIndex'][$sTableName] = []; + if ($oldSchema[$tableName]['INDEXES'][$indexName] != $indexFields) { + if (!isset($changes['tablesToAlterIndex'][$tableName])) { + $changes['tablesToAlterIndex'][$tableName] = []; } - $aChanges['tablesToAlterIndex'][$sTableName][$indexName] = $indexFields; + $changes['tablesToAlterIndex'][$tableName][$indexName] = $indexFields; + } + } + } + } + + // Now check the "fulltext" indexes of the table + if (isset($newSchema[$tableName]['FULLTEXT'])) { + foreach ($newSchema[$tableName]['FULLTEXT'] as $indexName => $indexFields) { + if (!isset($oldSchema[$tableName]['FULLTEXT'][$indexName])) { + if (!isset($changes['tablesWithNewFulltext'][$tableName])) { + $changes['tablesWithNewFulltext'][$tableName] = []; + } + $changes['tablesWithNewFulltext'][$tableName][$indexName] = $indexFields; + } else { + if ($oldSchema[$tableName]['FULLTEXT'][$indexName] != $indexFields) { + if (!isset($changes['tablesToAlterFulltext'][$tableName])) { + $changes['tablesToAlterFulltext'][$tableName] = []; + } + $changes['tablesToAlterFulltext'][$tableName][$indexName] = $indexFields; } } } } } - //for-else table exists } - //for new schema - return $aChanges; + return $changes; } public static function getEmailConfiguration() diff --git a/workflow/engine/src/ProcessMaker/Model/Delegation.php b/workflow/engine/src/ProcessMaker/Model/Delegation.php index 0749b00ba..7b36f8124 100644 --- a/workflow/engine/src/ProcessMaker/Model/Delegation.php +++ b/workflow/engine/src/ProcessMaker/Model/Delegation.php @@ -225,7 +225,14 @@ class Delegation extends Model $query->join('APPLICATION', function ($join) use ($filterBy, $search, $status, $query) { $join->on('APP_DELEGATION.APP_NUMBER', '=', 'APPLICATION.APP_NUMBER'); if ($filterBy == 'APP_TITLE' && $search) { - $join->where('APPLICATION.APP_TITLE', 'LIKE', "%${search}%"); + // Cleaning "fulltext" operators in order to avoid unexpected results + $search = str_replace(['-', '+', '<', '>', '(', ')', '~', '*', '"'], ['', '', '', '', '', '', '', '', ''], $search); + + // Build the "fulltext" expression + $search = '+"' . preg_replace('/\s+/', '" +"', addslashes($search)) . '"'; + + // Searching using "fulltext" index + $join->whereRaw("MATCH(APPLICATION.APP_TITLE) AGAINST('{$search}' IN BOOLEAN MODE)"); } // Based on the below, we can further limit the join so that we have a smaller data set based on join criteria switch ($status) {