OK, I'm going to assume that I can modify your Category class. If not, you can simply derive a new class from it, and place my additions in that.
First, lets stop using that nasty "field" method. We can simply define:
sub name { shift->field('name') }
sub sub_cat_ids { @{shift->field('sub_cats') }
That'll get rid of a bit of the line noise.
Next, I want a more powerful 'new' operator. To avoid confusion, I'll name it new_tree. Later, we may rename it back to "new":
sub new_tree
{
my $class = shift;
my $id = shift;
my $depth = shift;
my $self = $class->new($id);
$self->{_depth} = $depth;
$self->{_sub_cats} = [
sort { $a->name cmp $b->name }
map { $class->new_tree($_, $depth+1) }
$self->sub_cat_ids
];
return $self;
}
sub sub_cats { @{shift->{_sub_cats} }
With these methods in place, we can add one final method to return the flattened list:
sub as_hash
{
my $self = shift;
my $name = $self->name;
my $depth = $self->depth;
my $id = $self->id;
return { depth->$depth, id=>$id, name=>$name };
}
sub as_flattened_list
{
my $self=shift;
return
$self->as_hash,
map { $_->as_flattened_list } $self->sub_cats
}
Finally, we need to modify your BuildCatList function to use the upgraded Category class:
sub BuildCatList
{
my $top = Category->new_tree("top", 0);
my @cats_list = $top->as_flattened_list;
my $cats = &main::GetDB('cats');
$cats->{'~cat_list'} = &main::nfreeze( \@cat_list );
}
I've omitted all your undef checks; you can add them back if you want. --Dave. |