Index: /trunk/admin/include/plugins.class.php
===================================================================
--- /trunk/admin/include/plugins.class.php	(revision 25405)
+++ /trunk/admin/include/plugins.class.php	(revision 25406)
@@ -22,4 +22,39 @@
 // +-----------------------------------------------------------------------+
 
+/**
+ * class DummyPlugin_maintain
+ * used when a plugin uses the old procedural declaration of maintenance methods
+ */
+class DummyPlugin_maintain extends PluginMaintain
+{
+  function install($plugin_version, &$errors=array())
+  {
+    return $this->__call(__FUNCTION__, func_get_args());
+  }
+  function activate($plugin_version, &$errors=array())
+  {
+    return $this->__call(__FUNCTION__, func_get_args());
+  }
+  function deactivate()
+  {
+    return $this->__call(__FUNCTION__, func_get_args());
+  }
+  function uninstall()
+  {
+    return $this->__call(__FUNCTION__, func_get_args());
+  }
+
+  function __call($name, $arguments)
+  {
+    if (is_callable('plugin_'.$name))
+    {
+      array_unshift($arguments, $this->plugin_id);
+      return call_user_func_array('plugin_'.$name, $arguments);
+    }
+    return null;
+  }
+}
+
+
 class plugins
 {
@@ -31,5 +66,5 @@
   /**
    * Initialize $fs_plugins and $db_plugins_by_id
-  */
+   */
   function plugins()
   {
@@ -42,10 +77,41 @@
   }
 
- /**
+  /**
+   * Returns the maintain class of a plugin
+   * or build a new class with the procedural methods
+   * @param string $plugin_id
+   */
+  private static function build_maintain_class($plugin_id)
+  {
+    $file_to_include = PHPWG_PLUGINS_PATH . $plugin_id . '/maintain.inc.php';
+    $classname = $plugin_id.'_maintain';
+
+    if (file_exists($file_to_include))
+    {
+      include_once($file_to_include);
+
+      if (class_exists($classname))
+      {
+        $plugin_maintain = new $classname($plugin_id);
+      }
+      else
+      {
+        $plugin_maintain = new DummyPlugin_maintain($plugin_id);
+      }
+    }
+    else
+    {
+      $plugin_maintain = new DummyPlugin_maintain($plugin_id);
+    }
+
+    return $plugin_maintain;
+  }
+
+  /**
    * Perform requested actions
-  *  @param string - action
-  * @param string - plugin id
-  * @param array - errors
-  */
+   * @param string - action
+   * @param string - plugin id
+   * @param array - errors
+   */
   function perform_action($action, $plugin_id)
   {
@@ -54,5 +120,6 @@
       $crt_db_plugin = $this->db_plugins_by_id[$plugin_id];
     }
-    $file_to_include = PHPWG_PLUGINS_PATH . $plugin_id . '/maintain.inc.php';
+    
+    $plugin_maintain = self::build_maintain_class($plugin_id);
 
     $errors = array();
@@ -65,18 +132,13 @@
           break;
         }
-        if (file_exists($file_to_include))
-        {
-          include_once($file_to_include);
-          if (function_exists('plugin_install'))
-          {
-            plugin_install($plugin_id, $this->fs_plugins[$plugin_id]['version'], $errors);
-          }
-        }
+
+        $plugin_maintain->install($this->fs_plugins[$plugin_id]['version'], $errors);
+
         if (empty($errors))
         {
           $query = '
-INSERT INTO ' . PLUGINS_TABLE . ' (id,version) VALUES (\''
-. $plugin_id . '\',\'' . $this->fs_plugins[$plugin_id]['version'] . '\'
-)';
+INSERT INTO '. PLUGINS_TABLE .' (id,version)
+  VALUES (\''. $plugin_id .'\', \''. $this->fs_plugins[$plugin_id]['version'] .'\')
+;';
           pwg_query($query);
         }
@@ -94,18 +156,18 @@
           break;
         }
-        if (empty($errors) and file_exists($file_to_include))
-        {
-          include_once($file_to_include);
-          if (function_exists('plugin_activate'))
-          {
-            plugin_activate($plugin_id, $crt_db_plugin['version'], $errors);
-          }
-        }
+
         if (empty($errors))
         {
+          $plugin_maintain->activate($crt_db_plugin['version'], $errors);
+        }
+
+        if (empty($errors))
+        {
           $query = '
-UPDATE ' . PLUGINS_TABLE . '
-SET state=\'active\', version=\''.$this->fs_plugins[$plugin_id]['version'].'\'
-WHERE id=\'' . $plugin_id . '\'';
+UPDATE '. PLUGINS_TABLE .'
+  SET state=\'active\',
+    version=\''. $this->fs_plugins[$plugin_id]['version'] .'\'
+  WHERE id=\''. $plugin_id .'\'
+;';
           pwg_query($query);
         }
@@ -117,15 +179,13 @@
           break;
         }
+
         $query = '
