aboutsummaryrefslogtreecommitdiff
path: root/mod/thewire
diff options
context:
space:
mode:
Diffstat (limited to 'mod/thewire')
-rw-r--r--mod/thewire/actions/add.php34
-rw-r--r--mod/thewire/actions/delete.php39
-rw-r--r--mod/thewire/activate.php10
-rw-r--r--mod/thewire/classes/ElggWire.php40
-rw-r--r--mod/thewire/deactivate.php6
-rw-r--r--mod/thewire/graphics/river_icon_thewire.gifbin0 -> 365 bytes
-rw-r--r--mod/thewire/graphics/thewire_speech_bubble.gifbin0 -> 278 bytes
-rw-r--r--mod/thewire/languages/en.php61
-rw-r--r--mod/thewire/manifest.xml17
-rw-r--r--mod/thewire/pages/thewire/everyone.php31
-rw-r--r--mod/thewire/pages/thewire/friends.php31
-rw-r--r--mod/thewire/pages/thewire/owner.php39
-rw-r--r--mod/thewire/pages/thewire/previous.php20
-rw-r--r--mod/thewire/pages/thewire/reply.php28
-rw-r--r--mod/thewire/pages/thewire/tag.php35
-rw-r--r--mod/thewire/pages/thewire/thread.php27
-rw-r--r--mod/thewire/pages/thewire/view.php31
-rw-r--r--mod/thewire/start.php475
-rw-r--r--mod/thewire/tests/regex.php303
-rw-r--r--mod/thewire/upgrades/2012122701-fix_entity_class.php8
-rw-r--r--mod/thewire/views/default/forms/thewire/add.php41
-rw-r--r--mod/thewire/views/default/js/thewire.php86
-rw-r--r--mod/thewire/views/default/object/thewire.php63
-rw-r--r--mod/thewire/views/default/river/object/thewire/create.php31
-rw-r--r--mod/thewire/views/default/thewire/css.php35
-rw-r--r--mod/thewire/views/default/thewire/previous.php11
-rw-r--r--mod/thewire/views/default/thewire/profile_status.php44
-rw-r--r--mod/thewire/views/default/thewire/reply.php14
-rw-r--r--mod/thewire/views/default/thewire/scripts/counter.js25
-rw-r--r--mod/thewire/views/default/thewire/sidebar.php9
-rw-r--r--mod/thewire/views/default/widgets/thewire/content.php30
-rw-r--r--mod/thewire/views/default/widgets/thewire/edit.php22
-rw-r--r--mod/thewire/views/rss/object/thewire.php36
-rw-r--r--mod/thewire/views/rss/search/object/thewire/entity.php27
34 files changed, 1709 insertions, 0 deletions
diff --git a/mod/thewire/actions/add.php b/mod/thewire/actions/add.php
new file mode 100644
index 000000000..6b3d8d5ba
--- /dev/null
+++ b/mod/thewire/actions/add.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Action for adding a wire post
+ *
+ */
+
+// don't filter since we strip and filter escapes some characters
+$body = get_input('body', '', false);
+
+$access_id = ACCESS_PUBLIC;
+$method = 'site';
+$parent_guid = (int) get_input('parent_guid');
+
+// make sure the post isn't blank
+if (empty($body)) {
+ register_error(elgg_echo("thewire:blank"));
+ forward(REFERER);
+}
+
+$guid = thewire_save_post($body, elgg_get_logged_in_user_guid(), $access_id, $parent_guid, $method);
+if (!$guid) {
+ register_error(elgg_echo("thewire:error"));
+ forward(REFERER);
+}
+
+// Send response to original poster if not already registered to receive notification
+if ($parent_guid) {
+ thewire_send_response_notification($guid, $parent_guid, $user);
+ $parent = get_entity($parent_guid);
+ forward("thewire/thread/$parent->wire_thread");
+}
+
+system_message(elgg_echo("thewire:posted"));
+forward(REFERER);
diff --git a/mod/thewire/actions/delete.php b/mod/thewire/actions/delete.php
new file mode 100644
index 000000000..38355d25e
--- /dev/null
+++ b/mod/thewire/actions/delete.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Action for deleting a wire post
+ *
+ */
+
+// Get input data
+$guid = (int) get_input('guid');
+
+// Make sure we actually have permission to edit
+$thewire = get_entity($guid);
+if ($thewire->getSubtype() == "thewire" && $thewire->canEdit()) {
+
+ // unset reply metadata on children
+ $children = elgg_get_entities_from_relationship(array(
+ 'relationship' => 'parent',
+ 'relationship_guid' => $post_guid,
+ 'inverse_relationship' => true,
+ ));
+ if ($children) {
+ foreach ($children as $child) {
+ $child->reply = false;
+ }
+ }
+
+ // Get owning user
+ $owner = get_entity($thewire->getOwnerGUID());
+
+ // Delete it
+ $rowsaffected = $thewire->delete();
+ if ($rowsaffected > 0) {
+ // Success message
+ system_message(elgg_echo("thewire:deleted"));
+ } else {
+ register_error(elgg_echo("thewire:notdeleted"));
+ }
+
+ forward("thewire/owner/" . $owner->username);
+}
diff --git a/mod/thewire/activate.php b/mod/thewire/activate.php
new file mode 100644
index 000000000..1cc64ceb1
--- /dev/null
+++ b/mod/thewire/activate.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Register the ElggWire class for the object/thewire subtype
+ */
+
+if (get_subtype_id('object', 'thewire')) {
+ update_subtype('object', 'thewire', 'ElggWire');
+} else {
+ add_subtype('object', 'thewire', 'ElggWire');
+}
diff --git a/mod/thewire/classes/ElggWire.php b/mod/thewire/classes/ElggWire.php
new file mode 100644
index 000000000..9c92dd8f2
--- /dev/null
+++ b/mod/thewire/classes/ElggWire.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * ElggWire Class
+ *
+ * @property string $method The method used to create the wire post (site, sms, api)
+ * @property bool $reply Whether this wire post was a reply to another post
+ * @property int $wire_thread The identifier of the thread for this wire post
+ */
+class ElggWire extends ElggObject {
+
+ /**
+ * Set subtype to thewire
+ *
+ * @return void
+ */
+ protected function initializeAttributes() {
+ parent::initializeAttributes();
+
+ $this->attributes['subtype'] = 'thewire';
+ }
+
+ /**
+ * Can a user comment on this wire post?
+ *
+ * @see ElggObject::canComment()
+ *
+ * @param int $user_guid User guid (default is logged in user)
+ * @return bool
+ * @since 1.8.0
+ */
+ public function canComment($user_guid = 0) {
+ $result = parent::canComment($user_guid);
+ if ($result == false) {
+ return $result;
+ }
+
+ return false;
+ }
+
+}
diff --git a/mod/thewire/deactivate.php b/mod/thewire/deactivate.php
new file mode 100644
index 000000000..3e20207a1
--- /dev/null
+++ b/mod/thewire/deactivate.php
@@ -0,0 +1,6 @@
+<?php
+/**
+ * Deregister the ElggWire class
+ */
+
+update_subtype('object', 'thewire'); \ No newline at end of file
diff --git a/mod/thewire/graphics/river_icon_thewire.gif b/mod/thewire/graphics/river_icon_thewire.gif
new file mode 100644
index 000000000..59cc6bfaa
--- /dev/null
+++ b/mod/thewire/graphics/river_icon_thewire.gif
Binary files differ
diff --git a/mod/thewire/graphics/thewire_speech_bubble.gif b/mod/thewire/graphics/thewire_speech_bubble.gif
new file mode 100644
index 000000000..ec5b89773
--- /dev/null
+++ b/mod/thewire/graphics/thewire_speech_bubble.gif
Binary files differ
diff --git a/mod/thewire/languages/en.php b/mod/thewire/languages/en.php
new file mode 100644
index 000000000..3c83d145f
--- /dev/null
+++ b/mod/thewire/languages/en.php
@@ -0,0 +1,61 @@
+<?php
+/**
+ * The Wire English language file
+ */
+
+$english = array(
+
+ /**
+ * Menu items and titles
+ */
+ 'thewire' => "The Wire",
+ 'thewire:everyone' => "All wire posts",
+ 'thewire:user' => "%s's wire posts",
+ 'thewire:friends' => "Friends' wire posts",
+ 'thewire:reply' => "Reply",
+ 'thewire:replying' => "Replying to %s (@%s) who wrote",
+ 'thewire:thread' => "Thread",
+ 'thewire:charleft' => "characters remaining",
+ 'thewire:tags' => "Wire posts tagged with '%s'",
+ 'thewire:noposts' => "No wire posts yet",
+ 'item:object:thewire' => "Wire posts",
+ 'thewire:update' => 'Update',
+ 'thewire:by' => 'Wire post by %s',
+
+ 'thewire:previous' => "Previous",
+ 'thewire:hide' => "Hide",
+ 'thewire:previous:help' => "View previous post",
+ 'thewire:hide:help' => "Hide previous post",
+
+ /**
+ * The wire river
+ */
+ 'river:create:object:thewire' => "%s posted to the %s",
+ 'thewire:wire' => 'wire',
+
+ /**
+ * Wire widget
+ */
+ 'thewire:widget:desc' => 'Display your latest wire posts',
+ 'thewire:num' => 'Number of posts to display',
+ 'thewire:moreposts' => 'More wire posts',
+
+ /**
+ * Status messages
+ */
+ 'thewire:posted' => "Your message was successfully posted to the wire.",
+ 'thewire:deleted' => "The wire post was successfully deleted.",
+ 'thewire:blank' => "Sorry, you need to enter some text before we can post this.",
+ 'thewire:notfound' => "Sorry, we could not find the specified wire post.",
+ 'thewire:notdeleted' => "Sorry. We could not delete this wire post.",
+
+ /**
+ * Notifications
+ */
+ 'thewire:notify:subject' => "New wire post",
+ 'thewire:notify:reply' => '%s responded to %s on the wire:',
+ 'thewire:notify:post' => '%s posted on the wire:',
+
+);
+
+add_translation("en", $english);
diff --git a/mod/thewire/manifest.xml b/mod/thewire/manifest.xml
new file mode 100644
index 000000000..962ed12f1
--- /dev/null
+++ b/mod/thewire/manifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<plugin_manifest xmlns="http://www.elgg.org/plugin_manifest/1.8">
+ <name>The Wire</name>
+ <author>JHU/APL and core developers</author>
+ <version>1.8</version>
+ <category>bundled</category>
+ <category>content</category>
+ <description>Microblogging for Elgg</description>
+ <website>http://www.elgg.org/</website>
+ <copyright>See COPYRIGHT.txt</copyright>
+ <license>GNU General Public License version 2</license>
+ <requires>
+ <type>elgg_release</type>
+ <version>1.8</version>
+ </requires>
+ <activate_on_install>true</activate_on_install>
+</plugin_manifest>
diff --git a/mod/thewire/pages/thewire/everyone.php b/mod/thewire/pages/thewire/everyone.php
new file mode 100644
index 000000000..c7438747e
--- /dev/null
+++ b/mod/thewire/pages/thewire/everyone.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * All wire posts
+ *
+ */
+
+elgg_push_breadcrumb(elgg_echo('thewire'));
+
+$title = elgg_echo('thewire:everyone');
+
+$content = '';
+if (elgg_is_logged_in()) {
+ $form_vars = array('class' => 'thewire-form');
+ $content .= elgg_view_form('thewire/add', $form_vars);
+ $content .= elgg_view('input/urlshortener');
+}
+
+$content .= elgg_list_entities(array(
+ 'type' => 'object',
+ 'subtype' => 'thewire',
+ 'limit' => get_input('limit', 15),
+));
+
+$body = elgg_view_layout('content', array(
+ 'filter_context' => 'all',
+ 'content' => $content,
+ 'title' => $title,
+ 'sidebar' => elgg_view('thewire/sidebar'),
+));
+
+echo elgg_view_page($title, $body);
diff --git a/mod/thewire/pages/thewire/friends.php b/mod/thewire/pages/thewire/friends.php
new file mode 100644
index 000000000..efa7e7a56
--- /dev/null
+++ b/mod/thewire/pages/thewire/friends.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Wire posts of your friends
+ */
+
+$owner = elgg_get_page_owner_entity();
+if (!$owner) {
+ forward('', '404');
+}
+
+$title = elgg_echo('thewire:friends');
+
+elgg_push_breadcrumb(elgg_echo('thewire'), "thewire/all");
+elgg_push_breadcrumb($owner->name, "thewire/owner/$owner->username");
+elgg_push_breadcrumb(elgg_echo('friends'));
+
+if (elgg_get_logged_in_user_guid() == $owner->guid) {
+ $form_vars = array('class' => 'thewire-form');
+ $content = elgg_view_form('thewire/add', $form_vars);
+ $content .= elgg_view('input/urlshortener');
+}
+
+$content .= list_user_friends_objects($owner->guid, 'thewire', 15, false);
+
+$body = elgg_view_layout('content', array(
+ 'filter_context' => 'friends',
+ 'content' => $content,
+ 'title' => $title,
+));
+
+echo elgg_view_page($title, $body);
diff --git a/mod/thewire/pages/thewire/owner.php b/mod/thewire/pages/thewire/owner.php
new file mode 100644
index 000000000..dc25940e1
--- /dev/null
+++ b/mod/thewire/pages/thewire/owner.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * User's wire posts
+ *
+ */
+
+$owner = elgg_get_page_owner_entity();
+if (!$owner) {
+ forward('', '404');
+}
+
+$title = elgg_echo('thewire:user', array($owner->name));
+
+elgg_push_breadcrumb(elgg_echo('thewire'), "thewire/all");
+elgg_push_breadcrumb($owner->name);
+
+$context = '';
+if (elgg_get_logged_in_user_guid() == $owner->guid) {
+ $form_vars = array('class' => 'thewire-form');
+ $content = elgg_view_form('thewire/add', $form_vars);
+ $content .= elgg_view('input/urlshortener');
+ $context = 'mine';
+}
+
+$content .= elgg_list_entities(array(
+ 'type' => 'object',
+ 'subtype' => 'thewire',
+ 'owner_guid' => $owner->guid,
+ 'limit' => get_input('limit', 15),
+));
+
+$body = elgg_view_layout('content', array(
+ 'filter_context' => $context,
+ 'content' => $content,
+ 'title' => $title,
+ 'sidebar' => elgg_view('thewire/sidebar'),
+));
+
+echo elgg_view_page($title, $body);
diff --git a/mod/thewire/pages/thewire/previous.php b/mod/thewire/pages/thewire/previous.php
new file mode 100644
index 000000000..a3f1cb01c
--- /dev/null
+++ b/mod/thewire/pages/thewire/previous.php
@@ -0,0 +1,20 @@
+<?php
+/**
+ * Serve up html for a post's parent
+ */
+
+$guid = (int) get_input('guid');
+$title = elgg_echo('thewire:previous');
+
+$parent = thewire_get_parent($guid);
+if ($parent) {
+ $body = elgg_view_entity($parent);
+}
+
+$body = elgg_view_layout('content', array(
+ 'filter' => false,
+ 'content' => $body,
+ 'title' => $title,
+));
+
+echo elgg_view_page($title, $body); \ No newline at end of file
diff --git a/mod/thewire/pages/thewire/reply.php b/mod/thewire/pages/thewire/reply.php
new file mode 100644
index 000000000..df4511c51
--- /dev/null
+++ b/mod/thewire/pages/thewire/reply.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Reply page
+ *
+ */
+
+gatekeeper();
+
+$post = get_entity(get_input('guid'));
+
+$title = elgg_echo('thewire:reply');
+
+elgg_push_breadcrumb(elgg_echo('thewire'), 'thewire/all');
+elgg_push_breadcrumb($title);
+
+$content = elgg_view('thewire/reply', array('post' => $post));
+$form_vars = array('class' => 'thewire-form');
+$content .= elgg_view_form('thewire/add', $form_vars, array('post' => $post));
+$content .= elgg_view('input/urlshortener');
+
+
+$body = elgg_view_layout('content', array(
+ 'filter' => false,
+ 'content' => $content,
+ 'title' => $title,
+));
+
+echo elgg_view_page($title, $body);
diff --git a/mod/thewire/pages/thewire/tag.php b/mod/thewire/pages/thewire/tag.php
new file mode 100644
index 000000000..1c88030ec
--- /dev/null
+++ b/mod/thewire/pages/thewire/tag.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Wire posts tagged with <tag>
+ */
+
+$tag = get_input('tag');
+if (!$tag) {
+ forward('thewire/all');
+}
+
+elgg_push_breadcrumb(elgg_echo('thewire'), 'thewire/all');
+elgg_push_breadcrumb('#' . $tag);
+
+// remove # from tag
+$tag = trim($tag, '# ');
+
+$title = elgg_echo('thewire:tags', array($tag));
+
+
+$content = elgg_list_entities_from_metadata(array(
+ 'metadata_name' => 'tags',
+ 'metadata_value' => $tag,
+ 'metadata_case_sensitive' => false,
+ 'type' => 'object',
+ 'subtype' => 'thewire',
+ 'limit' => 15,
+));
+
+$body = elgg_view_layout('content', array(
+ 'filter' => false,
+ 'content' => $content,
+ 'title' => $title,
+));
+
+echo elgg_view_page($title, $body);
diff --git a/mod/thewire/pages/thewire/thread.php b/mod/thewire/pages/thewire/thread.php
new file mode 100644
index 000000000..ec2709430
--- /dev/null
+++ b/mod/thewire/pages/thewire/thread.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * View conversation thread
+ */
+
+$thread_id = get_input('thread_id');
+
+$title = elgg_echo('thewire:thread');
+
+elgg_push_breadcrumb(elgg_echo('thewire'), 'thewire/all');
+elgg_push_breadcrumb($title);
+
+$content = elgg_list_entities_from_metadata(array(
+ "metadata_name" => "wire_thread",
+ "metadata_value" => $thread_id,
+ "type" => "object",
+ "subtype" => "thewire",
+ "limit" => 20,
+));
+
+$body = elgg_view_layout('content', array(
+ 'filter' => false,
+ 'content' => $content,
+ 'title' => $title,
+));
+
+echo elgg_view_page($title, $body);
diff --git a/mod/thewire/pages/thewire/view.php b/mod/thewire/pages/thewire/view.php
new file mode 100644
index 000000000..1709e5e9a
--- /dev/null
+++ b/mod/thewire/pages/thewire/view.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * View individual wire post
+ */
+
+$post = get_entity(get_input('guid'));
+if (!$post) {
+ register_error(elgg_echo('noaccess'));
+ $_SESSION['last_forward_from'] = current_page_url();
+ forward('');
+}
+$owner = $post->getOwnerEntity();
+if (!$owner) {
+ forward();
+}
+
+$title = elgg_echo('thewire:by', array($owner->name));
+
+elgg_push_breadcrumb(elgg_echo('thewire'), 'thewire/all');
+elgg_push_breadcrumb($owner->name, 'thewire/owner/' . $owner->username);
+elgg_push_breadcrumb($title);
+
+$content = elgg_view_entity($post);
+
+$body = elgg_view_layout('content', array(
+ 'filter' => false,
+ 'content' => $content,
+ 'title' => $title,
+));
+
+echo elgg_view_page($title, $body);
diff --git a/mod/thewire/start.php b/mod/thewire/start.php
new file mode 100644
index 000000000..8b01cc57a
--- /dev/null
+++ b/mod/thewire/start.php
@@ -0,0 +1,475 @@
+<?php
+/**
+ * Elgg wire plugin
+ *
+ * Forked from Curverider's version
+ *
+ * JHU/APL Contributors:
+ * Cash Costello
+ * Clark Updike
+ * John Norton
+ * Max Thomas
+ * Nathan Koterba
+ */
+
+elgg_register_event_handler('init', 'system', 'thewire_init');
+
+/**
+ * The Wire initialization
+ */
+function thewire_init() {
+
+ // register the wire's JavaScript
+ $thewire_js = elgg_get_simplecache_url('js', 'thewire');
+ elgg_register_simplecache_view('js/thewire');
+ elgg_register_js('elgg.thewire', $thewire_js, 'footer');
+
+ elgg_register_ajax_view('thewire/previous');
+
+ // add a site navigation item
+ $item = new ElggMenuItem('thewire', elgg_echo('thewire'), 'thewire/all');
+ elgg_register_menu_item('site', $item);
+
+ // owner block menu
+ elgg_register_plugin_hook_handler('register', 'menu:owner_block', 'thewire_owner_block_menu');
+
+ // remove edit and access and add thread, reply, view previous
+ elgg_register_plugin_hook_handler('register', 'menu:entity', 'thewire_setup_entity_menu_items');
+
+ // Extend system CSS with our own styles, which are defined in the thewire/css view
+ elgg_extend_view('css/elgg', 'thewire/css');
+
+ //extend views
+ elgg_extend_view('activity/thewire', 'thewire/activity_view');
+ elgg_extend_view('profile/status', 'thewire/profile_status');
+ elgg_extend_view('js/initialise_elgg', 'thewire/js/textcounter');
+
+ // Register a page handler, so we can have nice URLs
+ elgg_register_page_handler('thewire', 'thewire_page_handler');
+
+ // Register a URL handler for thewire posts
+ elgg_register_entity_url_handler('object', 'thewire', 'thewire_url');
+
+ elgg_register_widget_type('thewire', elgg_echo('thewire'), elgg_echo("thewire:widget:desc"));
+
+ // Register for search
+ elgg_register_entity_type('object', 'thewire');
+
+ // Register granular notification for this type
+ register_notification_object('object', 'thewire', elgg_echo('thewire:notify:subject'));
+
+ // Listen to notification events and supply a more useful message
+ elgg_register_plugin_hook_handler('notify:entity:message', 'object', 'thewire_notify_message');
+
+ // Register actions
+ $action_base = elgg_get_plugins_path() . 'thewire/actions';
+ elgg_register_action("thewire/add", "$action_base/add.php");
+ elgg_register_action("thewire/delete", "$action_base/delete.php");
+
+ elgg_register_plugin_hook_handler('unit_test', 'system', 'thewire_test');
+
+ elgg_register_event_handler('upgrade', 'system', 'thewire_run_upgrades');
+}
+
+/**
+ * The wire page handler
+ *
+ * Supports:
+ * thewire/all View site wire posts
+ * thewire/owner/<username> View this user's wire posts
+ * thewire/following/<username> View the posts of those this user follows
+ * thewire/reply/<guid> Reply to a post
+ * thewire/view/<guid> View a post
+ * thewire/thread/<id> View a conversation thread
+ * thewire/tag/<tag> View wire posts tagged with <tag>
+ *
+ * @param array $page From the page_handler function
+ * @return bool
+ */
+function thewire_page_handler($page) {
+
+ $base_dir = elgg_get_plugins_path() . 'thewire/pages/thewire';
+
+ if (!isset($page[0])) {
+ $page = array('all');
+ }
+
+ switch ($page[0]) {
+ case "all":
+ include "$base_dir/everyone.php";
+ break;
+
+ case "friends":
+ include "$base_dir/friends.php";
+ break;
+
+ case "owner":
+ include "$base_dir/owner.php";
+ break;
+
+ case "view":
+ if (isset($page[1])) {
+ set_input('guid', $page[1]);
+ }
+ include "$base_dir/view.php";
+ break;
+
+ case "thread":
+ if (isset($page[1])) {
+ set_input('thread_id', $page[1]);
+ }
+ include "$base_dir/thread.php";
+ break;
+
+ case "reply":
+ if (isset($page[1])) {
+ set_input('guid', $page[1]);
+ }
+ include "$base_dir/reply.php";
+ break;
+
+ case "tag":
+ if (isset($page[1])) {
+ set_input('tag', $page[1]);
+ }
+ include "$base_dir/tag.php";
+ break;
+
+ case "previous":
+ if (isset($page[1])) {
+ set_input('guid', $page[1]);
+ }
+ include "$base_dir/previous.php";
+ break;
+
+ default:
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Override the url for a wire post to return the thread
+ *
+ * @param ElggObject $thewirepost Wire post object
+ */
+function thewire_url($thewirepost) {
+ global $CONFIG;
+ return $CONFIG->url . "thewire/view/" . $thewirepost->guid;
+}
+
+/**
+ * Returns the notification body
+ *
+ * @return $string
+ */
+function thewire_notify_message($hook, $entity_type, $returnvalue, $params) {
+ global $CONFIG;
+
+ $entity = $params['entity'];
+ if (($entity instanceof ElggEntity) && ($entity->getSubtype() == 'thewire')) {
+ $descr = $entity->description;
+ $owner = $entity->getOwnerEntity();
+ if ($entity->reply) {
+ // have to do this because of poor design of Elgg notification system
+ $parent_post = get_entity(get_input('parent_guid'));
+ if ($parent_post) {
+ $parent_owner = $parent_post->getOwnerEntity();
+ }
+ $body = sprintf(elgg_echo('thewire:notify:reply'), $owner->name, $parent_owner->name);
+ } else {
+ $body = sprintf(elgg_echo('thewire:notify:post'), $owner->name);
+ }
+ $body .= "\n\n" . $descr . "\n\n";
+ $body .= elgg_echo('thewire') . ": {$CONFIG->url}thewire";
+ return $body;
+ }
+ return $returnvalue;
+}
+
+/**
+ * Get an array of hashtags from a text string
+ *
+ * @param string $text The text of a post
+ * @return array
+ */
+function thewire_get_hashtags($text) {
+ // beginning of text or white space followed by hashtag
+ // hashtag must begin with # and contain at least one character not digit, space, or punctuation
+ $matches = array();
+ preg_match_all('/(^|[^\w])#(\w*[^\s\d!-\/:-@]+\w*)/', $text, $matches);
+ return $matches[2];
+}
+
+/**
+ * Replace urls, hash tags, and @'s by links
+ *
+ * @param string $text The text of a post
+ * @return string
+ */
+function thewire_filter($text) {
+ global $CONFIG;
+
+ $text = ' ' . $text;
+
+ // email addresses
+ $text = preg_replace(
+ '/(^|[^\w])([\w\-\.]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})/i',
+ '$1<a href="mailto:$2@$3">$2@$3</a>',
+ $text);
+
+ // links
+ $text = parse_urls($text);
+
+ // usernames
+ $text = preg_replace(
+ '/(^|[^\w])@([\p{L}\p{Nd}._]+)/u',
+ '$1<a href="' . $CONFIG->wwwroot . 'thewire/owner/$2">@$2</a>',
+ $text);
+
+ // hashtags
+ $text = preg_replace(
+ '/(^|[^\w])#(\w*[^\s\d!-\/:-@]+\w*)/',
+ '$1<a href="' . $CONFIG->wwwroot . 'thewire/tag/$2">#$2</a>',
+ $text);
+
+ $text = trim($text);
+
+ return $text;
+}
+
+/**
+ * Create a new wire post.
+ *
+ * @param string $text The post text
+ * @param int $userid The user's guid
+ * @param int $access_id Public/private etc
+ * @param int $parent_guid Parent post guid (if any)
+ * @param string $method The method (default: 'site')
+ * @return guid or false if failure
+ */
+function thewire_save_post($text, $userid, $access_id, $parent_guid = 0, $method = "site") {
+ $post = new ElggObject();
+
+ $post->subtype = "thewire";
+ $post->owner_guid = $userid;
+ $post->access_id = $access_id;
+
+ // only 200 characters allowed
+ $text = elgg_substr($text, 0, 200);
+
+ // no html tags allowed so we escape
+ $post->description = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
+
+ $post->method = $method; //method: site, email, api, ...
+
+ $tags = thewire_get_hashtags($text);
+ if ($tags) {
+ $post->tags = $tags;
+ }
+
+ // must do this before saving so notifications pick up that this is a reply
+ if ($parent_guid) {
+ $post->reply = true;
+ }
+
+ $guid = $post->save();
+
+ // set thread guid
+ if ($parent_guid) {
+ $post->addRelationship($parent_guid, 'parent');
+
+ // name conversation threads by guid of first post (works even if first post deleted)
+ $parent_post = get_entity($parent_guid);
+ $post->wire_thread = $parent_post->wire_thread;
+ } else {
+ // first post in this thread
+ $post->wire_thread = $guid;
+ }
+
+ if ($guid) {
+ add_to_river('river/object/thewire/create', 'create', $post->owner_guid, $post->guid);
+
+ // let other plugins know we are setting a user status
+ $params = array(
+ 'entity' => $post,
+ 'user' => $post->getOwnerEntity(),
+ 'message' => $post->description,
+ 'url' => $post->getURL(),
+ 'origin' => 'thewire',
+ );
+ elgg_trigger_plugin_hook('status', 'user', $params);
+ }
+
+ return $guid;
+}
+
+/**
+ * Send notification to poster of parent post if not notified already
+ *
+ * @param int $guid The guid of the reply wire post
+ * @param int $parent_guid The guid of the original wire post
+ * @param ElggUser $user The user who posted the reply
+ * @return void
+ */
+function thewire_send_response_notification($guid, $parent_guid, $user) {
+ $parent_owner = get_entity($parent_guid)->getOwnerEntity();
+ $user = elgg_get_logged_in_user_entity();
+
+ // check to make sure user is not responding to self
+ if ($parent_owner->guid != $user->guid) {
+ // check if parent owner has notification for this user
+ $send_response = true;
+ global $NOTIFICATION_HANDLERS;
+ foreach ($NOTIFICATION_HANDLERS as $method => $foo) {
+ if (check_entity_relationship($parent_owner->guid, 'notify' . $method, $user->guid)) {
+ $send_response = false;
+ }
+ }
+
+ // create the notification message
+ if ($send_response) {
+ // grab same notification message that goes to everyone else
+ $params = array(
+ 'entity' => get_entity($guid),
+ 'method' => "email",
+ );
+ $msg = thewire_notify_message("", "", "", $params);
+
+ notify_user(
+ $parent_owner->guid,
+ $user->guid,
+ elgg_echo('thewire:notify:subject'),
+ $msg);
+ }
+ }
+}
+
+/**
+ * Get the latest wire guid - used for ajax update
+ *
+ * @return guid
+ */
+function thewire_latest_guid() {
+ $post = elgg_get_entities(array(
+ 'type' => 'object',
+ 'subtype' => 'thewire',
+ 'limit' => 1,
+ ));
+ if ($post) {
+ return $post[0]->guid;
+ } else {
+ return 0;
+ }
+}
+
+/**
+ * Get the parent of a wire post
+ *
+ * @param int $post_guid The guid of the reply
+ * @return ElggObject or null
+ */
+function thewire_get_parent($post_guid) {
+ $parents = elgg_get_entities_from_relationship(array(
+ 'relationship' => 'parent',
+ 'relationship_guid' => $post_guid,
+ ));
+ if ($parents) {
+ return $parents[0];
+ }
+ return null;
+}
+
+/**
+ * Sets up the entity menu for thewire
+ *
+ * Adds reply, thread, and view previous links. Removes edit and access.
+ *
+ * @param string $hook Hook name
+ * @param string $type Hook type
+ * @param array $value Array of menu items
+ * @param array $params Array with the entity
+ * @return array
+ */
+function thewire_setup_entity_menu_items($hook, $type, $value, $params) {
+ $handler = elgg_extract('handler', $params, false);
+ if ($handler != 'thewire') {
+ return $value;
+ }
+
+ foreach ($value as $index => $item) {
+ $name = $item->getName();
+ if ($name == 'access' || $name == 'edit') {
+ unset($value[$index]);
+ }
+ }
+
+ $entity = $params['entity'];
+
+ if (elgg_is_logged_in()) {
+ $options = array(
+ 'name' => 'reply',
+ 'text' => elgg_echo('thewire:reply'),
+ 'href' => "thewire/reply/$entity->guid",
+ 'priority' => 150,
+ );
+ $value[] = ElggMenuItem::factory($options);
+ }
+
+ if ($entity->reply) {
+ $options = array(
+ 'name' => 'previous',
+ 'text' => elgg_echo('thewire:previous'),
+ 'href' => "thewire/previous/$entity->guid",
+ 'priority' => 160,
+ 'link_class' => 'thewire-previous',
+ 'title' => elgg_echo('thewire:previous:help'),
+ );
+ $value[] = ElggMenuItem::factory($options);
+ }
+
+ $options = array(
+ 'name' => 'thread',
+ 'text' => elgg_echo('thewire:thread'),
+ 'href' => "thewire/thread/$entity->wire_thread",
+ 'priority' => 170,
+ );
+ $value[] = ElggMenuItem::factory($options);
+
+ return $value;
+}
+
+/**
+ * Add a menu item to an ownerblock
+ *
+ * @return array
+ */
+function thewire_owner_block_menu($hook, $type, $return, $params) {
+ if (elgg_instanceof($params['entity'], 'user')) {
+ $url = "thewire/owner/{$params['entity']->username}";
+ $item = new ElggMenuItem('thewire', elgg_echo('item:object:thewire'), $url);
+ $return[] = $item;
+ }
+
+ return $return;
+}
+
+/**
+ * Runs unit tests for the wire
+ *
+ * @return array
+ */
+function thewire_test($hook, $type, $value, $params) {
+ global $CONFIG;
+ $value[] = $CONFIG->pluginspath . 'thewire/tests/regex.php';
+ return $value;
+}
+
+function thewire_run_upgrades() {
+ $path = dirname(__FILE__) . '/upgrades/';
+ $files = elgg_get_upgrade_files($path);
+
+ foreach ($files as $file) {
+ include $path . $file;
+ }
+} \ No newline at end of file
diff --git a/mod/thewire/tests/regex.php b/mod/thewire/tests/regex.php
new file mode 100644
index 000000000..c73e06bdc
--- /dev/null
+++ b/mod/thewire/tests/regex.php
@@ -0,0 +1,303 @@
+<?php
+/**
+ * Regular expression tests for the wire
+ */
+class TheWireRegexTest extends ElggCoreUnitTest {
+
+ /**
+ * Called before each test object.
+ */
+ public function __construct() {
+ $this->ia = elgg_set_ignore_access(TRUE);
+ parent::__construct();
+
+ // all __construct() code should come after here
+ }
+
+ /**
+ * Called before each test method.
+ */
+ public function setUp() {
+
+ }
+
+ /**
+ * Called after each test method.
+ */
+ public function tearDown() {
+ // do not allow SimpleTest to interpret Elgg notices as exceptions
+ $this->swallowErrors();
+ }
+
+ /**
+ * Called after each test object.
+ */
+ public function __destruct() {
+ elgg_set_ignore_access($this->ia);
+ // all __destruct() code should go above here
+ parent::__destruct();
+ }
+
+ /**
+ * Get the link for a user's wire page
+ *
+ * @param string $username Username
+ * @return string
+ */
+ protected function getUserWireLink($username) {
+ $url = "thewire/owner/$username";
+ $url = elgg_normalize_url($url);
+ return "<a href=\"$url\">@$username</a>";
+ }
+
+ /**
+ * Get the link for a hashtag page
+ *
+ * @param string $tag Tag string
+ * @return string
+ */
+ protected function getHashtagLink($tag) {
+ $url = "thewire/tag/$tag";
+ $url = elgg_normalize_url($url);
+ return "<a href=\"$url\">#$tag</a>";
+ }
+
+ /**
+ * Get a link for an email address mailto
+ *
+ * @param string $address Email address
+ * @return string
+ */
+ protected function getEmailLink($address) {
+ return "<a href=\"mailto:$address\">$address</a>";
+ }
+
+ /**
+ * Get the html for a link
+ *
+ * @param string $address URL
+ * @return string
+ */
+ protected function getLink($address) {
+ return parse_urls($address);
+ }
+
+ /**
+ * Usernames: @user
+ */
+ public function testReplaceUsernames() {
+ // beginning of text
+ $text = "@user test";
+ $expected = $this->getUserWireLink('user') . " test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // after space
+ $text = "test @user test";
+ $expected = "test " . $this->getUserWireLink('user') . " test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // followed by comma
+ $text = "test @user, test";
+ $expected = "test " . $this->getUserWireLink('user') . ", test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // preceded by comma
+ $text = "test ,@user test";
+ $expected = "test ," . $this->getUserWireLink('user') . " test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // include digit
+ $text = "@3user test";
+ $expected = $this->getUserWireLink('3user') . " test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // include underscore
+ $text = "@user_name test";
+ $expected = $this->getUserWireLink('user_name') . " test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // parentheses
+ $text = "test (@user) test";
+ $expected = "test (" . $this->getUserWireLink('user') . ") test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // utf8 characters
+ $text = "@tyúkanyó";
+ $expected = $this->getUserWireLink('tyúkanyó');
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+ }
+
+ /**
+ * Hashtags: #tag
+ */
+ public function testReplaceHashtags() {
+ // tag at beginning
+ $text = "#tag test";
+ $expected = $this->getHashtagLink('tag') . " test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // tag not at beginning
+ $text = "test #tag test";
+ $expected = "test " . $this->getHashtagLink('tag') . " test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // followed by comma
+ $text = "test #tag, test";
+ $expected = "test " . $this->getHashtagLink('tag') . ", test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // preceded by comma
+ $text = "test,#tag test";
+ $expected = "test," . $this->getHashtagLink('tag') . " test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // followed by period
+ $text = "test #tag. test";
+ $expected = "test " . $this->getHashtagLink('tag') . ". test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // parentheses
+ $text = "test (#tag) test";
+ $expected = "test (" . $this->getHashtagLink('tag') . ") test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // include number
+ $text = "test #tag2000 test";
+ $expected = "test " . $this->getHashtagLink('tag2000') . " test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // cannot be just a number
+ $text = "test #1 test";
+ $expected = $text;
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+}
+
+ /**
+ * Email: johndoe@gmail.com
+ */
+ public function testReplaceEmailAddress() {
+ // email at beginning of text
+ $text = "test@test.com test";
+ $expected = $this->getEmailLink('test@test.com') . " test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // after space
+ $text = "test test@test.com test";
+ $expected = "test " . $this->getEmailLink('test@test.com') . " test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // followed by comma
+ $text = "test test@test.com, test";
+ $expected = "test " . $this->getEmailLink('test@test.com') . ", test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // preceded by comma
+ $text = "test,test@test.com test";
+ $expected = "test," . $this->getEmailLink('test@test.com') . " test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // followed by period
+ $text = "test test@test.com. test";
+ $expected = "test " . $this->getEmailLink('test@test.com') . ". test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // parentheses
+ $text = "test (test@test.com) test";
+ $expected = "test (" . $this->getEmailLink('test@test.com') . ") test";
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // includes digits
+ $text = "user1@domain1.com";
+ $expected = $this->getEmailLink('user1@domain1.com');
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // includes underscore
+ $text = "user_name@domain.com";
+ $expected = $this->getEmailLink('user_name@domain.com');
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // includes period
+ $text = "user.name@domain.com";
+ $expected = $this->getEmailLink('user.name@domain.com');
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // includes subdomains
+ $text = "user.name@domain.com.uk";
+ $expected = $this->getEmailLink('user.name@domain.com.uk');
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+ }
+
+ /**
+ * Links: http://www.example.org/
+ */
+ public function testReplaceLinks() {
+ // beginning of text
+ $text = "http://www.test.org";
+ $expected = $this->getLink('http://www.test.org');
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // not at beginning of text
+ $text = "test http://www.test.org";
+ $expected = 'test ' . $this->getLink('http://www.test.org');
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // followed by comma
+ $text = "test http://www.test.org, test";
+ $expected = 'test ' . $this->getLink('http://www.test.org') . ', test';
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // preceeded by comma
+ $text = "test,http://www.test.org test";
+ $expected = 'test,' . $this->getLink('http://www.test.org') . ' test';
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // followed by period
+ $text = "test http://www.test.org. test";
+ $expected = 'test ' . $this->getLink('http://www.test.org') . '. test';
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // surrounded by parentheses
+ $text = "test (http://www.test.org) test";
+ $expected = 'test (' . $this->getLink('http://www.test.org') . ') test';
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+
+ // no http://
+ $text = "test www.test.org test";
+ $expected = 'test ' . $this->getLink('www.test.org') . ' test';
+ $result = thewire_filter($text);
+ $this->assertEqual($result, $expected);
+ }
+
+}
diff --git a/mod/thewire/upgrades/2012122701-fix_entity_class.php b/mod/thewire/upgrades/2012122701-fix_entity_class.php
new file mode 100644
index 000000000..a1f382712
--- /dev/null
+++ b/mod/thewire/upgrades/2012122701-fix_entity_class.php
@@ -0,0 +1,8 @@
+<?php
+/**
+ * Register thewire objects with the ElggWire class.
+ */
+
+if (get_subtype_id('object', 'thewire')) {
+ update_subtype('object', 'thewire', 'ElggWire');
+} \ No newline at end of file
diff --git a/mod/thewire/views/default/forms/thewire/add.php b/mod/thewire/views/default/forms/thewire/add.php
new file mode 100644
index 000000000..8607b3662
--- /dev/null
+++ b/mod/thewire/views/default/forms/thewire/add.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Wire add form body
+ *
+ * @uses $vars['post']
+ */
+
+elgg_load_js('elgg.thewire');
+
+$post = elgg_extract('post', $vars);
+
+$text = elgg_echo('post');
+if ($post) {
+ $text = elgg_echo('thewire:reply');
+}
+
+if ($post) {
+ echo elgg_view('input/hidden', array(
+ 'name' => 'parent_guid',
+ 'value' => $post->guid,
+ ));
+}
+
+echo elgg_view('input/plaintext', array(
+ 'name' => 'body',
+ 'class' => 'mtm',
+ 'id' => 'thewire-textarea',
+));
+?>
+<div id="thewire-characters-remaining">
+ <span>140</span> <?php echo elgg_echo('thewire:charleft'); ?>
+</div>
+<div class="elgg-foot mts">
+<?php
+
+echo elgg_view('input/submit', array(
+ 'value' => $text,
+ 'id' => 'thewire-submit-button',
+));
+?>
+</div> \ No newline at end of file
diff --git a/mod/thewire/views/default/js/thewire.php b/mod/thewire/views/default/js/thewire.php
new file mode 100644
index 000000000..ba8f35050
--- /dev/null
+++ b/mod/thewire/views/default/js/thewire.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * The wire's JavaScript
+ */
+
+$site_url = elgg_get_site_url();
+
+?>
+
+elgg.provide('elgg.thewire');
+
+elgg.thewire.init = function() {
+ $("#thewire-textarea").live('keydown', function() {
+ elgg.thewire.textCounter(this, $("#thewire-characters-remaining span"), 140);
+ });
+ $("#thewire-textarea").live('keyup', function() {
+ elgg.thewire.textCounter(this, $("#thewire-characters-remaining span"), 140);
+ });
+
+ $(".thewire-previous").live('click', elgg.thewire.viewPrevious);
+};
+
+/**
+ * Update the number of characters left with every keystroke
+ *
+ * @param {Object} textarea
+ * @param {Object} status
+ * @param {integer} limit
+ * @return void
+ */
+elgg.thewire.textCounter = function(textarea, status, limit) {
+
+ var remaining_chars = limit - $(textarea).val().length;
+ status.html(remaining_chars);
+
+ if (remaining_chars < 0) {
+ status.parent().addClass("thewire-characters-remaining-warning");
+ $("#thewire-submit-button").attr('disabled', 'disabled');
+ $("#thewire-submit-button").addClass('elgg-state-disabled');
+ } else {
+ status.parent().removeClass("thewire-characters-remaining-warning");
+ $("#thewire-submit-button").removeAttr('disabled', 'disabled');
+ $("#thewire-submit-button").removeClass('elgg-state-disabled');
+ }
+};
+
+/**
+ * Display the previous wire post
+ *
+ * Makes Ajax call to load the html and handles changing the previous link
+ *
+ * @param {Object} event
+ * @return void
+ */
+elgg.thewire.viewPrevious = function(event) {
+ var $link = $(this);
+ var postGuid = $link.attr("href").split("/").pop();
+ var $previousDiv = $("#thewire-previous-" + postGuid);
+
+ if ($link.html() == elgg.echo('thewire:hide')) {
+ $link.html(elgg.echo('thewire:previous'));
+ $link.attr("title", elgg.echo('thewire:previous:help'));
+ $previousDiv.slideUp(400);
+ } else {
+ $link.html(elgg.echo('thewire:hide'));
+ $link.attr("title", elgg.echo('thewire:hide:help'));
+
+ $.ajax({type: "GET",
+ url: elgg.config.wwwroot + "ajax/view/thewire/previous",
+ dataType: "html",
+ cache: false,
+ data: {guid: postGuid},
+ success: function(htmlData) {
+ if (htmlData.length > 0) {
+ $previousDiv.html(htmlData);
+ $previousDiv.slideDown(600);
+ }
+ }
+ });
+
+ }
+
+ event.preventDefault();
+};
+
+elgg.register_hook_handler('init', 'system', elgg.thewire.init);
diff --git a/mod/thewire/views/default/object/thewire.php b/mod/thewire/views/default/object/thewire.php
new file mode 100644
index 000000000..134c87243
--- /dev/null
+++ b/mod/thewire/views/default/object/thewire.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * View a wire post
+ *
+ * @uses $vars['entity']
+ */
+
+elgg_load_js('elgg.thewire');
+
+$full = elgg_extract('full_view', $vars, FALSE);
+$post = elgg_extract('entity', $vars, FALSE);
+
+if (!$post) {
+ return true;
+}
+
+// make compatible with posts created with original Curverider plugin
+$thread_id = $post->wire_thread;
+if (!$thread_id) {
+ $post->wire_thread = $post->guid;
+}
+
+$owner = $post->getOwnerEntity();
+
+$owner_icon = elgg_view_entity_icon($owner, 'tiny');
+$owner_link = elgg_view('output/url', array(
+ 'href' => "thewire/owner/$owner->username",
+ 'text' => $owner->name,
+ 'is_trusted' => true,
+));
+$author_text = elgg_echo('byline', array($owner_link));
+$date = elgg_view_friendly_time($post->time_created);
+
+$metadata = elgg_view_menu('entity', array(
+ 'entity' => $post,
+ 'handler' => 'thewire',
+ 'sort_by' => 'priority',
+ 'class' => 'elgg-menu-hz',
+));
+
+$subtitle = "$author_text $date";
+
+// do not show the metadata and controls in widget view
+if (elgg_in_context('widgets')) {
+ $metadata = '';
+}
+
+$params = array(
+ 'entity' => $post,
+ 'metadata' => $metadata,
+ 'subtitle' => $subtitle,
+ 'content' => thewire_filter($post->description),
+ 'tags' => false,
+);
+$params = $params + $vars;
+$list_body = elgg_view('object/elements/summary', $params);
+
+echo elgg_view_image_block($owner_icon, $list_body);
+
+if ($post->reply) {
+ echo "<div class=\"thewire-parent hidden\" id=\"thewire-previous-{$post->guid}\">";
+ echo "</div>";
+}
diff --git a/mod/thewire/views/default/river/object/thewire/create.php b/mod/thewire/views/default/river/object/thewire/create.php
new file mode 100644
index 000000000..c75a42b3f
--- /dev/null
+++ b/mod/thewire/views/default/river/object/thewire/create.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * File river view.
+ */
+
+$object = $vars['item']->getObjectEntity();
+$excerpt = strip_tags($object->description);
+$excerpt = thewire_filter($excerpt);
+
+$subject = $vars['item']->getSubjectEntity();
+$subject_link = elgg_view('output/url', array(
+ 'href' => $subject->getURL(),
+ 'text' => $subject->name,
+ 'class' => 'elgg-river-subject',
+ 'is_trusted' => true,
+));
+
+$object_link = elgg_view('output/url', array(
+ 'href' => "thewire/owner/$subject->username",
+ 'text' => elgg_echo('thewire:wire'),
+ 'class' => 'elgg-river-object',
+ 'is_trusted' => true,
+));
+
+$summary = elgg_echo("river:create:object:thewire", array($subject_link, $object_link));
+
+echo elgg_view('river/elements/layout', array(
+ 'item' => $vars['item'],
+ 'message' => $excerpt,
+ 'summary' => $summary,
+)); \ No newline at end of file
diff --git a/mod/thewire/views/default/thewire/css.php b/mod/thewire/views/default/thewire/css.php
new file mode 100644
index 000000000..d11cce74a
--- /dev/null
+++ b/mod/thewire/views/default/thewire/css.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * The Wire CSS
+ */
+
+?>
+/********************************
+The Wire
+*********************************/
+#thewire-textarea {
+ height: 40px;
+ padding: 6px;
+}
+#thewire-characters-remaining {
+ text-align: right;
+ float: right;
+ font-weight: bold;
+ color: #333333;
+}
+.thewire-characters-remaining {
+ color:#333333;
+ border:none;
+ font-size: 100%;
+ font-weight: bold;
+ padding:0 2px 0 0;
+ margin:0;
+ text-align: right;
+ background: white;
+}
+.thewire-characters-remaining-warning {
+ color: #D40D12 !important;
+}
+.thewire-parent {
+ margin-left: 40px;
+}
diff --git a/mod/thewire/views/default/thewire/previous.php b/mod/thewire/views/default/thewire/previous.php
new file mode 100644
index 000000000..e1ca83e24
--- /dev/null
+++ b/mod/thewire/views/default/thewire/previous.php
@@ -0,0 +1,11 @@
+<?php
+/**
+ * Serve up html for a post
+ */
+
+$guid = (int) get_input('guid');
+
+$parent = thewire_get_parent($guid);
+if ($parent) {
+ echo elgg_view_entity($parent);
+}
diff --git a/mod/thewire/views/default/thewire/profile_status.php b/mod/thewire/views/default/thewire/profile_status.php
new file mode 100644
index 000000000..26e1403fe
--- /dev/null
+++ b/mod/thewire/views/default/thewire/profile_status.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Latest wire post on profile page
+ *
+ * @uses $vars['entity'] User that owns this profile page
+ */
+
+$owner = $vars['entity']->guid;
+
+//grab the user's latest from the wire
+$params = array(
+ 'type' => 'object',
+ 'subtype' => 'thewire',
+ 'owner_guid' => $owner,
+ 'limit' => 1,
+);
+$latest_wire = elgg_get_entities($params);
+
+if ($latest_wire && count($latest_wire) > 0) {
+ $latest_wire = $latest_wire[0];
+ $content = thewire_filter($latest_wire->description);
+ $time = "<p class='elgg-subtext'>(" . elgg_view_friendly_time($latest_wire->time_created) . ")</p>";
+
+ $button = '';
+ if ($owner == elgg_get_logged_in_user_guid()) {
+ $url_to_wire = "thewire/owner/" . $vars['entity']->username;
+ $button = elgg_view('output/url', array(
+ 'text' => elgg_echo('thewire:update'),
+ 'href' => $url_to_wire,
+ 'class' => 'elgg-button elgg-button-action float-alt',
+ 'is_trusted' => true,
+ ));
+ }
+
+ $body = $content . $time;
+ $content = elgg_view_image_block('', $body, array('image_alt' => $button));
+
+ echo <<< HTML
+<div class="wire-status elgg-border-plain pam mbm clearfix">
+ $content
+</div>
+HTML;
+
+}
diff --git a/mod/thewire/views/default/thewire/reply.php b/mod/thewire/views/default/thewire/reply.php
new file mode 100644
index 000000000..341b691b1
--- /dev/null
+++ b/mod/thewire/views/default/thewire/reply.php
@@ -0,0 +1,14 @@
+<?php
+/**
+ * Reply header
+ */
+
+$post = $vars['post'];
+$poster = $post->getOwnerEntity();
+$poster_details = array(
+ htmlspecialchars($poster->name, ENT_QUOTES, 'UTF-8'),
+ htmlspecialchars($poster->username, ENT_QUOTES, 'UTF-8'),
+);
+?>
+<b><?php echo elgg_echo('thewire:replying', $poster_details); ?>: </b>
+<?php echo $post->description; \ No newline at end of file
diff --git a/mod/thewire/views/default/thewire/scripts/counter.js b/mod/thewire/views/default/thewire/scripts/counter.js
new file mode 100644
index 000000000..0d416fa9a
--- /dev/null
+++ b/mod/thewire/views/default/thewire/scripts/counter.js
@@ -0,0 +1,25 @@
+/**
+ * Elgg thewire text counter
+ *
+ * @package ElggTheWire
+ *
+ * @question - do we want users to be able to edit thewire?
+ *
+ * @uses $vars['entity'] Optionally, the note to view
+
+<!-- Dynamic Version by: Nannette Thacker -->
+<!-- http://www.shiningstar.net -->
+<!-- Original by : Ronnie T. Moore -->
+<!-- Web Site: The JavaScript Source -->
+<!-- Limit the number of characters per textarea -->
+*/
+
+function textCounter(field,cntfield,maxlimit) {
+ // if too long...trim it!
+ if (field.value.length > maxlimit) {
+ field.value = field.value.substring(0, maxlimit);
+ } else {
+ // otherwise, update 'characters left' counter
+ cntfield.value = maxlimit - field.value.length;
+ }
+}
diff --git a/mod/thewire/views/default/thewire/sidebar.php b/mod/thewire/views/default/thewire/sidebar.php
new file mode 100644
index 000000000..a8aadd1f8
--- /dev/null
+++ b/mod/thewire/views/default/thewire/sidebar.php
@@ -0,0 +1,9 @@
+<?php
+/**
+ * The wire sidebar
+ */
+
+echo elgg_view('page/elements/tagcloud_block', array(
+ 'subtypes' => 'thewire',
+ 'owner_guid' => elgg_get_page_owner_guid(),
+));
diff --git a/mod/thewire/views/default/widgets/thewire/content.php b/mod/thewire/views/default/widgets/thewire/content.php
new file mode 100644
index 000000000..7212d4397
--- /dev/null
+++ b/mod/thewire/views/default/widgets/thewire/content.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * User wire post widget display view
+ */
+
+$num = $vars['entity']->num_display;
+
+$options = array(
+ 'type' => 'object',
+ 'subtype' => 'thewire',
+ 'container_guid' => $vars['entity']->owner_guid,
+ 'limit' => $num,
+ 'full_view' => FALSE,
+ 'pagination' => FALSE,
+);
+$content = elgg_list_entities($options);
+
+echo $content;
+
+if ($content) {
+ $owner_url = "thewire/owner/" . elgg_get_page_owner_entity()->username;
+ $more_link = elgg_view('output/url', array(
+ 'href' => $owner_url,
+ 'text' => elgg_echo('thewire:moreposts'),
+ 'is_trusted' => true,
+ ));
+ echo "<span class=\"elgg-widget-more\">$more_link</span>";
+} else {
+ echo elgg_echo('thewire:noposts');
+}
diff --git a/mod/thewire/views/default/widgets/thewire/edit.php b/mod/thewire/views/default/widgets/thewire/edit.php
new file mode 100644
index 000000000..cee3f769d
--- /dev/null
+++ b/mod/thewire/views/default/widgets/thewire/edit.php
@@ -0,0 +1,22 @@
+<?php
+/**
+ * User wire widget edit view
+ */
+
+// set default value
+if (!isset($vars['entity']->num_display)) {
+ $vars['entity']->num_display = 4;
+}
+
+$params = array(
+ 'name' => 'params[num_display]',
+ 'value' => $vars['entity']->num_display,
+ 'options' => array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
+);
+$dropdown = elgg_view('input/dropdown', $params);
+
+?>
+<div>
+ <?php echo elgg_echo('thewire:num'); ?>:
+ <?php echo $dropdown; ?>
+</div>
diff --git a/mod/thewire/views/rss/object/thewire.php b/mod/thewire/views/rss/object/thewire.php
new file mode 100644
index 000000000..8fddb8aa8
--- /dev/null
+++ b/mod/thewire/views/rss/object/thewire.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Elgg thewire rss view
+ *
+ * @package ElggTheWire
+ */
+
+$owner = $vars['entity']->getOwnerEntity();
+if (!$owner) {
+ return true;
+}
+
+$title = elgg_echo('thewire:by', array($owner->name));
+
+$permalink = htmlspecialchars($vars['entity']->getURL(), ENT_NOQUOTES, 'UTF-8');
+$pubdate = date('r', $vars['entity']->getTimeCreated());
+
+$description = elgg_autop($vars['entity']->description);
+
+$creator = elgg_view('page/components/creator', $vars);
+$georss = elgg_view('page/components/georss', $vars);
+$extension = elgg_view('extensions/item', $vars);
+
+$item = <<<__HTML
+<item>
+ <guid isPermaLink="true">$permalink</guid>
+ <pubDate>$pubdate</pubDate>
+ <link>$permalink</link>
+ <title><![CDATA[$title]]></title>
+ <description><![CDATA[$description]]></description>
+ $creator$georss$extension
+</item>
+
+__HTML;
+
+echo $item;
diff --git a/mod/thewire/views/rss/search/object/thewire/entity.php b/mod/thewire/views/rss/search/object/thewire/entity.php
new file mode 100644
index 000000000..d9ea81ad1
--- /dev/null
+++ b/mod/thewire/views/rss/search/object/thewire/entity.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Elgg thewire.
+ * Search entity view for RSS feeds.
+ *
+ * @package ElggTheWire
+ */
+
+if (!array_key_exists('entity', $vars)) {
+ return FALSE;
+}
+
+$owner = $vars['entity']->getOwnerEntity();
+if ($owner) {
+ $title = elgg_echo('thewire:by', array($owner->name));
+}
+$description = $vars['entity']->getVolatileData('search_matched_description');
+
+?>
+
+<item>
+ <guid isPermaLink='false'><?php echo $vars['entity']->getGUID(); ?></guid>
+ <pubDate><?php echo date("r", $vars['entity']->time_created) ?></pubDate>
+ <link><?php echo htmlspecialchars($vars['entity']->getURL()); ?></link>
+ <title><![CDATA[<?php echo $title; ?>]]></title>
+ <description><![CDATA[<?php echo $description; ?>]]></description>
+</item>