/** * Creates a new table * @access private * * @param CBSimpleXMLElement $table Table * @param string $colNamePrefix Prefix to add to all column names * @return boolean True: success, False: failure */ function createTable(&$table, $colNamePrefix) { if ($table->name() == 'table') { $tableName = $this->_prefixedName($table, $colNamePrefix); $columns =& $table->getElementByPath('columns'); if ($tableName && $columns !== false) { $sqlColumns = array(); $tableOptions = array(); foreach ($columns->children() as $column) { if ($column->name() == 'column') { $colNamePrefixed = $this->_prefixedName($column, $colNamePrefix); $sqlColumns[] = "\n " . $this->_db->NameQuote($colNamePrefixed) . ' ' . $this->_fullColumnType($column); if ((int) $column->attributes('auto_increment')) { $tableOptions[] = 'AUTO_INCREMENT=' . (int) $column->attributes('auto_increment'); } } } $indexes =& $table->getElementByPath('indexes'); if ($indexes !== false) { foreach ($indexes->children() as $index) { if ($index->name() == 'index') { $sqlIndexText = $this->_fullIndexType($index, $colNamePrefix); if ($sqlIndexText) { $sqlColumns[] = "\n " . $sqlIndexText; } } } } if ($this->_db->versionCompare('4.0')) { $tableOptions[] = 'ENGINE=MyISAM'; } $collation = $table->attributes('collation'); if ($collation && $this->_db->versionCompare('4.1')) { $charSet = substr($collation, 0, strpos($collation, '_')); if ($charSet) { $tableOptions[] = 'CHARACTER SET = ' . preg_replace('/[^a-z0-9_]/', '', $charSet); $tableOptions[] = 'COLLATE = ' . preg_replace('/[^a-z0-9_]/', '', $collation); } } $sql = 'CREATE TABLE ' . $this->_db->NameQuote($tableName) . ' (' . implode(',', $sqlColumns) . "\n )" . implode(', ', $tableOptions); if (!$this->_doQuery($sql)) { $this->_setError(sprintf('%s::createTableof Table %s failed with SQL error: %s', get_class($this), $tableName, $this->_db->getErrorMsg()), $sql); return false; } else { $this->_setLog(sprintf('Table %s successfully created', $tableName), $sql, 'change'); return true; } } } return false; }
/** * Deletes this record (no checks) * * @param int $oid Key id of row to delete (otherwise it's the one of $this) * @return boolean TRUE if OK, FALSE if error */ function delete( $oid = null ) { $k = $this->_tbl_key; if ( $oid ) { $this->$k = (int) $oid; } $query = "DELETE FROM " . $this->_db->NameQuote( $this->_tbl ) . "\n WHERE " . $this->_db->NameQuote( $this->_tbl_key ) . " = " . ( is_int( $this->$k ) ? (int) $this->$k : $this->_db->Quote( $this->$k ) ) ; $this->_db->setQuery( $query ); if ($this->_db->query()) { return true; } else { $this->_error = $this->_db->getErrorMsg(); return false; } }
function _fixCBmandatoryDb( $dryRun ) { cbimport( 'cb.sql.upgrader' ); $this->_sqlUpgrader = new CBSQLupgrader( $this->_db, $this->_silentWhenOK ); $this->_sqlUpgrader->setDryRun( $dryRun ); $sql = 'SELECT * FROM `#__comprofiler_tabs` ORDER BY `tabid`'; // `tabid`, `pluginclass` $this->_db->setQuery( $sql ); $tabs = $this->_db->loadObjectList( 'tabid' ); if ( $this->_db->getErrorNum() ) { $this->_sqlUpgrader->_setError( 'Tabs selection query error: ' . $this->_db->getErrorMsg() ); return false; } $sql = 'SELECT `fieldid`, `tabid` FROM `#__comprofiler_fields` ORDER BY `tabid`'; $this->_db->setQuery( $sql ); $fields = $this->_db->loadObjectList( 'fieldid' ); if ( $this->_db->getErrorNum() ) { $this->_sqlUpgrader->_setError( sprintf( 'Fields selection query error: ' . $this->_db->getErrorMsg() ), $sql ); return false; } // 1) count and index tabs by core pluginclass and tabid holding array of fieldsids, so we can delete empty duplicate core tabs: $coreTabs = array(); foreach ( $tabs as $t ) { if ( in_array( $t->pluginclass, $this->_tabsShouldBe ) ) { $coreTabs[$t->pluginclass][$t->tabid] = array(); } } // 2) group fieldids by tabid // 3) add fields to $coreTabs[pluginclass][tabid][fieldid] $tabsFields = array(); foreach ( $fields as $f ) { if ( isset( $tabs[$f->tabid] ) ) { $tabsFields[$f->tabid][$f->fieldid] = $f->fieldid; if ( $tabs[$f->tabid]->pluginclass != '' ) { $coreTabs[$tabs[$f->tabid]->pluginclass][$f->tabid][$f->fieldid] = $f->fieldid; } } } // 4) delete empty duplicate core tabs according to $coreTabs[pluginclass][tabid][fieldid] foreach ( $coreTabs as /* $pluginClass => */ $tabIds ) { if ( count( $tabIds ) > 1 ) { // there is more than one core tab for this core plugin class ! We need to decide which to keep: $tabidCandidatesToKeep = array(); // 1st priority: keep tabs that are enabled AND have fields: foreach ( $tabIds as $tId => $tFields ) { if ( ( $tabs[$tId]->enabled == 1 ) && ( count( $tFields ) > 0 ) ) { $tabidCandidatesToKeep[] = $tId; } } // 2nd priority: keep tabs that have fields: if ( count( $tabidCandidatesToKeep ) == 0 ) { foreach ( $tabIds as $tId => $tFields ) { if ( count( $tFields ) > 0 ) { $tabidCandidatesToKeep[] = $tId; } } } // 3rd priority: keep tabs that are enabled: if ( count( $tabidCandidatesToKeep ) == 0 ) { foreach ( $tabIds as $tId => $tFields ) { if ( $tabs[$tId]->enabled == 1 ) { $tabidCandidatesToKeep[] = $tId; } } } // 4th priority: keep tab with the correct id: if ( count( $tabidCandidatesToKeep ) == 0 ) { foreach ( $tabIds as $tId => $tFields ) { if ( isset( $this->_tabsShouldBe[$tId] ) && ( $tabs[$tId]->pluginclass == $this->_tabsShouldBe[$tId] ) ) { $tabidCandidatesToKeep[] = $tId; } } } // 5th priority: well no more priorities to think of ! : just take first one ! if ( count( $tabidCandidatesToKeep ) == 0 ) { foreach ( $tabIds as $tId => $tFields ) { $tabidCandidatesToKeep[] = $tId; break; } } // ok, by now we got at least one tab to keep: let's see which, in case we got more than one: if ( count( $tabidCandidatesToKeep ) == 1 ) { $tabToKeep = (int) $tabidCandidatesToKeep[0]; } else { $tabToKeep = null; // a) has the right core id: foreach ( $tabidCandidatesToKeep as $tId ) { if ( isset( $this->_tabsShouldBe[$tId] ) && ( $tabs[$tId]->pluginclass == $this->_tabsShouldBe[$tId] ) ) { $tabToKeep = $tId; break; } } // b) first with fields: if ( $tabToKeep === null ) { foreach ( $tabidCandidatesToKeep as $tId ) { if ( count( $coreTabs[$tabs[$tId]->pluginclass][$tId] ) > 0 ) { $tabToKeep = $tId; break; } } } // c) first enabled one: if ( $tabToKeep === null ) { foreach ( $tabidCandidatesToKeep as $tId ) { if ( $tabs[$tId]->enabled == 1 ) { $tabToKeep = $tId; break; } } } // d) first one: if ( $tabToKeep === null ) { foreach ( $tabidCandidatesToKeep as $tId ) { $tabToKeep = $tId; break; } } } if ( $tabToKeep !== null ) { $tabsToDelete = array_diff( array_keys( $tabIds ), array( $tabToKeep ) ); // first reassign the fields of the tabs to delete: $fieldsToReassign = array(); foreach ( $tabIds as $tId => $tFields ) { if ( ( $tId != $tabToKeep ) && count( $tFields ) > 0 ) { $fieldsToReassign = array_merge( $fieldsToReassign, $tFields ); } } if ( count( $fieldsToReassign ) > 0 ) { cbArrayToInts( $fieldsToReassign ); $sql = 'UPDATE `#__comprofiler_fields` SET `tabid` = ' . (int) $tabToKeep . ' WHERE `fieldid` IN (' . implode( ',', $fieldsToReassign ) . ')'; if ( ! $this->_sqlUpgrader->_doQuery( $sql ) ) { $this->_sqlUpgrader->_setError( 'Failed changing fieldids ' . implode( ',', $fieldsToReassign ) . ' from duplicates of kept core tabid: ' . $tabToKeep . ' because of error:' . $this->_db->getErrorMsg(), $sql ); break; } else { $this->_sqlUpgrader->_setLog( 'Changed fieldids ' . implode( ',', $fieldsToReassign ) . ' from duplicates of kept core tabid: ' . $tabToKeep, $sql, 'change' ); } } cbArrayToInts( $tabsToDelete ); // c) remove duplicate core tabs: $sql = 'DELETE FROM `#__comprofiler_tabs` WHERE `tabid` IN (' . implode( ',', $tabsToDelete ) . ')'; if ( ! $this->_sqlUpgrader->_doQuery( $sql ) ) { $this->_sqlUpgrader->_setError( 'Failed deleting duplicates tabids ' . implode( ',', $tabsToDelete ) . ' of the used core tabid: ' . $tabToKeep . ' because of error:' . $this->_db->getErrorMsg(), $sql ); break; } else { $this->_sqlUpgrader->_setLog( 'Deleted duplicate core tabs tabids ' . implode( ',', $tabsToDelete ) . ' of the used core tabid: ' . $tabToKeep, $sql, 'change' ); } } } } // 5) refetch tabs with now free space at reserved positions: $sql = 'SELECT * FROM `#__comprofiler_tabs` ORDER BY `tabid`'; // `tabid`, `pluginclass` $this->_db->setQuery( $sql ); $tabs = $this->_db->loadObjectList( 'tabid' ); if ( $this->_db->getErrorNum() ) { $this->_sqlUpgrader->_setError( 'Tabs 2nd selection query error: ' . $this->_db->getErrorMsg(), $sql ); return false; } unset( $coreTabs ); // this one is now invalid, and not needed anymore $sql = 'SELECT `fieldid`, `tabid` FROM `#__comprofiler_fields` ORDER BY `tabid`'; $this->_db->setQuery( $sql ); $fields = $this->_db->loadObjectList( 'fieldid' ); if ( $this->_db->getErrorNum() ) { $this->_sqlUpgrader->_setError( 'Fields 3nd selection query error: ' . $this->_db->getErrorMsg(), $sql ); return false; } // group fieldids by tabid $tabsFields = array(); foreach ( $fields as $f ) { if ( isset( $tabs[$f->tabid] ) ) { $tabsFields[$f->tabid][$f->fieldid] = $f->fieldid; } } // 6) check tabs one by one, making room in reserved positions: foreach ( $tabs as $t ) { if ( isset( $this->_tabsShouldBe[$t->tabid] ) && ( $t->pluginclass == $this->_tabsShouldBe[$t->tabid] ) ) { // ok, cool, tabid and plugin matches: no corrective action: continue; } if ( isset( $this->_tabsShouldBe[$t->tabid] ) ) { // not ok: tabid is taken by another tab: we need to relocate this tab at last position: // a) insert same tab in another tabid $oldTabId = $t->tabid; if ( ! $dryRun ) { $t->tabid = null; if ( ! $this->_db->insertObject( '#__comprofiler_tabs', $t, 'tabid' ) ) { $this->_sqlUpgrader->_setError( 'Failed moving (inserting) non-core tabid: ' . $oldTabId . ' because of error:' . $this->_db->getErrorMsg(), $sql ); break; } $t->tabid = $this->_db->insertid(); } else { $t->tabid = $t->tabid + 10000; // just to fake the insert } $this->_sqlUpgrader->_setLog( 'Inserted old tabid ' . $oldTabId . ' as new tabid ' . $t->tabid, ( $dryRun ? 'INSERT tabobject' : $this->_db->getQuery() ), 'change' ); // b) change fields' tabid: if ( isset( $tabsFields[$oldTabId] ) && ( count( $tabsFields[$oldTabId] ) > 0 ) ) { $sql = 'UPDATE `#__comprofiler_fields` SET `tabid` = ' . (int) $t->tabid . ' WHERE `tabid` = ' . (int) $oldTabId; if ( ! $this->_sqlUpgrader->_doQuery( $sql ) ) { $this->_sqlUpgrader->_setError( 'Failed changing fields from old non-core tab with core tabid: ' . $oldTabId . ' to new tabid: ' . $t->tabid . ' because of error:' . $this->_db->getErrorMsg(), $sql ); break; } else { $this->_sqlUpgrader->_setLog( 'Changed fields from old non-core tab with core tabid: ' . $oldTabId . ' (that must be for ' . $this->_tabsShouldBe[$oldTabId] . ') to new tabid: ' . $t->tabid, $sql, 'change' ); } } // c) remove old tab: $sql = 'DELETE FROM `#__comprofiler_tabs` WHERE tabid = ' . (int) $oldTabId; if ( ! $this->_sqlUpgrader->_doQuery( $sql ) ) { $this->_sqlUpgrader->_setError( 'Failed deleting old non-core tabid: ' . $oldTabId . ' which is already copied to new tabid: ' . $t->tabid . ' because of error:' . $this->_db->getErrorMsg(), $sql ); break; } else { $this->_sqlUpgrader->_setLog( 'Deleted old non-core tabid: ' . $oldTabId . ' which is already copied to new tabid: ' . $t->tabid, $sql, 'change' ); } } } // 7) refetch tabs with now free space at reserved positions as well as fields and recompute $tabFields: $sql = 'SELECT * FROM `#__comprofiler_tabs` ORDER BY `tabid`'; // `tabid`, `pluginclass` $this->_db->setQuery( $sql ); $tabs = $this->_db->loadObjectList( 'tabid' ); if ( $this->_db->getErrorNum() ) { $this->_sqlUpgrader->_setError( 'Tabs 3rd selection query error: ' . $this->_db->getErrorMsg(), $sql ); return false; } $sql = 'SELECT `fieldid`, `tabid` FROM `#__comprofiler_fields` ORDER BY `tabid`'; $this->_db->setQuery( $sql ); $fields = $this->_db->loadObjectList( 'fieldid' ); if ( $this->_db->getErrorNum() ) { $this->_sqlUpgrader->_setError( 'Fields 3nd selection query error: ' . $this->_db->getErrorMsg(), $sql ); return false; } // group fieldids by tabid $tabsFields = array(); foreach ( $fields as $f ) { if ( isset( $tabs[$f->tabid] ) ) { $tabsFields[$f->tabid][$f->fieldid] = $f->fieldid; } } // 8) check tabs one by one, moving tabs back to reserved positions if needed: foreach ( $tabs as $t ) { if ( isset( $this->_tabsShouldBe[$t->tabid] ) && ( $t->pluginclass == $this->_tabsShouldBe[$t->tabid] ) ) { // ok, cool, tabid and plugin matches: no corrective action: continue; } if ( ( ! isset( $this->_tabsShouldBe[$t->tabid] ) ) && in_array( $t->pluginclass, $this->_tabsShouldBe ) ) { // ok we found a core CB tab which doesn't have the right id: the right id is now free, so just update the tab: $newTabId = array_search( $t->pluginclass, $this->_tabsShouldBe ); if ( $newTabId !== false ) { // a) move the core tab to the right tabid: $sql = 'UPDATE `#__comprofiler_tabs` SET `tabid` = ' . (int) $newTabId . ' WHERE `tabid` = ' . (int) $t->tabid; if ( ! $this->_sqlUpgrader->_doQuery( $sql ) ) { $this->_sqlUpgrader->_setError( 'Failed moving core tab from old tabid: ' . $t->tabid . ' to new tabid: ' . $newTabId . ' because of error:' . $this->_db->getErrorMsg(), $sql ); break; } else { $this->_sqlUpgrader->_setLog( 'Moved core tab from old tabid: ' . $t->tabid . ' to new tabid: ' . $newTabId, $sql, 'change' ); } // b) change fields' tabid: if ( isset( $tabsFields[$t->tabid] ) && ( count( $tabsFields[$t->tabid] ) > 0 ) ) { $sql = 'UPDATE `#__comprofiler_fields` SET `tabid` = ' . (int) $newTabId . ' WHERE `tabid` = ' . (int) $t->tabid; if ( ! $this->_sqlUpgrader->_doQuery( $sql ) ) { $this->_sqlUpgrader->_setError( 'Failed changing fields from old core tabid: ' . $oldTabId . ' to new tabid: ' . $t->tabid . ' because of error:' . $this->_db->getErrorMsg(), $sql ); break; } else { $this->_sqlUpgrader->_setLog( 'Changed fields from old core tabid: ' . $oldTabId . ' to new tabid: ' . $t->tabid, $sql, 'change' ); } } } } } // now missing core tabs will be inserted in the new 1.2 upgrader in next step. return true; }