David Létourneau
David Létourneau

Reputation: 1250

Need to convert piece of PHP code to C#

I need to convert two PhP functions (sfGetCategoryAllTree and sfSideTree) to C#. I'm not used to PhP at all. I will show you the functions and what I did by now.

/**
 * Retrieves user data given a user id or user object.
 *
 * @param string $output Optional, default is Object. Either OBJECT, ARRAY_A, or ARRAY_N.
 * @return Category|null Category on success or null on failure
 */
function sfGetCategoryAllTree($output = OBJECT,$id='') {

    global $sfdb, $table_category, $table_category_lang;

    $categories = $sfdb->run("SELECT * FROM $table_category c"'
        ORDER BY position ASC", '', true)
            ->fetchAll($output);

    $all_categories = array();
    $all_relation = array();
    $tree = array();
    foreach ($categories as $c) {

        $all_categories[$c['id']] = $c;
        if ($c['parent_id'] == null) {
            $tree[] = $c;
            $all_relation[0][] = $c['id'];
        } else {
            $all_relation[$c['parent_id']][] = $c['id'];
        }
    }

    if (isset($all_relation[0])) {
        $tree = sfSideTree($all_relation[0], $all_categories, $all_relation);
    }
    return ($tree) ? $tree : array();
}

/**
 * Helps create the tree
 *
 * @param array $branch
 * @param array $categories
 * @param array $relation
 * @return array
 */
function sfSideTree($branch, $categories, $relation) {
    $tree = array();
    if (!empty($branch)) {
        foreach ($branch as $b) {
            $aux = $categories[$b];
            if (isset($relation[$b]) && is_array($relation[$b])) {
                $aux['categories'] = sfSideTree($relation[$b], $categories, $relation);
            } else {
                $aux['categories'] = array();
            }
            $tree[] = $aux;
        }
    }
    return $tree;
}

Here what I did so far:

public void sfSideTree(int[] branch, Category[] categories, int[] relation)
        {
            Category[] tree = new Category[10];

            foreach (var b in branch)
            {
                var aux = categories[b];
                if (relation[b] != null)
                {
                    aux[]....
                }
            }
        }

        public void sfGetCategoryAllTree()
        {
            var categories = this.Query().Select().ToList();

            /*
            $all_categories = array();
            $all_relation = array();
            $tree = array();
            */
            //IList<Category> all_categories = new List<Category>();
            //IList<Category> all_relation = new List<Category>();
            //IList<Category> tree = new List<Category>();
            Category[] all_categories = new Category[10];
            int[] all_relation = new int[10];
            Category[] tree = new Category[10];


            foreach (var c in categories)
            {
                //$all_categories[$c['id']] = $c;
                all_categories[c.Id] = c;
                //all_categories.Add(new Category() { Id = item.Id });
                if (c.ParentId == 0)
                {
                    tree[??] = c; //???
                    all_relation[0] = c.Id;
                    /*

                    $tree[] = $c;
                    $all_relation[0][] = $c['id'];*/
                }
                else
                {
                    all_relation[c.ParentId] = c.Id;
                    //$all_relation[$c['parent_id']][] = $c['id'];
                }
            }

            if (all_relation != null)
            {
                sfSideTree(all_relation[0], all_categories, all_relation);
            }

                return tree;
            /*return ($tree) ? $tree: array();*/
        }

PhP arrays make life harder to translate. Does someone can help me?

David

Edit

To answer to OwlSolo here the structure of Category class

public class Category
    {
        public int Id { get; set; }
        public int ParentId { get; set; }
        public int Position { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public bool Enabled { get; set; }
    }

Upvotes: 0

Views: 143

Answers (2)

srandppl
srandppl

Reputation: 571

Coming from your comment on my last answer, this is how I would implement this in C#:

public void makeTree()
{
    //Make a Dictionary with the ID als key
    Dictionary<int, Category> categories = this.Query().Select().ToDictionary(a => a.ID, a => a);

    foreach (Category c in categories)
    {
        if (c.ParentID != 0)
        {
            if (categories[c.ParentID].children == null)
            {
                categories[c.ParentID].children = new List<Category>();
            }
            categories[c.ParentID].children.add(c);         
        }//ParentID == 0 means its a root element
    }
}

This simply creates a tree structure from you query. If you need to expand a Category just access its list of children. Unless I'm overlooking something, this is what you really want to do here. There is no need to keep separate lists or another cluttery method for traversing the tree.

If you want to list all root Categories just go:

public List<Category> getRootNodes()
{
   List<Category> rootNodes = new List<Category>();
   foreach (Category c in categories)
   {
       if (c.ParentID == 0) rootNodes.Add(c);
   }
   return rootNodes;
}

EDIT Just realized that last function is pretty uneccessary as you can do it with linq much more easily

rootNodes = catergories.Where(x => x.ParentID == 0);

Upvotes: 1

srandppl
srandppl

Reputation: 571

PHP arrays are not really 100% compatible to C# types, but you can get around that by using a lot of Dictionary for instance, as PHP lets you address field types by both int or string equivalents. This is certainly not the best practice, but so far is it rather unclear what data youre actually storing. I gave it a shot, but it probably wont work right out of the box. Depending on what data it actually is you have, some adjustments might be needed.

EDIT: In order for this to become a tree, your Category class also need a way to reference its children - in PHP this is accomplished by the ["categories"] field.

class Category
{
    [...]
    IList<Category> children;
}


//For instance as global arrays...
int[] all_categories;
int[] all_relation;



List<Category>  sfGetCategoryAllTree(output, id)
{   
    List<Category> tree;
    //$categories = $sfdb->run("SELECT * FROM $table_category c"'
    //    ORDER BY position ASC", '', true)
    //        ->fetchAll($output);  
    List<Category> categories = this.Query().Select().ToList();// Assuming this is aquivalent to the above selection statement...

    foreach (Category c in categories)
    {       
        all_categories[c.Id]  
        if (c.ParentId != 0) // The is no NULL for int, you might want to use the nullable type "int?" or an additional bool isRoot
        {
            if (tree == null) tree = new List<Category>();
            tree.Add(c);
            all_relation[0] = c.Id; 
        }else
        {
            all_relation[c.ParentId] = c.Id;
        }
    }   
    if (all_relation[0] != 0)
    {
        tree = sfSideTree(all_relation[0], all_categories, all_relation);
    }

    return tree;//returns the tree, or NULL 
}

List<Category> sfSideTree (int[] branch, Dictionary<int, Category> categories, int[] relation)
{
    List<Category> tree = new List<Category>();
    if (branch != null)
    {
        foreach (var b in branch)
        {
            if (relation[b] != null)
            {

                categories[b].categories = sdSideTree(relation[b], categories, relation)                        
            } else
            {
                categories[b].categories = new List<Category>();
            }
            tree = aux;
        }
    }
    return tree;
}

Upvotes: 1

Related Questions