<?php
/**
 * Phoebe pedagogic planner
 *
 * PHP version 5
 *
 * LICENSE: The GNU General Public License (GPL), version 2. See LICENSE.txt
 *
 * Copyright (c) 2006-2008 JISC/HEFCE/University of Oxford
 *
 * @author      David Balch <david.balch@conted.ox.ac.uk>
 * @license     http://opensource.org/licenses/gpl-license.php GPL2
 * @link        http://phoebe-project.conted.ox.ac.uk/
 */

include_once($_SERVER['DOCUMENT_ROOT'].'/inc/core.php');
include_once($_SERVER['DOCUMENT_ROOT'].'/inc/utils.php');
include_once($_SERVER['DOCUMENT_ROOT'].'/inc/session.php');

if (isset($_GET) && !isset($cloneId)) {
    // Page called directly: Get the design id, and return data automatically.
    if (ctype_digit($_GET['design_id'])) {
        $design_id = $_GET['design_id'];
        if(userOwnsDesign($design_id, $_SESSION['userid'])) {
            switch ($_GET['mode']) {
                case "debug":
                    echo tablefromArray(getAll($design_id, 'array'));
                    break;

                case "json":
                    // Build JSON format result
                    $json = json_encode(getAll($design_id, 'array'));
                    // Return the JSON result
                    header("Content-Type: application/json");
                    echo $json;
                    break;

                case "printArray":
                    print_r(getAll($design_id, 'array'));
                    break;
            }
        } else if($_SERVER['SCRIPT_NAME'] != '/view/viewDesign.php') {
            echo "{OWNER: false}";
        }
    }
} else if (ctype_digit($cloneId)) {
    // Get the design id (data will be retrived via a function call).
    $design_id = $cloneId;
}

if (!isset($design_id)) {
    die("No design id.");
} else if(strpos($content['settings'], 'designEdit') !== false || strpos($content['settings'], 'structureEdit') !== false) {
    // user wants to edit the design or structure - are they allowed?
    //$_SESSION['userid']
}

// Check ownership of a design
function userOwnsDesign($design_id, $user_id) {
    global $mdb2;
    //echo "Des: $design_id, User: $user_id\n";
    $sql = 'SELECT owner_id FROM designs '.
           'WHERE design_id = '.$design_id;

    //echo $sql.'<br>';
    $design = $mdb2->queryRow($sql);
    if (PEAR::isError($design)) {
        die($design->getMessage());
    } else if($design['owner_id'] == $user_id) {
        return true;
    } else {
        return false;
    }
}

// Get all design properties, info, references, etc. in a specified format
function getAll($design_id, $format, $startProp = null) {
    $arrayAll = array(
                'designInfo' => getDesignInfoArray($design_id),
                'props' => getDesignArray($design_id, $startProp),
                'propertyTypes' => getPropTypeArray(),
                'referenceTypes' => getRefTypeArray()
                );

    switch ($format) {
        case "array":
            return $arrayAll;
            break;
        case "json":
            return json_encode($arrayAll);
            break;
    }
}

function getDesign($design_id, $format, $startProp) {
    $arrayDesign = getDesignArray($design_id, $startProp);
    switch ($format) {
        case "array":
            return $arrayDesign;
            break;
        case "json":
            return json_encode($arrayDesign);
            break;
    }
}

function getDesignXml() {
    global $design_id;
    // Build XML format result
    require_once 'XML/Serializer.php';
    // An array of serializer options
    $serializer_options = array (
       'addDecl' => false,
       'encoding' => 'UTF-8',
       'indent' => '  ',
       'rootName' => 'data',
       'defaultTagName' => 'item',
       'replaceEntities' => false,
    ); 
    // Instantiate the serializer with the options
    $Serializer = &new XML_Serializer($serializer_options);

    // Serialize the data structure
    $designXml = $Serializer->serialize(getAll($design_id, 'array'));

    // Check whether serialization worked
    if (PEAR::isError($designXml)) {
       die($designXml->getMessage());
    } else {
        $designXml = $Serializer->getSerializedData();
        $decl = '<?xml version="1.0" encoding="UTF-8"?>';
        $ent = '<!DOCTYPE xsl:stylesheet [<!ENTITY nbsp "&#160;">]>';
        $designXml = $decl.$ent.$designXml;
    }
    //echo $designXml;
    return $designXml;
}

