Hi,
I have had to bulk update user options in the past as well and wrote a short python script that iterates over all the users and sets the options. It's not generalized yet (this was a one-off), so you would need to change the code slightly to connect to the db and set specific options, but its simple enough that this isn't too cumbersome.
I guess its goofy to have rewritten the de/coding in another language, but the user option blob was simple enough and I just needed to do this once.
hope that helps, /Jonah
#!/usr/bin/python
""" simple script to deal w/ bulk modifications of mediawiki user options, which are blobs
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.
"""
import sys import re import MySQLdb
DB_USER="xxxxxxxxx" DB_PASSWD="xxxxxxxxx"
def getConnection(): conn = MySQLdb.connect(host="localhost", user=DB_USER, passwd=DB_PASSWD, db="susdev_wiki") return conn
class UserOptions: def __init__(self, conn, name): self.name = name self.optionsDict = {} self.loadOptions(conn)
def loadOptions(self, conn): c = conn.cursor() c.execute("SELECT user_options FROM user WHERE user_name = '%s'" % self.name) optionsBlob = c.fetchone()[0] # print optionsBlob self._decodeOptions(optionsBlob) c.close() # return self.optionsDict
def setOption(self, name, value): print "Changing %s's %s->%s\n" % (self.name, name, value) self.optionsDict[name] = value
def saveOptions(self, conn): optionsBlob = self._encodeOptions() c = conn.cursor() c.execute("update user SET user_options = '%s' WHERE user_name = '%s'" % (optionsBlob, self.name)) c.close()
def _encodeOptions(self): blobList = ["%s=%s" % (i,k) for i,k in self.optionsDict.items()] return "\n".join(blobList)
def _decodeOptions(self, optionsBlob): """ ripped from the User.php functions that do this in teh mediwiki """ pattern = re.compile("^(.[^=]*)=(.*)$") optionPairs = optionsBlob.split("\n") # import pdb; pdb.set_trace() for pair in optionPairs: m = pattern.match(pair) if m: name, value = (m.group(1), m.group(2)) self.optionsDict[name] = value
def main (argv=None): conn = getConnection()
cur = conn.cursor() cur.execute("SELECT user_name from user") usernames = [row[0] for row in cur.fetchall()] cur.close() for user in usernames: print "Processing %s" % user u = UserOptions(conn, user) u.setOption("skin", "<NEW VALUE>") u.saveOptions(conn)
conn.close() print "Done\n"
if __name__ == "__main__": sys.exit(main())
Hi,
Finally, I simply ran the following SQL command yesterday and everything seems to work. I hope that this was not a bad choice and that I won't have problems in the future? Coud someone confirm that it's ok?
The SQL command:
UPDATE user SET user_options = "quickbar=1 underline=0 cols=4 rows=4 searchlimit=20 contextlines=5 contextchars=50 skin= math=1 rcdays=1 rclimit=50 wllimit=250 highlightbroken=0 stubthreshold=0 previewontop=0 editsection=0 editsectiononrightclick=0 showtoc=0 showtoolbar=0 date=default imagesize=0 thumbsize=0 rememberpassword=0 enotifwatchlistpages=0 enotifusertalkpages=1 enotifminoredits=0 enotifrevealaddr=0 shownumberswatching=0 fancysig=0 externaleditor=0 externaldiff=0 showjumplinks=0 numberheadings=0 uselivepreview=0 watchlistdays=3 variant= language=fr searchNs0=0 nickname=Admin timecorrection=02:00 searchNs1=0 searchNs2=0 searchNs3=0 searchNs4=0 searchNs5=0 searchNs6=0 searchNs7=0 searchNs8=0 searchNs9=0 searchNs10=0 searchNs11=0 searchNs12=0 searchNs13=0 searchNs14=0 searchNs15=0 disablemail=1 justify=0 hideminor=0 extendwatchlist=0 usenewrc=0 editondblclick=0 editwidth=0 watchcreations=0 watchdefault=0 watchmoves=0 watchdeletion=0 minordefault=0 previewonfirst=0 nocache=0 forceeditsummary=0 watchlisthideown=0 watchlisthidebots=0 watchlisthideminor=0 ccmeonemails=0 diffonly=0 riched_disable=0 riched_disable_ns_main=0 riched_disable_ns_talk=0 riched_disable_ns_user=0 riched_disable_ns_user_talk=0 riched_disable_ns_project=0 riched_disable_ns_project_talk=0 riched_disable_ns_image=0 riched_disable_ns_image_talk=0 riched_disable_ns_mediawiki=0 riched_disable_ns_mediawiki_talk=0 riched_disable_ns_template=0 riched_disable_ns_template_talk=0 riched_disable_ns_help=0 riched_disable_ns_help_talk=0 riched_disable_ns_category=0 riched_disable_ns_category_talk=0 ajaxsearch= searchNs90=0 searchNs91=0 searchNs92=0 searchNs93=0 lqt_sort_order=3 disablesuggest= showhiddencats=0"
Thank you for your feed back.
Laurent
2008/10/2 Jonah Bossewitch mrenoch@phantomcynthetics.com
Hi,
I have had to bulk update user options in the past as well and wrote a short python script that iterates over all the users and sets the options. It's not generalized yet (this was a one-off), so you would need to change the code slightly to connect to the db and set specific options, but its simple enough that this isn't too cumbersome.
I guess its goofy to have rewritten the de/coding in another language, but the user option blob was simple enough and I just needed to do this once.
hope that helps, /Jonah
#!/usr/bin/python
""" simple script to deal w/ bulk modifications of mediawiki user options, which are blobs
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.
"""
import sys import re import MySQLdb
DB_USER="xxxxxxxxx" DB_PASSWD="xxxxxxxxx"
def getConnection(): conn = MySQLdb.connect(host="localhost", user=DB_USER, passwd=DB_PASSWD, db="susdev_wiki") return conn
class UserOptions: def __init__(self, conn, name): self.name = name self.optionsDict = {} self.loadOptions(conn)
def loadOptions(self, conn): c = conn.cursor() c.execute("SELECT user_options FROM user WHERE user_name = '%s'" % self.name) optionsBlob = c.fetchone()[0] # print optionsBlob self._decodeOptions(optionsBlob) c.close() # return self.optionsDict
def setOption(self, name, value): print "Changing %s's %s->%s\n" % (self.name, name, value) self.optionsDict[name] = value
def saveOptions(self, conn): optionsBlob = self._encodeOptions() c = conn.cursor() c.execute("update user SET user_options = '%s' WHERE user_name = '%s'" % (optionsBlob, self.name)) c.close()
def _encodeOptions(self): blobList = ["%s=%s" % (i,k) for i,k in self.optionsDict.items()] return "\n".join(blobList)
def _decodeOptions(self, optionsBlob): """ ripped from the User.php functions that do this in teh mediwiki """ pattern = re.compile("^(.[^=]*)=(.*)$") optionPairs = optionsBlob.split("\n") # import pdb; pdb.set_trace() for pair in optionPairs: m = pattern.match(pair) if m: name, value = (m.group(1), m.group(2)) self.optionsDict[name] = value
def main (argv=None): conn = getConnection()
cur = conn.cursor() cur.execute("SELECT user_name from user") usernames = [row[0] for row in cur.fetchall()] cur.close() for user in usernames: print "Processing %s" % user u = UserOptions(conn, user) u.setOption("skin", "<NEW VALUE>") u.saveOptions(conn)
conn.close() print "Done\n"
if __name__ == "__main__": sys.exit(main())
mediawiki-l@lists.wikimedia.org