function wordlift_footer()
{
    if ("true" !== get_option("wordlift_show_footer_bar", "true")) {
        return;
    }
    if (is_home()) {
        $args = array("numberposts" => 1, "orderby" => "post_date", "order" => "DESC", "post_type" => "post", "post_status" => "publish", "suppress_filters" => true);
        $recentPosts = wp_get_recent_posts($args, $output = ARRAY_A);
        if (0 === count($recentPosts)) {
            return;
        }
        $id = $recentPosts[0]["ID"];
    } else {
        $id = get_the_ID();
    }
    $context = WordPress_XmlApplication::getContext("wordLift");
    $postEntitiesService = $context->getClass("postEntitiesService");
    $entities = $postEntitiesService->get($id);
    $entitiesCount = count($entities);
    if (0 === $entitiesCount) {
        return;
    }
    $index = 0;
    $languages = @$postEntitiesService->getPostLanguages($id);
    echo "<div id=\"wordlift-bar\">";
    echo "<ul>";
    echo "<li class=\"separator\"></li>";
    foreach ($entities as $key => &$entity) {
        $index++;
        $link = admin_url("admin-ajax.php?action=wordlift.gotoentity&e=" . urlencode($key));
        $type = $postEntitiesService->getFirstValue($entity, "type");
        $shortType = strtolower(substr($type, strrpos($type, "/") + 1));
        $name = $postEntitiesService->getValueByLanguage($entity, "name", $languages);
        $name = htmlspecialchars($name, ENT_COMPAT, "UTF-8");
        if (empty($name)) {
            continue;
        }
        $title = $postEntitiesService->getValueByLanguage($entity, "title", $languages);
        $image = $postEntitiesService->getFirstValue($entity, "image");
        $description = $postEntitiesService->getValueByLanguage($entity, "description", $languages);
        $description = htmlspecialchars($description, ENT_COMPAT, "UTF-8");
        echo "<li itemscope itemtype=\"{$type}\" class=\"entity {$shortType}\">";
        echo "<a href=\"{$link}\">";
        echo "<h1 itemprop=\"name\">{$name}</h1>\n";
        if (!empty($title)) {
            echo "<h2 itemprop=\"title\">{$title}<h2>\n";
        }
        echo "<img onerror=\"this.parentNode.removeChild(this);\" itemprop=\"image\" src=\"{$image}\" />\n";
        echo "<p itemprop=\"description\">{$description}</p>\n";
        echo "</a>";
        echo "</li>";
        echo "<li class=\"separator\"></li>";
    }
    echo "</ul>";
    echo "<div id=\"wordlift-bar-switch\">";
    echo "</div>";
    echo "</div>";
}
 function __construct($id_base = false, $name, $widget_options = array(), $control_options = array())
 {
     parent::__construct($id_base, $name, $widget_options, $control_options);
     $classID = self::$applicationContext->getClassID(get_class($this));
     self::$applicationContext->getClass($classID, NULL, NULL, $this);
 }
 function __construct($rootFolder, $fileName, $loggerConfiguration)
 {
     $this->rootFolder = $rootFolder;
     $fileName = $rootFolder . $fileName;
     $loggerConfiguration = $rootFolder . $loggerConfiguration;
     // get the logger.
     $this->logger = WordPress_XmlApplication::getLogger($loggerConfiguration);
     // check that we're in WordPress.
     if (false === function_exists("add_filter")) {
         throw new Exception("Cannot find the [add_filter] function. Are we in a WordPress environment?");
     }
     // check if the file exists. if not throw an exception.
     if (false === file_exists($fileName)) {
         throw new Exception("Xml Application configuration file [{$fileName}] is not found.");
     }
     // load the configuration.
     // $this->logger->trace( "Creating application from [$fileName]." );
     $xmlConfiguration = simplexml_load_file($fileName);
     $this->xmlConfiguration = $xmlConfiguration;
     // register the wordpress namespace.
     $xmlConfiguration->registerXPathNamespace("application", self::APPLICATION_NAMESPACE);
     $xmlConfiguration->registerXPathNamespace("wordpress", self::WORDPRESS_NAMESPACE);
     // ***** C O N T E X T   N A M E ***** //
     $contexts = $xmlConfiguration->xpath("//application:context");
     if (1 === count($contexts)) {
         $context = reset($contexts);
         $contextName = (string) $context->attributes()->name;
         if ("" !== $contextName) {
             // $this->logger->trace( "Found a named context [$contextName]." );
             self::addContext($contextName, $this);
         }
     }
     // ***** T H U M B N A I L S ***** //
     // get the thumbnails.
     $thumbnails = $xmlConfiguration->xpath("//wordpress:thumbnail");
     // $this->logger->trace( count($thumbnails) . " thumbnail(s) found in file [$fileName]." );
     $this->loadThumbnails($thumbnails);
     // ***** P R O P E R T I E S ***** //
     $properties = $xmlConfiguration->xpath("//application:property");
     // $this->logger->trace( count($properties) . " property(ies) found in file [$fileName]." );
     $this->loadProperties($properties);
     // ***** M E T A B O X E S ***** //
     $metaBoxes = $xmlConfiguration->xpath("//wordpress:metaBox");
     // $this->logger->trace( count($metaBoxes) . " meta-boxes(s) found in file [$fileName]." );
     $this->loadMetaBoxes($metaBoxes);
     // ***** P O S T  T Y P E S ***** //
     // get the post types.
     $types = $xmlConfiguration->xpath("//wordpress:postType");
     // $this->logger->trace( count($types) . " type(s) found in file [$fileName]." );
     foreach ($types as $type) {
         $typeName = (string) $type->attributes()->name;
         $classID = (string) $type->attributes()->class;
         if ("" === $typeName || 20 < strlen($typeName)) {
             throw new Exception("A postType configuration element requires a name attribute [{$typeName}] of maximum 20 characters.");
         }
         if ("" === $classID) {
             throw new Exception("A postType configuration element requires a class attribute.");
         }
         $instance = $this->getClass($classID, $rootFolder, $xmlConfiguration);
         if (NULL === $instance || false === method_exists($instance, "getArguments")) {
             throw new Exception("A postType configuration is invalid. The referenced class does not exist or does not support the getArguments method.");
         }
         // $this->logger->trace( "Registering post custom type [$typeName]." );
         $postTypeConfiguration = $instance->getArguments();
         $postTypeConfiguration[self::WP_REGISTER_META_BOX_CB] = array($instance, self::REGISTER_META_BOX_CALLBACK);
         register_post_type($typeName, $postTypeConfiguration);
         add_filter("manage_edit-" . $typeName . "_columns", array($instance, "getColumns"));
         // TODO: make this compatible with WordPress pre-3.1 http://codex.wordpress.org/Plugin_API/Action_Reference/manage_$post_type_posts_custom_column
         add_action("manage_posts_custom_column", array($instance, "getColumnValue"), 10, 2);
     }
     // flush_rewrite_rules(true);
     // ***** F I L T E R S *****
     // get the filters.
     $filters = $xmlConfiguration->xpath("//wordpress:filter");
     // $this->logger->trace( count($filters) . " filter(s) found in file [$fileName]." );
     $this->loadActionOrFilter(self::FILTER, $filters);
     // ***** A C T I O N S *****
     $actions = $xmlConfiguration->xpath("//wordpress:action");
     // $this->logger->trace( count($actions) . " action(s) found in file [$fileName]." );
     $this->loadActionOrFilter(self::ACTION, $actions);
     // ***** S H O R T C O D E S *****
     $shortCodes = $xmlConfiguration->xpath("//wordpress:shortCode");
     // $this->logger->trace( count($filters) . " short-code(s) found in file [$fileName]." );
     // each filter has a name and optionally a priority and acceptedArguments.
     foreach ($shortCodes as $shortCode) {
         $attributes = $shortCode->attributes();
         $name = (string) $attributes->name;
         $class = (string) $attributes->class;
         $method = (string) $attributes->method;
         if ("" === $name) {
             throw new Exception("A short-code is missing a name in [{$fileName}].");
         }
         if ("" === $class) {
             throw new Exception("A short-code is missing the class attribute in [{$fileName}].");
         }
         if ("" === $method) {
             throw new Exception("A short-code is missing the method attribute in [{$fileName}].");
         }
         $class = $this->getClass($class);
         add_shortcode($name, array($class, $method));
     }
     // ***** S T Y L E S *****
     // get the filters.
     $styles = $xmlConfiguration->xpath("//wordpress:style");
     // $this->logger->trace( count($styles) . " style(s) found in file [$fileName]." );
     $this->styles = array();
     foreach ($styles as $style) {
         array_push($this->styles, $this->getStyle($style));
     }
     /***** S C R I P T S *****/
     $scripts = $xmlConfiguration->xpath("//wordpress:script");
     // $this->logger->trace( count($scripts) . " script(s) found in file [$fileName]." );
     $this->scripts = array();
     foreach ($scripts as $script) {
         array_push($this->scripts, $this->getScript($script));
     }
     // $this->logger->trace( "Hooking enqueue scripts actions." );
     add_action("admin_enqueue_scripts", array($this, "queueAdminScripts"));
     add_action("wp_enqueue_scripts", array($this, "queueUserScripts"));
     add_filter("mce_css", array($this, "setEditorStyles"));
     // ***** A J A X S E R V I C E S *****
     $ajaxes = $xmlConfiguration->xpath("//wordpress:ajax");
     // $this->logger->trace( count($ajaxes) . " ajax service(s) found in file [$fileName]." );
     $this->loadAjax($ajaxes);
     // ***** E D I T O R *****
     $editorProperties = $xmlConfiguration->xpath("//wordpress:editor");
     // $this->logger->trace( count( $editorProperties ) . " editor option(s) found in file [$fileName]." );
     $this->loadEditorProperties($editorProperties);
     add_filter("tiny_mce_before_init", array($this, "initializeEditorConfiguration"));
     // ***** W I D G E T S *****
     $widgets = $xmlConfiguration->xpath("//wordpress:widget");
     require_once $rootFolder . "/php/insideout/wordpress/services/WidgetProxy.php";
     $this->loadWidgets($widgets);
     // ***** A D M I N  M E N U S *****
     $this->adminMenus = $xmlConfiguration->xpath("//wordpress:adminMenu");
     $this->subAdminMenus = $xmlConfiguration->xpath("//wordpress:subAdminMenu");
     add_action("admin_menu", array($this, "loadAdminMenus"));
     // ***** S E T T I N G S *****
     $this->settings = $xmlConfiguration->xpath("//wordpress:settings");
     add_action("admin_menu", array($this, "loadSettings"));
     // ***** N O T I C E S *****
     $notices = $xmlConfiguration->xpath("//wordpress:notice");
     foreach ($notices as $notice) {
         $class = (string) $notice->attributes()->class;
         $method = (string) $notice->attributes()->method;
         if (empty($class) || empty($method)) {
             $this->logger->error("The attributes class and method are required (notice).");
             continue;
         }
         $instance = $this->getClass($class, $this->rootFolder, $this->xmlConfiguration);
         add_action("admin_notices", array($instance, $method));
     }
     // ***** A C T I V A T E  H O O K S *****
     // $activates = $xmlConfiguration->xpath("//wordpress:activate");
     // foreach ( $activates as $activate ) {
     //     $class = (string) $activate->attributes()->class;
     //     $method = (string) $activate->attributes()->method;
     //     if ( empty( $class ) || empty( $method ) ) {
     //         $this->logger->error( "The attributes class and method are required (activate)." );
     //         continue;
     //     }
     //     $instance = $this->getClass( $class, $this->rootFolder, $this->xmlConfiguration );
     //     register_activation_hook( __FILE__, array( $instance, $method ) );
     // }
 }