// Get metadata for the design
function getDesignInfoArray($design_id) {
    global $mdb2;
    $sql = 'SELECT * FROM designs '.
           ' LEFT OUTER JOIN users'.
           ' ON designs.owner_id = users.user_id '.
           'WHERE designs.design_id = '.$design_id;

    //echo $sql.'<br>';
    $design = $mdb2->queryRow($sql);
    if (PEAR::isError($design)) {
        echo ($design->getMessage());
    }

    unset($design['password_hash']);
    unset($design['confirmation_code']);

    return $design;
}

// Get the design
function getDesignArray($design_id, $rootPropId = null, $rootPropType = null) {
    global $mdb2, $properties;
    //echo "getDesignArray($design_id, $rootPropId)";
    // Get design properties
    $sql = 'SELECT * FROM properties'.
           ' WHERE parent_design_id = '.$design_id.
           ' ORDER BY root_item';
    //echo $sql.'<br>';
    $properties = $mdb2->queryAll($sql);
    if (PEAR::isError($properties)) {
        echo ($properties->getMessage());
    }
    //echo tablefromArray($properties);

    // Get design references
    $sql = 'SELECT * FROM refs '.
           'WHERE parent_design_id = '.$design_id;
    //echo $sql.'<br>';
    $refs = $mdb2->queryAll($sql);
    if (PEAR::isError($refs)) {
        echo ($refs->getMessage());
    }

    // Add references to properties
    foreach($refs as $ref) {
        foreach($properties as &$prop) {
            if ($prop['prop_id'] == $ref['parent_property_id']) {
                $prop['references'][] = $ref;
            }
        }
    }

    // Build hierarchy of properties from the array
    $props = array();
    if (isset($rootPropId)) {
        // Use specified prop as root
        foreach($properties as $theProp) {
            // Add top level properties
            if($theProp['prop_id'] == $rootPropId) {
                // Add new property as a child
                addChild($theProp, $props, $rootPropType, false);
            }
        }
    } else {
        // Use all props for this design
        foreach($properties as $theProp) {
            // Add top level properties
            if($theProp['root_item'] != '') {
                // Add new property as a child
                addChild($theProp, $props, 0);
            }
        }
    }

    return $props;
}

function addChild($child, &$parentNode, $propType, $followSiblings=true) {
    // Add a given property to the hierarchy
    // $child - from the $properties array of database results, and should be copied
    // $parentNode - a reference to the parent node in the $props array hierarchy
    // $propType - number representing how deep in the hierarchy a property is

    // Mark parent id
    $child['parent_id'] = $parentNode['prop_id'];
    // Mark hierarchy level
    $child['type'] = $propType;

    // Copy the node
    $newNode = $child;

    // Add the property to the parent as a reference
    $parentNode['children'][] = &$newNode;

    // Add any child properties
    if (isset($child['first_child_id'])) {
        $test = getPropById($child['first_child_id']);
        addChild(getPropById($child['first_child_id']), $newNode, $propType+1);
    }

    if ($followSiblings) {
        // Add any siblings
        if (isset($child['next_sibling_id'])) {
            addChild(getPropById($child['next_sibling_id']), $parentNode, $propType);
        }
    }

}

function &getPropById($id) {
    // Get a property from the array, given it's id
    global $properties;
    foreach($properties as $theProp) {
        if($theProp['prop_id'] == $id) {
            return $theProp;
        }
    }
}

function &getNodeById($id, &$node) {
    // Return a reference to a hierarchy node with a given id
    foreach($node['children'] as &$prop) {
        if ($prop['prop_id'] == $id) {
            // If this property matches by id, use it
            $node =& $prop;
        } elseif (isset($prop['children'])) {
            // Recurse along branches looking for the matching id
            $node =& getNodeById($id, $prop);
        }
    }
    // Return the node
    return $node;
}

// Get property types
function getPropTypeArray() {
    global $mdb2;
    $sql = 'SELECT * FROM property_types';
    $property_types = $mdb2->queryAll($sql);
    if (PEAR::isError($property_types)) {
        echo ($property_types->getMessage());
    }
    $propertyTypes = array();
    foreach($property_types as $type) {
        $propertyTypes[$type['property_type_id']] = $type['property_type_name'];
    }
    return $propertyTypes;
    unset($property_types);
}

// Get reference types
function getRefTypeArray() {
    global $mdb2;
    $sql = 'SELECT * FROM ref_types';
    $ref_types = $mdb2->queryAll($sql);
    if (PEAR::isError($ref_types)) {
        echo ($ref_types->getMessage());
    }
    $referenceTypes = array();
    foreach($ref_types as $type) {
        $referenceTypes[$type['ref_type_id']] = array('name'=>$type['ref_name'], 'description'=>$type['description']);
    }
    return $referenceTypes;
    unset($property_types);
}
?>