#!/usr/bin/env php
<?php
/**
 * This script migrates Kronolith's share data from the datatree Horde_Share
 * driver to the SQL Horde_Share driver.
 */
if (file_exists(__DIR__ . '/../../kronolith/lib/Application.php')) {
    $baseDir = __DIR__ . '/../';
} else {
    require_once 'PEAR/Config.php';
    $baseDir = PEAR_Config::singleton()
        ->get('horde_dir', null, 'pear.horde.org') . '/kronolith/';
}
require_once $baseDir . 'lib/Application.php';
Horde_Registry::appInit('kronolith', array('cli' => true));

$db = $injector->getInstance('Horde_Db_Adapter');
$error_cnt = 0;
$delete_dt_data = false;
$answer = $cli->prompt('Do you want to keep your old datatree data or delete it?', array('Keep', 'Delete'));
if ($answer == 1) {
    $delete_dt_data = true;
}
$answer = $cli->prompt(sprintf("Data will be copied into the new tables, and %s be deleted from the datatree.\n Is this what you want?", (($delete_dt_data) ? 'WILL' : 'WILL NOT')), array('y' => 'Yes', 'n' => 'No'));
if ($answer != 'y') {
    exit;
}

/* Get the share entries */
try {
    $shares_result = $db->selectAssoc('SELECT datatree_id, datatree_name FROM horde_datatree WHERE group_uid = ' . $db->quoteString('horde.shares.kronolith'));
} catch (Horde_Db_Exception $e) {
    die($e->getMessage());
}

$query = 'SELECT attribute_name, attribute_key, attribute_value FROM horde_datatree_attributes WHERE datatree_id = ?';
foreach ($shares_result as $share_id => $share_name) {
    $data = array('share_name' => $share_name);
    $rows = $db->selectAll($query, array($share_id));
    $users = array();
    $groups = array();
    foreach ($rows as $row) {
        if ($row['attribute_name'] == 'perm_groups') {
            /* Group table entry */
            $groups[] = array('group_uid' => $row['attribute_key'],
                              'perm' => $row['attribute_value']);
        } elseif ($row['attribute_name'] == 'perm_users') {
            /* User table entry */
            $users[] = array('user_uid' => $row['attribute_key'],
                             'perm' => $row['attribute_value']);
        } else {
            /* Everything else goes in the main share table */
            switch ($row['attribute_name']) {
            case 'perm_creator':
            case 'perm_default':
            case 'perm_guest':
                $data[$row['attribute_name']] = $row['attribute_value'];
                break;

            case 'owner':
                $data['share_owner'] = $row['attribute_value'];
                break;

            case 'name':
                // Note the key to the $data array is not related to
                // the attribute_name field in the dt_attributes table.
                $data['attribute_name'] = $row['attribute_value'];
                break;

            case 'desc':
                $data['attribute_desc'] = $row['attribute_value'];
                break;
            }
        }
    }

    /* Set flags */
    $data['share_flags'] = 0;
    if (count($users)) {
        $data['share_flags'] |= 1;
    }
    if (count($groups)) {
        $data['share_flags'] |= 2;
    }

    /* Insert the new data */
    $cli->message('Migrating share data for share_id: ' . $share_id, 'cli.message');
    $error = false;
    $db->beginDbTransaction();
    try {
        $newId = insertData('kronolith_shares', $data, $db);
    } catch (Horde_Db_Exception $e) {
        $cli->message($e->getMessage(), 'cli.error');
        $error=true;
    }
    if (count($groups)) {
        foreach ($groups as $group) {
            try {
                $group['share_id'] = $newId;
                insertData('kronolith_shares_groups', $group, $db);
            } catch (Horde_Db_Exception $e) {
                $cli->message($e->getMessage(), 'cli.error');
                $error = true;
            }
        }
    }
    if (count($users)) {
        foreach ($users as $user) {
            try {
                $user['share_id'] = $newId;
                insertData('kronolith_shares_users', $user, $db);
            } catch (Horde_Db_Exception $e) {
                $cli->message($e->getMessage(), 'cli.error');
                $error = true;
            }
        }
    }

    /* Delete the datatree data, but ONLY if it was requested */
    if ($delete_dt_data && !$error) {
        $cli->message('DELETING datatree data for share_id: ' . $share_id, 'cli.message');
        try {
            $db->delete('DELETE FROM horde_datatree_attributes WHERE datatree_id = ?', array($share_id));
            $db->delete('DELETE FROM horde_datatree WHERE datatree_id = ?', array($share_id));
        } catch (Horde_Db_Exception $e) {
            $cli->message($e->getMessage(), 'cli.error');
            $error = true;
        }
    }

    /* Cleanup */
    unset($row, $rows, $data, $groups, $users);
    if ($error) {
        $db->rollbackDbTransaction();
        $cli->message('Rollback for share data for share_id: ' . $share_id, 'cli.message');
        ++$error_cnt;
    } else {
        $db->commitDbTransaction();
        $cli->message('Commit for share data for share_id: ' . $share_id, 'cli.message');
    }
}

if ($error_cnt) {
    $cli->message(sprintf("Encountered %u errors.", $error_cnt));
}
echo "\nDone.\n";

/**
 * Helper function
 */
function insertData($table, $data, $db)
{
    $fields = array_keys($data);
    $values = array_values($data);
    $sql = 'INSERT INTO ' . $table . ' (' . implode(', ', $fields) . ') VALUES (' . str_repeat('?, ', count($values) - 1) . '?)';
    return $db->insert($sql, $values);
}
