Add share NG migrations.
authorJan Schneider <jan@horde.org>
Fri, 21 Jan 2011 13:28:44 +0000 (14:28 +0100)
committerJan Schneider <jan@horde.org>
Fri, 21 Jan 2011 13:31:33 +0000 (14:31 +0100)
ingo/migration/3_ingo_upgrade_sqlng.php [new file with mode: 0644]
ingo/scripts/upgrades/convert_sql_shares_to_sqlng.php [new file with mode: 0755]
mnemo/migration/3_mnemo_upgrade_sqlng.php [new file with mode: 0644]
mnemo/scripts/upgrades/convert_sql_shares_to_sqlng.php [new file with mode: 0755]
nag/migration/6_nag_upgrade_sqlng.php [new file with mode: 0644]
nag/scripts/upgrades/convert_sql_shares_to_sqlng.php [new file with mode: 0755]
turba/migration/3_turba_upgrade_sqlng.php [new file with mode: 0644]
turba/scripts/upgrades/convert_sql_shares_to_sqlng.php [new file with mode: 0755]
whups/migration/3_whups_upgrade_sqlng.php [new file with mode: 0644]
whups/scripts/upgrades/convert_sql_shares_to_sqlng.php [new file with mode: 0755]

diff --git a/ingo/migration/3_ingo_upgrade_sqlng.php b/ingo/migration/3_ingo_upgrade_sqlng.php
new file mode 100644 (file)
index 0000000..0f9c35d
--- /dev/null
@@ -0,0 +1,154 @@
+<?php
+/**
+ * Adds tables for the Sqlng share driver.
+ *
+ * Copyright 2011 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (ASL).  If you
+ * did not receive this file, see http://www.horde.org/licenses/asl.php.
+ *
+ * @author   Jan Schneider <jan@horde.org>
+ * @category Horde
+ * @license  http://www.horde.org/licenses/asl.php ASL
+ * @package  Ingo
+ */
+class IngoUpgradeSqlng extends Horde_Db_Migration_Base
+{
+    /**
+     * Upgrade.
+     */
+    public function up()
+    {
+        $t = $this->createTable('ingo_sharesng', array('primaryKey' => 'share_id'));
+        $t->column('share_name', 'string', array('limit' => 255, 'null' => false));
+        $t->column('share_owner', 'string', array('limit' => 255));
+        $t->column('share_flags', 'integer', array('default' => 0, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->column('attribute_name', 'string', array('limit' => 255, 'null' => false));
+        $t->column('attribute_desc', 'string', array('limit' => 255));
+        $t->end();
+
+        $this->addIndex('ingo_sharesng', array('share_name'));
+        $this->addIndex('ingo_sharesng', array('share_owner'));
+        $this->addIndex('ingo_sharesng', array('perm_creator_' . Horde_Perms::SHOW));
+        $this->addIndex('ingo_sharesng', array('perm_creator_' . Horde_Perms::READ));
+        $this->addIndex('ingo_sharesng', array('perm_creator_' . Horde_Perms::EDIT));
+        $this->addIndex('ingo_sharesng', array('perm_creator_' . Horde_Perms::DELETE));
+        $this->addIndex('ingo_sharesng', array('perm_default_' . Horde_Perms::SHOW));
+        $this->addIndex('ingo_sharesng', array('perm_default_' . Horde_Perms::READ));
+        $this->addIndex('ingo_sharesng', array('perm_default_' . Horde_Perms::EDIT));
+        $this->addIndex('ingo_sharesng', array('perm_default_' . Horde_Perms::DELETE));
+        $this->addIndex('ingo_sharesng', array('perm_guest_' . Horde_Perms::SHOW));
+        $this->addIndex('ingo_sharesng', array('perm_guest_' . Horde_Perms::READ));
+        $this->addIndex('ingo_sharesng', array('perm_guest_' . Horde_Perms::EDIT));
+        $this->addIndex('ingo_sharesng', array('perm_guest_' . Horde_Perms::DELETE));
+
+        $t = $this->createTable('ingo_sharesng_groups', array('primaryKey' => false));
+        $t->column('share_id', 'integer', array('null' => false));
+        $t->column('group_uid', 'string', array('limit' => 255, 'null' => false));
+        $t->column('perm_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->end();
+
+        $this->addIndex('ingo_sharesng_groups', array('share_id'));
+        $this->addIndex('ingo_sharesng_groups', array('group_uid'));
+        $this->addIndex('ingo_sharesng_groups', array('perm_' . Horde_Perms::SHOW));
+        $this->addIndex('ingo_sharesng_groups', array('perm_' . Horde_Perms::READ));
+        $this->addIndex('ingo_sharesng_groups', array('perm_' . Horde_Perms::EDIT));
+        $this->addIndex('ingo_sharesng_groups', array('perm_' . Horde_Perms::DELETE));
+
+        $t = $this->createTable('ingo_sharesng_users', array('primaryKey' => false));
+        $t->column('share_id', 'integer', array('null' => false));
+        $t->column('user_uid', 'string', array('limit' => 255));
+        $t->column('perm_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->end();
+
+        $this->addIndex('ingo_sharesng_users', array('share_id'));
+        $this->addIndex('ingo_sharesng_users', array('user_uid'));
+        $this->addIndex('ingo_sharesng_users', array('perm_' . Horde_Perms::SHOW));
+        $this->addIndex('ingo_sharesng_users', array('perm_' . Horde_Perms::READ));
+        $this->addIndex('ingo_sharesng_users', array('perm_' . Horde_Perms::EDIT));
+        $this->addIndex('ingo_sharesng_users', array('perm_' . Horde_Perms::DELETE));
+
+        $this->dataUp();
+    }
+
+    /**
+     * Downgrade
+     */
+    public function down()
+    {
+        $this->dropTable('ingo_sharesng');
+        $this->dropTable('ingo_sharesng_groups');
+        $this->dropTable('ingo_sharesng_users');
+    }
+
+    public function dataUp()
+    {
+        $whos = array('creator', 'default', 'guest');
+        $perms = array(Horde_Perms::SHOW,
+                       Horde_Perms::READ,
+                       Horde_Perms::EDIT,
+                       Horde_Perms::DELETE);
+
+        $sql = 'INSERT INTO ingo_sharesng (share_id, share_name, share_owner, share_flags, attribute_name, attribute_desc';
+        $count = 0;
+        foreach ($whos as $who) {
+            foreach ($perms as $perm) {
+                $sql .= ', perm_' . $who . '_' . $perm;
+                $count++;
+            }
+        }
+        $sql .= ') VALUES (?, ?, ?, ?, ?, ?' . str_repeat(', ?', $count) . ')';
+
+        foreach ($this->select('SELECT * FROM ingo_shares') as $share) {
+            $values = array($share['share_id'],
+                            $share['share_name'],
+                            $share['share_owner'],
+                            $share['share_flags'],
+                            $share['attribute_name'],
+                            $share['attribute_desc']);
+            foreach ($whos as $who) {
+                foreach ($perms as $perm) {
+                    $values[] = (bool)($share['perm_' . $who] & $perm);
+                }
+            }
+            $this->insert($sql, $values);
+        }
+
+        foreach (array('user', 'group') as $what) {
+            $sql = 'INSERT INTO ingo_sharesng_' . $what . 's (share_id, ' . $what . '_uid';
+            $count = 0;
+            foreach ($perms as $perm) {
+                $sql .= ', perm_' . $perm;
+                $count++;
+            }
+            $sql .= ') VALUES (?, ?' . str_repeat(', ?', $count) . ')';
+
+            foreach ($this->select('SELECT * FROM ingo_shares_' . $what . 's') as $share) {
+                $values = array($share['share_id'],
+                                $share[$what . '_uid']);
+                foreach ($perms as $perm) {
+                    $values[] = (bool)($share['perm'] & $perm);
+                }
+                $this->insert($sql, $values);
+            }
+        }
+    }
+}
diff --git a/ingo/scripts/upgrades/convert_sql_shares_to_sqlng.php b/ingo/scripts/upgrades/convert_sql_shares_to_sqlng.php
new file mode 100755 (executable)
index 0000000..c062f8f
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/env php
+<?php
+/**
+ * This script migrates Ingo's share data from the SQL Horde_Share
+ * driver to the next-generation SQL Horde_Share driver.
+ *
+ * It is supposed to run at any time after migrating Ingo to the latest DB
+ * schema version. The schema migration already migrates the data once, but
+ * this script can be used to migrate the data again, e.g. if starting to use
+ * the NG driver at a later time.
+ */
+
+/* Set up the CLI environment */
+require_once dirname(__FILE__) . '/../../lib/Application.php';
+Horde_Registry::appInit('ingo', array('cli' => true));
+
+require_once dirname(__FILE__) . '/../../migration/3_ingo_upgrade_sqlng.php';
+
+$db = $injector->getInstance('Horde_Db_Adapter');
+$migration = new IngoUpgradeSqlng($db);
+
+$delete = $cli->prompt('Delete existing shares from the NEW backend before migrating the OLD backend? This should be done to avoid duplicate entries or primary key collisions in the storage backend from earlier migrations.', array('y' => 'Yes', 'n' => 'No'), 'n');
+
+if ($delete == 'y' || $delete == 'Y') {
+    $db->delete('DELETE FROM ingo_sharesng');
+    $db->delete('DELETE FROM ingo_sharesng_users');
+    $db->delete('DELETE FROM ingo_sharesng_groups');
+}
+
+$migration->dataUp();
diff --git a/mnemo/migration/3_mnemo_upgrade_sqlng.php b/mnemo/migration/3_mnemo_upgrade_sqlng.php
new file mode 100644 (file)
index 0000000..0c1a202
--- /dev/null
@@ -0,0 +1,154 @@
+<?php
+/**
+ * Adds tables for the Sqlng share driver.
+ *
+ * Copyright 2011 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (ASL). If you
+ * did not receive this file, see http://www.horde.org/licenses/asl.php.
+ *
+ * @author   Jan Schneider <jan@horde.org>
+ * @category Horde
+ * @license  http://www.horde.org/licenses/asl.php ASL
+ * @package  Mnemo
+ */
+class MnemoUpgradeSqlng extends Horde_Db_Migration_Base
+{
+    /**
+     * Upgrade.
+     */
+    public function up()
+    {
+        $t = $this->createTable('mnemo_sharesng', array('primaryKey' => 'share_id'));
+        $t->column('share_name', 'string', array('limit' => 255, 'null' => false));
+        $t->column('share_owner', 'string', array('limit' => 255));
+        $t->column('share_flags', 'integer', array('default' => 0, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->column('attribute_name', 'string', array('limit' => 255, 'null' => false));
+        $t->column('attribute_desc', 'string', array('limit' => 255));
+        $t->end();
+
+        $this->addIndex('mnemo_sharesng', array('share_name'));
+        $this->addIndex('mnemo_sharesng', array('share_owner'));
+        $this->addIndex('mnemo_sharesng', array('perm_creator_' . Horde_Perms::SHOW));
+        $this->addIndex('mnemo_sharesng', array('perm_creator_' . Horde_Perms::READ));
+        $this->addIndex('mnemo_sharesng', array('perm_creator_' . Horde_Perms::EDIT));
+        $this->addIndex('mnemo_sharesng', array('perm_creator_' . Horde_Perms::DELETE));
+        $this->addIndex('mnemo_sharesng', array('perm_default_' . Horde_Perms::SHOW));
+        $this->addIndex('mnemo_sharesng', array('perm_default_' . Horde_Perms::READ));
+        $this->addIndex('mnemo_sharesng', array('perm_default_' . Horde_Perms::EDIT));
+        $this->addIndex('mnemo_sharesng', array('perm_default_' . Horde_Perms::DELETE));
+        $this->addIndex('mnemo_sharesng', array('perm_guest_' . Horde_Perms::SHOW));
+        $this->addIndex('mnemo_sharesng', array('perm_guest_' . Horde_Perms::READ));
+        $this->addIndex('mnemo_sharesng', array('perm_guest_' . Horde_Perms::EDIT));
+        $this->addIndex('mnemo_sharesng', array('perm_guest_' . Horde_Perms::DELETE));
+
+        $t = $this->createTable('mnemo_sharesng_groups', array('primaryKey' => false));
+        $t->column('share_id', 'integer', array('null' => false));
+        $t->column('group_uid', 'string', array('limit' => 255, 'null' => false));
+        $t->column('perm_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->end();
+
+        $this->addIndex('mnemo_sharesng_groups', array('share_id'));
+        $this->addIndex('mnemo_sharesng_groups', array('group_uid'));
+        $this->addIndex('mnemo_sharesng_groups', array('perm_' . Horde_Perms::SHOW));
+        $this->addIndex('mnemo_sharesng_groups', array('perm_' . Horde_Perms::READ));
+        $this->addIndex('mnemo_sharesng_groups', array('perm_' . Horde_Perms::EDIT));
+        $this->addIndex('mnemo_sharesng_groups', array('perm_' . Horde_Perms::DELETE));
+
+        $t = $this->createTable('mnemo_sharesng_users', array('primaryKey' => false));
+        $t->column('share_id', 'integer', array('null' => false));
+        $t->column('user_uid', 'string', array('limit' => 255));
+        $t->column('perm_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->end();
+
+        $this->addIndex('mnemo_sharesng_users', array('share_id'));
+        $this->addIndex('mnemo_sharesng_users', array('user_uid'));
+        $this->addIndex('mnemo_sharesng_users', array('perm_' . Horde_Perms::SHOW));
+        $this->addIndex('mnemo_sharesng_users', array('perm_' . Horde_Perms::READ));
+        $this->addIndex('mnemo_sharesng_users', array('perm_' . Horde_Perms::EDIT));
+        $this->addIndex('mnemo_sharesng_users', array('perm_' . Horde_Perms::DELETE));
+
+        $this->dataUp();
+    }
+
+    /**
+     * Downgrade
+     */
+    public function down()
+    {
+        $this->dropTable('mnemo_sharesng');
+        $this->dropTable('mnemo_sharesng_groups');
+        $this->dropTable('mnemo_sharesng_users');
+    }
+
+    public function dataUp()
+    {
+        $whos = array('creator', 'default', 'guest');
+        $perms = array(Horde_Perms::SHOW,
+                       Horde_Perms::READ,
+                       Horde_Perms::EDIT,
+                       Horde_Perms::DELETE);
+
+        $sql = 'INSERT INTO mnemo_sharesng (share_id, share_name, share_owner, share_flags, attribute_name, attribute_desc';
+        $count = 0;
+        foreach ($whos as $who) {
+            foreach ($perms as $perm) {
+                $sql .= ', perm_' . $who . '_' . $perm;
+                $count++;
+            }
+        }
+        $sql .= ') VALUES (?, ?, ?, ?, ?, ?' . str_repeat(', ?', $count) . ')';
+
+        foreach ($this->select('SELECT * FROM mnemo_shares') as $share) {
+            $values = array($share['share_id'],
+                            $share['share_name'],
+                            $share['share_owner'],
+                            $share['share_flags'],
+                            $share['attribute_name'],
+                            $share['attribute_desc']);
+            foreach ($whos as $who) {
+                foreach ($perms as $perm) {
+                    $values[] = (bool)($share['perm_' . $who] & $perm);
+                }
+            }
+            $this->insert($sql, $values);
+        }
+
+        foreach (array('user', 'group') as $what) {
+            $sql = 'INSERT INTO mnemo_sharesng_' . $what . 's (share_id, ' . $what . '_uid';
+            $count = 0;
+            foreach ($perms as $perm) {
+                $sql .= ', perm_' . $perm;
+                $count++;
+            }
+            $sql .= ') VALUES (?, ?' . str_repeat(', ?', $count) . ')';
+
+            foreach ($this->select('SELECT * FROM mnemo_shares_' . $what . 's') as $share) {
+                $values = array($share['share_id'],
+                                $share[$what . '_uid']);
+                foreach ($perms as $perm) {
+                    $values[] = (bool)($share['perm'] & $perm);
+                }
+                $this->insert($sql, $values);
+            }
+        }
+    }
+}
diff --git a/mnemo/scripts/upgrades/convert_sql_shares_to_sqlng.php b/mnemo/scripts/upgrades/convert_sql_shares_to_sqlng.php
new file mode 100755 (executable)
index 0000000..b1cf07b
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/env php
+<?php
+/**
+ * This script migrates Mnemo's share data from the SQL Horde_Share
+ * driver to the next-generation SQL Horde_Share driver.
+ *
+ * It is supposed to run at any time after migrating Mnemo to the latest DB
+ * schema version. The schema migration already migrates the data once, but
+ * this script can be used to migrate the data again, e.g. if starting to use
+ * the NG driver at a later time.
+ */
+
+/* Set up the CLI environment */
+require_once dirname(__FILE__) . '/../../lib/Application.php';
+Horde_Registry::appInit('mnemo', array('cli' => true));
+
+require_once dirname(__FILE__) . '/../../migration/3_mnemo_upgrade_sqlng.php';
+
+$db = $injector->getInstance('Horde_Db_Adapter');
+$migration = new MnemoUpgradeSqlng($db);
+
+$delete = $cli->prompt('Delete existing shares from the NEW backend before migrating the OLD backend? This should be done to avoid duplicate entries or primary key collisions in the storage backend from earlier migrations.', array('y' => 'Yes', 'n' => 'No'), 'n');
+
+if ($delete == 'y' || $delete == 'Y') {
+    $db->delete('DELETE FROM mnemo_sharesng');
+    $db->delete('DELETE FROM mnemo_sharesng_users');
+    $db->delete('DELETE FROM mnemo_sharesng_groups');
+}
+
+$migration->dataUp();
diff --git a/nag/migration/6_nag_upgrade_sqlng.php b/nag/migration/6_nag_upgrade_sqlng.php
new file mode 100644 (file)
index 0000000..6c1af8f
--- /dev/null
@@ -0,0 +1,156 @@
+<?php
+/**
+ * Adds tables for the Sqlng share driver.
+ *
+ * Copyright 2011 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author   Jan Schneider <jan@horde.org>
+ * @category Horde
+ * @license  http://www.fsf.org/copyleft/gpl.html GPL
+ * @package  Nag
+ */
+class NagUpgradeSqlng extends Horde_Db_Migration_Base
+{
+    /**
+     * Upgrade.
+     */
+    public function up()
+    {
+        $t = $this->createTable('nag_sharesng', array('primaryKey' => 'share_id'));
+        $t->column('share_name', 'string', array('limit' => 255, 'null' => false));
+        $t->column('share_owner', 'string', array('limit' => 255));
+        $t->column('share_flags', 'integer', array('default' => 0, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->column('attribute_name', 'string', array('limit' => 255, 'null' => false));
+        $t->column('attribute_desc', 'string', array('limit' => 255));
+        $t->column('attribute_color', 'string', array('limit' => 7));
+        $t->end();
+
+        $this->addIndex('nag_sharesng', array('share_name'));
+        $this->addIndex('nag_sharesng', array('share_owner'));
+        $this->addIndex('nag_sharesng', array('perm_creator_' . Horde_Perms::SHOW));
+        $this->addIndex('nag_sharesng', array('perm_creator_' . Horde_Perms::READ));
+        $this->addIndex('nag_sharesng', array('perm_creator_' . Horde_Perms::EDIT));
+        $this->addIndex('nag_sharesng', array('perm_creator_' . Horde_Perms::DELETE));
+        $this->addIndex('nag_sharesng', array('perm_default_' . Horde_Perms::SHOW));
+        $this->addIndex('nag_sharesng', array('perm_default_' . Horde_Perms::READ));
+        $this->addIndex('nag_sharesng', array('perm_default_' . Horde_Perms::EDIT));
+        $this->addIndex('nag_sharesng', array('perm_default_' . Horde_Perms::DELETE));
+        $this->addIndex('nag_sharesng', array('perm_guest_' . Horde_Perms::SHOW));
+        $this->addIndex('nag_sharesng', array('perm_guest_' . Horde_Perms::READ));
+        $this->addIndex('nag_sharesng', array('perm_guest_' . Horde_Perms::EDIT));
+        $this->addIndex('nag_sharesng', array('perm_guest_' . Horde_Perms::DELETE));
+
+        $t = $this->createTable('nag_sharesng_groups', array('primaryKey' => false));
+        $t->column('share_id', 'integer', array('null' => false));
+        $t->column('group_uid', 'string', array('limit' => 255, 'null' => false));
+        $t->column('perm_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->end();
+
+        $this->addIndex('nag_sharesng_groups', array('share_id'));
+        $this->addIndex('nag_sharesng_groups', array('group_uid'));
+        $this->addIndex('nag_sharesng_groups', array('perm_' . Horde_Perms::SHOW));
+        $this->addIndex('nag_sharesng_groups', array('perm_' . Horde_Perms::READ));
+        $this->addIndex('nag_sharesng_groups', array('perm_' . Horde_Perms::EDIT));
+        $this->addIndex('nag_sharesng_groups', array('perm_' . Horde_Perms::DELETE));
+
+        $t = $this->createTable('nag_sharesng_users', array('primaryKey' => false));
+        $t->column('share_id', 'integer', array('null' => false));
+        $t->column('user_uid', 'string', array('limit' => 255));
+        $t->column('perm_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->end();
+
+        $this->addIndex('nag_sharesng_users', array('share_id'));
+        $this->addIndex('nag_sharesng_users', array('user_uid'));
+        $this->addIndex('nag_sharesng_users', array('perm_' . Horde_Perms::SHOW));
+        $this->addIndex('nag_sharesng_users', array('perm_' . Horde_Perms::READ));
+        $this->addIndex('nag_sharesng_users', array('perm_' . Horde_Perms::EDIT));
+        $this->addIndex('nag_sharesng_users', array('perm_' . Horde_Perms::DELETE));
+
+        $this->dataUp();
+    }
+
+    /**
+     * Downgrade
+     */
+    public function down()
+    {
+        $this->dropTable('nag_sharesng');
+        $this->dropTable('nag_sharesng_groups');
+        $this->dropTable('nag_sharesng_users');
+    }
+
+    public function dataUp()
+    {
+        $whos = array('creator', 'default', 'guest');
+        $perms = array(Horde_Perms::SHOW,
+                       Horde_Perms::READ,
+                       Horde_Perms::EDIT,
+                       Horde_Perms::DELETE);
+
+        $sql = 'INSERT INTO nag_sharesng (share_id, share_name, share_owner, share_flags, attribute_name, attribute_desc, attribute_color';
+        $count = 0;
+        foreach ($whos as $who) {
+            foreach ($perms as $perm) {
+                $sql .= ', perm_' . $who . '_' . $perm;
+                $count++;
+            }
+        }
+        $sql .= ') VALUES (?, ?, ?, ?, ?, ?, ?' . str_repeat(', ?', $count) . ')';
+
+        foreach ($this->select('SELECT * FROM nag_shares') as $share) {
+            $values = array($share['share_id'],
+                            $share['share_name'],
+                            $share['share_owner'],
+                            $share['share_flags'],
+                            $share['attribute_name'],
+                            $share['attribute_desc'],
+                            $share['attribute_color']);
+            foreach ($whos as $who) {
+                foreach ($perms as $perm) {
+                    $values[] = (bool)($share['perm_' . $who] & $perm);
+                }
+            }
+            $this->insert($sql, $values);
+        }
+
+        foreach (array('user', 'group') as $what) {
+            $sql = 'INSERT INTO nag_sharesng_' . $what . 's (share_id, ' . $what . '_uid';
+            $count = 0;
+            foreach ($perms as $perm) {
+                $sql .= ', perm_' . $perm;
+                $count++;
+            }
+            $sql .= ') VALUES (?, ?' . str_repeat(', ?', $count) . ')';
+
+            foreach ($this->select('SELECT * FROM nag_shares_' . $what . 's') as $share) {
+                $values = array($share['share_id'],
+                                $share[$what . '_uid']);
+                foreach ($perms as $perm) {
+                    $values[] = (bool)($share['perm'] & $perm);
+                }
+                $this->insert($sql, $values);
+            }
+        }
+    }
+}
diff --git a/nag/scripts/upgrades/convert_sql_shares_to_sqlng.php b/nag/scripts/upgrades/convert_sql_shares_to_sqlng.php
new file mode 100755 (executable)
index 0000000..8d84271
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/env php
+<?php
+/**
+ * This script migrates Nag's share data from the SQL Horde_Share
+ * driver to the next-generation SQL Horde_Share driver.
+ *
+ * It is supposed to run at any time after migrating Nag to the latest DB
+ * schema version. The schema migration already migrates the data once, but
+ * this script can be used to migrate the data again, e.g. if starting to use
+ * the NG driver at a later time.
+ */
+
+/* Set up the CLI environment */
+require_once dirname(__FILE__) . '/../../lib/Application.php';
+Horde_Registry::appInit('nag', array('cli' => true));
+
+require_once dirname(__FILE__) . '/../../migration/6_nag_upgrade_sqlng.php';
+
+$db = $injector->getInstance('Horde_Db_Adapter');
+$migration = new NagUpgradeSqlng($db);
+
+$delete = $cli->prompt('Delete existing shares from the NEW backend before migrating the OLD backend? This should be done to avoid duplicate entries or primary key collisions in the storage backend from earlier migrations.', array('y' => 'Yes', 'n' => 'No'), 'n');
+
+if ($delete == 'y' || $delete == 'Y') {
+    $db->delete('DELETE FROM nag_sharesng');
+    $db->delete('DELETE FROM nag_sharesng_users');
+    $db->delete('DELETE FROM nag_sharesng_groups');
+}
+
+$migration->dataUp();
diff --git a/turba/migration/3_turba_upgrade_sqlng.php b/turba/migration/3_turba_upgrade_sqlng.php
new file mode 100644 (file)
index 0000000..7aa24be
--- /dev/null
@@ -0,0 +1,156 @@
+<?php
+/**
+ * Adds tables for the Sqlng share driver.
+ *
+ * Copyright 2011 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (ASL).  If you
+ * did not receive this file, see http://www.horde.org/licenses/asl.php.
+ *
+ * @author   Jan Schneider <jan@horde.org>
+ * @category Horde
+ * @license  http://www.horde.org/licenses/asl.php ASL
+ * @package  Turba
+ */
+class TurbaUpgradeSqlng extends Horde_Db_Migration_Base
+{
+    /**
+     * Upgrade.
+     */
+    public function up()
+    {
+        $t = $this->createTable('turba_sharesng', array('primaryKey' => 'share_id'));
+        $t->column('share_name', 'string', array('limit' => 255, 'null' => false));
+        $t->column('share_owner', 'string', array('limit' => 255));
+        $t->column('share_flags', 'integer', array('default' => 0, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->column('attribute_name', 'string', array('limit' => 255, 'null' => false));
+        $t->column('attribute_desc', 'string', array('limit' => 255));
+        $t->column('attribute_params', 'string', array('limit' => 7));
+        $t->end();
+
+        $this->addIndex('turba_sharesng', array('share_name'));
+        $this->addIndex('turba_sharesng', array('share_owner'));
+        $this->addIndex('turba_sharesng', array('perm_creator_' . Horde_Perms::SHOW));
+        $this->addIndex('turba_sharesng', array('perm_creator_' . Horde_Perms::READ));
+        $this->addIndex('turba_sharesng', array('perm_creator_' . Horde_Perms::EDIT));
+        $this->addIndex('turba_sharesng', array('perm_creator_' . Horde_Perms::DELETE));
+        $this->addIndex('turba_sharesng', array('perm_default_' . Horde_Perms::SHOW));
+        $this->addIndex('turba_sharesng', array('perm_default_' . Horde_Perms::READ));
+        $this->addIndex('turba_sharesng', array('perm_default_' . Horde_Perms::EDIT));
+        $this->addIndex('turba_sharesng', array('perm_default_' . Horde_Perms::DELETE));
+        $this->addIndex('turba_sharesng', array('perm_guest_' . Horde_Perms::SHOW));
+        $this->addIndex('turba_sharesng', array('perm_guest_' . Horde_Perms::READ));
+        $this->addIndex('turba_sharesng', array('perm_guest_' . Horde_Perms::EDIT));
+        $this->addIndex('turba_sharesng', array('perm_guest_' . Horde_Perms::DELETE));
+
+        $t = $this->createTable('turba_sharesng_groups', array('primaryKey' => false));
+        $t->column('share_id', 'integer', array('null' => false));
+        $t->column('group_uid', 'string', array('limit' => 255, 'null' => false));
+        $t->column('perm_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->end();
+
+        $this->addIndex('turba_sharesng_groups', array('share_id'));
+        $this->addIndex('turba_sharesng_groups', array('group_uid'));
+        $this->addIndex('turba_sharesng_groups', array('perm_' . Horde_Perms::SHOW));
+        $this->addIndex('turba_sharesng_groups', array('perm_' . Horde_Perms::READ));
+        $this->addIndex('turba_sharesng_groups', array('perm_' . Horde_Perms::EDIT));
+        $this->addIndex('turba_sharesng_groups', array('perm_' . Horde_Perms::DELETE));
+
+        $t = $this->createTable('turba_sharesng_users', array('primaryKey' => false));
+        $t->column('share_id', 'integer', array('null' => false));
+        $t->column('user_uid', 'string', array('limit' => 255));
+        $t->column('perm_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->end();
+
+        $this->addIndex('turba_sharesng_users', array('share_id'));
+        $this->addIndex('turba_sharesng_users', array('user_uid'));
+        $this->addIndex('turba_sharesng_users', array('perm_' . Horde_Perms::SHOW));
+        $this->addIndex('turba_sharesng_users', array('perm_' . Horde_Perms::READ));
+        $this->addIndex('turba_sharesng_users', array('perm_' . Horde_Perms::EDIT));
+        $this->addIndex('turba_sharesng_users', array('perm_' . Horde_Perms::DELETE));
+
+        $this->dataUp();
+    }
+
+    /**
+     * Downgrade
+     */
+    public function down()
+    {
+        $this->dropTable('turba_sharesng');
+        $this->dropTable('turba_sharesng_groups');
+        $this->dropTable('turba_sharesng_users');
+    }
+
+    public function dataUp()
+    {
+        $whos = array('creator', 'default', 'guest');
+        $perms = array(Horde_Perms::SHOW,
+                       Horde_Perms::READ,
+                       Horde_Perms::EDIT,
+                       Horde_Perms::DELETE);
+
+        $sql = 'INSERT INTO turba_sharesng (share_id, share_name, share_owner, share_flags, attribute_name, attribute_desc, attribute_params';
+        $count = 0;
+        foreach ($whos as $who) {
+            foreach ($perms as $perm) {
+                $sql .= ', perm_' . $who . '_' . $perm;
+                $count++;
+            }
+        }
+        $sql .= ') VALUES (?, ?, ?, ?, ?, ?, ?' . str_repeat(', ?', $count) . ')';
+
+        foreach ($this->select('SELECT * FROM turba_shares') as $share) {
+            $values = array($share['share_id'],
+                            $share['share_name'],
+                            $share['share_owner'],
+                            $share['share_flags'],
+                            $share['attribute_name'],
+                            $share['attribute_desc'],
+                            $share['attribute_params']);
+            foreach ($whos as $who) {
+                foreach ($perms as $perm) {
+                    $values[] = (bool)($share['perm_' . $who] & $perm);
+                }
+            }
+            $this->insert($sql, $values);
+        }
+
+        foreach (array('user', 'group') as $what) {
+            $sql = 'INSERT INTO turba_sharesng_' . $what . 's (share_id, ' . $what . '_uid';
+            $count = 0;
+            foreach ($perms as $perm) {
+                $sql .= ', perm_' . $perm;
+                $count++;
+            }
+            $sql .= ') VALUES (?, ?' . str_repeat(', ?', $count) . ')';
+
+            foreach ($this->select('SELECT * FROM turba_shares_' . $what . 's') as $share) {
+                $values = array($share['share_id'],
+                                $share[$what . '_uid']);
+                foreach ($perms as $perm) {
+                    $values[] = (bool)($share['perm'] & $perm);
+                }
+                $this->insert($sql, $values);
+            }
+        }
+    }
+}
diff --git a/turba/scripts/upgrades/convert_sql_shares_to_sqlng.php b/turba/scripts/upgrades/convert_sql_shares_to_sqlng.php
new file mode 100755 (executable)
index 0000000..3c5de3c
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/env php
+<?php
+/**
+ * This script migrates Turba's share data from the SQL Horde_Share
+ * driver to the next-generation SQL Horde_Share driver.
+ *
+ * It is supposed to run at any time after migrating Turba to the latest DB
+ * schema version. The schema migration already migrates the data once, but
+ * this script can be used to migrate the data again, e.g. if starting to use
+ * the NG driver at a later time.
+ */
+
+/* Set up the CLI environment */
+require_once dirname(__FILE__) . '/../../lib/Application.php';
+Horde_Registry::appInit('turba', array('cli' => true));
+
+require_once dirname(__FILE__) . '/../../migration/3_turba_upgrade_sqlng.php';
+
+$db = $injector->getInstance('Horde_Db_Adapter');
+$migration = new TurbaUpgradeSqlng($db);
+
+$delete = $cli->prompt('Delete existing shares from the NEW backend before migrating the OLD backend? This should be done to avoid duplicate entries or primary key collisions in the storage backend from earlier migrations.', array('y' => 'Yes', 'n' => 'No'), 'n');
+
+if ($delete == 'y' || $delete == 'Y') {
+    $db->delete('DELETE FROM turba_sharesng');
+    $db->delete('DELETE FROM turba_sharesng_users');
+    $db->delete('DELETE FROM turba_sharesng_groups');
+}
+
+$migration->dataUp();
diff --git a/whups/migration/3_whups_upgrade_sqlng.php b/whups/migration/3_whups_upgrade_sqlng.php
new file mode 100644 (file)
index 0000000..494aa4a
--- /dev/null
@@ -0,0 +1,154 @@
+<?php
+/**
+ * Adds tables for the Sqlng share driver.
+ *
+ * Copyright 2011 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you
+ * did not receive this file, see http://www.horde.org/licenses/bsdl.php.
+ *
+ * @author   Jan Schneider <jan@horde.org>
+ * @category Horde
+ * @license  http://www.horde.org/licenses/bsdl.php BSD
+ * @package  Whups
+ */
+class WhupsUpgradeSqlng extends Horde_Db_Migration_Base
+{
+    /**
+     * Upgrade.
+     */
+    public function up()
+    {
+        $t = $this->createTable('whups_sharesng', array('primaryKey' => 'share_id'));
+        $t->column('share_name', 'string', array('limit' => 255, 'null' => false));
+        $t->column('share_owner', 'string', array('limit' => 255));
+        $t->column('share_flags', 'integer', array('default' => 0, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_creator_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_default_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_guest_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->column('attribute_name', 'string', array('limit' => 255, 'null' => false));
+        $t->column('attribute_slug', 'string', array('limit' => 255));
+        $t->end();
+
+        $this->addIndex('whups_sharesng', array('share_name'));
+        $this->addIndex('whups_sharesng', array('share_owner'));
+        $this->addIndex('whups_sharesng', array('perm_creator_' . Horde_Perms::SHOW));
+        $this->addIndex('whups_sharesng', array('perm_creator_' . Horde_Perms::READ));
+        $this->addIndex('whups_sharesng', array('perm_creator_' . Horde_Perms::EDIT));
+        $this->addIndex('whups_sharesng', array('perm_creator_' . Horde_Perms::DELETE));
+        $this->addIndex('whups_sharesng', array('perm_default_' . Horde_Perms::SHOW));
+        $this->addIndex('whups_sharesng', array('perm_default_' . Horde_Perms::READ));
+        $this->addIndex('whups_sharesng', array('perm_default_' . Horde_Perms::EDIT));
+        $this->addIndex('whups_sharesng', array('perm_default_' . Horde_Perms::DELETE));
+        $this->addIndex('whups_sharesng', array('perm_guest_' . Horde_Perms::SHOW));
+        $this->addIndex('whups_sharesng', array('perm_guest_' . Horde_Perms::READ));
+        $this->addIndex('whups_sharesng', array('perm_guest_' . Horde_Perms::EDIT));
+        $this->addIndex('whups_sharesng', array('perm_guest_' . Horde_Perms::DELETE));
+
+        $t = $this->createTable('whups_sharesng_groups', array('primaryKey' => false));
+        $t->column('share_id', 'integer', array('null' => false));
+        $t->column('group_uid', 'string', array('limit' => 255, 'null' => false));
+        $t->column('perm_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->end();
+
+        $this->addIndex('whups_sharesng_groups', array('share_id'));
+        $this->addIndex('whups_sharesng_groups', array('group_uid'));
+        $this->addIndex('whups_sharesng_groups', array('perm_' . Horde_Perms::SHOW));
+        $this->addIndex('whups_sharesng_groups', array('perm_' . Horde_Perms::READ));
+        $this->addIndex('whups_sharesng_groups', array('perm_' . Horde_Perms::EDIT));
+        $this->addIndex('whups_sharesng_groups', array('perm_' . Horde_Perms::DELETE));
+
+        $t = $this->createTable('whups_sharesng_users', array('primaryKey' => false));
+        $t->column('share_id', 'integer', array('null' => false));
+        $t->column('user_uid', 'string', array('limit' => 255));
+        $t->column('perm_' . Horde_Perms::SHOW, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::READ, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::EDIT, 'boolean', array('default' => false, 'null' => false));
+        $t->column('perm_' . Horde_Perms::DELETE, 'boolean', array('default' => false, 'null' => false));
+        $t->end();
+
+        $this->addIndex('whups_sharesng_users', array('share_id'));
+        $this->addIndex('whups_sharesng_users', array('user_uid'));
+        $this->addIndex('whups_sharesng_users', array('perm_' . Horde_Perms::SHOW));
+        $this->addIndex('whups_sharesng_users', array('perm_' . Horde_Perms::READ));
+        $this->addIndex('whups_sharesng_users', array('perm_' . Horde_Perms::EDIT));
+        $this->addIndex('whups_sharesng_users', array('perm_' . Horde_Perms::DELETE));
+
+        $this->dataUp();
+    }
+
+    /**
+     * Downgrade
+     */
+    public function down()
+    {
+        $this->dropTable('whups_sharesng');
+        $this->dropTable('whups_sharesng_groups');
+        $this->dropTable('whups_sharesng_users');
+    }
+
+    public function dataUp()
+    {
+        $whos = array('creator', 'default', 'guest');
+        $perms = array(Horde_Perms::SHOW,
+                       Horde_Perms::READ,
+                       Horde_Perms::EDIT,
+                       Horde_Perms::DELETE);
+
+        $sql = 'INSERT INTO whups_sharesng (share_id, share_name, share_owner, share_flags, attribute_name, attribute_slug';
+        $count = 0;
+        foreach ($whos as $who) {
+            foreach ($perms as $perm) {
+                $sql .= ', perm_' . $who . '_' . $perm;
+                $count++;
+            }
+        }
+        $sql .= ') VALUES (?, ?, ?, ?, ?, ?' . str_repeat(', ?', $count) . ')';
+
+        foreach ($this->select('SELECT * FROM whups_shares') as $share) {
+            $values = array($share['share_id'],
+                            $share['share_name'],
+                            $share['share_owner'],
+                            $share['share_flags'],
+                            $share['attribute_name'],
+                            $share['attribute_slug']);
+            foreach ($whos as $who) {
+                foreach ($perms as $perm) {
+                    $values[] = (bool)($share['perm_' . $who] & $perm);
+                }
+            }
+            $this->insert($sql, $values);
+        }
+
+        foreach (array('user', 'group') as $what) {
+            $sql = 'INSERT INTO whups_sharesng_' . $what . 's (share_id, ' . $what . '_uid';
+            $count = 0;
+            foreach ($perms as $perm) {
+                $sql .= ', perm_' . $perm;
+                $count++;
+            }
+            $sql .= ') VALUES (?, ?' . str_repeat(', ?', $count) . ')';
+
+            foreach ($this->select('SELECT * FROM whups_shares_' . $what . 's') as $share) {
+                $values = array($share['share_id'],
+                                $share[$what . '_uid']);
+                foreach ($perms as $perm) {
+                    $values[] = (bool)($share['perm'] & $perm);
+                }
+                $this->insert($sql, $values);
+            }
+        }
+    }
+}
diff --git a/whups/scripts/upgrades/convert_sql_shares_to_sqlng.php b/whups/scripts/upgrades/convert_sql_shares_to_sqlng.php
new file mode 100755 (executable)
index 0000000..e2fc801
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/env php
+<?php
+/**
+ * This script migrates Whups's share data from the SQL Horde_Share
+ * driver to the next-generation SQL Horde_Share driver.
+ *
+ * It is supposed to run at any time after migrating Whups to the latest DB
+ * schema version. The schema migration already migrates the data once, but
+ * this script can be used to migrate the data again, e.g. if starting to use
+ * the NG driver at a later time.
+ */
+
+/* Set up the CLI environment */
+require_once dirname(__FILE__) . '/../../lib/Application.php';
+Horde_Registry::appInit('whups', array('cli' => true));
+
+require_once dirname(__FILE__) . '/../../migration/3_whups_upgrade_sqlng.php';
+
+$db = $injector->getInstance('Horde_Db_Adapter');
+$migration = new WhupsUpgradeSqlng($db);
+
+$delete = $cli->prompt('Delete existing shares from the NEW backend before migrating the OLD backend? This should be done to avoid duplicate entries or primary key collisions in the storage backend from earlier migrations.', array('y' => 'Yes', 'n' => 'No'), 'n');
+
+if ($delete == 'y' || $delete == 'Y') {
+    $db->delete('DELETE FROM whups_sharesng');
+    $db->delete('DELETE FROM whups_sharesng_users');
+    $db->delete('DELETE FROM whups_sharesng_groups');
+}
+
+$migration->dataUp();