| blib/lib/Netscape/Bookmarks/Category.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % |
| statement | 138 | 185 | 74.5 |
| branch | 44 | 62 | 70.9 |
| condition | 23 | 33 | 69.7 |
| subroutine | 26 | 35 | 74.2 |
| pod | 21 | 22 | 95.4 |
| total | 252 | 337 | 74.7 |
| line | stmt | bran | cond | sub | pod | time | code |
|---|---|---|---|---|---|---|---|
| 1 | package Netscape::Bookmarks::Category; | ||||||
| 2 | |||||||
| 3 | =encoding utf8 | ||||||
| 4 | |||||||
| 5 | =head1 NAME | ||||||
| 6 | |||||||
| 7 | Netscape::Bookmarks::Category - manipulate, or create Netscape Bookmarks files | ||||||
| 8 | |||||||
| 9 | =head1 SYNOPSIS | ||||||
| 10 | |||||||
| 11 | use Netscape::Bookmarks; | ||||||
| 12 | |||||||
| 13 | #parse an existing file | ||||||
| 14 | my $bookmarks = new Netscape::Bookmarks $bookmarks_file; | ||||||
| 15 | |||||||
| 16 | #print a Netscape compatible file | ||||||
| 17 | print $bookmarks->as_string; | ||||||
| 18 | |||||||
| 19 | =head1 DESCRIPTION | ||||||
| 20 | |||||||
| 21 | THIS IS AN ABANDONED MODULE. THERE IS NO SUPPORT. YOU CAN ADOPT IT | ||||||
| 22 | IF YOU LIKE: https://pause.perl.org/pause/query?ACTION=pause_04about#takeover | ||||||
| 23 | |||||||
| 24 | The Netscape bookmarks file has several basic components: | ||||||
| 25 | |||||||
| 26 | title | ||||||
| 27 | folders (henceforth called categories) | ||||||
| 28 | links | ||||||
| 29 | aliases | ||||||
| 30 | separators | ||||||
| 31 | |||||||
| 32 | On disk, Netscape browsers store this information in HTML. In the browser, | ||||||
| 33 | it is displayed under the "Bookmarks" menu. The data can be manipulated | ||||||
| 34 | through the browser interface. | ||||||
| 35 | |||||||
| 36 | This module allows one to manipulate the bookmarks file programmatically. One | ||||||
| 37 | can parse an existing bookmarks file, manipulate the information, and write it | ||||||
| 38 | as a bookmarks file again. Furthermore, one can skip the parsing step to create | ||||||
| 39 | a new bookmarks file and write it in the proper format to be used by a Netscape | ||||||
| 40 | browser. | ||||||
| 41 | |||||||
| 42 | The Bookmarks.pm module simply parses the bookmarks file passed to it as the | ||||||
| 43 | only argument to the constructor: | ||||||
| 44 | |||||||
| 45 | my $bookmarks = new Netscape::Bookmarks $bookmarks_file; | ||||||
| 46 | |||||||
| 47 | The returned object is a Netscape::Bookmarks::Category object, since the bookmark file is | ||||||
| 48 | simply a collection of categories that contain any of the components listed | ||||||
| 49 | above. The top level (i.e. root) category is treated specially and defines the | ||||||
| 50 | title of the bookmarks file. | ||||||
| 51 | |||||||
| 52 | =head1 METHODS | ||||||
| 53 | |||||||
| 54 | =over 4 | ||||||
| 55 | |||||||
| 56 | =cut | ||||||
| 57 | |||||||
| 58 | 6 | 6 | 59607 | use strict; | |||
| 6 | 19 | ||||||
| 6 | 348 | ||||||
| 59 | |||||||
| 60 | 6 | 6 | 71 | use base qw( Netscape::Bookmarks::AcceptVisitor Netscape::Bookmarks::Isa ); | |||
| 6 | 11 | ||||||
| 6 | 1104 | ||||||
| 61 | 6 | 6 | 35 | use subs qw(); | |||
| 6 | 40 | ||||||
| 6 | 135 | ||||||
| 62 | 6 | 6 | 28 | use vars qw( $VERSION $ERROR $LAST_ID %IDS ); | |||
| 6 | 10 | ||||||
| 6 | 345 | ||||||
| 63 | |||||||
| 64 | 6 | 6 | 32 | use constant START_LIST => ' '; |
|||
| 6 | 10 | ||||||
| 6 | 468 | ||||||
| 65 | 6 | 6 | 34 | use constant END_LIST => ' '; |
|||
| 6 | 19 | ||||||
| 6 | 256 | ||||||
| 66 | 6 | 6 | 32 | use constant START_LIST_ITEM => ' |
|||
| 6 | 10 | ||||||
| 6 | 263 | ||||||
| 67 | 6 | 6 | 32 | use constant TAB => ' '; | |||
| 6 | 12 | ||||||
| 6 | 260 | ||||||
| 68 | 6 | 6 | 31 | use constant FOLDED_TRUE => 1; | |||
| 6 | 10 | ||||||
| 6 | 237 | ||||||
| 69 | 6 | 6 | 30 | use constant FOLDED_FALSE => 0; | |||
| 6 | 16 | ||||||
| 6 | 253 | ||||||
| 70 | 6 | 6 | 32 | use constant TRUE => 'true'; | |||
| 6 | 7 | ||||||
| 6 | 9697 | ||||||
| 71 | |||||||
| 72 | $VERSION = "2.304"; | ||||||
| 73 | |||||||
| 74 | %IDS = (); | ||||||
| 75 | $LAST_ID = -1; | ||||||
| 76 | |||||||
| 77 | =item Netscape::Bookmarks::Category-E |
||||||
| 78 | |||||||
| 79 | The new method creates a Category. It takes a hash reference | ||||||
| 80 | that specifies the properties of the category. The valid keys | ||||||
| 81 | in that hash are | ||||||
| 82 | |||||||
| 83 | folded collapsed state of the category ( 1 or 0 ) | ||||||
| 84 | title | ||||||
| 85 | add_date | ||||||
| 86 | description | ||||||
| 87 | |||||||
| 88 | =cut | ||||||
| 89 | |||||||
| 90 | sub new | ||||||
| 91 | { | ||||||
| 92 | 78 | 78 | 1 | 146 | my $class = shift; | ||
| 93 | 78 | 118 | my $param = shift; | ||||
| 94 | |||||||
| 95 | 78 | 105 | my $self = {}; | ||||
| 96 | 78 | 138 | bless $self, $class; | ||||
| 97 | |||||||
| 98 | 78 | 100 | 178 | $self->{'folded'} = FOLDED_TRUE unless $param->{'folded'} == FOLDED_FALSE; | |||
| 99 | 78 | 100 | 154 | $self->{'personal_toolbar_folder'} = TRUE if $param->{'personal_toolbar_folder'}; | |||
| 100 | |||||||
| 101 | 78 | 100 | 66 | 410 | unless( exists $IDS{$param->{'id'}} or $param->{'id'} =~ /\D/) | ||
| 102 | { | ||||||
| 103 | 12 | 21 | $param->{'id'} = ++$LAST_ID; | ||||
| 104 | 12 | 29 | $IDS{$LAST_ID}++; | ||||
| 105 | } | ||||||
| 106 | |||||||
| 107 | 78 | 50 | 66 | 262 | if( defined $param->{'add_date'} and $param->{'add_date'} =~ /\D/ ) | ||
| 108 | { | ||||||
| 109 | 0 | 0 | $param->{'add_date'} = 0; | ||||
| 110 | } | ||||||
| 111 | |||||||
| 112 | 78 | 176 | $self->{'mozilla'} = $param->{'mozilla'}; | ||||
| 113 | 78 | 133 | $self->{'title'} = $param->{'title'}; | ||||
| 114 | 78 | 119 | $self->{'add_date'} = $param->{'add_date'}; | ||||
| 115 | 78 | 145 | $self->{'last_modified'} = $param->{'last_modified'}; | ||||
| 116 | 78 | 115 | $self->{'id'} = $param->{'id'}; | ||||
| 117 | 78 | 129 | $self->{'description'} = $param->{'description'}; | ||||
| 118 | 78 | 156 | $self->{'thingys'} = []; | ||||
| 119 | |||||||
| 120 | 78 | 183 | $self; | ||||
| 121 | } | ||||||
| 122 | |||||||
| 123 | sub mozilla | ||||||
| 124 | { | ||||||
| 125 | 41 | 41 | 0 | 58 | my $self = shift; | ||
| 126 | 41 | 51 | my $value = shift; | ||||
| 127 | |||||||
| 128 | 41 | 50 | 75 | $self->{'mozilla'} = $value if defined $value; | |||
| 129 | |||||||
| 130 | 41 | 86 | $self->{'mozilla'}; | ||||
| 131 | } | ||||||
| 132 | |||||||
| 133 | =item $category-E |
||||||
| 134 | |||||||
| 135 | The add() function adds an element to a category. The element must be a Alias, | ||||||
| 136 | Link, Category, or Separator object. Returns TRUE or FALSE. | ||||||
| 137 | |||||||
| 138 | =cut | ||||||
| 139 | |||||||
| 140 | sub add | ||||||
| 141 | { | ||||||
| 142 | 536 | 536 | 1 | 725 | my $self = shift; | ||
| 143 | 536 | 628 | my $thingy = shift; | ||||
| 144 | |||||||
| 145 | return unless | ||||||
| 146 | 536 | 50 | 100 | 1228 | ref $thingy eq 'Netscape::Bookmarks::Link' or | ||
| 100 | |||||||
| 66 | |||||||
| 147 | ref $thingy eq 'Netscape::Bookmarks::Category' or | ||||||
| 148 | ref $thingy eq 'Netscape::Bookmarks::Separator' or | ||||||
| 149 | ref $thingy eq 'Netscape::Bookmarks::Alias'; | ||||||
| 150 | |||||||
| 151 | 536 | 717 | push @{ $self->{'thingys'} }, $thingy; | ||||
| 536 | 1194 | ||||||
| 152 | } | ||||||
| 153 | |||||||
| 154 | =item $category-E |
||||||
| 155 | |||||||
| 156 | Removes the given object from the Category by calling the object's | ||||||
| 157 | remove() method. | ||||||
| 158 | |||||||
| 159 | Returns the number of objects removed from the Category. | ||||||
| 160 | |||||||
| 161 | =cut | ||||||
| 162 | |||||||
| 163 | sub remove_element | ||||||
| 164 | { | ||||||
| 165 | 0 | 0 | 1 | 0 | my $self = shift; | ||
| 166 | 0 | 0 | my $thingy = shift; | ||||
| 167 | |||||||
| 168 | 0 | 0 | my $old_count = $self->count; | ||||
| 169 | |||||||
| 170 | $self->{'thingys'} = | ||||||
| 171 | 0 | 0 | 0 | [ grep { $_ ne $thingy and $_->remove } $self->elements ]; | |||
| 0 | 0 | ||||||
| 172 | |||||||
| 173 | 0 | 0 | return $old_count - $self->count; | ||||
| 174 | } | ||||||
| 175 | |||||||
| 176 | =item $category-E |
||||||
| 177 | |||||||
| 178 | Performs any clean up necessary to remove this object from the | ||||||
| 179 | Bookmarks tree. Although this method does not recursively remove | ||||||
| 180 | objects which it contains, it probably should. | ||||||
| 181 | |||||||
| 182 | =cut | ||||||
| 183 | |||||||
| 184 | 0 | 0 | 1 | 0 | sub remove { 1; } | ||
| 185 | |||||||
| 186 | =item $category-E |
||||||
| 187 | |||||||
| 188 | Returns title to the category. With a | ||||||
| 189 | defined argument TITLE, it replaces the current | ||||||
| 190 | title. | ||||||
| 191 | |||||||
| 192 | =cut | ||||||
| 193 | |||||||
| 194 | sub title | ||||||
| 195 | { | ||||||
| 196 | 39 | 39 | 1 | 52 | my $self = shift; | ||
| 197 | |||||||
| 198 | 39 | 50 | 76 | if( defined $_[0] ) | |||
| 199 | { | ||||||
| 200 | 0 | 0 | $self->{'title'} = shift; | ||||
| 201 | } | ||||||
| 202 | |||||||
| 203 | 39 | 76 | $self->{'title'}; | ||||
| 204 | } | ||||||
| 205 | |||||||
| 206 | =item $category-E |
||||||
| 207 | |||||||
| 208 | Returns the ID of the category. This is an arbitrary, unique number. | ||||||
| 209 | |||||||
| 210 | =cut | ||||||
| 211 | |||||||
| 212 | sub id | ||||||
| 213 | { | ||||||
| 214 | 37 | 37 | 1 | 51 | my $self = shift; | ||
| 215 | |||||||
| 216 | 37 | 66 | $self->{'id'}; | ||||
| 217 | } | ||||||
| 218 | |||||||
| 219 | =item $category-E |
||||||
| 220 | |||||||
| 221 | Returns the description of the category. With a | ||||||
| 222 | defined argument DESCRIPTION, it replaces the current | ||||||
| 223 | description. | ||||||
| 224 | |||||||
| 225 | =cut | ||||||
| 226 | |||||||
| 227 | sub description | ||||||
| 228 | { | ||||||
| 229 | 49 | 49 | 1 | 69 | my $self = shift; | ||
| 230 | |||||||
| 231 | 49 | 100 | 88 | if( defined $_[0] ) | |||
| 232 | { | ||||||
| 233 | 10 | 19 | $self->{'description'} = shift; | ||||
| 234 | } | ||||||
| 235 | |||||||
| 236 | 49 | 84 | $self->{'description'}; | ||||
| 237 | } | ||||||
| 238 | |||||||
| 239 | =item $category-E |
||||||
| 240 | |||||||
| 241 | Returns the folded state of the category (TRUE or FALSE). If the category is | ||||||
| 242 | "folded", Netscape shows a collapsed folder for this category. | ||||||
| 243 | |||||||
| 244 | =cut | ||||||
| 245 | |||||||
| 246 | sub folded | ||||||
| 247 | { | ||||||
| 248 | 37 | 37 | 1 | 49 | my $self = shift; | ||
| 249 | |||||||
| 250 | 37 | 100 | 89 | return $self->{'folded'} ? 1 : 0; | |||
| 251 | } | ||||||
| 252 | |||||||
| 253 | =item $category-E |
||||||
| 254 | |||||||
| 255 | Returns the ADD_DATE attribute of the category. | ||||||
| 256 | |||||||
| 257 | =cut | ||||||
| 258 | |||||||
| 259 | sub add_date | ||||||
| 260 | { | ||||||
| 261 | 37 | 37 | 1 | 45 | my $self = shift; | ||
| 262 | |||||||
| 263 | 37 | 83 | return $self->{'add_date'}; | ||||
| 264 | } | ||||||
| 265 | |||||||
| 266 | =item $category-E |
||||||
| 267 | |||||||
| 268 | Returns the LAST_MODIFIED attribute of the category. | ||||||
| 269 | |||||||
| 270 | =cut | ||||||
| 271 | |||||||
| 272 | sub last_modified | ||||||
| 273 | { | ||||||
| 274 | 37 | 37 | 1 | 47 | my $self = shift; | ||
| 275 | |||||||
| 276 | 37 | 53 | return $self->{'last_modified'}; | ||||
| 277 | } | ||||||
| 278 | |||||||
| 279 | =item $category-E |
||||||
| 280 | |||||||
| 281 | Returns the PERSONAL_TOOLBAR_FOLDER attribute of the category. | ||||||
| 282 | |||||||
| 283 | =cut | ||||||
| 284 | |||||||
| 285 | sub personal_toolbar_folder | ||||||
| 286 | { | ||||||
| 287 | 37 | 37 | 1 | 49 | my $self = shift; | ||
| 288 | |||||||
| 289 | 37 | 58 | return $self->{'personal_toolbar_folder'}; | ||||
| 290 | } | ||||||
| 291 | |||||||
| 292 | =item $category-E |
||||||
| 293 | |||||||
| 294 | In scalar context returns an array reference to the elements in | ||||||
| 295 | the category. In list context returns a list of the elements in | ||||||
| 296 | the category. | ||||||
| 297 | |||||||
| 298 | =cut | ||||||
| 299 | |||||||
| 300 | sub elements | ||||||
| 301 | { | ||||||
| 302 | 44 | 44 | 1 | 63 | my $self = shift; | ||
| 303 | |||||||
| 304 | 44 | 50 | 71 | if( wantarray ) { @{ $self->{'thingys'} } } | |||
| 44 | 56 | ||||||
| 44 | 133 | ||||||
| 305 | 0 | 0 | else { $self->{'thingys'} } | ||||
| 306 | } | ||||||
| 307 | |||||||
| 308 | =item $category-E |
||||||
| 309 | |||||||
| 310 | Returns a count of the number of objects in the Category. | ||||||
| 311 | |||||||
| 312 | =cut | ||||||
| 313 | |||||||
| 314 | 0 | 0 | 1 | 0 | sub count { scalar @{ $_[0]->{'thingys'} } } | ||
| 0 | 0 | ||||||
| 315 | |||||||
| 316 | =item $category-E |
||||||
| 317 | |||||||
| 318 | Returns a list of the Category objects in the category. | ||||||
| 319 | |||||||
| 320 | =cut | ||||||
| 321 | |||||||
| 322 | sub categories | ||||||
| 323 | { | ||||||
| 324 | 0 | 0 | 1 | 0 | my $self = shift; | ||
| 325 | |||||||
| 326 | 0 | 0 | my @list = grep ref $_ eq 'Netscape::Bookmarks::Category', | ||||
| 327 | $self->elements; | ||||||
| 328 | |||||||
| 329 | 0 | 0 | return @list; | ||||
| 330 | } | ||||||
| 331 | |||||||
| 332 | =item $category-E |
||||||
| 333 | |||||||
| 334 | Returns a list of the Link objects in the category. | ||||||
| 335 | |||||||
| 336 | =cut | ||||||
| 337 | |||||||
| 338 | sub links | ||||||
| 339 | { | ||||||
| 340 | 0 | 0 | 1 | 0 | my $self = shift; | ||
| 341 | |||||||
| 342 | 0 | 0 | my @list = grep ref $_ eq 'Netscape::Bookmarks::Link', | ||||
| 343 | $self->elements; | ||||||
| 344 | |||||||
| 345 | 0 | 0 | return @list; | ||||
| 346 | } | ||||||
| 347 | |||||||
| 348 | =item $category-E |
||||||
| 349 | |||||||
| 350 | Returns an HTML string representation of the category, but not | ||||||
| 351 | the elements of the category. | ||||||
| 352 | |||||||
| 353 | =cut | ||||||
| 354 | |||||||
| 355 | sub as_headline | ||||||
| 356 | { | ||||||
| 357 | 37 | 37 | 1 | 54 | my $self = shift; | ||
| 358 | |||||||
| 359 | 37 | 100 | 58 | my $folded = $self->folded ? "FOLDED" : ""; | |||
| 360 | 37 | 65 | my $title = $self->title; | ||||
| 361 | 37 | 66 | my $desc = $self->description; | ||||
| 362 | 37 | 64 | my $add_date = $self->add_date; | ||||
| 363 | 37 | 62 | my $last_modified = $self->last_modified; | ||||
| 364 | 37 | 59 | my $id = $self->id; | ||||
| 365 | 37 | 341 | my $personal_toolbar_folder = $self->personal_toolbar_folder; | ||||
| 366 | |||||||
| 367 | 37 | 100 | 66 | 104 | $desc = defined $desc && $desc ne '' ? "\n |
||
| 368 | |||||||
| 369 | 37 | 100 | 56 | $folded = $folded ? qq|FOLDED| : ''; | |||
| 370 | 37 | 100 | 63 | $add_date = $add_date ? qq|ADD_DATE="$add_date"| : ''; | |||
| 371 | 37 | 100 | 62 | $last_modified = $last_modified ? qq|LAST_MODIFIED="$last_modified"| : ''; | |||
| 372 | 37 | 100 | 57 | $personal_toolbar_folder = $personal_toolbar_folder | |||
| 373 | ? qq|PERSONAL_TOOLBAR_FOLDER="true"| : ''; | ||||||
| 374 | 37 | 100 | 123 | $id = $id =~ m/\D/ ? qq|ID="$id"| : ''; | |||
| 375 | |||||||
| 376 | 37 | 104 | my $attr = join " ", grep $_, ($folded, $add_date, $last_modified, | ||||
| 377 | $personal_toolbar_folder, $id ); | ||||||
| 378 | |||||||
| 379 | 37 | 50 | 101 | $attr = " " . $attr if $attr; | |||
| 380 | 37 | 106 | $attr =~ s/\s+$//; # XXX: ugh | ||||
| 381 | |||||||
| 382 | 37 | 116 | return qq|$title$desc| |
||||
| 383 | } | ||||||
| 384 | |||||||
| 385 | =item $category-E |
||||||
| 386 | |||||||
| 387 | This method performs a depth-first traversal of the Bookmarks | ||||||
| 388 | tree and executes the CODE reference at each node. | ||||||
| 389 | |||||||
| 390 | The CODE reference receives two arguments - the object on which | ||||||
| 391 | it should operate and its level in the tree. | ||||||
| 392 | |||||||
| 393 | =cut | ||||||
| 394 | |||||||
| 395 | sub recurse | ||||||
| 396 | { | ||||||
| 397 | 0 | 0 | 1 | 0 | my $self = shift; | ||
| 398 | 0 | 0 | my $sub = shift; | ||||
| 399 | 0 | 0 | 0 | my $level = shift || 0; | |||
| 400 | |||||||
| 401 | 0 | 0 | 0 | unless( ref $sub eq 'CODE' ) | |||
| 402 | { | ||||||
| 403 | 0 | 0 | warn "Argument to recurse is not a code reference"; | ||||
| 404 | 0 | 0 | return; | ||||
| 405 | } | ||||||
| 406 | |||||||
| 407 | 0 | 0 | $sub->( $self, $level ); | ||||
| 408 | |||||||
| 409 | 0 | 0 | ++$level; | ||||
| 410 | 0 | 0 | foreach my $element ( $self->elements ) | ||||
| 411 | { | ||||||
| 412 | 0 | 0 | 0 | if( $element->isa( __PACKAGE__ ) ) | |||
| 413 | { | ||||||
| 414 | 0 | 0 | $element->recurse( $sub, $level ); | ||||
| 415 | } | ||||||
| 416 | else | ||||||
| 417 | { | ||||||
| 418 | 0 | 0 | $sub->( $element, $level ); | ||||
| 419 | } | ||||||
| 420 | } | ||||||
| 421 | 0 | 0 | --$level; | ||||
| 422 | |||||||
| 423 | } | ||||||
| 424 | |||||||
| 425 | =item $category-E |
||||||
| 426 | |||||||
| 427 | This method performs a depth-first traversal of the Bookmarks | ||||||
| 428 | tree and introduces the visitor object to each object. | ||||||
| 429 | |||||||
| 430 | This is different from recurse() which only calls its | ||||||
| 431 | CODEREF on nodes. The VISITOR operates on nodes and | ||||||
| 432 | vertices. The VISITOR must have a visit() method | ||||||
| 433 | recognizable by can(). This method does not trap | ||||||
| 434 | errors in the VISITOR. | ||||||
| 435 | |||||||
| 436 | See L |
||||||
| 437 | Visitors. | ||||||
| 438 | |||||||
| 439 | =cut | ||||||
| 440 | |||||||
| 441 | sub introduce | ||||||
| 442 | { | ||||||
| 443 | 5 | 5 | 1 | 369 | my $self = shift; | ||
| 444 | 5 | 9 | my $visitor = shift; | ||||
| 445 | 5 | 100 | 18 | my $level = shift || 0; | |||
| 446 | |||||||
| 447 | 5 | 50 | 29 | unless( $visitor->can('visit') ) | |||
| 448 | { | ||||||
| 449 | 0 | 0 | warn "Argument to introduce cannot visit()!"; | ||||
| 450 | 0 | 0 | return; | ||||
| 451 | } | ||||||
| 452 | |||||||
| 453 | 5 | 25 | $self->visitor( $visitor ); | ||||
| 454 | |||||||
| 455 | 5 | 11 | ++$level; | ||||
| 456 | 5 | 17 | foreach my $element ( $self->elements ) | ||||
| 457 | { | ||||||
| 458 | |||||||
| 459 | 16 | 100 | 209 | if( $element->isa( __PACKAGE__ ) ) | |||
| 460 | { | ||||||
| 461 | 4 | 17 | $element->introduce( $visitor, $level ); | ||||
| 462 | } | ||||||
| 463 | else | ||||||
| 464 | { | ||||||
| 465 | 12 | 67 | $element->visitor( $visitor ); | ||||
| 466 | } | ||||||
| 467 | |||||||
| 468 | } | ||||||
| 469 | 5 | 141 | --$level; | ||||
| 470 | |||||||
| 471 | } | ||||||
| 472 | |||||||
| 473 | =item $category-E |
||||||
| 474 | |||||||
| 475 | Sorts the elements in the category using the provided CODE | ||||||
| 476 | reference. If you do not specify a CODE reference, the | ||||||
| 477 | elements are sorted by title (with the side effect of | ||||||
| 478 | removing Separators from the Category). | ||||||
| 479 | |||||||
| 480 | This function does not recurse, although you can use | ||||||
| 481 | the recurse() method to do that. | ||||||
| 482 | |||||||
| 483 | Since the built-in sort() uses the package variables | ||||||
| 484 | C<$a> and C<$b>, your sort subroutine has to make sure | ||||||
| 485 | that it is accessing the right C<$a> and C<$b>, which | ||||||
| 486 | are the ones in the package C |
||||||
| 487 | You can start your CODE reference with a package | ||||||
| 488 | declaration to ensure the right thing happens: | ||||||
| 489 | |||||||
| 490 | my $sub = sub { | ||||||
| 491 | package Netscape::Bookmarks::Category; | ||||||
| 492 | |||||||
| 493 | $b->title cmp $a->title; | ||||||
| 494 | }; | ||||||
| 495 | |||||||
| 496 | $category->sort_elements( $sub ); | ||||||
| 497 | |||||||
| 498 | If you know a better way to do this, please let me know. :) | ||||||
| 499 | |||||||
| 500 | =cut | ||||||
| 501 | |||||||
| 502 | sub sort_elements | ||||||
| 503 | { | ||||||
| 504 | 0 | 0 | 1 | 0 | my $self = shift; | ||
| 505 | 0 | 0 | my $sub = shift; | ||||
| 506 | |||||||
| 507 | 0 | 0 | 0 | 0 | if( defined $sub and not ref $sub eq 'CODE' ) | ||
| 0 | |||||||
| 508 | { | ||||||
| 509 | 0 | 0 | warn "Second argument to sort_elements is not a CODE reference."; | ||||
| 510 | 0 | 0 | return; | ||||
| 511 | } | ||||||
| 512 | elsif( not defined $sub ) | ||||||
| 513 | { | ||||||
| 514 | 0 | 0 | 0 | $sub = sub { $a->title cmp $b->title }; | |||
| 0 | 0 | ||||||
| 515 | } | ||||||
| 516 | |||||||
| 517 | 0 | 0 | local *my_sorter = $sub; | ||||
| 518 | |||||||
| 519 | $self->{'thingys'} = [ sort my_sorter | ||||||
| 520 | 0 | 0 | grep { not $_->isa( 'Netscape::Bookmarks::Separator' ) } | ||||
| 521 | 0 | 0 | @{ $self->{'thingys'} } ]; | ||||
| 0 | 0 | ||||||
| 522 | } | ||||||
| 523 | |||||||
| 524 | =item $category-E |
||||||
| 525 | |||||||
| 526 | Returns an HTML string representation of the category as the | ||||||
| 527 | top level category, along with all of the elements of the | ||||||
| 528 | category and the Categories that it contains, recursively. | ||||||
| 529 | |||||||
| 530 | =cut | ||||||
| 531 | |||||||
| 532 | sub as_string | ||||||
| 533 | { | ||||||
| 534 | 2 | 2 | 1 | 1277 | my $self = shift; | ||
| 535 | |||||||
| 536 | 2 | 10 | my $title = $self->title; | ||||
| 537 | 2 | 100 | 7 | my $desc = $self->description || "\n"; | |||
| 538 | |||||||
| 539 | 2 | 100 | 7 | my $meta = $self->mozilla ? | |||
| 540 | qq|\n| : | ||||||
| 541 | ''; | ||||||
| 542 | |||||||
| 543 | 2 | 10 | my $str = <<"HTML"; | ||||
| 544 | |||||||
| 545 | $meta | ||||||
| 548 | |
||||||
| 549 | $title |
||||||
| 550 | |||||||
| 551 | HTML | ||||||
| 552 | |||||||
| 553 | 2 | 100 | 66 | 6 | $str .= " |
||
| 554 | |||||||
| 555 | 2 | 6 | $str .= START_LIST . "\n"; | ||||
| 556 | |||||||
| 557 | 2 | 10 | foreach my $element ( $self->elements ) | ||||
| 558 | { | ||||||
| 559 | 34 | 73 | $str .= $self->_as_string( $element, 1 ); | ||||
| 560 | } | ||||||
| 561 | |||||||
| 562 | 2 | 6 | $str .= END_LIST . "\n"; | ||||
| 563 | |||||||
| 564 | 2 | 167 | return $str; | ||||
| 565 | } | ||||||
| 566 | |||||||
| 567 | # _as_string does most of the work that as_string would normally | ||||||
| 568 | # do. | ||||||
| 569 | sub _as_string | ||||||
| 570 | { | ||||||
| 571 | 268 | 268 | 345 | my $self = shift; | |||
| 572 | 268 | 309 | my $obj = shift; | ||||
| 573 | 268 | 356 | my $level = shift; | ||||
| 574 | |||||||
| 575 | 268 | 314 | my $str; | ||||
| 576 | 268 | 100 | 100 | 648 | if( ref $obj eq 'Netscape::Bookmarks::Category' ) | ||
| 100 | |||||||
| 50 | |||||||
| 577 | { | ||||||
| 578 | 37 | 95 | $str .= TAB x ($level) . START_LIST_ITEM . $obj->as_headline; | ||||
| 579 | |||||||
| 580 | 37 | 100 | 71 | unless( $self->mozilla ) | |||
| 581 | { | ||||||
| 582 | 4 | 8 | $str .= TAB x ($level-1) . START_LIST . "\n"; | ||||
| 583 | } | ||||||
| 584 | else | ||||||
| 585 | { | ||||||
| 586 | 33 | 62 | $str .= TAB x ($level) . START_LIST . "\n"; | ||||
| 587 | } | ||||||
| 588 | |||||||
| 589 | 37 | 46 | ++$level; | ||||
| 590 | 37 | 67 | foreach my $ref ( $obj->elements ) | ||||
| 591 | { | ||||||
| 592 | 234 | 410 | $str .= $self->_as_string( $ref, $level ); | ||||
| 593 | } | ||||||
| 594 | 37 | 59 | --$level; | ||||
| 595 | |||||||
| 596 | 37 | 73 | $str .= TAB x ($level) . END_LIST . "\n"; | ||||
| 597 | } | ||||||
| 598 | elsif( ref $obj eq 'Netscape::Bookmarks::Link' or | ||||||
| 599 | ref $obj eq 'Netscape::Bookmarks::Alias' ) | ||||||
| 600 | { | ||||||
| 601 | 229 | 537 | $str .= TAB x ($level) . START_LIST_ITEM | ||||
| 602 | . $obj->as_string . "\n" | ||||||
| 603 | } | ||||||
| 604 | elsif( ref $obj eq 'Netscape::Bookmarks::Separator' ) | ||||||
| 605 | { | ||||||
| 606 | 2 | 6 | $str .= TAB x ($level) . $obj->as_string . "\n" | ||||
| 607 | } | ||||||
| 608 | |||||||
| 609 | 268 | 782 | return $str; | ||||
| 610 | |||||||
| 611 | } | ||||||
| 612 | |||||||
| 613 | =item $obj->write_file( FILENAME ) | ||||||
| 614 | |||||||
| 615 | UNIMPLEMENTED! | ||||||
| 616 | |||||||
| 617 | =cut | ||||||
| 618 | |||||||
| 619 | sub write_file | ||||||
| 620 | { | ||||||
| 621 | 0 | 0 | 1 | my $self = shift; | |||
| 622 | 0 | my $filename = shift; | |||||
| 623 | |||||||
| 624 | 0 | return; | |||||
| 625 | } | ||||||
| 626 | |||||||
| 627 | "if you want to beleive everything you read, so be it."; | ||||||
| 628 | |||||||
| 629 | __END__ |