Commit: 2a1dceab02947e8fe6f223c74feb226901609768
Author: Jon Adams | Date: 2009-11-29 00:10:51 -0800
diff --git a/config/connections.php b/config/connections.php
index eae8daf..fa5f99f 100644
--- a/config/connections.php
+++ b/config/connections.php
@@ -8,9 +8,10 @@
use \lithium\data\Connections;
-Connections::add('couch', 'http', array(
- 'adapter' => 'Couch',
+Connections::add('default', 'http', array(
+ 'adapter' => 'CouchDb',
'host' => '127.0.0.1',
'port' => 5984,
));
+
?>
diff --git a/config/routes.php b/config/routes.php
index dfe8d0b..8e639cc 100644
--- a/config/routes.php
+++ b/config/routes.php
@@ -3,7 +3,7 @@
use \lithium\http\Router;
Router::connect('/', array('controller' => 'anologue', 'action' => 'index'));
-Router::connect('/new', array('controller' => 'anologue', 'action' => 'add'));
+Router::connect('/add', array('controller' => 'anologue', 'action' => 'add'));
Router::connect('/say/{:id}', array('controller' => 'anologue', 'action' => 'say'));
Router::connect('/{:id}.{:type}', array('controller' => 'anologue', 'action' => 'view'));
Router::connect('/{:id}', array('controller' => 'anologue', 'action' => 'view'));
diff --git a/controllers/AnologueController.php b/controllers/AnologueController.php
index b206021..67c6b6e 100644
--- a/controllers/AnologueController.php
+++ b/controllers/AnologueController.php
@@ -5,52 +5,78 @@ namespace app\controllers;
use \app\models\Anologue;
use \lithium\http\Media;
+/**
+ * The core controller for Anologue.
+ *
+ * @see lithium\action\controller
+ */
class AnologueController extends \lithium\action\Controller {
+ /**
+ * This action is used to render the index view, which is essentially a static page.
+ */
public function index() {
$this->set(array('index' => true));
$this->render();
}
- public function say() {
- $status = 'error';
- if (!empty($this->request->params['id'])) {
- $data = $this->request->data;
- $data['ip'] = $this->request->env('REMOTE_ADDR');
- if (!empty($data)) {
- $status = 'fail';
- $result = Anologue::addMessage($this->request->params['id'], $data);
- $status = (!empty($result->ok)) ? 'success' : 'fail';
- }
- }
- $this->render(array('json' => (object) compact('status', 'data')));
- }
-
+ /**
+ * View an anologue. By default, the anologue data is requested and passed to the view to be
+ * rendered as html. However, a `type` param can be passed, currently utilized by the router to
+ * render the data as json.
+ */
public function view() {
$status = 'error';
$data = null;
+ $result = array();
+
if (!empty($this->request->params['id'])) {
- $data = Anologue::findById($this->request->params['id']);
+ $data = Anologue::find($this->request->params['id']);
$status = (!empty($data)) ? 'success' : 'fail';
}
- $result = array();
- $this->set(compact('data'));
-
+
+ if (!empty($data->error)) {
+ $this->redirect(array('controller' => 'anologue', 'action' => 'index'));
+ }
+
if (!empty($this->request->params['type'])) {
+ $data = $data->to('array');
$result = array(
- $this->request->params['type'] => (object) compact('status', 'anologue')
+ $this->request->params['type'] => compact('status', 'data')
);
}
+
+ $this->set(compact('data'));
$this->render($result);
}
+ /**
+ * Create a new anologue and redirect to view it.
+ *
+ * @see app\controllers\AnologueController::view()
+ */
public function add() {
$anologue = Anologue::create();
- if (!empty($anologue->error)) {
- throw new \Exception('CouchDB Error: ' . $anologue->error . ' | Reason: ' . $anologue->reason);
+ $anologue->save();
+ $this->redirect(array('controller' => 'anologue', 'action' => 'view', 'id' => $anologue->id));
+ }
+
+ /**
+ * Add a message to the an existing anologue.
+ */
+ public function say() {
+ $status = 'error';
+ if (!empty($this->request->params['id'])) {
+ $data = $this->request->data;
+ $data['ip'] = $this->request->env('REMOTE_ADDR');
+ if (!empty($data)) {
+ $status = 'fail';
+ $result = Anologue::addMessage($this->request->params['id'], $data);
+ $status = ($result) ? 'success' : 'fail';
+ }
}
- $this->redirect(array('controller' => 'anologue', 'action' => 'view', 'id' => $anologue->_id));
+ $this->render(array('json' => (object) compact('status', 'data')));
}
}
-?>
\ No newline at end of file
+?>
diff --git a/models/Anologue.php b/models/Anologue.php
index 18a7ea4..1f1753f 100644
--- a/models/Anologue.php
+++ b/models/Anologue.php
@@ -2,90 +2,69 @@
namespace app\models;
-use \lithium\data\Connections;
+use \lithium\data\model\Document;
/**
- * Data model for anologue store in couchdb.
+ * The core model and messages container for Anologue.
+ *
+ * @see lithium\data\Model
*/
-class Anologue extends \lithium\core\StaticObject {
+class Anologue extends \lithium\data\Model {
- public static $alias = 'anologue';
+ public static $alias = 'Anologue';
- protected static $_schema = array(
- 'anologue' => array(
- 'messages' => null
- ),
- 'message' => array(
- 'author' => 'anonymous',
- 'ip' => null,
- 'email' => null,
- 'timestamp' => null,
- 'text' => null
- )
- );
-
- protected static $_meta = array(
+ /**
+ * Anologue meta
+ *
+ * @var array
+ * @see lithium\data\Model::$_meta
+ */
+ protected $_meta = array(
'source' => 'anologue'
);
- public static function findById($id) {
- $uri = static::$_meta['source'] . '/' . $id;
- $result = Connections::get('couch')->get($uri);
- $result->messages = static::decodeMessages($result->messages);
- return $result;
- }
+ /**
+ * Default key/values for messages.
+ *
+ * @var array
+ * @see app\models\Anologue::addMessage()
+ */
+ protected static $_defaultMessage = array(
+ 'author' => 'anonymous',
+ 'ip' => null,
+ 'email' => null,
+ 'timestamp' => null,
+ 'text' => null
+ );
- public static function create() {
- $data = static::$_schema['anologue'];
- $result = Connections::get('couch')->post(static::$_meta['source'], $data);
- if (!empty($result->ok)) {
- $result->_id = $result->id;
- $result->_rev = $result->rev;
- unset($result->ok);
- unset($result->id);
- unset($result->rev);
- }
- return $result;
+ /**
+ * Create a new analogue using schema.
+ *
+ * @param array $data
+ * @return void
+ * @see lithium\data\Model::create()
+ */
+ public static function create($data = array()) {
+ $default = array(
+ 'messages' => null
+ );
+ $data = $data + $default;
+ return parent::create($data);
}
- public static function addMessage($id = null, $message = array()) {
- if (!empty($id) && is_string($id)) {
- $anologue = static::findById($id);
- } else {
- $message = $id;
- $id = null;
- $anologue = static::create();
- }
+ /**
+ * Append a message to an existing anologue. For user privacy, hashes the email before saving.
+ *
+ * @param integer $id
+ * @param array $message
+ * @see lithium\data\Model::save()
+ */
+ public static function addMessage($id, $message = array()) {
+ $anologue = static::find($id);
$message['email'] = md5($message['email']);
- $message = $message + array('timestamp' => time()) + static::$_schema['message'];
- $anologue->messages[] = $message;
- $anologue->messages = static::encodeMessages($anologue->messages);
- $result = Connections::get('couch')->post(static::$_meta['source'], $anologue);
- return $result;
- }
-
- public static function encodeMessages($messages = array()) {
- if (!empty($messages)) {
- foreach ($messages as $key => $message) {
- if (is_object($message)) {
- $message->text = rawurlencode($message->text);
- } else {
- $message['text'] = rawurlencode($message['text']);
- }
- $messages[$key] = $message;
- }
- }
- return $messages;
- }
-
- public static function decodeMessages($messages = array()) {
- if (!empty($messages)) {
- foreach ($messages as $key => $message) {
- $message->text = rawurldecode($message->text);
- $messages[$key] = $message;
- }
- }
- return $messages;
+ $message = $message + array('timestamp' => time()) + static::$_defaultMessage;
+ $anologue->messages->append($message);
+ return $anologue->save();
}
}
diff --git a/views/anologue/view.html.php b/views/anologue/view.html.php
index d928575..5e28208 100644
--- a/views/anologue/view.html.php
+++ b/views/anologue/view.html.php
@@ -25,12 +25,12 @@
</div>
<h1 class="smaller-title"><?php echo $this->html->link('anologue', array('controller' => 'anologue', 'action' => 'index')); ?></h1>
-<h3 class="hash"><?php echo $this->html->link($data->_id, array('action' => 'view', 'id' => $data->_id), array('title' => 'Copy this url and give it to others')); ?></h3>
+<h3 class="hash"><?php echo $this->html->link($data->id, array('action' => 'view', 'id' => $data->_id), array('title' => 'Copy this url and give it to others')); ?></h3>
<div class="anologue-help">
<p><strong>hello.</strong></p>
- <p>to get started, type your text in the box at the very bottom and press <enter>. <br />markdown is supported, to an extent.</p>
+ <p>to get started, type your text in the box at the very bottom and click 'send'. <br />markdown is supported, to an extent.</p>
<p><strong>for your privacy,</strong> your email is only used to generate your <?php echo $this->html->link('gravatar', 'http://gravatar.com'); ?> and is stored in an unreadable, encoded format.</p>
</div>
@@ -63,6 +63,9 @@
<div class="text">
<textarea name="anologue-text" id="anologue-text"></textarea>
</div>
+ <div class="submit">
+ <button id="anologue-submit"><span>send</span></button>
+ </div>
</div>
</form>
@@ -76,7 +79,7 @@
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
anologue.setup({
- id: '<?=$data->_id?>',
+ id: '<?=$data->id?>',
base: '<?php echo $this->_request->env('base') ?>',
line: <?php echo count($data->messages); ?>,
icon: '<?php echo $avatar; ?>'
diff --git a/webroot/css/anologue.css b/webroot/css/anologue.css
index c28bce7..a7da5ca 100644
--- a/webroot/css/anologue.css
+++ b/webroot/css/anologue.css
@@ -35,7 +35,7 @@ p.last { padding:.5em 0 4em 0; }
.anologue-settings label { font-weight:bold; opacity:.35; }
.anologue-settings input { border:1px solid #666; font-size:.85em; padding:.5em; margin:.25em 0 0 0; border:0; }
.anologue-help { clear:left; float:left; opacity:.5; display:block; padding: .5em 2em; text-align:left; font-size:.85em; }
- .anologue { position:relative; z-index:10; width:100%; display:block; clear:both; margin:0 0 4em 0; padding:2em 0 0; }
+ .anologue { position:relative; z-index:10; width:100%; display:block; clear:both; margin:0 0 5.5em 0; padding:2em 0 0; }
.anologue .message { position:relative; display:block; background:#fafafa; border-bottom:3px solid white; vertical-align:top; font-size:.85em; min-height:3em; }
.anologue .message:hover { background:white; }
.anologue .data { position:relative; }
@@ -43,20 +43,24 @@ p.last { padding:.5em 0 4em 0; }
.anologue li.time { position:absolute; z-index:50; opacity:.05; white-space:nowrap; text-align:center; width:4em; top:0; left:0; }
.anologue li.ip { position:absolute; z-index:50; opacity:.05; whitespace:nowrap; text-align:left; width:4em; left:.25em; top:1.6em; font-size:.85em; }
.anologue .message:hover li.time, .anologue .message:hover li.ip { opacity:.25; }
- .anologue li.author { font-weight:bold; white-space:nowrap; text-align:right; width:14em; padding:1em .5em 1em 5.5em; background:#ededed; }
+ .anologue li.author { font-weight:bold; white-space:nowrap; text-align:right; width:14em; padding:.75em .5em .25em 5.5em; min-height:2em; background:#ededed; }
.anologue li.author img { float:right; margin:0 0 0 .5em; }
.anologue li.author span { max-width:12em; overflow:hidden; display:block; }
- .anologue li.text { position:relative; padding:.5em .5em .5em 2em; margin:0 0 0 19.90em; background:url(../img/pointer.png) no-repeat top left; in-height:1em; }
+ .anologue li.text { position:relative; padding:.25em .5em 0 2em; margin:0 0 0 19.90em; background:url(../img/pointer.png) no-repeat top left; min-height:2.75em; }
.anologue .text a { border-bottom:1px dotted #77458c; }
.anologue .text .markdown { }
.anologue .text .markdown ul { padding:.25em 1em; }
- .anologue-speak { position:fixed; z-index:50; bottom:0; left:0; display:block; padding:.5em 2%; width:96%; clear:both; background:#4c2c59 url(../img/bg.png); color:white; }
- .anologue-speak span.label { display:block; position:absolute; z-index:100; top:.5em; left:.5em; font-size:.85em; padding:.5em 1em; width:19.5em; color:white; text-align:right; }
+ .anologue-speak { position:fixed; z-index:50; bottom:0; left:0; display:block; padding:1%; width:98%; clear:both; background:#4c2c59 url(../img/bg.png); color:white; }
+ .anologue-speak span.label { display:block; position:absolute; z-index:100; top:.5em; left:.5em; font-size:.85em; padding:.5em 1em; width:17.5em; color:white; text-align:right; }
.anologue-speak .label.about { top:3em; text-align:left; }
.anologue-speak .label.about a { color:white; color:#77458c; border:none; }
.anologue-speak .text { padding:0 0 0 19.5em; font-size:.85em; }
- .anologue-speak textarea { display:block; width:96%; border:0; padding:.5em 1em; height:4em; font-size:1em; color:white; background:#666; background:rgba(0,0,0,.35); overflow:hidden; }
+ .anologue-speak textarea { display:block; width:90%; border:0; padding:.5em 1%; height:4em; font-size:1em; color:white; background:#666; background:rgba(0,0,0,.35); }
.anologue-speak textarea:focus { outline:0; background:#999; background:rgba(0,0,0,.5); }
+ .anologue-speak .submit { position:absolute; top:11%; right:1%; width:5%}
+ .anologue-speak .submit button { display:block; border:none; background:#efefef; color:#666; width:100%; text-align:center; font-weight:bold; padding:.5em 0; height:4em; font-size:1em; }
+ .anologue-speak .submit button:hover { background:white; color:black; }
+
diff --git a/webroot/js/anologue.js b/webroot/js/anologue.js
index 0def99f..da74d81 100644
--- a/webroot/js/anologue.js
+++ b/webroot/js/anologue.js
@@ -12,15 +12,13 @@ var anologue = {
anologue.say();
return false;
});
- $("#anologue-text").keypress(function(e) {
- if (e.which == 13) {
- anologue.say();
- return false;
- }
+ $("#anologue-submit").click(function(e) {
+ anologue.say();
+ return false;
});
this.markdown();
this.listener();
- $(".anologue-speak").css("bottom", '-200px').animate({ bottom: 0}, 3000);
+ $(".anologue-speak").css("bottom", '-200px').animate({ bottom: 0, opacity: 100}, 3000);
$("#anologue-author").focus();
},