-UPDATE ' . PLUGINS_TABLE . ' SET state=\'inactive\' WHERE id=\'' . $plugin_id . '\'';
+UPDATE '. PLUGINS_TABLE .'
+  SET state=\'inactive\'
+  WHERE id=\''. $plugin_id .'\'
+;';
         pwg_query($query);
-        if (file_exists($file_to_include))
-        {
-          include_once($file_to_include);
-          if (function_exists('plugin_deactivate'))
-          {
-            plugin_deactivate($plugin_id);
-          }
-        }
+        
+        $plugin_maintain->deactivate();
         break;
 
@@ -139,15 +199,12 @@
           $this->perform_action('deactivate', $plugin_id);
         }
+
         $query = '
-DELETE FROM ' . PLUGINS_TABLE . ' WHERE id=\'' . $plugin_id . '\'';
+DELETE FROM '. PLUGINS_TABLE .'
+  WHERE id=\''. $plugin_id .'\'
+;';
         pwg_query($query);
-        if (file_exists($file_to_include))
-        {
-          include_once($file_to_include);
-          if (function_exists('plugin_uninstall'))
-          {
-            plugin_uninstall($plugin_id);
-          }
-        }
+        
+        $plugin_maintain->uninstall();
         break;
 
@@ -167,13 +224,15 @@
           break;
         }
+
         deltree(PHPWG_PLUGINS_PATH . $plugin_id, PHPWG_PLUGINS_PATH . 'trash');
         break;
     }
+
     return $errors;
   }
 
   /**
-  *  Get plugins defined in the plugin directory
-  */  
+   * Get plugins defined in the plugin directory
+   */  
   function get_fs_plugins()
   {
Index: /trunk/admin/include/themes.class.php
===================================================================
--- /trunk/admin/include/themes.class.php	(revision 25405)
+++ /trunk/admin/include/themes.class.php	(revision 25406)
@@ -22,4 +22,35 @@
 // +-----------------------------------------------------------------------+
 
+/**
+ * class DummyTheme_maintain
+ * used when a theme uses the old procedural declaration of maintenance methods
+ */
+class DummyTheme_maintain extends ThemeMaintain
+{
+  function activate($theme_version, &$errors=array())
+  {
+    return $this->__call(__FUNCTION__, func_get_args());
+  }
+  function deactivate()
+  {
+    return $this->__call(__FUNCTION__, func_get_args());
+  }
+  function delete()
+  {
+    return $this->__call(__FUNCTION__, func_get_args());
+  }
+
+  function __call($name, $arguments)
+  {
+    if (is_callable('theme_'.$name))
+    {
+      array_unshift($arguments, $this->theme_id);
+      return call_user_func_array('theme_'.$name, $arguments);
+    }
+    return null;
+  }
+}
+
+
 class themes
 {
@@ -39,4 +70,35 @@
       $this->db_themes_by_id[$db_theme['id']] = $db_theme;
     }
+  }
+
+  /**
+   * Returns the maintain class of a theme
+   * or build a new class with the procedural methods
+   * @param string $theme_id
+   */
+  private static function build_maintain_class($theme_id)
+  {
+    $file_to_include = PHPWG_THEMES_PATH.'/'.$theme_id.'/admin/maintain.inc.php';
+    $classname = $theme_id.'_maintain';
+
+    if (file_exists($file_to_include))
+    {
+      include_once($file_to_include);
+
+      if (class_exists($classname))
+      {
+        $theme_maintain = new $classname($theme_id);
+      }
+      else
+      {
+        $theme_maintain = new DummyTheme_maintain($theme_id);
+      }
+    }
+    else
+    {
+      $theme_maintain = new DummyTheme_maintain($theme_id);
+    }
+
+    return $theme_maintain;
   }
 
@@ -56,5 +118,5 @@
     }
 
-    $file_to_include = PHPWG_THEMES_PATH.'/'.$theme_id.'/admin/maintain.inc.php';
+    $theme_maintain = self::build_maintain_class($theme_id);
 
     $errors = array();
@@ -86,5 +148,4 @@
         }
 
-
         if ($this->fs_themes[$theme_id]['mobile']
             and !empty($conf['mobile_theme'])
@@ -95,12 +156,5 @@
         }
 
-        if (file_exists($file_to_include))
-        {
-          include($file_to_include);
-          if (function_exists('theme_activate'))
-          {
-            theme_activate($theme_id, $this->fs_themes[$theme_id]['version'], $errors);
-          }
-        }
+        $theme_maintain->activate($this->fs_themes[$theme_id]['version'], $errors);
 
         if (empty($errors))
@@ -142,6 +196,5 @@
 
           $query = '
-SELECT
-    id
+SELECT id
   FROM '.THEMES_TABLE.'
   WHERE id != \''.$theme_id.'\'
@@ -160,12 +213,5 @@
         }
 
-        if (file_exists($file_to_include))
-        {
-          include($file_to_include);
-          if (function_exists('theme_deactivate'))
-          {
-            theme_deactivate($theme_id);
-          }
-        }
+        $theme_maintain->deactivate();
 
         $query = '
@@ -204,12 +250,5 @@
         }
 
