url = $url; } } class Badge { public $sections = array( "profile" => "Profile", "friends" => "Friends", "friends_ext" => "Imported friends", "groups" => "Groups", "networks" => "Networks", "posts" => "Blog posts and SB content", "images" => "Photos", "audio" => "Audio", "video" => "Videos", ); public $section_singular_names = array( "friends" => "friend", "friends_ext" => "friend", "groups" => "group", "networks" => "network", ); public $display_keys = array( "friends" => "friends", "friends_ext" => "friends", "groups" => "groups", "networks" => "networks", ); public $friends_per_page = 20; public $showing_states = array( 'only' => "Showing ONLY blue highlighted %KEY% from below", 'all' => "Showing first blue, then grey highlighted %KEY% from below", ); function __construct($user, $badge_tag) { $this->user = $user; $this->badge_tag = $badge_tag; try { $this->widget = $user->load_widget($this->badge_tag); $this->state =& $this->widget->config; } catch (PAException $e) { switch ($e->code) { case ROW_DOES_NOT_EXIST: // we need to have a default widget, so if we don't // have one, make it now. otherwise rethrow the // exception, and the user will be redirected to the // default widget. if ($badge_tag != 'default') throw $e; $this->widget = new Widget($this->user->user_id); $this->widget->badge_tag = $this->widget->title = $badge_tag; $this->widget->save(); $this->state =& $this->widget->config; break; default: throw $e; } } $this->url = BASE_URL_REL."/badge_create.php"; } private function save_state() { try { $this->widget->save(); } catch (PAException $e) { echo "

error occurred saving badge!

$e->code | ".$e->getMessage()."

"; exit; } } function op($op, $section, $params) { $section_singular = @$this->section_singular_names[$section]; if (method_exists($this, "op_$section")) { $ret = $this->{"op_$section"}($op, $params); if ($ret !== NULL) return $ret; } switch ($op) { // enable/disable a section case 'enable': if (!isset($this->sections[$section])) return "invalid section for enable"; if (!isset($this->state[$section])) $this->state[$section] = array(); $this->state[$section]['enabled'] = TRUE; $this->save_state(); return $this->render_section_inner($section); case 'disable': if (!isset($this->sections[$section])) return "invalid section for disable"; if (isset($this->state[$section])) $this->state[$section]['enabled'] = FALSE; $this->save_state(); return $this->render_section_inner($section); // include/exclude an individual friend/group/etc case 'include': case 'exclude': $subid = @$params['id']; if (is_string($subid) && substr($subid, 0, 1) == '_') { $subid = pack("H*", substr($subid, 1)); } // echo "op with section $section ..."; //FIXME: verify that the subid is actually a valid network $this->handle_op_include_exclude($section, $op, $subid); return $this->{"render_".$section_singular."_image"}($subid); // change show_state case 'show': $show_state = $params['show']; $this->handle_op_show($section, $show_state); return $this->render_section_inner($section); case 'display': return $this->render_section_inner($section); case 'create': $this->assert_post(); return $this->handle_op_create_new_badge($_POST); break; case 'rename': $this->assert_post(); return $this->handle_op_rename_badge($_POST); break; case 'delete': $this->assert_post(); return $this->handle_op_delete_badge($_POST); break; default: return "invalid $section op"; } } private function assert_post() { if ($_SERVER['REQUEST_METHOD'] != "POST") throw new PAException(OPERATION_NOT_PERMITTED, "This operation requires an HTTP POST"); } private function handle_op_create_new_badge($params) { $title = $params['new_widget_name']; // sanitize name $new_name = preg_replace("~[^A-Za-z0-9\-\_]~", "_", $title); // make sure we don't already have one with that name try { $this->user->load_widget($new_name); // that should throw an exception; if it doesn't, the name is a duplicate return new Badge_Redirect("$this->url?focus=new_widget_name&error=".urlencode("You already have a widget called $new_name. Please select another name.")); } catch (PAException $e) { switch ($e->getCode()) { case ROW_DOES_NOT_EXIST: // Good - this is what we want (no existing widget with this name). break; default: // A real error occurred; pass it through. throw $e; } } $widget = new Widget($this->user->user_id); $widget->badge_tag = $new_name; $widget->title = $title; $widget->save(); return new Badge_Redirect("$this->url/$new_name"); } private function handle_op_rename_badge($params) { $widget = $this->user->load_widget($this->badge_tag); $widget->rename($params['new_name']); return new Badge_Redirect("$this->url/$this->badge_tag"); } private function handle_op_delete_badge($params) { $widget = $this->user->load_widget($this->badge_tag); $widget->delete(); return new Badge_Redirect($this->url); } private function handle_op_include_exclude($section, $op, $subid) { $incl =& $this->state[$section]['included']; // echo "section: $section; id: $subid"; echo "
before:"; var_dump($incl); if (!isset($incl)) {$incl = array(); $this->save_state();} if (is_numeric($subid)) $subid = (int)$subid; if ($op == 'include') { $incl[$subid] = 1; } else { if (isset($incl)) unset($incl[$subid]); } // echo "
after:"; var_dump($incl); $this->save_state(); } private function handle_op_show($section, $show_state) { if (!@$this->showing_states[$show_state]) return "invalid show_state"; $this->state[$section]['show'] = $show_state; $this->save_state(); } // render the entire editing interface function render() { $ret = ""; foreach ($this->sections as $key => $title) { $ret .= $this->render_section($key, $title, "this:render_$key"); } return $ret; } // render an entire section (e.g. friends, groups, ...) function render_section($key, $title, $body) { $inner = $this->render_section_inner($key, $title, $body); return << $inner ENS; } // render just the internal part of a section div function render_section_inner($key) { $title = $this->sections[$key]; $section_state = @$this->state[$key]; $enabled = @$section_state['enabled']; $enable_op = $enabled ? "disable" : "enable"; $selection_count = ""; if ($enabled) { if (method_exists($this, "count_$key")) { $selection_count = $this->{"count_$key"}(); } else if (in_array($key, array("friends", "friends_ext", "groups", "networks"))) { $selection_count = '('.count(@$section_state['included'])." selected)"; } } $inner = $enabled ? $this->{"render_$key"}() : '

This section is disabled. Click the checkbox above to show it in your sidebar widget.

'; $checkbox_checked = $enabled ? 'checked="checked"' : ''; $enabled_text = $enabled ? 'included' : '← click to include'; return <<$title $enabled_text $selection_count $inner ENS; } // section-specific renderers function render_friend_image($rel_or_id) { if (is_integer($rel_or_id) || is_string($rel_or_id)) { // it's an id $rel = Relation::get_relation_record($this->user->user_id, $rel_or_id); } else { $rel = $rel_or_id; } if (!$rel) return "invalid relation"; // echo "
render image: ".var_export($rel, TRUE); $section = is_numeric($rel['user_id']) ? 'friends' : 'friends_ext'; $friends = $this->state[$section]; $included = isset($friends['included'][$rel['user_id']]); // echo "
friends-included: "; var_dump($friends['included']); // echo "
included: "; var_dump($included); if (preg_match("|^http://|", $rel['picture'])) { $img = ''; } else { $img = uihelper_resize_mk_user_img($rel['picture'], 75, 75); } $name = $rel['display_name']; $cls = "friend_pic"; if ($included) $cls .= " included_friend"; $include_op = $included ? "exclude" : "include"; $uid = $rel['user_id']; $div_id = is_numeric($uid) ? $uid : md5($uid); $munge_id = is_numeric($uid) ? $uid : "_".bin2hex($rel['user_id']); $onclick = "badge.include_obj('$section', 'friend_$div_id', '$munge_id', '$include_op');"; return <<

$img

$name

ENS; } private function make_showing_link(&$state, $section_key, $qs) { $keys = array_keys($this->showing_states); if (!@$state['show']) { $state['show'] = $keys[0]; $this->save_state(); } // default $next_showing_state = $keys[(array_search($state['show'], $keys) + 1) % count($keys)]; // next one $all_checked = $state['show'] == 'all' ? 'checked="checked"' : ''; $only_checked = $state['show'] == 'only' ? 'checked="checked"' : ''; $section_key_friendly = strtolower($this->sections[$section_key]); return "
url/$this->badge_tag/$section_key?op=show&show=all&$qs')\" $all_checked> Show a random selection from all of my ${section_key_friendly}
url/$this->badge_tag/$section_key?op=show&show=only&$qs')\" $only_checked> Show only the ${section_key_friendly} highlighted below
"; } function render_profile() { return $this->_render_template("profile"); } function render_friends() { return $this->_render_friends("internal"); } function render_friends_ext() { return $this->_render_friends("external"); } function _render_friends($scope) { $section = ($scope == 'internal') ? 'friends' : 'friends_ext'; $section_singular = $this->section_singular_names[$section]; $page = (int)@$_REQUEST['friend_page']; $friend_state =& $this->state[$section]; // paging controls $total_friends = Relation::count_relations($this->user->user_id, $scope); $total_pages = (int)ceil((float)$total_friends / $this->friends_per_page); if ($page > $total_pages) $page = $total_pages; if ($page < 1) $page = 1; $paging = "Show page: "; for ($i = 1; $i < $total_pages+1; ++$i) { if ($i == $page) { $paging .= "$i "; } else { $paging .= "url/$this->badge_tag/$section?friend_page=$i');\">$i "; } } $first_friend = ($page-1)*$this->friends_per_page + 1; $last_friend = min($first_friend + $this->friends_per_page - 1, $total_friends); $paging .= "(showing $first_friend-$last_friend of $total_friends friends)"; // 'showing XXX' link $showing = $this->make_showing_link($friend_state, $section, "friend_page=$page"); // facewall display $facewall = ""; foreach (Relation::get_all_relations($this->user->user_id, 0, FALSE, $this->friends_per_page, $page, 'created', 'desc', $scope) as $rel) { $facewall .= '
'.$this->render_friend_image($rel, $scope).'
'; } // outer template return <<$showing

$facewall

$paging

ENS; } function render_group_image($grp_or_id) { $grp = new Group(); if (is_numeric($grp_or_id)) { // it's an id $grp->load((int)$grp_or_id); } else { $grp->load($grp_or_id['gid']); } $groups = $this->state['groups']; $included = isset($groups['included'][(int)$grp->collection_id]); $img = uihelper_resize_mk_user_img($grp->picture, 75, 75); $name = $grp->title; $cls = "friend_pic"; if ($included) $cls .= " included_friend"; $include_op = $included ? "exclude" : "include"; $onclick = "badge.include_obj('groups', 'group_$grp->collection_id', $grp->collection_id, '$include_op');"; return <<

$img

$name

ENS; } function render_groups() { $page = 1; $group_state =& $this->state['groups']; $showing = $this->make_showing_link($group_state, "groups", ""); $facewall = ""; foreach (Group::get_user_groups($this->user->user_id, FALSE, $this->friends_per_page, $page) as $grp) { $facewall .= '
'.$this->render_group_image($grp).'
'; } return <<$showing

$facewall
ENS; } function render_network_image($net_or_id) { // find the id if (is_numeric($net_or_id)) { // there's no easy way to get info about a network; we have to go through this incantation... $net_obj = new Network(); $net_obj->network_id = $net_or_id; $net = $net_obj->get(); $net = $net[0]; } else { $net = $net_or_id; } // and display $networks = $this->state['networks']; $included = isset($networks['included'][(int)$net->network_id]); $img = uihelper_resize_mk_user_img($net->inner_logo_image, 75, 75); $name = $net->name; $cls = "friend_pic"; if ($included) $cls .= " included_friend"; $include_op = $included ? "exclude" : "include"; $onclick = "badge.include_obj('networks', 'network_$net->network_id', $net->network_id, '$include_op');"; return <<

$img

$name

ENS; } function render_networks() { $page = 1; $network_state =& $this->state['networks']; $showing = $this->make_showing_link($network_state, "networks", ""); $facewall = ""; foreach (Network::get_user_networks($this->user->user_id, FALSE, $this->friends_per_page, $page) as $net) { $facewall .= '
'.$this->render_network_image($net).'
'; } return <<$showing

$facewall
ENS; } function render_posts() { return "

Showing recent blog posts in sidebar widget.

"; } function render_images() { return "

Showing recent photos in sidebar widget.

"; } function render_audio() { return "

Showing recent audio in sidebar widget.

"; } function render_video() { return "

Showing recent video in sidebar widget.

"; } private function _render_template($template) { $tpl =& new Template(CURRENT_THEME_FSPATH."/widget_$template.tpl"); return $tpl->fetch(); } } // --- controller (part 2) // find user and badge $user = new user(); $user->load((int)$login_uid); try { $badge = new Badge($user, $badge_tag); } catch (PAException $e) { switch ($e->code) { case CONTENT_HAS_BEEN_DELETED: case ROW_DOES_NOT_EXIST: header("Location: $base_url/badge_create.php"); exit; default: throw $e; } } function badge_disp($content) { if ($content instanceof Badge_Redirect) { header("Location: ".$content->url); } else { echo $content; } exit; } // execute op if required if (@$params['op']) { badge_disp($badge->op($params['op'], $section, $params)); } else if (@$section) { badge_disp($badge->op('display', $section, $params)); } // --- left sidebar (widget selection) html function render_left_sidebar() { global $user, $base_url; $badge_list = ""; foreach ($user->list_widgets() as $badge_info) { list($badge_id, $title) = $badge_info; $badge_list .= '
  • '.htmlspecialchars($title ? $title : $badge_id)."
  • "; } $badges_html = <<

    Your widgets

      $badge_list

    Create another:

    Paste this into your blog

    Paste this HTML into your blog to display this information:

    ENS; return $badges_html; } // --- main center column html ob_start(); ?>

    Design your sidebar widget: widget->title ? $badge->widget->title : $badge_tag) ?>

    Rename this widget:

    Or:

    render(); ?>

    Preview

    badges: "; var_dump($user->list_widgets()); echo "

    "; try { $default_badge = $user->load_widget("default"); echo "

    default badge: "; var_dump($default_badge); echo "

    "; } catch (PAException $e) { echo "

    no default badge available.

    "; } $debug_sidebar = ob_get_contents(); ob_end_clean(); return $debug_sidebar; } // --- $page = new PageRenderer(NULL, PAGE_BADGE_CREATE, sprintf(__("%s - My Widgets - %s"), $login_user->get_name(), $network_info->name), "container_three_column.tpl", 'header_user.tpl'); $page->onload = "badge.update();"; $page->add_header_css("$current_theme_path/badge_create.css"); $page->add_module("left", "top", render_left_sidebar()); //$page->add_module("left", "top", render_debug_sidebar()); // debugging $page->add_module("middle", "top", $page_html); $page->add_module("right", "top", render_right_sidebar()); uihelper_set_user_heading($page); echo $page->render(); ?>