/** * @return Collation */ static function singleton() { if ( !self::$instance ) { global $wgCategoryCollation; self::$instance = self::factory( $wgCategoryCollation ); } return self::$instance; }
function doCategoryQuery() { $dbr = wfGetDB(DB_SLAVE, 'category'); $this->nextPage = array('page' => null, 'subcat' => null, 'file' => null); $this->flip = array('page' => false, 'subcat' => false, 'file' => false); foreach (array('page', 'subcat', 'file') as $type) { # Get the sortkeys for start/end, if applicable. Note that if # the collation in the database differs from the one # set in $wgCategoryCollation, pagination might go totally haywire. $extraConds = array('cl_type' => $type); if ($this->from[$type] !== null) { $extraConds[] = 'cl_sortkey >= ' . $dbr->addQuotes($this->collation->getSortKey($this->from[$type])); } elseif ($this->until[$type] !== null) { $extraConds[] = 'cl_sortkey < ' . $dbr->addQuotes($this->collation->getSortKey($this->until[$type])); $this->flip[$type] = true; } /* Wikia change begin - @author: TomekO */ /* Changed by MoLi (1.19 ugrade) */ wfRunHooks('CategoryViewer::beforeCategoryData', array(&$extraConds)); /* Wikia change end */ $res = $dbr->select(array('page', 'categorylinks', 'category'), array('page_id', 'page_title', 'page_namespace', 'page_len', 'page_is_redirect', 'cl_sortkey', 'cat_id', 'cat_title', 'cat_subcats', 'cat_pages', 'cat_files', 'cl_sortkey_prefix', 'cl_collation'), array_merge(array('cl_to' => $this->title->getDBkey()), $extraConds), __METHOD__, array('USE INDEX' => array('categorylinks' => 'cl_sortkey'), 'LIMIT' => is_integer($this->limit) ? $this->limit + 1 : null, 'ORDER BY' => $this->flip[$type] ? 'cl_sortkey DESC' : 'cl_sortkey'), array('categorylinks' => array('INNER JOIN', 'cl_from = page_id'), 'category' => array('LEFT JOIN', 'cat_title = page_title AND page_namespace = ' . NS_CATEGORY))); $count = 0; foreach ($res as $row) { $title = Title::newFromRow($row); if ($row->cl_collation === '') { // Hack to make sure that while updating from 1.16 schema // and db is inconsistent, that the sky doesn't fall. // See r83544. Could perhaps be removed in a couple decades... $humanSortkey = $row->cl_sortkey; } else { $humanSortkey = $title->getCategorySortkey($row->cl_sortkey_prefix); } if (++$count > $this->limit && is_integer($this->limit)) { # We've reached the one extra which shows that there # are additional pages to be had. Stop here... $this->nextPage[$type] = $humanSortkey; break; } if ($title->getNamespace() == NS_CATEGORY) { $cat = Category::newFromRow($row, $title); $this->addSubcategoryObject($cat, $humanSortkey, $row->page_len); } elseif ($title->getNamespace() == NS_FILE) { $this->addImage($title, $humanSortkey, $row->page_len, $row->page_is_redirect); } else { # <Wikia> if (wfRunHooks("CategoryViewer::addPage", array(&$this, &$title, &$row, $humanSortkey))) { $this->addPage($title, $humanSortkey, $row->page_len, $row->page_is_redirect); } # </Wikia> } } } }
function doCategoryQuery() { $dbr = wfGetDB(DB_REPLICA, 'category'); $this->nextPage = ['page' => null, 'subcat' => null, 'file' => null]; $this->prevPage = ['page' => null, 'subcat' => null, 'file' => null]; $this->flip = ['page' => false, 'subcat' => false, 'file' => false]; foreach (['page', 'subcat', 'file'] as $type) { # Get the sortkeys for start/end, if applicable. Note that if # the collation in the database differs from the one # set in $wgCategoryCollation, pagination might go totally haywire. $extraConds = ['cl_type' => $type]; if (isset($this->from[$type]) && $this->from[$type] !== null) { $extraConds[] = 'cl_sortkey >= ' . $dbr->addQuotes($this->collation->getSortKey($this->from[$type])); } elseif (isset($this->until[$type]) && $this->until[$type] !== null) { $extraConds[] = 'cl_sortkey < ' . $dbr->addQuotes($this->collation->getSortKey($this->until[$type])); $this->flip[$type] = true; } $res = $dbr->select(['page', 'categorylinks', 'category'], array_merge(LinkCache::getSelectFields(), ['page_namespace', 'page_title', 'cl_sortkey', 'cat_id', 'cat_title', 'cat_subcats', 'cat_pages', 'cat_files', 'cl_sortkey_prefix', 'cl_collation']), array_merge(['cl_to' => $this->title->getDBkey()], $extraConds), __METHOD__, ['USE INDEX' => ['categorylinks' => 'cl_sortkey'], 'LIMIT' => $this->limit + 1, 'ORDER BY' => $this->flip[$type] ? 'cl_sortkey DESC' : 'cl_sortkey'], ['categorylinks' => ['INNER JOIN', 'cl_from = page_id'], 'category' => ['LEFT JOIN', ['cat_title = page_title', 'page_namespace' => NS_CATEGORY]]]); Hooks::run('CategoryViewer::doCategoryQuery', [$type, $res]); $linkCache = MediaWikiServices::getInstance()->getLinkCache(); $count = 0; foreach ($res as $row) { $title = Title::newFromRow($row); $linkCache->addGoodLinkObjFromRow($title, $row); if ($row->cl_collation === '') { // Hack to make sure that while updating from 1.16 schema // and db is inconsistent, that the sky doesn't fall. // See r83544. Could perhaps be removed in a couple decades... $humanSortkey = $row->cl_sortkey; } else { $humanSortkey = $title->getCategorySortkey($row->cl_sortkey_prefix); } if (++$count > $this->limit) { # We've reached the one extra which shows that there # are additional pages to be had. Stop here... $this->nextPage[$type] = $humanSortkey; break; } if ($count == $this->limit) { $this->prevPage[$type] = $humanSortkey; } if ($title->getNamespace() == NS_CATEGORY) { $cat = Category::newFromRow($row, $title); $this->addSubcategoryObject($cat, $humanSortkey, $row->page_len); } elseif ($title->getNamespace() == NS_FILE) { $this->addImage($title, $humanSortkey, $row->page_len, $row->page_is_redirect); } else { $this->addPage($title, $humanSortkey, $row->page_len, $row->page_is_redirect); } } } }
public function execute() { global $wgCategoryCollation, $wgMiserMode; $dbw = wfGetDB(DB_MASTER); $force = $this->getOption('force'); $options = array('LIMIT' => self::BATCH_SIZE); if ($force) { $options['ORDER BY'] = 'cl_from, cl_to'; $collationConds = array(); } else { $collationConds = array(0 => 'cl_collation != ' . $dbw->addQuotes($wgCategoryCollation)); if (!$wgMiserMode) { $count = $dbw->selectField('categorylinks', 'COUNT(*)', $collationConds, __METHOD__); if ($count == 0) { $this->output("Collations up-to-date.\n"); return; } $this->output("Fixing collation for {$count} rows.\n"); } } $count = 0; $row = false; $batchConds = array(); do { $this->output('Processing next ' . self::BATCH_SIZE . ' rows... '); $res = $dbw->select(array('categorylinks', 'page'), array('cl_from', 'cl_to', 'cl_sortkey_prefix', 'cl_collation', 'cl_sortkey', 'page_namespace', 'page_title'), array_merge($collationConds, $batchConds, array('cl_from = page_id')), __METHOD__, $options); $dbw->begin(); foreach ($res as $row) { $title = Title::newFromRow($row); if (!$row->cl_collation) { # This is an old-style row, so the sortkey needs to be # converted. if ($row->cl_sortkey == $title->getText() || $row->cl_sortkey == $title->getPrefixedText()) { $prefix = ''; } else { # Custom sortkey, use it as a prefix $prefix = $row->cl_sortkey; } } else { $prefix = $row->cl_sortkey_prefix; } # cl_type will be wrong for lots of pages if cl_collation is 0, # so let's update it while we're here. if ($title->getNamespace() == NS_CATEGORY) { $type = 'subcat'; } elseif ($title->getNamespace() == NS_FILE) { $type = 'file'; } else { $type = 'page'; } $dbw->update('categorylinks', array('cl_sortkey' => Collation::singleton()->getSortKey($title->getCategorySortkey($prefix)), 'cl_sortkey_prefix' => $prefix, 'cl_collation' => $wgCategoryCollation, 'cl_type' => $type, 'cl_timestamp = cl_timestamp'), array('cl_from' => $row->cl_from, 'cl_to' => $row->cl_to), __METHOD__); } $dbw->commit(); if ($force && $row) { $encFrom = $dbw->addQuotes($row->cl_from); $encTo = $dbw->addQuotes($row->cl_to); $batchConds = array("(cl_from = {$encFrom} AND cl_to > {$encTo}) " . " OR cl_from > {$encFrom}"); } $count += $res->numRows(); $this->output("{$count} done.\n"); $this->syncDBs(); } while ($res->numRows() == self::BATCH_SIZE); }
/** * @param User $user * @param string $reason * @param bool $createRedirect * @return Status */ public function move(User $user, $reason, $createRedirect) { global $wgCategoryCollation; Hooks::run('TitleMove', [$this->oldTitle, $this->newTitle, $user]); // If it is a file, move it first. // It is done before all other moving stuff is done because it's hard to revert. $dbw = wfGetDB(DB_MASTER); if ($this->oldTitle->getNamespace() == NS_FILE) { $file = wfLocalFile($this->oldTitle); $file->load(File::READ_LATEST); if ($file->exists()) { $status = $file->move($this->newTitle); if (!$status->isOK()) { return $status; } } // Clear RepoGroup process cache RepoGroup::singleton()->clearCache($this->oldTitle); RepoGroup::singleton()->clearCache($this->newTitle); # clear false negative cache } $dbw->startAtomic(__METHOD__); Hooks::run('TitleMoveStarting', [$this->oldTitle, $this->newTitle, $user]); $pageid = $this->oldTitle->getArticleID(Title::GAID_FOR_UPDATE); $protected = $this->oldTitle->isProtected(); // Do the actual move; if this fails, it will throw an MWException(!) $nullRevision = $this->moveToInternal($user, $this->newTitle, $reason, $createRedirect); // Refresh the sortkey for this row. Be careful to avoid resetting // cl_timestamp, which may disturb time-based lists on some sites. // @todo This block should be killed, it's duplicating code // from LinksUpdate::getCategoryInsertions() and friends. $prefixes = $dbw->select('categorylinks', ['cl_sortkey_prefix', 'cl_to'], ['cl_from' => $pageid], __METHOD__); if ($this->newTitle->getNamespace() == NS_CATEGORY) { $type = 'subcat'; } elseif ($this->newTitle->getNamespace() == NS_FILE) { $type = 'file'; } else { $type = 'page'; } foreach ($prefixes as $prefixRow) { $prefix = $prefixRow->cl_sortkey_prefix; $catTo = $prefixRow->cl_to; $dbw->update('categorylinks', ['cl_sortkey' => Collation::singleton()->getSortKey($this->newTitle->getCategorySortkey($prefix)), 'cl_collation' => $wgCategoryCollation, 'cl_type' => $type, 'cl_timestamp=cl_timestamp'], ['cl_from' => $pageid, 'cl_to' => $catTo], __METHOD__); } $redirid = $this->oldTitle->getArticleID(); if ($protected) { # Protect the redirect title as the title used to be... $res = $dbw->select('page_restrictions', '*', ['pr_page' => $pageid], __METHOD__, 'FOR UPDATE'); $rowsInsert = []; foreach ($res as $row) { $rowsInsert[] = ['pr_page' => $redirid, 'pr_type' => $row->pr_type, 'pr_level' => $row->pr_level, 'pr_cascade' => $row->pr_cascade, 'pr_user' => $row->pr_user, 'pr_expiry' => $row->pr_expiry]; } $dbw->insert('page_restrictions', $rowsInsert, __METHOD__, ['IGNORE']); // Build comment for log $comment = wfMessage('prot_1movedto2', $this->oldTitle->getPrefixedText(), $this->newTitle->getPrefixedText())->inContentLanguage()->text(); if ($reason) { $comment .= wfMessage('colon-separator')->inContentLanguage()->text() . $reason; } // reread inserted pr_ids for log relation $insertedPrIds = $dbw->select('page_restrictions', 'pr_id', ['pr_page' => $redirid], __METHOD__); $logRelationsValues = []; foreach ($insertedPrIds as $prid) { $logRelationsValues[] = $prid->pr_id; } // Update the protection log $logEntry = new ManualLogEntry('protect', 'move_prot'); $logEntry->setTarget($this->newTitle); $logEntry->setComment($comment); $logEntry->setPerformer($user); $logEntry->setParameters(['4::oldtitle' => $this->oldTitle->getPrefixedText()]); $logEntry->setRelations(['pr_id' => $logRelationsValues]); $logId = $logEntry->insert(); $logEntry->publish($logId); } // Update *_from_namespace fields as needed if ($this->oldTitle->getNamespace() != $this->newTitle->getNamespace()) { $dbw->update('pagelinks', ['pl_from_namespace' => $this->newTitle->getNamespace()], ['pl_from' => $pageid], __METHOD__); $dbw->update('templatelinks', ['tl_from_namespace' => $this->newTitle->getNamespace()], ['tl_from' => $pageid], __METHOD__); $dbw->update('imagelinks', ['il_from_namespace' => $this->newTitle->getNamespace()], ['il_from' => $pageid], __METHOD__); } # Update watchlists $oldtitle = $this->oldTitle->getDBkey(); $newtitle = $this->newTitle->getDBkey(); $oldsnamespace = MWNamespace::getSubject($this->oldTitle->getNamespace()); $newsnamespace = MWNamespace::getSubject($this->newTitle->getNamespace()); if ($oldsnamespace != $newsnamespace || $oldtitle != $newtitle) { $store = MediaWikiServices::getInstance()->getWatchedItemStore(); $store->duplicateAllAssociatedEntries($this->oldTitle, $this->newTitle); } Hooks::run('TitleMoveCompleting', [$this->oldTitle, $this->newTitle, $user, $pageid, $redirid, $reason, $nullRevision]); $dbw->endAtomic(__METHOD__); $params = [&$this->oldTitle, &$this->newTitle, &$user, $pageid, $redirid, $reason, $nullRevision]; // Keep each single hook handler atomic DeferredUpdates::addUpdate(new AtomicSectionUpdate($dbw, __METHOD__, function () use($params) { Hooks::run('TitleMoveComplete', $params); })); return Status::newGood(); }
'; var row = $('#' + idPrefix).closest("tr").prev(); row.attr('id', 'columns_<?php echo $column->COLUMN_NAME; ?> '); row.children('td:eq(1)').html('<?php echo $column->COLUMN_NAME; ?> '); row.children('td:eq(2)').html(<?php echo CJSON::encode($column->COLUMN_TYPE); ?> ); row.children('td:eq(3)').html('<?php echo $column->COLLATION_NAME ? '<dfn class="collation" title="' . Collation::getDefinition($column->COLLATION_NAME) . '">' . $column->COLLATION_NAME . '</dfn>' : ''; ?> '); row.children('td:eq(4)').html('<?php echo Yii::t('core', $column->isNullable ? 'yes' : 'no'); ?> '); row.children('td:eq(5)').html(<?php echo !is_null($column->COLUMN_DEFAULT) ? CJSON::encode($column->COLUMN_DEFAULT) : ($column->isNullable ? CJSON::encode('<span class="null">NULL</span>') : '\'\''); ?> ); row.children('td:eq(6)').html('<?php echo $column->EXTRA; ?> '); $('#' + idPrefix).parent().slideUp(500, function() {
/** * Move a title to a new location * * @param $nt Title the new title * @param $auth Bool indicates whether $wgUser's permissions * should be checked * @param $reason String the reason for the move * @param $createRedirect Bool Whether to create a redirect from the old title to the new title. * Ignored if the user doesn't have the suppressredirect right. * @return Mixed true on success, getUserPermissionsErrors()-like array on failure */ public function moveTo(&$nt, $auth = true, $reason = '', $createRedirect = true) { global $wgUser; $err = $this->isValidMoveOperation($nt, $auth, $reason); if (is_array($err)) { // Auto-block user's IP if the account was "hard" blocked $wgUser->spreadAnyEditBlock(); return $err; } // If it is a file, move it first. It is done before all other moving stuff is // done because it's hard to revert $dbw = wfGetDB(DB_MASTER); if ($this->getNamespace() == NS_FILE) { $file = wfLocalFile($this); if ($file->exists()) { $status = $file->move($nt); if (!$status->isOk()) { return $status->getErrorsArray(); } } } $dbw->begin(); # If $file was a LocalFile, its transaction would have closed our own. $pageid = $this->getArticleID(self::GAID_FOR_UPDATE); $protected = $this->isProtected(); $pageCountChange = ($createRedirect ? 1 : 0) - ($nt->exists() ? 1 : 0); // Do the actual move $err = $this->moveToInternal($nt, $reason, $createRedirect); if (is_array($err)) { # @todo FIXME: What about the File we have already moved? $dbw->rollback(); return $err; } $redirid = $this->getArticleID(); // Refresh the sortkey for this row. Be careful to avoid resetting // cl_timestamp, which may disturb time-based lists on some sites. $prefixes = $dbw->select('categorylinks', array('cl_sortkey_prefix', 'cl_to'), array('cl_from' => $pageid), __METHOD__); foreach ($prefixes as $prefixRow) { $prefix = $prefixRow->cl_sortkey_prefix; $catTo = $prefixRow->cl_to; $dbw->update('categorylinks', array('cl_sortkey' => Collation::singleton()->getSortKey($nt->getCategorySortkey($prefix)), 'cl_timestamp=cl_timestamp'), array('cl_from' => $pageid, 'cl_to' => $catTo), __METHOD__); } if ($protected) { # Protect the redirect title as the title used to be... $dbw->insertSelect('page_restrictions', 'page_restrictions', array('pr_page' => $redirid, 'pr_type' => 'pr_type', 'pr_level' => 'pr_level', 'pr_cascade' => 'pr_cascade', 'pr_user' => 'pr_user', 'pr_expiry' => 'pr_expiry'), array('pr_page' => $pageid), __METHOD__, array('IGNORE')); # Update the protection log $log = new LogPage('protect'); $comment = wfMsgForContent('prot_1movedto2', $this->getPrefixedText(), $nt->getPrefixedText()); if ($reason) { $comment .= wfMsgForContent('colon-separator') . $reason; } // @todo FIXME: $params? $log->addEntry('move_prot', $nt, $comment, array($this->getPrefixedText())); } # Update watchlists $oldnamespace = $this->getNamespace() & ~1; $newnamespace = $nt->getNamespace() & ~1; $oldtitle = $this->getDBkey(); $newtitle = $nt->getDBkey(); if ($oldnamespace != $newnamespace || $oldtitle != $newtitle) { WatchedItem::duplicateEntries($this, $nt); } # Update search engine $u = new SearchUpdate($pageid, $nt->getPrefixedDBkey()); $u->doUpdate(); $u = new SearchUpdate($redirid, $this->getPrefixedDBkey(), ''); $u->doUpdate(); $dbw->commit(); # Update site_stats if ($this->isContentPage() && !$nt->isContentPage()) { # No longer a content page # Not viewed, edited, removing $u = new SiteStatsUpdate(0, 1, -1, $pageCountChange); } elseif (!$this->isContentPage() && $nt->isContentPage()) { # Now a content page # Not viewed, edited, adding $u = new SiteStatsUpdate(0, 1, +1, $pageCountChange); } elseif ($pageCountChange) { # Redirect added $u = new SiteStatsUpdate(0, 0, 0, 1); } else { # Nothing special $u = false; } if ($u) { $u->doUpdate(); } # Update message cache for interface messages if ($this->getNamespace() == NS_MEDIAWIKI) { # @bug 17860: old article can be deleted, if this the case, # delete it from message cache if ($this->getArticleID() === 0) { MessageCache::singleton()->replace($this->getDBkey(), false); } else { $oldarticle = new Article($this); MessageCache::singleton()->replace($this->getDBkey(), $oldarticle->getContent()); } } if ($nt->getNamespace() == NS_MEDIAWIKI) { $newarticle = new Article($nt); MessageCache::singleton()->replace($nt->getDBkey(), $newarticle->getContent()); } global $wgUser; wfRunHooks('TitleMoveComplete', array(&$this, &$nt, &$wgUser, $pageid, $redirid)); return true; }
function __construct($title, $from = '', $until = '', $query = array()) { global $wgCategoryPagingLimit; $this->title = $title; $this->from = $from; $this->until = $until; $this->limit = $wgCategoryPagingLimit; $this->cat = Category::newFromTitle($title); $this->query = $query; $this->collation = Collation::singleton(); unset($this->query['title']); }
} ?> </td> <td> <?php echo $table->getRowCount(); ?> </td> <td> <?php echo $table->ENGINE; ?> </td> <td> <dfn title="<?php echo Collation::getDefinition($table->TABLE_COLLATION); ?> "><?php echo $table->TABLE_COLLATION; ?> </dfn> </td> <td style="text-align: right"> <?php echo Formatter::fileSize($table->DATA_LENGTH + $table->INDEX_LENGTH); ?> </td> <td style="text-align: right"> <?php echo Formatter::fileSize($table->DATA_FREE); ?>
/** * Update a schema. * * @todo(mburtscher): Renaming. Requires copying the whole schema. */ public function actionUpdate() { $isSubmitted = false; $sql = null; $schema = $this->loadSchema(); if (isset($_POST['Schema'])) { $schema->attributes = $_POST['Schema']; if ($sql = $schema->save()) { $isSubmitted = true; } } $collations = Collation::model()->findAll(array('order' => 'COLLATION_NAME', 'select' => 'COLLATION_NAME, CHARACTER_SET_NAME AS collationGroup')); $this->render('form', array('schema' => $schema, 'collations' => $collations, 'isSubmitted' => $isSubmitted, 'sql' => $sql)); }
public function execute() { global $wgCategoryCollation; $dbw = $this->getDB(DB_MASTER); $dbr = $this->getDB(DB_SLAVE); $force = $this->getOption('force'); $dryRun = $this->getOption('dry-run'); $verboseStats = $this->getOption('verbose-stats'); if ($this->hasOption('target-collation')) { $collationName = $this->getOption('target-collation'); $collation = Collation::factory($collationName); } else { $collationName = $wgCategoryCollation; $collation = Collation::singleton(); } // Collation sanity check: in some cases the constructor will work, // but this will raise an exception, breaking all category pages $collation->getFirstLetter('MediaWiki'); // Locally at least, (my local is a rather old version of mysql) // mysql seems to filesort if there is both an equality // (but not for an inequality) condition on cl_collation in the // WHERE and it is also the first item in the ORDER BY. if ($this->hasOption('previous-collation')) { $orderBy = 'cl_to, cl_type, cl_from'; } else { $orderBy = 'cl_collation, cl_to, cl_type, cl_from'; } $options = ['LIMIT' => self::BATCH_SIZE, 'ORDER BY' => $orderBy, 'STRAIGHT_JOIN']; if ($force || $dryRun) { $collationConds = []; } else { if ($this->hasOption('previous-collation')) { $collationConds['cl_collation'] = $this->getOption('previous-collation'); } else { $collationConds = [0 => 'cl_collation != ' . $dbw->addQuotes($collationName)]; } $count = $dbr->estimateRowCount('categorylinks', '*', $collationConds, __METHOD__); // Improve estimate if feasible if ($count < 1000000) { $count = $dbr->selectField('categorylinks', 'COUNT(*)', $collationConds, __METHOD__); } if ($count == 0) { $this->output("Collations up-to-date.\n"); return; } $this->output("Fixing collation for {$count} rows.\n"); wfWaitForSlaves(); } $count = 0; $batchCount = 0; $batchConds = []; do { $this->output("Selecting next " . self::BATCH_SIZE . " rows..."); // cl_type must be selected as a number for proper paging because // enums suck. if ($dbw->getType() === 'mysql') { $clType = 'cl_type+0 AS "cl_type_numeric"'; } else { $clType = 'cl_type'; } $res = $dbw->select(['categorylinks', 'page'], ['cl_from', 'cl_to', 'cl_sortkey_prefix', 'cl_collation', 'cl_sortkey', $clType, 'page_namespace', 'page_title'], array_merge($collationConds, $batchConds, ['cl_from = page_id']), __METHOD__, $options); $this->output(" processing..."); if (!$dryRun) { $this->beginTransaction($dbw, __METHOD__); } foreach ($res as $row) { $title = Title::newFromRow($row); if (!$row->cl_collation) { # This is an old-style row, so the sortkey needs to be # converted. if ($row->cl_sortkey == $title->getText() || $row->cl_sortkey == $title->getPrefixedText()) { $prefix = ''; } else { # Custom sortkey, use it as a prefix $prefix = $row->cl_sortkey; } } else { $prefix = $row->cl_sortkey_prefix; } # cl_type will be wrong for lots of pages if cl_collation is 0, # so let's update it while we're here. if ($title->getNamespace() == NS_CATEGORY) { $type = 'subcat'; } elseif ($title->getNamespace() == NS_FILE) { $type = 'file'; } else { $type = 'page'; } $newSortKey = $collation->getSortKey($title->getCategorySortkey($prefix)); if ($verboseStats) { $this->updateSortKeySizeHistogram($newSortKey); } if (!$dryRun) { $dbw->update('categorylinks', ['cl_sortkey' => $newSortKey, 'cl_sortkey_prefix' => $prefix, 'cl_collation' => $collationName, 'cl_type' => $type, 'cl_timestamp = cl_timestamp'], ['cl_from' => $row->cl_from, 'cl_to' => $row->cl_to], __METHOD__); } if ($row) { $batchConds = [$this->getBatchCondition($row, $dbw)]; } } if (!$dryRun) { $this->commitTransaction($dbw, __METHOD__); } $count += $res->numRows(); $this->output("{$count} done.\n"); if (!$dryRun && ++$batchCount % self::SYNC_INTERVAL == 0) { $this->output("Waiting for slaves ... "); wfWaitForSlaves(); $this->output("done\n"); } } while ($res->numRows() == self::BATCH_SIZE); $this->output("{$count} rows processed\n"); if ($verboseStats) { $this->output("\n"); $this->showSortKeySizeHistogram(); } }
public function getColumnDefinition() { if (DataType::check($this->DATA_TYPE, DataType::SUPPORTS_COLLATION)) { $collate = ' CHARACTER SET ' . Collation::getCharacterSet($this->COLLATION_NAME) . ' COLLATE ' . $this->COLLATION_NAME; } else { $collate = ''; } if ($this->attribute) { if ($this->attribute == 'unsigned' && DataType::check($this->DATA_TYPE, DataType::SUPPORTS_UNSIGNED) || $this->attribute == 'unsigned zerofill' && DataType::check($this->DATA_TYPE, DataType::SUPPORTS_UNSIGNED_ZEROFILL) || $this->attribute == 'on update current_timestamp' && DataType::check($this->DATA_TYPE, DataType::SUPPORTS_ON_UPDATE_CURRENT_TIMESTAMP)) { $attribute = ' ' . $this->attribute; } else { $attribute = ''; } } else { $attribute = ''; } if (strlen($this->COLUMN_DEFAULT) > 0 && $this->EXTRA != 'auto_increment') { if ($this->DATA_TYPE == 'timestamp' && strtolower($this->COLUMN_DEFAULT) == 'current_timestamp') { $defaultValue = 'CURRENT_TIMESTAMP'; } elseif ($this->DATA_TYPE == 'bit') { if (preg_match('/b\'[01]+\'/', $this->COLUMN_DEFAULT)) { $defaultValue = $this->COLUMN_DEFAULT; } else { $defaultValue = 'b' . self::$db->quoteValue($this->COLUMN_DEFAULT); } } else { $defaultValue = self::$db->quoteValue($this->COLUMN_DEFAULT); } $default = ' DEFAULT ' . $defaultValue; } else { if ($this->getIsNullable() && $this->EXTRA != 'auto_increment') { $default = ' DEFAULT NULL'; } else { $default = ''; } } return trim(self::$db->quoteColumnName($this->COLUMN_NAME) . ' ' . $this->getColumnType() . $attribute . $collate . ($this->getIsNullable() ? ' NULL' : ' NOT NULL') . $default . ($this->EXTRA == 'auto_increment' ? ' AUTO_INCREMENT' : '') . ($this->createPrimaryKey ? ' PRIMARY KEY' : '') . ($this->createUniqueKey ? ' UNIQUE KEY' : '') . (strlen($this->COLUMN_COMMENT) ? ' COMMENT ' . self::$db->quoteValue($this->COLUMN_COMMENT) : '')); }
public function actionUpdate() { $isSubmitted = false; $sql = false; $column = Column::model()->findByPk(array('TABLE_SCHEMA' => $this->schema, 'TABLE_NAME' => $this->table, 'COLUMN_NAME' => $this->column)); if (isset($_POST['Column'])) { $column->attributes = $_POST['Column']; $sql = $column->save(); if ($sql) { $isSubmitted = true; } } $collations = Collation::model()->findAll(array('order' => 'COLLATION_NAME', 'select' => 'COLLATION_NAME, CHARACTER_SET_NAME AS collationGroup')); CHtml::generateRandomIdPrefix(); $data = array('column' => $column, 'collations' => $collations, 'isSubmitted' => $isSubmitted, 'sql' => $sql); $data['formBody'] = $this->renderPartial('formBody', $data, true); $this->render('form', $data); }
echo $charset['Description']; ?> </th> </tr> </thead> <tbody> <?php foreach ($charset['collations'] as $collation) { ?> <tr> <td><?php echo $collation['Collation']; ?> </td> <td><?php echo Collation::getDefinition($collation['Collation'], false); ?> </td> </tr> <?php } ?> </tbody> </table> </div> <?php } ?> <script type="text/javascript"> breadCrumb.set([
/** * @param ApiPageSet $resultPageSet * @return void */ private function run($resultPageSet = null) { $params = $this->extractRequestParams(); $categoryTitle = $this->getTitleOrPageId($params)->getTitle(); if ($categoryTitle->getNamespace() != NS_CATEGORY) { $this->dieUsage('The category name you entered is not valid', 'invalidcategory'); } $prop = array_flip($params['prop']); $fld_ids = isset($prop['ids']); $fld_title = isset($prop['title']); $fld_sortkey = isset($prop['sortkey']); $fld_sortkeyprefix = isset($prop['sortkeyprefix']); $fld_timestamp = isset($prop['timestamp']); $fld_type = isset($prop['type']); if (is_null($resultPageSet)) { $this->addFields(array('cl_from', 'cl_sortkey', 'cl_type', 'page_namespace', 'page_title')); $this->addFieldsIf('page_id', $fld_ids); $this->addFieldsIf('cl_sortkey_prefix', $fld_sortkeyprefix); } else { $this->addFields($resultPageSet->getPageTableFields()); // will include page_ id, ns, title $this->addFields(array('cl_from', 'cl_sortkey', 'cl_type')); } $this->addFieldsIf('cl_timestamp', $fld_timestamp || $params['sort'] == 'timestamp'); $this->addTables(array('page', 'categorylinks')); // must be in this order for 'USE INDEX' $this->addWhereFld('cl_to', $categoryTitle->getDBkey()); $queryTypes = $params['type']; $contWhere = false; // Scanning large datasets for rare categories sucks, and I already told // how to have efficient subcategory access :-) ~~~~ (oh well, domas) $miser_ns = array(); if ($this->getConfig()->get('MiserMode')) { $miser_ns = $params['namespace']; } else { $this->addWhereFld('page_namespace', $params['namespace']); } $dir = in_array($params['dir'], array('asc', 'ascending', 'newer')) ? 'newer' : 'older'; if ($params['sort'] == 'timestamp') { $this->addTimestampWhereRange('cl_timestamp', $dir, $params['start'], $params['end']); // Include in ORDER BY for uniqueness $this->addWhereRange('cl_from', $dir, null, null); if (!is_null($params['continue'])) { $cont = explode('|', $params['continue']); $this->dieContinueUsageIf(count($cont) != 2); $op = $dir === 'newer' ? '>' : '<'; $db = $this->getDB(); $continueTimestamp = $db->addQuotes($db->timestamp($cont[0])); $continueFrom = (int) $cont[1]; $this->dieContinueUsageIf($continueFrom != $cont[1]); $this->addWhere("cl_timestamp {$op} {$continueTimestamp} OR " . "(cl_timestamp = {$continueTimestamp} AND " . "cl_from {$op}= {$continueFrom})"); } $this->addOption('USE INDEX', 'cl_timestamp'); } else { if ($params['continue']) { $cont = explode('|', $params['continue'], 3); $this->dieContinueUsageIf(count($cont) != 3); // Remove the types to skip from $queryTypes $contTypeIndex = array_search($cont[0], $queryTypes); $queryTypes = array_slice($queryTypes, $contTypeIndex); // Add a WHERE clause for sortkey and from $this->dieContinueUsageIf(!$this->validateHexSortkey($cont[1])); // pack( "H*", $foo ) is used to convert hex back to binary $escSortkey = $this->getDB()->addQuotes(pack('H*', $cont[1])); $from = intval($cont[2]); $op = $dir == 'newer' ? '>' : '<'; // $contWhere is used further down $contWhere = "cl_sortkey {$op} {$escSortkey} OR " . "(cl_sortkey = {$escSortkey} AND " . "cl_from {$op}= {$from})"; // The below produces ORDER BY cl_sortkey, cl_from, possibly with DESC added to each of them $this->addWhereRange('cl_sortkey', $dir, null, null); $this->addWhereRange('cl_from', $dir, null, null); } else { if ($params['startsortkeyprefix'] !== null) { $startsortkey = Collation::singleton()->getSortkey($params['startsortkeyprefix']); } elseif ($params['starthexsortkey'] !== null) { if (!$this->validateHexSortkey($params['starthexsortkey'])) { $this->dieUsage('The starthexsortkey provided is not valid', 'bad_starthexsortkey'); } $startsortkey = pack('H*', $params['starthexsortkey']); } else { if ($params['startsortkey'] !== null) { $this->logFeatureUsage('list=categorymembers&cmstartsortkey'); } $startsortkey = $params['startsortkey']; } if ($params['endsortkeyprefix'] !== null) { $endsortkey = Collation::singleton()->getSortkey($params['endsortkeyprefix']); } elseif ($params['endhexsortkey'] !== null) { if (!$this->validateHexSortkey($params['endhexsortkey'])) { $this->dieUsage('The endhexsortkey provided is not valid', 'bad_endhexsortkey'); } $endsortkey = pack('H*', $params['endhexsortkey']); } else { if ($params['endsortkey'] !== null) { $this->logFeatureUsage('list=categorymembers&cmendsortkey'); } $endsortkey = $params['endsortkey']; } // The below produces ORDER BY cl_sortkey, cl_from, possibly with DESC added to each of them $this->addWhereRange('cl_sortkey', $dir, $startsortkey, $endsortkey); $this->addWhereRange('cl_from', $dir, null, null); } $this->addOption('USE INDEX', 'cl_sortkey'); } $this->addWhere('cl_from=page_id'); $limit = $params['limit']; $this->addOption('LIMIT', $limit + 1); if ($params['sort'] == 'sortkey') { // Run a separate SELECT query for each value of cl_type. // This is needed because cl_type is an enum, and MySQL has // inconsistencies between ORDER BY cl_type and // WHERE cl_type >= 'foo' making proper paging impossible // and unindexed. $rows = array(); $first = true; foreach ($queryTypes as $type) { $extraConds = array('cl_type' => $type); if ($first && $contWhere) { // Continuation condition. Only added to the // first query, otherwise we'll skip things $extraConds[] = $contWhere; } $res = $this->select(__METHOD__, array('where' => $extraConds)); $rows = array_merge($rows, iterator_to_array($res)); if (count($rows) >= $limit + 1) { break; } $first = false; } } else { // Sorting by timestamp // No need to worry about per-type queries because we // aren't sorting or filtering by type anyway $res = $this->select(__METHOD__); $rows = iterator_to_array($res); } $result = $this->getResult(); $count = 0; foreach ($rows as $row) { if (++$count > $limit) { // We've reached the one extra which shows that there are // additional pages to be had. Stop here... // @todo Security issue - if the user has no right to view next // title, it will still be shown if ($params['sort'] == 'timestamp') { $this->setContinueEnumParameter('continue', "{$row->cl_timestamp}|{$row->cl_from}"); } else { $sortkey = bin2hex($row->cl_sortkey); $this->setContinueEnumParameter('continue', "{$row->cl_type}|{$sortkey}|{$row->cl_from}"); } break; } // Since domas won't tell anyone what he told long ago, apply // cmnamespace here. This means the query may return 0 actual // results, but on the other hand it could save returning 5000 // useless results to the client. ~~~~ if (count($miser_ns) && !in_array($row->page_namespace, $miser_ns)) { continue; } if (is_null($resultPageSet)) { $vals = array(ApiResult::META_TYPE => 'assoc'); if ($fld_ids) { $vals['pageid'] = intval($row->page_id); } if ($fld_title) { $title = Title::makeTitle($row->page_namespace, $row->page_title); ApiQueryBase::addTitleInfo($vals, $title); } if ($fld_sortkey) { $vals['sortkey'] = bin2hex($row->cl_sortkey); } if ($fld_sortkeyprefix) { $vals['sortkeyprefix'] = $row->cl_sortkey_prefix; } if ($fld_type) { $vals['type'] = $row->cl_type; } if ($fld_timestamp) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->cl_timestamp); } $fit = $result->addValue(array('query', $this->getModuleName()), null, $vals); if (!$fit) { if ($params['sort'] == 'timestamp') { $this->setContinueEnumParameter('continue', "{$row->cl_timestamp}|{$row->cl_from}"); } else { $sortkey = bin2hex($row->cl_sortkey); $this->setContinueEnumParameter('continue', "{$row->cl_type}|{$sortkey}|{$row->cl_from}"); } break; } } else { $resultPageSet->processDbRow($row); } } if (is_null($resultPageSet)) { $result->addIndexedTagName(array('query', $this->getModuleName()), 'cm'); } }
?> " /> </td> <td> <?php echo CHtml::link(CHtml::encode($model->SCHEMA_NAME), Yii::app()->createUrl('schema/' . urlencode($model->SCHEMA_NAME))); ?> </td> <td class="count"> <?php echo $model->tableCount; ?> </td> <td> <dfn class="collation" title="<?php echo Collation::getDefinition($model->DEFAULT_COLLATION_NAME); ?> "> <?php echo $model->DEFAULT_COLLATION_NAME; ?> </dfn> </td> <td> <?php echo Html::icon('privileges', 16, true, 'core.privileges'); ?> </td> <td> <?php if (Yii::app()->user->privileges->checkSchema($model->SCHEMA_NAME, 'ALTER')) {
/** * Move a title to a new location * * @param Title $nt The new title * @param bool $auth Indicates whether $wgUser's permissions * should be checked * @param string $reason The reason for the move * @param bool $createRedirect Whether to create a redirect from the old title to the new title. * Ignored if the user doesn't have the suppressredirect right. * @return array|bool True on success, getUserPermissionsErrors()-like array on failure */ public function moveTo(&$nt, $auth = true, $reason = '', $createRedirect = true) { global $wgUser; $err = $this->isValidMoveOperation($nt, $auth, $reason); if (is_array($err)) { // Auto-block user's IP if the account was "hard" blocked $wgUser->spreadAnyEditBlock(); return $err; } // Check suppressredirect permission if ($auth && !$wgUser->isAllowed('suppressredirect')) { $createRedirect = true; } wfRunHooks('TitleMove', array($this, $nt, $wgUser)); // If it is a file, move it first. // It is done before all other moving stuff is done because it's hard to revert. $dbw = wfGetDB(DB_MASTER); if ($this->getNamespace() == NS_FILE) { $file = wfLocalFile($this); if ($file->exists()) { $status = $file->move($nt); if (!$status->isOk()) { return $status->getErrorsArray(); } } // Clear RepoGroup process cache RepoGroup::singleton()->clearCache($this); RepoGroup::singleton()->clearCache($nt); # clear false negative cache } $dbw->begin(__METHOD__); # If $file was a LocalFile, its transaction would have closed our own. $pageid = $this->getArticleID(self::GAID_FOR_UPDATE); $protected = $this->isProtected(); // Do the actual move $this->moveToInternal($nt, $reason, $createRedirect); // Refresh the sortkey for this row. Be careful to avoid resetting // cl_timestamp, which may disturb time-based lists on some sites. $prefixes = $dbw->select('categorylinks', array('cl_sortkey_prefix', 'cl_to'), array('cl_from' => $pageid), __METHOD__); foreach ($prefixes as $prefixRow) { $prefix = $prefixRow->cl_sortkey_prefix; $catTo = $prefixRow->cl_to; $dbw->update('categorylinks', array('cl_sortkey' => Collation::singleton()->getSortKey($nt->getCategorySortkey($prefix)), 'cl_timestamp=cl_timestamp'), array('cl_from' => $pageid, 'cl_to' => $catTo), __METHOD__); } $redirid = $this->getArticleID(); if ($protected) { # Protect the redirect title as the title used to be... $dbw->insertSelect('page_restrictions', 'page_restrictions', array('pr_page' => $redirid, 'pr_type' => 'pr_type', 'pr_level' => 'pr_level', 'pr_cascade' => 'pr_cascade', 'pr_user' => 'pr_user', 'pr_expiry' => 'pr_expiry'), array('pr_page' => $pageid), __METHOD__, array('IGNORE')); # Update the protection log $log = new LogPage('protect'); $comment = wfMessage('prot_1movedto2', $this->getPrefixedText(), $nt->getPrefixedText())->inContentLanguage()->text(); if ($reason) { $comment .= wfMessage('colon-separator')->inContentLanguage()->text() . $reason; } // @todo FIXME: $params? $logId = $log->addEntry('move_prot', $nt, $comment, array($this->getPrefixedText()), $wgUser); // reread inserted pr_ids for log relation $insertedPrIds = $dbw->select('page_restrictions', 'pr_id', array('pr_page' => $redirid), __METHOD__); $logRelationsValues = array(); foreach ($insertedPrIds as $prid) { $logRelationsValues[] = $prid->pr_id; } $log->addRelations('pr_id', $logRelationsValues, $logId); } // Update *_from_namespace fields as needed if ($this->getNamespace() != $nt->getNamespace()) { $dbw->update('pagelinks', array('pl_from_namespace' => $nt->getNamespace()), array('pl_from' => $pageid), __METHOD__); $dbw->update('templatelinks', array('tl_from_namespace' => $nt->getNamespace()), array('tl_from' => $pageid), __METHOD__); $dbw->update('imagelinks', array('il_from_namespace' => $nt->getNamespace()), array('il_from' => $pageid), __METHOD__); } # Update watchlists $oldtitle = $this->getDBkey(); $newtitle = $nt->getDBkey(); $oldsnamespace = MWNamespace::getSubject($this->getNamespace()); $newsnamespace = MWNamespace::getSubject($nt->getNamespace()); if ($oldsnamespace != $newsnamespace || $oldtitle != $newtitle) { WatchedItem::duplicateEntries($this, $nt); } $dbw->commit(__METHOD__); wfRunHooks('TitleMoveComplete', array(&$this, &$nt, &$wgUser, $pageid, $redirid, $reason)); return true; }
<td> <?php echo $column->COLUMN_NAME; ?> </td> <td> <?php echo $column->COLUMN_TYPE; ?> </td> <td> <?php if (!is_null($column->COLLATION_NAME)) { ?> <dfn class="collation" title="<?php echo Collation::getDefinition($column->COLLATION_NAME); ?> "> <?php echo $column->COLLATION_NAME; ?> </dfn> <?php } ?> </td> <td> <?php echo Yii::t('core', strtolower($column->IS_NULLABLE)); ?> </td>
/** * Returns the query string for all options which need to be saved. * * @return string */ private function getSaveDefinition() { $sql = ''; $comma = ''; if ($this->TABLE_NAME !== @$this->originalAttributes['TABLE_NAME'] && !$this->getIsNewRecord()) { //@todo(mburtscher): Privileges are not copied automatically!!! $sql .= "\n\t" . 'RENAME ' . self::$db->quoteTableName($this->TABLE_NAME); $comma = ','; } if ($this->TABLE_COLLATION !== @$this->originalAttributes['TABLE_COLLATION']) { $sql .= $comma . "\n\t" . 'CHARACTER SET ' . Collation::getCharacterSet($this->TABLE_COLLATION) . ' COLLATE ' . $this->TABLE_COLLATION; $comma = ','; } if ($this->comment !== @$this->originalAttributes['comment']) { $sql .= $comma . "\n\t" . 'COMMENT ' . self::$db->quoteValue($this->comment); $comma = ','; } if ($this->ENGINE !== @$this->originalAttributes['ENGINE']) { $sql .= $comma . "\n\t" . 'ENGINE ' . $this->ENGINE; $comma = ','; } if ($this->optionChecksum !== $this->originalOptionChecksum) { $sql .= $comma . "\n\t" . 'CHECKSUM ' . $this->optionChecksum; $comma = ','; } if ($this->optionPackKeys !== $this->originalOptionPackKeys) { $sql .= $comma . "\n\t" . 'PACK_KEYS ' . $this->optionPackKeys; $comma = ','; } if ($this->optionDelayKeyWrite !== $this->originalOptionDelayKeyWrite) { $sql .= $comma . "\n\t" . 'DELAY_KEY_WRITE ' . $this->optionDelayKeyWrite; } return $sql; }
public function execute() { global $wgCategoryCollation; $dbw = $this->getDB( DB_MASTER ); $force = $this->getOption( 'force' ); $dryRun = $this->getOption( 'dry-run' ); $verboseStats = $this->getOption( 'verbose-stats' ); if ( $this->hasOption( 'target-collation' ) ) { $collationName = $this->getOption( 'target-collation' ); $collation = Collation::factory( $collationName ); } else { $collationName = $wgCategoryCollation; $collation = Collation::singleton(); } // Collation sanity check: in some cases the constructor will work, // but this will raise an exception, breaking all category pages $collation->getFirstLetter( 'MediaWiki' ); $options = array( 'LIMIT' => self::BATCH_SIZE, 'ORDER BY' => 'cl_to, cl_type, cl_from', 'STRAIGHT_JOIN', ); if ( $force || $dryRun ) { $collationConds = array(); } else { if ( $this->hasOption( 'previous-collation' ) ) { $collationConds['cl_collation'] = $this->getOption( 'previous-collation' ); } else { $collationConds = array( 0 => 'cl_collation != ' . $dbw->addQuotes( $collationName ) ); } $count = $dbw->estimateRowCount( 'categorylinks', '*', $collationConds, __METHOD__ ); // Improve estimate if feasible if ( $count < 1000000 ) { $count = $dbw->selectField( 'categorylinks', 'COUNT(*)', $collationConds, __METHOD__ ); } if ( $count == 0 ) { $this->output( "Collations up-to-date.\n" ); return; } $this->output( "Fixing collation for $count rows.\n" ); } $count = 0; $batchCount = 0; $batchConds = array(); do { $this->output( "Selecting next " . self::BATCH_SIZE . " rows..." ); $res = $dbw->select( array( 'categorylinks', 'page' ), array( 'cl_from', 'cl_to', 'cl_sortkey_prefix', 'cl_collation', 'cl_sortkey', 'cl_type', 'page_namespace', 'page_title' ), array_merge( $collationConds, $batchConds, array( 'cl_from = page_id' ) ), __METHOD__, $options ); $this->output( " processing..." ); if ( !$dryRun ) { $dbw->begin( __METHOD__ ); } foreach ( $res as $row ) { $title = Title::newFromRow( $row ); if ( !$row->cl_collation ) { # This is an old-style row, so the sortkey needs to be # converted. if ( $row->cl_sortkey == $title->getText() || $row->cl_sortkey == $title->getPrefixedText() ) { $prefix = ''; } else { # Custom sortkey, use it as a prefix $prefix = $row->cl_sortkey; } } else { $prefix = $row->cl_sortkey_prefix; } # cl_type will be wrong for lots of pages if cl_collation is 0, # so let's update it while we're here. if ( $title->getNamespace() == NS_CATEGORY ) { $type = 'subcat'; } elseif ( $title->getNamespace() == NS_FILE ) { $type = 'file'; } else { $type = 'page'; } $newSortKey = $collation->getSortKey( $title->getCategorySortkey( $prefix ) ); if ( $verboseStats ) { $this->updateSortKeySizeHistogram( $newSortKey ); } if ( !$dryRun ) { $dbw->update( 'categorylinks', array( 'cl_sortkey' => $newSortKey, 'cl_sortkey_prefix' => $prefix, 'cl_collation' => $collationName, 'cl_type' => $type, 'cl_timestamp = cl_timestamp', ), array( 'cl_from' => $row->cl_from, 'cl_to' => $row->cl_to ), __METHOD__ ); } } if ( !$dryRun ) { $dbw->commit( __METHOD__ ); } if ( $row ) { $batchConds = array( $this->getBatchCondition( $row ) ); } $count += $res->numRows(); $this->output( "$count done.\n" ); if ( !$dryRun && ++$batchCount % self::SYNC_INTERVAL == 0 ) { $this->output( "Waiting for slaves ... " ); wfWaitForSlaves(); $this->output( "done\n" ); } } while ( $res->numRows() == self::BATCH_SIZE ); $this->output( "$count rows processed\n" ); if ( $verboseStats ) { $this->output( "\n" ); $this->showSortKeySizeHistogram(); } }
/** * Updates a table. */ public function actionUpdate() { $this->layout = false; $isSubmitted = false; $sql = false; $table = Table::model()->findByPk(array('TABLE_SCHEMA' => $this->schema, 'TABLE_NAME' => $this->table)); if (isset($_POST['Table'])) { $table->attributes = $_POST['Table']; $sql = $table->save(); if ($sql) { $isSubmitted = true; } } $collations = Collation::model()->findAll(array('order' => 'COLLATION_NAME', 'select' => 'COLLATION_NAME, CHARACTER_SET_NAME AS collationGroup')); CHtml::generateRandomIdPrefix(); $this->render('form', array('table' => $table, 'collations' => $collations, 'storageEngines' => StorageEngine::getSupportedEngines(), 'isSubmitted' => $isSubmitted, 'sql' => $sql)); }
/** * @param User $user * @param string $reason * @param bool $createRedirect * @return Status */ public function move(User $user, $reason, $createRedirect) { global $wgCategoryCollation; Hooks::run('TitleMove', array($this->oldTitle, $this->newTitle, $user)); // If it is a file, move it first. // It is done before all other moving stuff is done because it's hard to revert. $dbw = wfGetDB(DB_MASTER); if ($this->oldTitle->getNamespace() == NS_FILE) { $file = wfLocalFile($this->oldTitle); $file->load(File::READ_LATEST); if ($file->exists()) { $status = $file->move($this->newTitle); if (!$status->isOk()) { return $status; } } // Clear RepoGroup process cache RepoGroup::singleton()->clearCache($this->oldTitle); RepoGroup::singleton()->clearCache($this->newTitle); # clear false negative cache } $dbw->begin(__METHOD__); # If $file was a LocalFile, its transaction would have closed our own. $pageid = $this->oldTitle->getArticleID(Title::GAID_FOR_UPDATE); $protected = $this->oldTitle->isProtected(); // Do the actual move $this->moveToInternal($user, $this->newTitle, $reason, $createRedirect); // Refresh the sortkey for this row. Be careful to avoid resetting // cl_timestamp, which may disturb time-based lists on some sites. // @todo This block should be killed, it's duplicating code // from LinksUpdate::getCategoryInsertions() and friends. $prefixes = $dbw->select('categorylinks', array('cl_sortkey_prefix', 'cl_to'), array('cl_from' => $pageid), __METHOD__); if ($this->newTitle->getNamespace() == NS_CATEGORY) { $type = 'subcat'; } elseif ($this->newTitle->getNamespace() == NS_FILE) { $type = 'file'; } else { $type = 'page'; } foreach ($prefixes as $prefixRow) { $prefix = $prefixRow->cl_sortkey_prefix; $catTo = $prefixRow->cl_to; $dbw->update('categorylinks', array('cl_sortkey' => Collation::singleton()->getSortKey($this->newTitle->getCategorySortkey($prefix)), 'cl_collation' => $wgCategoryCollation, 'cl_type' => $type, 'cl_timestamp=cl_timestamp'), array('cl_from' => $pageid, 'cl_to' => $catTo), __METHOD__); } $redirid = $this->oldTitle->getArticleID(); if ($protected) { # Protect the redirect title as the title used to be... $dbw->insertSelect('page_restrictions', 'page_restrictions', array('pr_page' => $redirid, 'pr_type' => 'pr_type', 'pr_level' => 'pr_level', 'pr_cascade' => 'pr_cascade', 'pr_user' => 'pr_user', 'pr_expiry' => 'pr_expiry'), array('pr_page' => $pageid), __METHOD__, array('IGNORE')); // Build comment for log $comment = wfMessage('prot_1movedto2', $this->oldTitle->getPrefixedText(), $this->newTitle->getPrefixedText())->inContentLanguage()->text(); if ($reason) { $comment .= wfMessage('colon-separator')->inContentLanguage()->text() . $reason; } // reread inserted pr_ids for log relation $insertedPrIds = $dbw->select('page_restrictions', 'pr_id', array('pr_page' => $redirid), __METHOD__); $logRelationsValues = array(); foreach ($insertedPrIds as $prid) { $logRelationsValues[] = $prid->pr_id; } // Update the protection log $logEntry = new ManualLogEntry('protect', 'move_prot'); $logEntry->setTarget($this->newTitle); $logEntry->setComment($comment); $logEntry->setPerformer($user); $logEntry->setParameters(array('4::oldtitle' => $this->oldTitle->getPrefixedText())); $logEntry->setRelations(array('pr_id' => $logRelationsValues)); $logId = $logEntry->insert(); $logEntry->publish($logId); } // Update *_from_namespace fields as needed if ($this->oldTitle->getNamespace() != $this->newTitle->getNamespace()) { $dbw->update('pagelinks', array('pl_from_namespace' => $this->newTitle->getNamespace()), array('pl_from' => $pageid), __METHOD__); $dbw->update('templatelinks', array('tl_from_namespace' => $this->newTitle->getNamespace()), array('tl_from' => $pageid), __METHOD__); $dbw->update('imagelinks', array('il_from_namespace' => $this->newTitle->getNamespace()), array('il_from' => $pageid), __METHOD__); } # Update watchlists $oldtitle = $this->oldTitle->getDBkey(); $newtitle = $this->newTitle->getDBkey(); $oldsnamespace = MWNamespace::getSubject($this->oldTitle->getNamespace()); $newsnamespace = MWNamespace::getSubject($this->newTitle->getNamespace()); if ($oldsnamespace != $newsnamespace || $oldtitle != $newtitle) { WatchedItem::duplicateEntries($this->oldTitle, $this->newTitle); } $dbw->commit(__METHOD__); Hooks::run('TitleMoveComplete', array(&$this->oldTitle, &$this->newTitle, &$user, $pageid, $redirid, $reason)); return Status::newGood(); }
/** * Test correct first letter is fetched. * * @param $collation String Collation name (aka uca-en) * @param $string String String to get first letter of * @param $firstLetter String Expected first letter. * * @dataProvider firstLetterProvider */ function testGetFirstLetter($collation, $string, $firstLetter) { $col = Collation::factory($collation); $this->assertEquals($firstLetter, $col->getFirstLetter($string)); }
/** * Tests to get character set name from collation name. */ public function testGetCharset() { // Get Charset for utf8_unicode_ci $this->assertEquals('utf8', Collation::getCharacterSet('utf8_unicode_ci')); }
/** * Get an array of category insertions * * @param array $existing Mapping existing category names to sort keys. If both * match a link in $this, the link will be omitted from the output * * @return array */ private function getCategoryInsertions($existing = array()) { global $wgContLang, $wgCategoryCollation; $diffs = array_diff_assoc($this->mCategories, $existing); $arr = array(); foreach ($diffs as $name => $prefix) { $nt = Title::makeTitleSafe(NS_CATEGORY, $name); $wgContLang->findVariantLink($name, $nt, true); if ($this->mTitle->getNamespace() == NS_CATEGORY) { $type = 'subcat'; } elseif ($this->mTitle->getNamespace() == NS_FILE) { $type = 'file'; } else { $type = 'page'; } # Treat custom sortkeys as a prefix, so that if multiple # things are forced to sort as '*' or something, they'll # sort properly in the category rather than in page_id # order or such. $sortkey = Collation::singleton()->getSortKey($this->mTitle->getCategorySortkey($prefix)); $arr[] = array('cl_from' => $this->mId, 'cl_to' => $name, 'cl_sortkey' => $sortkey, 'cl_timestamp' => $this->mDb->timestamp(), 'cl_sortkey_prefix' => $prefix, 'cl_collation' => $wgCategoryCollation, 'cl_type' => $type); } return $arr; }
<?php CHtml::generateRandomIdPrefix(); if (!$schema->isNewRecord && $isSubmitted) { ?> <script type="text/javascript"> var idPrefix = '<?php echo CHtml::$idPrefix; ?> '; var row = $('#' + idPrefix).closest("tr").prev(); row.find("td dfn.collation").html("<?php echo $schema->DEFAULT_COLLATION_NAME; ?> ").attr("title", "<?php echo Collation::getDefinition($schema->DEFAULT_COLLATION_NAME); ?> "); $('#' + idPrefix).parent().slideUp(500, function() { $('#' + idPrefix).parents("tr").remove(); }); Notification.add('success', '<?php echo Yii::t('core', 'successEditSchema', array('{schema}' => $schema->SCHEMA_NAME)); ?> ', null, <?php echo CJSON::encode($sql); ?> ); </script> <?php }