/** * setVarById * * used for saving new variable value, logging changes and update city_list * values * * Note that this function will return false and not do any updates if * wgWikicitiesReadOnly is true. * * @access public * @author eloy@wikia * @static * * @param integer $cv_variable_id variable id in city_variables_pool * @param integer $city_id wiki id in city list * @param mixed $value new value for variable * @param string $reason optional extra reason text * * @throws WikiFactoryDuplicateWgServer * @return boolean: transaction status */ public static function setVarById($cv_variable_id, $city_id, $value, $reason = null) { global $wgWikicitiesReadOnly; if (!self::isUsed()) { Wikia::log(__METHOD__, "", "WikiFactory is not used."); return false; } if ($wgWikicitiesReadOnly) { Wikia::log(__METHOD__, "", "wgWikicitiesReadOnly mode. Skipping update."); return false; } global $wgUser; if (empty($cv_variable_id) || empty($city_id)) { return; } wfProfileIn(__METHOD__); $dbw = self::db(DB_MASTER); $bStatus = true; $dbw->begin(); try { /** * use master connection for changing variables */ $variable = self::loadVariableFromDB($cv_variable_id, false, $city_id, true); $oldValue = isset($variable->cv_value) ? $variable->cv_value : false; /** * delete old value */ $dbw->delete("city_variables", ["cv_variable_id" => $cv_variable_id, "cv_city_id" => $city_id], __METHOD__); /** * insert new one */ $dbw->insert("city_variables", ["cv_variable_id" => $cv_variable_id, "cv_city_id" => $city_id, "cv_value" => serialize($value)], __METHOD__); wfProfileIn(__METHOD__ . "-changelog"); # if reason was passed non-null, prepare a string for sprintf, else a zero-len string $reason_extra = !empty($reason) ? " (reason: " . (string) $reason . ")" : ''; $needPreformat = in_array($variable->cv_variable_type, ['struct', 'array', 'hash', 'text']); if (isset($variable->cv_value)) { if (!$needPreformat) { $message = "Variable <strong>%s</strong> changed value from <strong>%s</strong> to <strong>%s</strong>%s"; } else { $message = '<div>Variable <strong>%s</strong> changed value </div>' . '<div class="v1"><strong>Old value:</strong><pre>%s</pre></div> ' . '<div class="v2"><strong>New value:</strong><pre>%s</pre></div>' . '<div class="clear">%s</div></div>'; } self::log(self::LOG_VARIABLE, sprintf($message, $variable->cv_name, var_export(unserialize($variable->cv_value), true), var_export($value, true), $reason_extra), $city_id, $cv_variable_id); } else { if (!$needPreformat) { $message = 'Variable <strong>%s</strong> set value: <strong>%s</strong> %s'; } else { $message = 'Variable <strong>%s</strong> set value: <pre>%s</pre> %s'; } self::log(self::LOG_VARIABLE, sprintf($message, $variable->cv_name, var_export($value, true), $reason_extra), $city_id, $cv_variable_id); } wfProfileOut(__METHOD__ . "-changelog"); /** * check if variable is connected with city_list (for example * city_language or city_url) and do some basic validation */ wfProfileIn(__METHOD__ . "-citylist"); wfRunHooks('WikiFactoryChanged', [$variable->cv_name, $city_id, $value]); switch ($variable->cv_name) { case "wgServer": case "wgScriptPath": /** * city_url is combination of $wgServer & $wgScriptPath */ /** * ...so get the other variable */ if ($variable->cv_name === "wgServer") { $tmp = self::getVarValueByName("wgScriptPath", $city_id); $server = is_null($value) ? "" : $value; $script_path = is_null($tmp) ? "/" : $tmp . "/"; } else { $tmp = self::getVarValueByName("wgServer", $city_id); $server = is_null($tmp) ? "" : $tmp; $script_path = is_null($value) ? "/" : $value . "/"; } $city_url = $server . $script_path; try { $dbw->update(self::table("city_list"), ["city_url" => $city_url], ["city_id" => $city_id], __METHOD__); } catch (DBQueryError $e) { if (preg_match("/Duplicate entry '[^']*' for key 'urlidx'/", $e->error)) { $res = $dbw->selectRow(self::table("city_list"), "city_id", ["city_url" => $city_url], __METHOD__); if (isset($res->city_id)) { $exc = new WikiFactoryDuplicateWgServer($city_id, $city_url, $res->city_id); Wikia::log(__METHOD__, "", $exc->getMessage()); $dbw->rollback(); throw $exc; } } throw $e; } break; case "wgLanguageCode": #--- city_lang $dbw->update(self::table("city_list"), ["city_lang" => $value], ["city_id" => $city_id], __METHOD__); #--- update language tags $tags = new WikiFactoryTags($city_id); $tags->removeTagsByName($oldValue); $tags->addTagsByName($value); break; case "wgSitename": #--- city_title $dbw->update(self::table("city_list"), ["city_title" => $value], ["city_id" => $city_id], __METHOD__); break; case "wgDBname": #--- city_dbname $dbw->update(self::table("city_list"), ["city_dbname" => $value], ["city_id" => $city_id], __METHOD__); break; case "wgDBcluster": /** * city_cluster * * city_cluster = null for first cluster * @todo handle deleting values of this variable */ $dbw->update(self::table("city_list"), ["city_cluster" => $value], ["city_id" => $city_id], __METHOD__); break; case 'wgMetaNamespace': case 'wgMetaNamespaceTalk': #--- these cannot contain spaces! if (strpos($value, ' ') !== false) { $value = str_replace(' ', '_', $value); $dbw->update(self::table('city_variables'), ['cv_value' => serialize($value)], ['cv_city_id' => $city_id, 'cv_variable_id' => $variable->cv_id], __METHOD__); } break; } wfProfileOut(__METHOD__ . "-citylist"); $dbw->commit(); $aHookParams = ['city_id' => $city_id, 'cv_name' => $variable->cv_name, 'cv_value' => $value]; wfRunHooks('WikiFactoryChangeCommitted', [$aHookParams]); } catch (DBQueryError $e) { Wikia::log(__METHOD__, "", "Database error, cannot write variable."); $dbw->rollback(); $bStatus = false; // rethrowing here does not seem to be right. Callers expect success or failure // as result value, not DBQueryError exception // throw $e; } self::clearCache($city_id); global $wgMemc; $wgMemc->delete(self::getVarValueKey($city_id, $variable->cv_id)); wfProfileOut(__METHOD__); return $bStatus; }
/** * main entry point, create wiki with given parameters * * @throw CreateWikiException an exception with status of operation set */ public function create() { global $wgExternalSharedDB, $wgSharedDB, $wgUser; $then = microtime(true); // Set this flag to ensure that all select operations go against master // Slave lag can cause random errors during wiki creation process global $wgForceMasterDatabase; $wgForceMasterDatabase = true; wfProfileIn(__METHOD__); if (wfReadOnly()) { wfProfileOut(__METHOD__); throw new CreateWikiException('DB is read only', self::ERROR_READONLY); } // check founder if ($this->mFounder->isAnon()) { wfProfileOut(__METHOD__); throw new CreateWikiException('Founder is anon', self::ERROR_USER_IN_ANON); } // check executables $status = $this->checkExecutables(); if ($status != 0) { wfProfileOut(__METHOD__); throw new CreateWikiException('checkExecutables() failed', $status); } // check domains $status = $this->checkDomain(); if ($status != 0) { wfProfileOut(__METHOD__); throw new CreateWikiException('Check domain failed', $status); } // prepare all values needed for creating wiki $this->prepareValues(); // prevent domain to be registered more than once if (!AutoCreateWiki::lockDomain($this->mDomain)) { wfProfileOut(__METHOD__); throw new CreateWikiException('Domain name taken', self::ERROR_DOMAIN_NAME_TAKEN); } // start counting time $this->mCurrTime = wfTime(); // check and create database $this->mDBw = wfGetDB(DB_MASTER, array(), $wgExternalSharedDB); # central /// // local database handled is handler to cluster we create new wiki. // It doesn't have to be the same like wikifactory cluster or db cluster // where Special:CreateWiki exists. // // @todo do not use hardcoded name, code below is only for test // // set $activeCluster to false if you want to create wikis on first // cluster // $this->mClusterDB = self::ACTIVE_CLUSTER ? "wikicities_" . self::ACTIVE_CLUSTER : "wikicities"; $this->mNewWiki->dbw = wfGetDB(DB_MASTER, array(), $this->mClusterDB); // database handler, old $dbwTarget // check if database is creatable // @todo move all database creation checkers to canCreateDatabase if (!$this->canCreateDatabase()) { wfProfileOut(__METHOD__); throw new CreateWikiException('DB exists - ' . $this->mNewWiki->dbname, self::ERROR_DATABASE_ALREADY_EXISTS); } else { $this->mNewWiki->dbw->query(sprintf("CREATE DATABASE `%s`", $this->mNewWiki->dbname)); wfDebugLog("createwiki", "Database {$this->mNewWiki->dbname} created\n", true); } /** * create position in wiki.factory * (I like sprintf construction, so sue me) */ if (!$this->addToCityList()) { wfDebugLog("createwiki", __METHOD__ . ": Cannot set data in city_list table\n", true); wfProfileOut(__METHOD__); throw new CreateWikiException('Cannot add wiki to city_list', self::ERROR_DATABASE_WRITE_TO_CITY_LIST_BROKEN); } // set new city_id $this->mNewWiki->city_id = $this->mDBw->insertId(); if (empty($this->mNewWiki->city_id)) { wfProfileOut(__METHOD__); throw new CreateWikiException('Cannot set data in city_list table. city_id is empty after insert', self::ERROR_DATABASE_WIKI_FACTORY_TABLES_BROKEN); } wfDebugLog("createwiki", __METHOD__ . ": Row added added into city_list table, city_id = {$this->mNewWiki->city_id}\n", true); /** * add domain and www.domain to the city_domains table */ if (!$this->addToCityDomains()) { wfProfileOut(__METHOD__); throw new CreateWikiException('Cannot set data in city_domains table', self::ERROR_DATABASE_WRITE_TO_CITY_DOMAINS_BROKEN); } wfDebugLog("createwiki", __METHOD__ . ": Row added into city_domains table, city_id = {$this->mNewWiki->city_id}\n", true); /** * create image folder */ global $wgEnableSwiftFileBackend; if (empty($wgEnableSwiftFileBackend)) { wfMkdirParents("{$this->mNewWiki->images_dir}"); wfDebugLog("createwiki", __METHOD__ . ": Folder {$this->mNewWiki->images_dir} created\n", true); } // Force initialize uploader user from correct shared db $uploader = User::newFromName('CreateWiki script'); $uploader->getId(); $oldUser = $wgUser; $wgUser = $uploader; /** * wikifactory variables */ wfDebugLog("createwiki", __METHOD__ . ": Populating city_variables\n", true); $this->setWFVariables(); $tmpSharedDB = $wgSharedDB; $wgSharedDB = $this->mNewWiki->dbname; $this->mDBw->commit(__METHOD__); // commit shared DB changes /** * we got empty database created, now we have to create tables and * populate it with some default values */ wfDebugLog("createwiki", __METHOD__ . ": Creating tables in database\n", true); $this->mNewWiki->dbw = wfGetDB(DB_MASTER, array(), $this->mNewWiki->dbname); if (!$this->createTables()) { wfProfileOut(__METHOD__); throw new CreateWikiException('Creating tables not finished', self::ERROR_SQL_FILE_BROKEN); } /** * import language starter */ if (!$this->importStarter()) { wfProfileOut(__METHOD__); throw new CreateWikiException('Starter import failed', self::ERROR_SQL_FILE_BROKEN); } /** * making the wiki founder a sysop/bureaucrat */ wfDebugLog("createwiki", __METHOD__ . ": Create user sysop/bureaucrat for user: {$this->mNewWiki->founderId} \n", true); if (!$this->addUserToGroups()) { wfDebugLog("createwiki", __METHOD__ . ": Create user sysop/bureaucrat for user: {$this->mNewWiki->founderId} failed \n", true); } /** * init site_stats table (add empty row) */ $this->mNewWiki->dbw->insert("site_stats", array("ss_row_id" => "1"), __METHOD__); /** * copy default logo */ $res = ImagesService::uploadImageFromUrl(self::CREATEWIKI_LOGO, (object) ['name' => 'Wiki.png'], $uploader); if ($res['status'] === true) { wfDebugLog("createwiki", __METHOD__ . ": Default logo has been uploaded\n", true); } else { wfDebugLog("createwiki", __METHOD__ . ": Default logo has not been uploaded - " . print_r($res['errors'], true) . "\n", true); } /** * destroy connection to newly created database */ $this->waitForSlaves(__METHOD__); $wgSharedDB = $tmpSharedDB; $oHub = WikiFactoryHub::getInstance(); $oHub->setVertical($this->mNewWiki->city_id, $this->mNewWiki->vertical, "CW Setup"); wfDebugLog("createwiki", __METHOD__ . ": Wiki added to the vertical: {$this->mNewWiki->vertical} \n", true); for ($i = 0; $i < count($this->mNewWiki->categories); $i++) { $oHub->addCategory($this->mNewWiki->city_id, $this->mNewWiki->categories[$i]); wfDebugLog("createwiki", __METHOD__ . ": Wiki added to the category: {$this->mNewWiki->categories[$i]} \n", true); } /** * define wiki type */ $wiki_type = 'default'; /** * modify variables */ global $wgUniversalCreationVariables; if (!empty($wgUniversalCreationVariables) && !empty($wiki_type) && isset($wgUniversalCreationVariables[$wiki_type])) { $this->addCustomSettings(0, $wgUniversalCreationVariables[$wiki_type], "universal"); wfDebugLog("createwiki", __METHOD__ . ": Custom settings added for wiki_type: {$wiki_type} \n", true); } /** * set variables per language */ global $wgLangCreationVariables; $langCreationVar = isset($wgLangCreationVariables[$wiki_type]) ? $wgLangCreationVariables[$wiki_type] : $wgLangCreationVariables; $this->addCustomSettings($this->mNewWiki->language, $langCreationVar, "language"); wfDebugLog("createwiki", __METHOD__ . ": Custom settings added for wiki_type: {$wiki_type} and language: {$this->mNewWiki->language} \n", true); /** * set tags per language and per hub * @FIXME the switch is !@#$ creazy, but I didn't find a core function */ $tags = new WikiFactoryTags($this->mNewWiki->city_id); $langTag = $this->mNewWiki->language; if ($langTag !== 'en') { switch ($langTag) { case 'pt-br': $langTag = 'pt'; break; case 'zh-tw': case 'zh-hk': case 'zh-clas': case 'zh-class': case 'zh-classical': case 'zh-cn': case 'zh-hans': case 'zh-hant': case 'zh-min-': case 'zh-min-n': case 'zh-mo': case 'zh-sg': case 'zh-yue': $langTag = 'zh'; break; } $tags->addTagsByName($langTag); } /** * move main page -> this code exists in CreateWikiLocalJob - so it is not needed anymore */ /** * Unset database from mNewWiki, because database objects cannot be serialized from MW1.19 */ unset($this->mNewWiki->dbw); // Restore wgUser $wgUser = $oldUser; unset($oldUser); /** * Schedule an async task */ $creationTask = new \Wikia\Tasks\Tasks\CreateNewWikiTask(); $job_params = new stdClass(); foreach ($this->mNewWiki as $id => $value) { if (!is_object($value)) { $job_params->{$id} = $value; } } // BugId:15644 - I need to pass this to CreateWikiLocalJob::changeStarterContributions $job_params->sDbStarter = $this->sDbStarter; $task_id = (new \Wikia\Tasks\AsyncTaskList())->wikiId($this->mNewWiki->city_id)->prioritize()->add($creationTask->call('postCreationSetup', $job_params))->add($creationTask->call('maintenance', rtrim($this->mNewWiki->url, "/")))->queue(); wfDebugLog("createwiki", __METHOD__ . ": Local maintenance task added as {$task_id}\n", true); $this->info(__METHOD__ . ': done', ['task_id' => $task_id, 'took' => microtime(true) - $then]); wfProfileOut(__METHOD__); }
$lang = $row->city_lang; switch ( $lang ) { case 'zh-tw': case 'zh-hk': case 'zh-clas': case 'zh-class': case 'zh-cn': case 'zh-hans': case 'zh-hant': case 'zh-min-': case 'zh-min-n': case 'zh-mo': case 'zh-sg': case 'zh-yue': $lang = 'zh'; break; case 'pt-br': $lang = 'pt'; break; } /** * set this as tag */ $tags = new WikiFactoryTags( $row->city_id ); wfWaitForSlaves( 5 ); $tags->addTagsByName( $lang ); Wikia::log( "AddLangTag", false, "$hub added as tag in {$row->city_id}" ); }
foreach (explode("\n", $csv) as $line) { $tags = explode(",", $line); $city_id = array_shift($tags); $city_dbname = array_shift($tags); $city_cat = array_shift($tags); $city_url = array_shift($tags); /** * add category as tag */ $tags[] = $city_cat; /** * skip first row = labels */ if (!is_numeric($city_id)) { continue; } $wfTags = new WikiFactoryTags($city_id); $wfTags->removeTagsAll(); /** * first remove all tags */ foreach ($tags as $tag) { if (strlen($tag)) { $tag = str_replace(" ", "_", strtolower(trim($tag))); $ready[$tag]++; $wfTags->addTagsByName($tag); } } } ksort($ready); print_r($ready);
/** * doMassTag * * data is stored in: * $this->mMassTag * $this->mMassTagWikis * * @access private * @author uberfuzzy@wikia-inc.com * @note yes, i know this is HORRIBLY ineffecient, but I was going for RAD, not clean. */ private function doMassTag() { wfProfileIn(__METHOD__); $this->mMassTagWikis = explode("\n", $this->mMassTagWikis); global $wgOut; $msg = false; $added = 0; foreach ($this->mMassTagWikis as $dart_string) { if (empty($dart_string)) { continue; } $dart_parts = explode("/", $dart_string); if (count($dart_parts) < 2) { continue; } $db = ltrim($dart_parts[1], '_'); $wkid = WikiFactory::DBtoID($db); // $wgOut->addHTML("id={$wkid}<br/>"); #debug $added++; $oTag = new WikiFactoryTags($wkid); $oTag->addTagsByName($this->mMassTag); #$oTag->clearCache(); } $oTQ = new WikiFactoryTagsQuery(''); // no tag, because we're just using it to uncache $oTQ->clearCache(); $msg = "Added '{$this->mMassTag}' to {$added} wikis"; wfProfileOut(__METHOD__); return Wikia::successbox($msg); }
/** * setVarById * * used for saving new variable value, logging changes and update city_list * values * * Note that this function will return false and not do any updates if * wgWikicitiesReadOnly is true. * * @access public * @author eloy@wikia * @static * * @param integer $cv_variable_id variable id in city_variables_pool * @param integer $city_id wiki id in city list * @param mixed $value new value for variable * @param string $reason optional extra reason text * * @return boolean: transaction status */ public static function setVarById($cv_variable_id, $city_id, $value, $reason = null) { global $wgWikicitiesReadOnly; if (!self::isUsed()) { Wikia::log(__METHOD__, "", "WikiFactory is not used."); return false; } if ($wgWikicitiesReadOnly) { Wikia::log(__METHOD__, "", "wgWikicitiesReadOnly mode. Skipping update."); return false; } global $wgUser; if (empty($cv_variable_id) || empty($city_id)) { return; } wfProfileIn(__METHOD__); $dbw = self::db(DB_MASTER); $bStatus = true; $dbw->begin(); try { /** * use master connection for changing variables */ $variable = self::loadVariableFromDB($cv_variable_id, false, $city_id, true); $oldValue = isset($variable->cv_value) ? $variable->cv_value : false; /** * delete old value */ $dbw->delete("city_variables", array("cv_variable_id" => $cv_variable_id, "cv_city_id" => $city_id), __METHOD__); /** * insert new one */ $dbw->insert("city_variables", array("cv_variable_id" => $cv_variable_id, "cv_city_id" => $city_id, "cv_value" => serialize($value)), __METHOD__); wfProfileIn(__METHOD__ . "-changelog"); # if reason was passed non-null, prepare a string for sprintf, else a zero-len string $reason_extra = !empty($reason) ? " (reason: " . (string) $reason . ")" : ''; if (isset($variable->cv_value)) { self::log(self::LOG_VARIABLE, sprintf("Variable %s changed value from %s to %s%s", $variable->cv_name, var_export(unserialize($variable->cv_value), true), var_export($value, true), $reason_extra), $city_id, $cv_variable_id); } else { self::log(self::LOG_VARIABLE, sprintf("Variable %s set value: %s%s", $variable->cv_name, var_export($value, true), $reason_extra), $city_id, $cv_variable_id); } wfProfileOut(__METHOD__ . "-changelog"); /** * check if variable is connected with city_list (for example * city_language or city_url) and do some basic validation */ wfProfileIn(__METHOD__ . "-citylist"); wfRunHooks('WikiFactoryChanged', array($variable->cv_name, $city_id, $value)); switch ($variable->cv_name) { case "wgServer": case "wgScriptPath": /** * city_url is combination of $wgServer & $wgScriptPath */ /** * ...so get the other variable */ if ($variable->cv_name === "wgServer") { $tmp = self::getVarValueByName("wgScriptPath", $city_id); $server = is_null($value) ? "" : $value; $script_path = is_null($tmp) ? "/" : $tmp . "/"; } else { $tmp = self::getVarValueByName("wgServer", $city_id); $server = is_null($tmp) ? "" : $tmp; $script_path = is_null($value) ? "/" : $value . "/"; } $city_url = $server . $script_path; $dbw->update(self::table("city_list"), array("city_url" => $city_url), array("city_id" => $city_id), __METHOD__); /** * clear cache with old domain (stored in $oldValue) */ break; case "wgLanguageCode": #--- city_lang $dbw->update(self::table("city_list"), array("city_lang" => $value), array("city_id" => $city_id), __METHOD__); #--- update language tags $tags = new WikiFactoryTags($city_id); $tags->removeTagsByName($oldValue); $tags->addTagsByName($value); break; case "wgSitename": #--- city_title $dbw->update(self::table("city_list"), array("city_title" => $value), array("city_id" => $city_id), __METHOD__); break; case "wgDBname": #--- city_dbname $dbw->update(self::table("city_list"), array("city_dbname" => $value), array("city_id" => $city_id), __METHOD__); break; case "wgDBcluster": /** * city_cluster * * city_cluster = null for first cluster * @todo handle deleting values of this variable */ $dbw->update(self::table("city_list"), array("city_cluster" => $value), array("city_id" => $city_id), __METHOD__); break; case 'wgMetaNamespace': case 'wgMetaNamespaceTalk': #--- these cannot contain spaces! if (strpos($value, ' ') !== false) { $value = str_replace(' ', '_', $value); $dbw->update(self::table('city_variables'), array('cv_value' => serialize($value)), array('cv_city_id' => $city_id, 'cv_variable_id' => $variable->cv_id), __METHOD__); } break; } wfProfileOut(__METHOD__ . "-citylist"); $dbw->commit(); } catch (DBQueryError $e) { Wikia::log(__METHOD__, "", "Database error, cannot write variable."); $dbw->rollback(); $bStatus = false; throw $e; } self::clearCache($city_id); wfProfileOut(__METHOD__); return $bStatus; }
<?php /** * @package MediaWiki * @addtopackage maintenance * @author eloy@wikia * * move category to tags table * */ ini_set("include_path", dirname(__FILE__) . "/.."); require_once "commandLine.inc"; ini_set("include_path", dirname(__FILE__) . "/.."); require_once "commandLine.inc"; $dbr = WikiFactory::db(DB_SLAVE); $sth = $dbr->select(array("city_list"), array("*"), array("city_public" => 1), __METHOD__); while ($row = $dbr->fetchObject($sth)) { /** * get category for wiki */ $hub = WikiFactoryHub::getInstance()->getCategoryName($row->city_id); /** * set this as tag */ $tags = new WikiFactoryTags($row->city_id); $tags->addTagsByName($hub); Wikia::log("CatAsTag", false, "{$hub} added as tag in {$row->city_id}"); }
private function tagSelectedWikis($tagName, array $tagWikis) { global $wgCityId; if (!class_exists('WikiFactoryTags', true)) { return "WikiFactory extension must be enabled"; } if (!empty($tagName)) { foreach ($tagWikis as $wikiId) { $wikiTags = new WikiFactoryTags($wikiId); $wikiTags->addTagsByName($tagName); } $wikiFactoryUrl = Title::makeTitle(NS_SPECIAL, 'WikiFactory')->getFullUrl() . '/' . $wgCityId . '/tags/' . $tagName; $msg = count($tagWikis) . " wiki(s) tagged with tag: <a href=\"{$wikiFactoryUrl}\">{$tagName}</a>"; } else { $msg = "Empty tag name"; } return $msg; }
/** * main entry point, create wiki with given parameters * * @return integer status of operation, 0 for success, non 0 for error */ public function create() { global $wgWikiaLocalSettingsPath, $wgExternalSharedDB, $wgSharedDB, $wgUser; wfProfileIn(__METHOD__); if (wfReadOnly()) { wfProfileOut(__METHOD__); return self::ERROR_READONLY; } if (wfIsDBLightMode()) { wfProfileOut(__METHOD__); return self::ERROR_DBLIGHTMODE; } // check founder if ($this->mFounder->isAnon()) { wfProfileOut(__METHOD__); return self::ERROR_USER_IN_ANON; } // check executables $status = $this->checkExecutables(); if ($status != 0) { wfProfileOut(__METHOD__); return $status; } // check domains $status = $this->checkDomain(); if ($status != 0) { wfProfileOut(__METHOD__); return $status; } // prepare all values needed for creating wiki $this->prepareValues(); // prevent domain to be registered more than once if (!AutoCreateWiki::lockDomain($this->mDomain)) { wfProfileOut(__METHOD__); return self::ERROR_DOMAIN_NAME_TAKEN; } // start counting time $this->mCurrTime = wfTime(); $startTime = $this->mCurrTime; // check and create database $this->mDBw = wfGetDB(DB_MASTER, array(), $wgExternalSharedDB); # central /// // local database handled is handler to cluster we create new wiki. // It doesn't have to be the same like wikifactory cluster or db cluster // where Special:CreateWiki exists. // // @todo do not use hardcoded name, code below is only for test // // set $activeCluster to false if you want to create wikis on first // cluster // $clusterdb = self::ACTIVE_CLUSTER ? "wikicities_" . self::ACTIVE_CLUSTER : "wikicities"; $this->mNewWiki->dbw = wfGetDB(DB_MASTER, array(), $clusterdb); // database handler, old $dbwTarget // check if database is creatable // @todo move all database creation checkers to canCreateDatabase if (!$this->canCreateDatabase()) { wfDebugLog("createwiki", "Database {$this->mNewWiki->dbname} exists\n", true); wfProfileOut(__METHOD__); return self::ERROR_DATABASE_ALREADY_EXISTS; } else { $this->mNewWiki->dbw->query(sprintf("CREATE DATABASE `%s`", $this->mNewWiki->dbname)); wfDebugLog("createwiki", "Database {$this->mNewWiki->dbname} created\n", true); } /** * create position in wiki.factory * (I like sprintf construction, so sue me) */ if (!$this->addToCityList()) { wfDebugLog("createwiki", __METHOD__ . ": Cannot set data in city_list table\n", true); wfProfileOut(__METHOD__); return self::ERROR_DATABASE_WRITE_TO_CITY_LIST_BROKEN; } // set new city_id $this->mNewWiki->city_id = $this->mDBw->insertId(); if (empty($this->mNewWiki->city_id)) { wfDebugLog("createwiki", __METHOD__ . ": Cannot set data in city_list table. city_id is empty after insert\n", true); wfProfileOut(__METHOD__); return self::ERROR_DATABASE_WIKI_FACTORY_TABLES_BROKEN; } wfDebugLog("createwiki", __METHOD__ . ": Row added added into city_list table, city_id = {$this->mNewWiki->city_id}\n", true); /** * add domain and www.domain to the city_domains table */ if (!$this->addToCityDomains()) { wfDebugLog("createwiki", __METHOD__ . ": Cannot set data in city_domains table\n", true); wfProfileOut(__METHOD__); return self::ERROR_DATABASE_WRITE_TO_CITY_DOMAINS_BROKEN; } wfDebugLog("createwiki", __METHOD__ . ": Row added into city_domains table, city_id = {$this->mNewWiki->city_id}\n", true); /** * create image folder */ wfMkdirParents("{$this->mNewWiki->images_dir}"); wfDebugLog("createwiki", __METHOD__ . ": Folder {$this->mNewWiki->images_dir} created\n", true); /** * copy default logo & favicon */ wfMkdirParents("{$this->mNewWiki->images_logo}"); wfMkdirParents("{$this->mNewWiki->images_icon}"); if (file_exists(self::CREATEWIKI_LOGO)) { copy(self::CREATEWIKI_LOGO, "{$this->mNewWiki->images_logo}/Wiki.png"); wfDebugLog("createwiki", __METHOD__ . ": Default logo has been copied\n", true); } else { wfDebugLog("createwiki", __METHOD__ . ": Default logo has not been copied\n", true); } if (file_exists(self::CREATEWIKI_ICON)) { copy(self::CREATEWIKI_ICON, "{$this->mNewWiki->images_icon}/Favicon.ico"); wfDebugLog("createwiki", __METHOD__ . ": Default favicon has been copied\n", true); } else { wfDebugLog("createwiki", __METHOD__ . ": Default favicon has not been copied\n", true); } /** * wikifactory variables */ wfDebugLog("createwiki", __METHOD__ . ": Populating city_variables\n", true); $this->setWFVariables(); $tmpSharedDB = $wgSharedDB; $wgSharedDB = $this->mNewWiki->dbname; /** * we got empty database created, now we have to create tables and * populate it with some default values */ wfDebugLog("createwiki", __METHOD__ . ": Creating tables in database\n", true); $this->mNewWiki->dbw = wfGetDB(DB_MASTER, array(), $this->mNewWiki->dbname); if (!$this->createTables()) { wfDebugLog("createwiki", __METHOD__ . ": Creating tables not finished\n", true); wfProfileOut(__METHOD__); return self::ERROR_SQL_FILE_BROKEN; } /** * import language starter */ if (!$this->importStarter()) { wfProfileOut(__METHOD__); return self::ERROR_SQL_FILE_BROKEN; } /** * making the wiki founder a sysop/bureaucrat */ wfDebugLog("createwiki", __METHOD__ . ": Create user sysop/bureaucrat for user: {$this->mNewWiki->founderId} \n", true); if (!$this->addUserToGroups()) { wfDebugLog("createwiki", __METHOD__ . ": Create user sysop/bureaucrat for user: {$this->mNewWiki->founderId} failed \n", true); } /** * init site_stats table (add empty row) */ $this->mNewWiki->dbw->insert("site_stats", array("ss_row_id" => "1"), __METHOD__); /** * add local job */ $job_params = new stdClass(); foreach ($this->mNewWiki as $id => $value) { if (!is_object($value)) { $job_params->{$id} = $value; } } // BugId:15644 - I need to pass this to CreateWikiLocalJob::changeStarterContributions $job_params->sDbStarter = $this->sDbStarter; $localJob = new CreateWikiLocalJob(Title::newFromText(NS_MAIN, "Main"), $job_params); $localJob->WFinsert($this->mNewWiki->city_id, $this->mNewWiki->dbname); wfDebugLog("createwiki", __METHOD__ . ": New createWiki local job created \n", true); /** * destroy connection to newly created database */ $this->mNewWiki->dbw->commit(); wfDebugLog("createwiki", __METHOD__ . ": Database changes commited \n", true); $wgSharedDB = $tmpSharedDB; /** * set hub/category */ $oldUser = $wgUser; $wgUser = User::newFromName('CreateWiki script'); $oHub = WikiFactoryHub::getInstance(); $oHub->setCategory($this->mNewWiki->city_id, $this->mNewWiki->hub, "CW Setup"); wfDebugLog("createwiki", __METHOD__ . ": Wiki added to the category hub: {$this->mNewWiki->hub} \n", true); $wgUser = $oldUser; unset($oldUser); /** * define wiki type */ $wiki_type = !empty($this->mType) ? $this->mType : 'default'; /** * modify variables */ global $wgUniversalCreationVariables; if (!empty($wgUniversalCreationVariables) && !empty($wiki_type) && isset($wgUniversalCreationVariables[$wiki_type])) { $this->addCustomSettings(0, $wgUniversalCreationVariables[$wiki_type], "universal"); wfDebugLog("createwiki", __METHOD__ . ": Custom settings added for wiki_type: {$wiki_type} \n", true); } /** * set variables per language */ global $wgLangCreationVariables; $langCreationVar = isset($wgLangCreationVariables[$wiki_type]) ? $wgLangCreationVariables[$wiki_type] : $wgLangCreationVariables; $this->addCustomSettings($this->mNewWiki->language, $langCreationVar, "language"); wfDebugLog("createwiki", __METHOD__ . ": Custom settings added for wiki_type: {$wiki_type} and language: {$this->mNewWiki->language} \n", true); /** * set tags per language and per hub * @FIXME the switch is !@#$ creazy, but I didn't find a core function */ $tags = new WikiFactoryTags($this->mNewWiki->city_id); $langTag = $this->mNewWiki->language; if ($langTag !== 'en') { switch ($langTag) { case 'pt-br': $langTag = 'pt'; break; case 'zh-tw': case 'zh-hk': case 'zh-clas': case 'zh-class': case 'zh-classical': case 'zh-cn': case 'zh-hans': case 'zh-hant': case 'zh-min-': case 'zh-min-n': case 'zh-mo': case 'zh-sg': case 'zh-yue': $langTag = 'zh'; break; } $tags->addTagsByName($langTag); } $tags->addTagsByName($this->mNewWiki->hub); /** * move main page */ $cmd = sprintf("SERVER_ID=%d %s %s/maintenance/wikia/moveMain.php -t '%s' --conf %s", $this->mNewWiki->city_id, $this->mPHPbin, $this->mIP, $this->mNewWiki->sitename, $wgWikiaLocalSettingsPath); $output = wfShellExec($cmd); wfDebugLog("createwiki", __METHOD__ . ": Main page moved \n", true); /** * show congratulation message */ /** * Unset database from mNewWiki, because database objects cannot be serialized from MW1.19 */ unset($this->mNewWiki->dbw); /** * inform task manager */ $Task = new LocalMaintenanceTask(); $Task->createTask(array("city_id" => $this->mNewWiki->city_id, "command" => "maintenance/runJobs.php", "type" => "CWLocal", "data" => $this->mNewWiki, "server" => rtrim($this->mNewWiki->url, "/")), TASK_QUEUED, BatchTask::PRIORITY_HIGH); wfDebugLog("createwiki", __METHOD__ . ": Local maintenance task added\n", true); wfProfileOut(__METHOD__); /** * return success */ return 0; }