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)
Creates a new element. The 'class' parameter is required and may be either the name of a top-level element class or a Krang::ElementClass 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()
Returns a unique ID for the element. Will be undef until after
the first save().
$class = $element->class()
An object descended from Krang::ElementClass which controls the
functionality of the element. You can set this with either the
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()
This scalar attribute contains the data associated with the element.
Depending on the element class it might be textual, numeric or even a
complex data structure. To get a flattened representation, call
freeze_data().
$object = $element->object()
Returns the object containing this element tree. This will be either a Krang::Story, a Krang::Category, or a Krang::Media object.
$object = $element->story()
Convenience method which returns $element->object() if
$element->object->isa('Krang::Story') and croaks otherwise.
$object = $element->media()
Convenience method which returns $element->object() if
$element->object->isa('Krang::Media') and croaks otherwise.
$object = $element->category()
Convenience method which returns $element->object() if
$element->object->isa('Krang::Category') and croaks otherwise.
$parent = $element->parent()
Returns the parent element for this element, or undef for the root
element.
$root = $element->root()
Returns the root element for this element tree.
@children = $element->children($name)
@children = $element->children(name => 'paragraph')
@children = $element->children(class => 'Default::image')
@children = $element->children(isa => 'Krang::ElementClass::Media')
Returns a list of child elements for this element. These will be
Krang::Element objects. Passing the optional $name argument (or
one of the named arguments shown in the examples above) will return
a list of child elements filtered accordingly. For adding a new
child, see 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')
Returns a list of the data slots of the element's children, optionally limited to children having the name passed in as the first argument. Alternatively, the list may be filtered by one of the named parameters shown in the examples above. The return list's items are guaranteed to be defined.
This method will croak when passed more than one named argument.
$count = $element->children_count()
Returns the number of children in the element.
$child = $element->add_child(class => "paragraph", %args)
$child = $element->add_child(class => $class_obj, %args)
Create a new element object and add it as a child in the 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)
Create a new element object and add it as a child in the 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
If the new element can't be added because of 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)
This call removes children from the list of child elements. You may call it with either a list of indexes into the list of children, or references to the children to be removed.
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)
This call reorders the list of children. You may pass either a list of indexes (0 based) into the list of children or a list of child objects. You may not leave out any existing children in the list.
my $deck = $element->child('deck')
Find a child by class name. If there are multiple children for this
class, returns the first one. Returns undef if a child of the
specified class does not exist.
$text = $element->child_data('deck')
Find a child by class name and returns its data. If there are
multiple children for this class, uses the first one. Returns
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()
Save the element, and all its children, to the database. After this
call, element_id is guaranteed to be filled in. Should only be
called on top-level elements.
@classes = $element->available_child_classes()
Taking into account $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)
Loads a Krang::Element object from the database. This will only find top-level elements and will load all child elements. The 'object' parameter is required and must contain a reference to the object containing this element.
delete()
Delete the element, and all its children, from the database. After
this call the element is empty, without children, data or an id. This
call only works for top-level elements. To remove elements from the
middle of a tree, simply remove them from the children list in the
parent and then call save.
$element_copy = $element->clone()
Creates a perfect copy of the element and all child elements. This
includes 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
Apply a block of code to each element in an element tree, recursing down through the tree breadth first. The subroutine is available for export.
$xpath = $element->xpath()
Get an xpath to uniquely identify this element. Can be used with
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'
The match() method performs a search in the element tree using a
simplified XPath-esque notation. This is useful for two purposes:
To retrieve a single element based on a unique path. For example, to retrieve the second paragraph of the third page:
($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)
Serialize as XML. See Krang::DataSet for details.
$element = Krang::Element->deserialize_xml(data => $data, set => $set, no_update => 0, object => $story)
Deserialize XML. See Krang::DataSet for details. This method differs only in that it takes a reference to the element data produced by XML::Simple rather than XML source. Also takes an object parameter pointing to the enclosing object.
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);
Make $element->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.