[#8179] implement add/remove_multivalue_pref methods in simple backwards compatible way, use them for user Contacts and Availability forms data
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 5aa0a7e..0299abd 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -963,7 +963,12 @@
     @validate(F.add_socialnetwork_form, error_handler=index)
     def add_social_network(self, **kw):
         require_authenticated()
-        c.user.add_socialnetwork(kw['socialnetwork'], kw['accounturl'])
+
+        if kw['socialnetwork'] == 'Twitter' and not kw['accounturl'].startswith('http'):
+            kw['accounturl'] = 'http://twitter.com/%s' % kw['accounturl'].replace('@', '')
+
+        c.user.add_multivalue_pref('socialnetworks',
+                                   {'socialnetwork': kw['socialnetwork'], 'accounturl': kw['accounturl']})
         flash('Your personal contacts were successfully updated!')
         redirect('.')
 
@@ -972,7 +977,8 @@
     @validate(F.remove_socialnetwork_form, error_handler=index)
     def remove_social_network(self, **kw):
         require_authenticated()
-        c.user.remove_socialnetwork(kw['socialnetwork'], kw['account'])
+        c.user.remove_multivalue_pref('socialnetworks',
+                                      {'socialnetwork': kw['socialnetwork'], 'accounturl': kw['account']})
         flash('Your personal contacts were successfully updated!')
         redirect('.')
 
@@ -981,7 +987,7 @@
     @validate(F.add_telnumber_form, error_handler=index)
     def add_telnumber(self, **kw):
         require_authenticated()
-        c.user.add_telephonenumber(kw['newnumber'])
+        c.user.add_multivalue_pref('telnumbers', kw['newnumber'])
         flash('Your personal contacts were successfully updated!')
         redirect('.')
 
@@ -990,7 +996,7 @@
     @validate(F.remove_textvalue_form, error_handler=index)
     def remove_telnumber(self, **kw):
         require_authenticated()
-        c.user.remove_telephonenumber(kw['oldvalue'])
+        c.user.remove_multivalue_pref('telnumbers', kw['oldvalue'])
         flash('Your personal contacts were successfully updated!')
         redirect('.')
 
@@ -999,7 +1005,7 @@
     @validate(F.add_website_form, error_handler=index)
     def add_webpage(self, **kw):
         require_authenticated()
-        c.user.add_webpage(kw['newwebsite'])
+        c.user.add_multivalue_pref('webpages', kw['newwebsite'])
         flash('Your personal contacts were successfully updated!')
         redirect('.')
 
@@ -1008,7 +1014,7 @@
     @validate(F.remove_textvalue_form, error_handler=index)
     def remove_webpage(self, **kw):
         require_authenticated()
-        c.user.remove_webpage(kw['oldvalue'])
+        c.user.remove_multivalue_pref('webpages', kw['oldvalue'])
         flash('Your personal contacts were successfully updated!')
         redirect('.')
 
@@ -1039,7 +1045,9 @@
     @validate(F.add_timeslot_form, error_handler=index)
     def add_timeslot(self, **kw):
         require_authenticated()
-        c.user.add_timeslot(kw['weekday'], kw['starttime'], kw['endtime'])
+        c.user.add_multivalue_pref('availability',
+                                   {'week_day': kw['weekday'], 'start_time': kw['starttime'],
+                                    'end_time':  kw['endtime']})
         flash('Your availability timeslots were successfully updated!')
         redirect('.')
 
@@ -1048,7 +1056,9 @@
     @validate(F.remove_timeslot_form, error_handler=index)
     def remove_timeslot(self, **kw):
         require_authenticated()
-        c.user.remove_timeslot(kw['weekday'], kw['starttime'], kw['endtime'])
+        c.user.remove_multivalue_pref('availability',
+                                      {'week_day': kw['weekday'], 'start_time': kw['starttime'],
+                                       'end_time':  kw['endtime']})
         flash('Your availability timeslots were successfully updated!')
         redirect('.')
 
@@ -1057,7 +1067,8 @@
     @validate(F.add_inactive_period_form, error_handler=index)
     def add_inactive_period(self, **kw):
         require_authenticated()
-        c.user.add_inactive_period(kw['startdate'], kw['enddate'])
+        c.user.add_multivalue_pref('inactiveperiod',
+                                   {'start_date': kw['startdate'], 'end_date': kw['enddate']})
         flash('Your inactivity periods were successfully updated!')
         redirect('.')
 
@@ -1066,7 +1077,8 @@
     @validate(F.remove_inactive_period_form, error_handler=index)
     def remove_inactive_period(self, **kw):
         require_authenticated()
-        c.user.remove_inactive_period(kw['startdate'], kw['enddate'])
+        c.user.remove_multivalue_pref('inactiveperiod',
+                                      {'start_date': kw['startdate'], 'end_date': kw['enddate']})
         flash('Your availability timeslots were successfully updated!')
         redirect('.')
 
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index 45bc309..34fe57a 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -1470,6 +1470,25 @@
                 urls[attr_name] = attr_value
         return urls
 
+    def add_multivalue_pref(self, user, pref_name, entry):
+        '''
+        :param user: a :class:`User <allura.model.auth.User>`
+        :param str pref_name:
+        :param entry: can be a simple value, or a dict structure
+        :raises: AttributeError if pref_name not found
+        '''
+        self.get_pref(user, pref_name).append(entry)
+
+    def remove_multivalue_pref(self, user, pref_name, entry):
+        '''
+        :param user: a :class:`User <allura.model.auth.User>`
+        :param str pref_name:
+        :param entry: can be a simple value, or a dict structure
+        :raises: AttributeError if pref_name not found
+        :raises: ValueError if data not found
+        '''
+        self.get_pref(user, pref_name).remove(entry)
+
 
 class LocalUserPreferencesProvider(UserPreferencesProvider):
 
diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py
index 4eb5a96..65e83b4 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -481,61 +481,11 @@
     def set_pref(self, pref_name, pref_value):
         return plugin.UserPreferencesProvider.get().set_pref(self, pref_name, pref_value)
 
-    def add_socialnetwork(self, socialnetwork, accounturl):
-        if socialnetwork == 'Twitter' and not accounturl.startswith('http'):
-            accounturl = 'http://twitter.com/%s' % accounturl.replace('@', '')
-        self.socialnetworks.append(dict(
-            socialnetwork=socialnetwork,
-            accounturl=accounturl))
+    def add_multivalue_pref(self, pref_name, pref_data):
+        return plugin.UserPreferencesProvider.get().add_multivalue_pref(self, pref_name, pref_data)
 
-    def remove_socialnetwork(self, socialnetwork, oldurl):
-        for el in self.socialnetworks:
-            if el.socialnetwork == socialnetwork and el.accounturl == oldurl:
-                del self.socialnetworks[self.socialnetworks.index(el)]
-                return
-
-    def add_telephonenumber(self, telnumber):
-        self.telnumbers.append(telnumber)
-
-    def remove_telephonenumber(self, oldvalue):
-        for el in self.telnumbers:
-            if el == oldvalue:
-                del self.telnumbers[self.telnumbers.index(el)]
-                return
-
-    def add_webpage(self, webpage):
-        self.webpages.append(webpage)
-
-    def remove_webpage(self, oldvalue):
-        for el in self.webpages:
-            if el == oldvalue:
-                del self.webpages[self.webpages.index(el)]
-                return
-
-    def add_timeslot(self, weekday, starttime, endtime):
-        self.availability.append(
-            dict(week_day=weekday,
-                 start_time=starttime,
-                 end_time=endtime))
-
-    def remove_timeslot(self, weekday, starttime, endtime):
-        oldel = dict(week_day=weekday, start_time=starttime, end_time=endtime)
-        for el in self.availability:
-            if el == oldel:
-                del self.availability[self.availability.index(el)]
-                return
-
-    def add_inactive_period(self, startdate, enddate):
-        self.inactiveperiod.append(
-            dict(start_date=startdate,
-                 end_date=enddate))
-
-    def remove_inactive_period(self, startdate, enddate):
-        oldel = dict(start_date=startdate, end_date=enddate)
-        for el in self.inactiveperiod:
-            if el == oldel:
-                del self.inactiveperiod[self.inactiveperiod.index(el)]
-                return
+    def remove_multivalue_pref(self, pref_name, pref_data):
+        return plugin.UserPreferencesProvider.get().remove_multivalue_pref(self, pref_name, pref_data)
 
     def get_localized_availability(self, tz_name):
         week_day = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
@@ -596,7 +546,7 @@
 
     def get_availability_timeslots(self):
         retval = []
-        for el in self.availability:
+        for el in self.get_pref('availability'):
             start, end = (el.get('start_time'), el.get('end_time'))
             (starth, startm) = (start.get('h'), start.get('m'))
             (endh, endm) = (end.get('h'), end.get('m'))