Commit: 2a1dceab02947e8fe6f223c74feb226901609768

Author: Jon Adams | Date: 2009-11-29 00:10:51 -0800
rewrite for 0.3nearing complete
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 &lt;enter&gt;. <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(); },