-        if (file_exists($file_to_include))
-        {
-          include($file_to_include);
-          if (function_exists('theme_delete'))
-          {
-            theme_delete($theme_id);
-          }
-        }
+        $theme_maintain->delete();
 
         deltree(PHPWG_THEMES_PATH.$theme_id, PHPWG_THEMES_PATH . 'trash');
Index: /trunk/include/functions_plugins.inc.php
===================================================================
--- /trunk/include/functions_plugins.inc.php	(revision 25405)
+++ /trunk/include/functions_plugins.inc.php	(revision 25406)
@@ -32,6 +32,115 @@
 
 define('PHPWG_PLUGINS_PATH', PHPWG_ROOT_PATH.'plugins/');
-
 define('EVENT_HANDLER_PRIORITY_NEUTRAL', 50);
+
+
+/**
+ * class PluginMaintain
+ * used to declare maintenance methods of a plugin
+ */
+abstract class PluginMaintain 
+{
+  protected $plugin_id;
+  
+  function __construct($id)
+  {
+    $this->plugin_id = $id;
+  }
+  
+  abstract function install($plugin_version, &$errors=array());
+  abstract function activate($plugin_version, &$errors=array());
+  abstract function deactivate();
+  abstract function uninstall();
+  
+  /*
+   * test if a plugin needs to be updated and call a update function
+   * @param: string $version, version exposed by the plugin
+   * @param: string $on_update, name of a method to call when an update is needed
+   *          it receives the previous version as first parameter
+   */
+  function autoUpdate($version, $on_update=null)
+  {
+    global $pwg_loaded_plugins;
+    
+    $current_version = $pwg_loaded_plugins[$this->plugin_id]['version'];
+    
+    if ( $version == 'auto' or $current_version == 'auto'
+        or version_compare($current_version, $version, '<')
+      )
+    {
+      if (!empty($on_update))
+      {
+        call_user_func(array(&$this, $on_update), $current_version);
+      }
+      
+      if ($version != 'auto')
+      {
+        $query = '
+UPDATE '. PLUGINS_TABLE .'
+  SET version = "'. $version .'"
+  WHERE id = "'. $this->plugin_id .'"
+;';
+        pwg_query($query);
+        
+        $pwg_loaded_plugins[$this->plugin_id]['version'] = $version;
+      }
+    }
+  }
+}
+
+/**
+ * class ThemeMaintain
+ * used to declare maintenance methods of a theme
+ */
+abstract class ThemeMaintain 
+{
+  protected $theme_id;
+  
+  function __construct($id)
+  {
+    $this->theme_id = $id;
+  }
+  
+  abstract function activate($theme_version, &$errors=array());
+  abstract function deactivate();
+  abstract function delete();
+  
+  /*
+   * test if a theme needs to be updated and call a update function
+   * @param: string $version, version exposed by the theme
+   * @param: string $on_update, name of a method to call when an update is needed
+   *          it receives the previous version as first parameter
+   */
+  function autoUpdate($version, $on_update=null)
+  {
+    $query = '
+SELECT version
+  FROM '. THEMES_TABLE .'
+  WHERE id = "'. $this->theme_id .'"
+;';
+    list($current_version) = pwg_db_fetch_row(pwg_query($query));
+    
+    if ( $version == 'auto' or $current_version == 'auto'
+        or version_compare($current_version, $version, '<')
+      )
+    {
+      if (!empty($on_update))
+      {
+        call_user_func(array(&$this, $on_update), $current_version);
+      }
+      
+      if ($version != 'auto')
+      {
+        $query = '
+UPDATE '. THEMES_TABLE .'
+  SET version = "'. $version .'"
+  WHERE id = "'. $this->theme_id .'"
+;';
+        pwg_query($query);
+      }
+    }
+  }
+}
+
 
 /* Register a event handler.
@@ -254,40 +363,3 @@
 }
 
-/*
- * test if a plugin needs to be updated and call a update function
- * @param: string $plugin_id, id of the plugin as seen in PLUGINS_TABLE and $pwg_loaded_plugins
- * @param: string $version, version exposed by the plugin
- * @param: callable $on_update, function to call when and update is needed
- *          it receives the previous version as first parameter
- */
-function request_plugin_update($plugin_id, $version, $on_update)
-{
-  global $pwg_loaded_plugins;
-  
-  if (
-    $version == 'auto' or
-    $pwg_loaded_plugins[$plugin_id]['version'] == 'auto' or
-    version_compare($pwg_loaded_plugins[$plugin_id]['version'], $version, '<')
-  )
-  {
-    // call update function
-    if (!empty($on_update))
-    {
-      call_user_func($on_update, $pwg_loaded_plugins[$plugin_id]['version']);
-    }
-    
-    // update plugin version in database
-    if ($version != 'auto')
-    {
-      $query = '
-UPDATE '. PLUGINS_TABLE .'
-SET version = "'. $version .'"
-WHERE id = "'. $plugin_id .'"';
-      pwg_query($query);
-      
-      $pwg_loaded_plugins[$plugin_id]['version'] = $version;
-    }
-  }
-}
-
 ?>
