Krang::Element - element data objects
use Krang::ClassLoader 'Element';
# create a new top-level element, passing in the class name and
# containing object
my $element = pkg('Element')->new(class => "article", object => $story);
# add a sub-element my $para = $element->add_child(class => "paragraph");
# add data to the sub-element
$para->data("some test data here");
# get a reference to the parent of $para, aka $element $parent = $para->parent();
# get a reference to the root element of this tree, also $element $root = $para->root();
# another way to add a paragraph, this time in one step
$element->add_child(class => "paragraph",
data => "some test data here",
);
# save the element to the database, cascading through children $element->save();
# make some changes $element->add_child(class => "horizontal_rule");
# make a copy of the element tree $copy = $element->clone();
# loop through child elements, printing out data elements
foreach ($element->children()) {
print $_->display_name, " => ", $_->data, "\n";
}
# same thing, but recurses through children of children too
use Krang::ClassLoader Element => qw(foreach_element);
foreach_element {
print $_->display_name, " => ", $_->data, "\n";
} $element;
# find a list of all paragraphs in the tree, using XPath-esque
# notation
@para = $element->match('//paragraph');
# get the first paragraph of the second page
($para) = $element->match('/page[1]/paragraph[0]');
# get a list of potential additional child classes, taking into # account max setting @classes = $element->available_child_classes();
# load a top-level element by id
$element1 = pkg('Element')->load(element_id => 1, object => $story);
# delete it from the database $element1->delete();
This module implements elements in Krang. Krang elements belong to a
single element class, see Krang::ElementClass for details. Krang
elements exist to contain child elements and/or store data. All
complex functionality, like publish() and display_form(), is proxied
to the element class.
$element = Krang::Element->new(class => "article", object => $object)The 'object' parameter is required for top-level elements and must contain a reference to the object containing this element.
Other options correspond to attribute methods below:
When an element is created, any child elements with
$child->class->min greater than one will be automatically created
as children of the new element. This may be supressed by passing
no_expand => 1 to new(), but this should only be done from within
this class.
$element_id = $element->element_id()undef until after
the first save().
$class = $element->class()name of a top-level element class (ex. ``article'') or an object.
The return value is always an object.
NOTE: Setting this after the object is created is not a good idea.
$element->data($data)$data = $element->data()freeze_data().
$object = $element->object()$object = $element->story()object() if
$element->object->isa('Krang::Story') and croaks otherwise.
$object = $element->media()object() if
$element->object->isa('Krang::Media') and croaks otherwise.
$object = $element->category()object() if
$element->object->isa('Krang::Category') and croaks otherwise.
$parent = $element->parent()undef for the root
element.
$root = $element->root()@children = $element->children($name)@children = $element->children(name => 'paragraph')@children = $element->children(class => 'Default::image')@children = $element->children(isa => 'Krang::ElementClass::Media')add_child(). To delete a child from the list of
children, see remove_children(). To reorder the list of
children, use reorder_children().
This method will croak when passed more than one named argument.
@children_data = $element->children_data($name)@children = $element->children_data(name => 'paragraph')@children = $element->children_data(class => 'Default::image')@children = $element->children_data(isa => 'Krang::ElementClass::Media')This method will croak when passed more than one named argument.
$count = $element->children_count()$child = $element->add_child(class => "paragraph", %args)$child = $element->add_child(class => $class_obj, %args)children
list. If called with a string then the class will be looked up in the
list of child classes for this element class. An object may be
passed, in which case it must belong to the
$element->class->children list of element classes.
Extra %args are passed along to Krang::Element->new()
unchanged.
Returns the newly created child object.
$child = $element->replace_child(class => "paragraph", position => 1)$child = $element->replace_child(class => $class_obj, position => 3)children
list in place of the element currently at the given position.
If called with a string then the class will be looked up in the list
of child classes for this element class. An object may be passed,
in which case it must belong to the $element->class->children
list of element classes.
Extra %args are passed along to Krang::Element->new() unchanged.
Returns the newly created child object.
Exceptions
max restriction rules
then a Krang::MaxChildClassViolation exception will be thrown.
If the new element can't replace the old one because of min restriction
rules then a MinChildClassViolation exception will be thrown.
$element->remove_children(10, 20)$element->remove_children($child10, $child20)Note that removing a child will alter the xpath()s of children in the same class later in the list. For example, removing the third page ('/page[2]') will cause '/page[3]' and '/page[4]' to become '/page[2]' and '/page[3]'.
$element->reorder_children(0, 1, 2, 4, 3)$element->reorder_children($child1, $child2, $child4, $child3)my $deck = $element->child('deck')undef if a child of the
specified class does not exist.
$text = $element->child_data('deck')undef if a child of the specified class does not exist. This is
better than using child('name')->data because it won't produce
an error if child('name') doesn't exist.
$element->save()element_id is guaranteed to be filled in. Should only be
called on top-level elements.
@classes = $element->available_child_classes()$child->class->max, and $child->class->hidden
returns a list of available child classes for new children.
$element = Krang::Element->load(element_id => $id, object => $object)delete()children list in the
parent and then call save.
$element_copy = $element->clone()element_ids if available, which means that calling save()
on the returned element will overwrite the source element in the
database.
foreach_element { print $_->name, "\n" } $element$xpath = $element->xpath()match() to find the element later. The xpath returned is guaranteed
to be unqiue within the element tree. For example, the third
paragraph element inside the second page element has the xpath
``/page[1]/paragraph[2]''.
This method is provided by Class::XPath. See the documentation for that module for more details.
($para) = $element->match('/page[0]/paragraph[2]/'@paras = $element->match('//paragraph'match() method performs a search in the element tree using a
simplified XPath-esque notation. This is useful for two purposes:
($para) = $element->match('/page[2]/paragraph[1]');
To retrieve a set of elements that match a given criteria. For
example, to get all the image captions regardless of where they exist
in the element tree:
@captions = $element->match('//image/caption');
This method is provided by Class::XPath. See the documentation for that module for more details, including a full description of the syntax supported by match().
$element->serialize_xml(writer => $writer, set => $set)$element = Krang::Element->deserialize_xml(data => $data, set => $set, no_update => 0, object => $story)
All Krang::ElementClass methods are proxied to the class object
for convenience, with the exception of children() and child(). For
example, you can write:
$display = $element->display_name();
Instead of the equivalent, but longer:
$display = $element->class->display_name();
For methods which take an element => $element parameter, this
paramter will be automatically filled in when called through the
proxied method. For example, you can write:
$element->input_form(query => $query);
Which is equivalent to:
$element->class->input_form(element => $element,
query => $query);
child('foo') and match('foo') faster than grepping
through $element->children() for 'foo'. This probably means caching
the name to element mappings and updating them on changes to
children(). That's not easy to do and still allow children() to
return a reference that can be used to make changes.