Exemple #1
0
 /**
  * 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;
 }
Exemple #2
0
 /**
  * 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;
 }