Anatomy of a Feather

Feathers enable Chyrp Lite to render different types of content in blog posts. Feathers are simply a class that extends the Feathers class and implements the Feather interface, named after the file and its containing directory (using camelization rules).

class CamelizedFolderName extends Feathers implements Feather {
    public function submit() {
        # Handles post submitting.

    public function update($post) {
        # Handles updating a post.

    public function title($post) {
        # Returns the appropriate source to be treated as a "title" of a post.

    public function excerpt($post) {
        # Returns the appropriate source, unmodified, to be used as an excerpt of a post.

    public function feed_content($post) {
        # Returns the appropriate content for a feed.

Feather Functions

__init(), __install(), and __uninstall() are optional, but the rest are required.


This function is called after all of the modules and feathers are instantiated. It exists because calling other triggers in your feather's __construct() function would be problematic because not every extension is ready to react.


This function is called when the Feather is enabled.


This function is called when the feather is disabled. There is one possible argument, and that's if your feather has a confirm metadata item; the argument will be a boolean of whether or not the user confirmed the dialogue.


This is the function called when submitting a post.


This is the function called when updating a post.


This function should return the most logical title for the post. If there is no obvious title field that you can return, use $post->title_from_excerpt().


This returns the source for the excerpt. You do not need to do any truncation, it's handled automatically by wherever it was called from.


This returns the content for a feed entry.

Feather Construct Functions

The Feathers class provides a few functions intended to be used in __construct() or __init().


This sets a field for your feather, for use on Write/Edit pages.

function __init() {
            # The name of the post attribute.
            "attr" => "body",

            # One of text, text_block, file, checkbox, select.
            "type" => "text_block",

            # The label for the field on the Write/Edit page.
            "label" => __("Body", "my_feather"),

            # If set, this will appear alongside the label.
            "note" => __("I am a note!", "my_feather"),

            # Can the field be blank?
            "optional" => true,

            # Can the field be previewed?
            "preview" => true,

            # For file fields: allow multiple files?
            "multiple" => false,

            # For file fields: accepted types.
            "accept" => ".jpg,.gif,.png",

            # For select fields: an array of options.
            "options" => array(array("name" => $name,
                                     "value" => $value,
                                     "selected" => true))

This function is used for applying a filter to a given attribute. Filters will be stacked and executed in the order that they are specified, therefore it is usually preferable to specify specialised filters before general-purpose ones.

function __init() {
    $this->setFilter("body", array("markup_post_text", "markup_text"));

This function behaves much like setFilter(), but the second argument is the name of a public function in your feather. Custom filters will be executed before any filters added with setFilter().

function __init() {
    $this->customFilter("body", "my_filter_function");

Calling this sets your feather up to respond to a trigger like a module would. The optional third parameter is the numeric priority for your trigger responder; the default is 10.

function __init() {
    $this->respondTo("feed_item", "my_filter_function", 10);