From 9be80a4b6880db73d3c4b8cc1487636d0b01abc2 Mon Sep 17 00:00:00 2001 From: John Coggeshall Date: Tue, 18 Mar 2014 05:11:05 -0400 Subject: [PATCH] More work on migration of annotations to the DB instead of ES. Metas (likes, etc.), comments, editing of annotation, etc. mostly working at this point. No ES yet though as I want to work out the bugs in the DB side first. --- app/controllers/AnnotationApiController.php | 77 +- app/controllers/DevController.php | 61 ++ ..._03_05_173240_create_annotations_table.php | 7 +- ...74006_create_annotation_comments_table.php | 4 +- ...05_174637_create_annotation_tags_table.php | 4 +- ...22_create_annotation_permissions_table.php | 4 +- ..._03_12_204746_create_annotation_ranges.php | 7 +- ...014_03_17_150518_alter_note_meta_table.php | 32 + ..._17_152535_add_foreign_index_note_meta.php | 33 + ...18_071119_drop_annotation_meta_columns.php | 36 + ...47_make_annotations_search_id_nullable.php | 29 + app/models/Annotation.php | 729 +++++++----------- app/models/DBAnnotation.php | 263 ------- app/models/NoteMeta.php | 2 + app/models/OldAnnotation.php | 580 ++++++++++++++ composer.json | 3 +- 16 files changed, 1115 insertions(+), 756 deletions(-) create mode 100644 app/controllers/DevController.php create mode 100644 app/database/migrations/2014_03_17_150518_alter_note_meta_table.php create mode 100644 app/database/migrations/2014_03_17_152535_add_foreign_index_note_meta.php create mode 100644 app/database/migrations/2014_03_18_071119_drop_annotation_meta_columns.php create mode 100644 app/database/migrations/2014_03_18_073947_make_annotations_search_id_nullable.php delete mode 100644 app/models/DBAnnotation.php create mode 100644 app/models/OldAnnotation.php diff --git a/app/controllers/AnnotationApiController.php b/app/controllers/AnnotationApiController.php index 53cf4f71c..7255d7154 100644 --- a/app/controllers/AnnotationApiController.php +++ b/app/controllers/AnnotationApiController.php @@ -14,6 +14,13 @@ public function __construct(){ // Returns json annotation if id found, // 404 with error message if id not found, // 404 if no id passed + + /** + * Get annotations by document ID and annotation ID + * @param interger $docId + * @param string $annotationId optional, if not provided get all + * @throws Exception + */ public function getIndex($docId, $annotationId = null){ try{ $userId = null; @@ -21,7 +28,7 @@ public function getIndex($docId, $annotationId = null){ $userId = Auth::user()->id; } - $results = DBAnnotation::loadAnnotationsForAnnotator($docId, $annotationId, $userId); + $results = Annotation::loadAnnotationsForAnnotator($docId, $annotationId, $userId); }catch(Exception $e){ throw $e; App::abort(500, $e->getMessage()); @@ -30,18 +37,23 @@ public function getIndex($docId, $annotationId = null){ return Response::json($results); } + /** + * Create a new annotation + * @param document ID $doc + */ public function postIndex($doc){ $body = Input::all(); $body['doc'] = $doc; - $annotation = new Annotation(); - $annotation->body($body); - - $id = $annotation->save(); + $annotation = Annotation::createFromAnnotatorArray($body); - return Redirect::to('/api/docs/' . $doc . '/annotations/' . $id, 303); + return Redirect::to('/api/docs/' . $doc . '/annotations/' . $annotation->id, 303); } + /** + * Update an existing annotation + * @param string $id + */ public function putIndex($id = null){ //If no id requested, return 404 @@ -50,18 +62,18 @@ public function putIndex($id = null){ } $body = Input::all(); - - $id = Input::get('id'); - - $annotation = Annotation::find($id); - - $annotation->body($body); - - $results = $annotation->update(); - - return Response::json($results); + + $annotation = Annotation::createFromAnnotatorArray($body); + + return Response::json($annotation); } + /** + * Delete an annotation by doc ID and annotation ID + * + * @param int $doc + * @param int $annotation + */ public function deleteIndex($doc, $annotation){ //If no id requested, return 404 if($annotation === null){ @@ -75,6 +87,9 @@ public function deleteIndex($doc, $annotation){ return Response::make(null, 204); } + /** + * Return search results for annotations + */ public function getSearch(){ return false; } @@ -114,9 +129,10 @@ public function postLikes($doc, $annotation = null){ App::abort(404, 'No note id passed'); } - $postAction = Annotation::addUserAction($annotation, Auth::user()->id, 'like'); + $annotation = Annotation::find($annotation); + $annotation->saveUserAction(Auth::user()->id, Annotation::ACTION_LIKE); - return Response::json($postAction); + return Response::json($annotation->toAnnotatorArray()); } public function postDislikes($doc, $annotation = null){ @@ -124,9 +140,10 @@ public function postDislikes($doc, $annotation = null){ App::abort(404, 'No note id passed'); } - $postAction = Annotation::addUserAction($annotation, Auth::user()->id, 'dislike'); + $annotation = Annotation::find($annotation); + $annotation->saveUserAction(Auth::user()->id, Annotation::ACTION_DISLIKE); - return Response::json($postAction); + return Response::json($annotation->toAnnotatorArray()); } public function postFlags($doc, $annotation = null){ @@ -134,23 +151,23 @@ public function postFlags($doc, $annotation = null){ App::abort(404, 'No note id passed'); } - $postAction = Annotation::addUserAction($annotation, Auth::user()->id, 'flag'); + $annotation = Annotation::find($annotation); + $annotation->saveUserAction(Auth::user()->id, Annotation::ACTION_FLAG); - return Response::json($postAction); + return Response::json($annotation->toAnnotatorArray()); } - public function postComments($doc, $annotation = null){ - if($annotation === null){ - throw new Exception("Unable to post comment without annotation id."); - } + public function postComments($docId, $annotationId){ $comment = Input::get('comment'); - $annotation = Annotation::find($annotation); - - $results = $annotation->addComment($comment); + $annotation = Annotation::where('doc', '=', $docId) + ->where('id', '=', $annotationId) + ->first(); - return Response::json($results); + $results = $annotation->addOrUpdateComment($comment); + + return Response::json($annotation->toAnnotatorArray()); } } diff --git a/app/controllers/DevController.php b/app/controllers/DevController.php new file mode 100644 index 000000000..fddfba099 --- /dev/null +++ b/app/controllers/DevController.php @@ -0,0 +1,61 @@ + array( + 'read' => array(), + 'update' => array(1), + 'delete' => array(1), + 'admin' => array(1) + ), + 'user' => array( + 'id' => 1, + 'email' => 'john@coggeshall.org', + 'user_level' => 1, + 'name' => "John C" + ), + 'ranges' => array( + array( + 'start' => '/div[2]/div[1]/p[2]', + 'startOffset' => 0, + 'end' => '/div[2]/div[1]/p[2]', + 'endOffset' => 127 + ) + ), + 'quote' => "This is the quote", + 'text' => "This is the comment text", + 'tags' => array('tacobell'), + 'uri' => '/docs/testing', + 'comments' => array( + array( + 'id' => 1, + 'text' => 'This is the comment on the comment', + 'created' => "Wed, 05 Mar 2014 12:40:47 -0500", + 'updated' => "Wed, 05 Mar 2014 12:40:47 -0500", + 'user' => array( + 'id' => 2, + 'user_level' => 3, + 'email' => 'joe@blow.com', + 'name' => "Joe B" + ) + ) + ), + 'doc' => 1, + 'created' => "Wed, 05 Mar 2014 12:40:47 -0500", + 'updated' => "Wed, 05 Mar 2014 12:40:47 -0500", + 'user_action' => null, + 'flags' => 1, + 'likes' => 0, + 'dislikes' => 0 + ); + + $annotation = Annotation::createFromAnnotatorArray($input); + + var_dump($annotation); + } + + +} \ No newline at end of file diff --git a/app/database/migrations/2014_03_05_173240_create_annotations_table.php b/app/database/migrations/2014_03_05_173240_create_annotations_table.php index a3091d512..07ed840ea 100644 --- a/app/database/migrations/2014_03_05_173240_create_annotations_table.php +++ b/app/database/migrations/2014_03_05_173240_create_annotations_table.php @@ -14,7 +14,9 @@ public function up() { Schema::create('annotations', function($table) { $table->engine = "InnoDB"; - $table->string('id'); + + $table->increments('id'); + $table->string('search_id'); $table->integer('user_id')->unsigned(); $table->integer('doc')->unsigned(); $table->string('quote'); @@ -25,9 +27,10 @@ public function up() $table->integer('flags'); $table->timestamps(); - $table->primary('id'); $table->foreign('user_id')->references('id')->on('users'); $table->foreign('doc')->references('id')->on('docs'); + $table->unique('search_id'); + }); } diff --git a/app/database/migrations/2014_03_05_174006_create_annotation_comments_table.php b/app/database/migrations/2014_03_05_174006_create_annotation_comments_table.php index ca935af4e..5f69403ba 100644 --- a/app/database/migrations/2014_03_05_174006_create_annotation_comments_table.php +++ b/app/database/migrations/2014_03_05_174006_create_annotation_comments_table.php @@ -16,12 +16,12 @@ public function up() $table->engine = "InnoDB"; $table->integer('id')->unsigned(); - $table->string('annotation_id'); + $table->integer('annotation_id')->unsigned(); $table->integer('user_id')->unsigned(); $table->string('text'); $table->timestamps(); - $table->foreign('annotation_id')->references('id')->on('annotations'); + $table->foreign('annotation_id')->references('id')->on('annotations')->on_delete('cascade'); $table->foreign('user_id')->references('id')->on('users'); $table->unique(array('annotation_id', 'id')); }); diff --git a/app/database/migrations/2014_03_05_174637_create_annotation_tags_table.php b/app/database/migrations/2014_03_05_174637_create_annotation_tags_table.php index 3f64c528a..302708486 100644 --- a/app/database/migrations/2014_03_05_174637_create_annotation_tags_table.php +++ b/app/database/migrations/2014_03_05_174637_create_annotation_tags_table.php @@ -16,11 +16,11 @@ public function up() $table->engine = "InnoDB"; $table->increments('id'); - $table->string('annotation_id'); + $table->integer('annotation_id')->unsigned(); $table->string('tag'); $table->timestamps(); - $table->foreign('annotation_id')->references('id')->on('annotations'); + $table->foreign('annotation_id')->references('id')->on('annotations')->on_delete('cascade'); }); } diff --git a/app/database/migrations/2014_03_05_192222_create_annotation_permissions_table.php b/app/database/migrations/2014_03_05_192222_create_annotation_permissions_table.php index c77533401..242395008 100644 --- a/app/database/migrations/2014_03_05_192222_create_annotation_permissions_table.php +++ b/app/database/migrations/2014_03_05_192222_create_annotation_permissions_table.php @@ -17,7 +17,7 @@ public function up() $table->engine = "InnoDB"; $table->increments('id'); - $table->string('annotation_id'); + $table->integer('annotation_id')->unsigned(); $table->integer('user_id')->unsigned(); $table->integer('read'); $table->integer('update'); @@ -26,7 +26,7 @@ public function up() $table->timestamps(); $table->foreign('user_id')->references('id')->on('users'); - $table->foreign('annotation_id')->references('id')->on('annotations'); + $table->foreign('annotation_id')->references('id')->on('annotations')->on_delete('cascade'); $table->unique(array('user_id', 'annotation_id')); }); diff --git a/app/database/migrations/2014_03_12_204746_create_annotation_ranges.php b/app/database/migrations/2014_03_12_204746_create_annotation_ranges.php index 93e63e4a6..0c966e403 100644 --- a/app/database/migrations/2014_03_12_204746_create_annotation_ranges.php +++ b/app/database/migrations/2014_03_12_204746_create_annotation_ranges.php @@ -13,15 +13,18 @@ class CreateAnnotationRanges extends Migration { public function up() { Schema::create('annotation_ranges', function($table) { + + $table->engine = "InnoDB"; + $table->increments('id'); - $table->string('annotation_id'); + $table->integer('annotation_id')->unsigned(); $table->string('start'); $table->string('end'); $table->integer('start_offset')->unsigned(); $table->integer('end_offset')->unsigned(); $table->timestamps(); - $table->foreign('annotation_id')->references('id')->on('annotations'); + $table->foreign('annotation_id')->references('id')->on('annotations')->on_delete('cascade'); $table->unique(array('annotation_id', 'start_offset')); $table->unique(array('annotation_id', 'end_offset')); }); diff --git a/app/database/migrations/2014_03_17_150518_alter_note_meta_table.php b/app/database/migrations/2014_03_17_150518_alter_note_meta_table.php new file mode 100644 index 000000000..7f8c51fdc --- /dev/null +++ b/app/database/migrations/2014_03_17_150518_alter_note_meta_table.php @@ -0,0 +1,32 @@ +dropColumn('note_id'); + $table->integer('annotation_id')->unsigned(); + }); + + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + throw new Exception("Can't rollback this migration"); + } + +} diff --git a/app/database/migrations/2014_03_17_152535_add_foreign_index_note_meta.php b/app/database/migrations/2014_03_17_152535_add_foreign_index_note_meta.php new file mode 100644 index 000000000..ecf13917e --- /dev/null +++ b/app/database/migrations/2014_03_17_152535_add_foreign_index_note_meta.php @@ -0,0 +1,33 @@ +foreign('annotation_id')->references('id')->on('annotations')->on_delete('cascade'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('note_meta', function($table) { + $table->dropIndex('note_meta_annotation_id_foreign'); + }); + + } + +} diff --git a/app/database/migrations/2014_03_18_071119_drop_annotation_meta_columns.php b/app/database/migrations/2014_03_18_071119_drop_annotation_meta_columns.php new file mode 100644 index 000000000..0379966a4 --- /dev/null +++ b/app/database/migrations/2014_03_18_071119_drop_annotation_meta_columns.php @@ -0,0 +1,36 @@ +dropColumn('likes'); + $table->dropColumn('dislikes'); + $table->dropColumn('flags'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('annotations', function($table) { + $table->integer('likes'); + $table->integer('dislikes'); + $table->integer('flags'); + }); + } + +} diff --git a/app/database/migrations/2014_03_18_073947_make_annotations_search_id_nullable.php b/app/database/migrations/2014_03_18_073947_make_annotations_search_id_nullable.php new file mode 100644 index 000000000..691157aff --- /dev/null +++ b/app/database/migrations/2014_03_18_073947_make_annotations_search_id_nullable.php @@ -0,0 +1,29 @@ +id = $id; - - if(isset($source)){ - foreach($source as $key => $value){ - $this->$key = $value; - } - } - - $this->index = Config::get('elasticsearch.annotationIndex'); - - $this->es = self::connect(); - } - - public function addComment($comment){ - $es = $this->es; - - $comment['created'] = Carbon::now('America/New_York')->toRFC2822String(); - $comment['updated'] = Carbon::now('America/New_York')->toRFC2822String(); - - array_push($this->comments, $comment); - - foreach($this->comments as $index => &$comment){ - $comment['id'] = $index + 1; - } - - $retval = $this->update(false); - - $dbComment = new AnnotationComment(); - $dbComment->text = $comment['text']; - $dbComment->user_id = $comment['user']['id']; - $dbComment->id = $comment['id']; - $dbComment->annotation_id = $this->id; - $dbComment->save(); - - return $retval; - } - - public function setUserAction($user_id){ - $meta = NoteMeta::where('user_id', $user_id)->where('note_id', '=', $this->id)->where('meta_key', '=', 'user_action'); - - if($meta->count() == 1){ - $this->user_action = $meta->first()->meta_value; - } + static protected $_esInstance = null; + static protected $_esIndex; + + static public function getEsClient() + { + static::connectToEs(); + return static::$_esInstance; } - - public function setActionCounts(){ - $this->likes = $this->likes(); - $this->dislikes = $this->dislikes(); - $this->flags = $this->flags(); + + static public function setEsIndex($index) + { + static::$_esIndex = $index; } - - public function update($updateTimestamp = true){ - $es = $this->es; - - if($updateTimestamp){ - $this->updated = Carbon::now('America/New_York')->toRFC2822String(); - } - - if(isset($body)){ - foreach($body as $name => $value){ - $this->$name = $value; - } - } - - if(isset($body['user_action'])){ - unset($body['user_action']); - } - - $params = array( - 'index' => $this->index, - 'type' => self::TYPE, - 'id' => $this->id, - ); - - $attributes = new ReflectionClass('Annotation'); - $attributes = $attributes->getProperties(ReflectionProperty::IS_PUBLIC); - - $body = array(); - - foreach($attributes as $attribute){ - $name = $attribute->name; - $body[$name] = $this->$name; - } - - $params['body']['doc'] = $body; - - $dbValues = $params['body']; - $dbValues['id'] = $params['id']; - - try{ - $results = $es->update($params); - }catch(Elasticsearch\Common\Exceptions\Missing404Exception $e){ - App::abort(404, 'Id not found'); - }catch(Exception $e){ - App::abort(404, $e->getMessage()); - } - - file_put_contents('/tmp/update.txt', var_export($params, true)); - - static::saveAnnotationModel($dbValues); - - return $results; + + static public function getEsIndex() + { + return static::$_esIndex; } - - public function save(){ - $es = $this->es; - - if(!isset($this->body)){ - throw new Exception('Annotation body not found. Cannot save.'); + + static public function connectToEs() + { + if(is_null(static::$_esInstance)) { + $params = array( + 'hosts' => Config::get('elasticsearch.hosts') + ); + + static::$_esInstance = new ElasticSearch\Client($params); } - - $dbValues = $this->body; - - $this->body['created'] = Carbon::now('America/New_York')->toRFC2822String(); - $this->body['updated'] = Carbon::now('America/New_York')->toRFC2822String(); - - $params = array( - 'index' => $this->index, - 'type' => self::TYPE, - 'body' => $this->body - ); - - $results = $es->index($params); - - $dbValues['id'] = $results['_id']; - - static::saveAnnotationModel($dbValues); - return $results['_id']; - } - - public function delete(){ - $es = self::connect(); - - $params = array( - 'index' => $this->index, - 'type' => self::TYPE, - 'id' => $this->id - ); - - $result = $es->delete($params); + static::setEsIndex(Config::get('elasticsearch.annotationIndex')); - if($result['ok'] == true){ - $metas = NoteMeta::where('note_id', $this->id); - $metas->delete(); - } + return static::$_esInstance; - return $result; - } - - /** - * Accessor Functions - */ - - public function id($id = null){ - return $this->access('id', $id); - } - - public function created($created = null){ - return $this->access('created', $created); } - public function updated($updated = null){ - return $this->access('updated', $updated); + public function comments() + { + return $this->hasMany('AnnotationComment', 'annotation_id'); } - public function quote($quote = null){ - return $this->access('quote', $quote); - } - - public function uri($uri = null){ - return $this->access('uri', $uri); + public function tags() + { + return $this->hasMany('AnnotationTag', 'annotation_id'); } - public function ranges($ranges = null){ - return $this->access('ranges', $ranges); - } - - public function tags($tags = null){ - return $this->access('tags', $tags); + public function permissions() + { + return $this->hasMany('AnnotationPermission', 'annotation_id'); } - public function permissions($permissions = null){ - return $this->access('permissions', $permissions); - } - - public function body($body = null){ - return $this->access('body', $body); - } - - public function text($text = null){ - return $this->access('text', $text); - } - - public function user($user = null){ - return $this->access('user', $user); - } - - public function likes($likes = null){ - $likes = NoteMeta::where('note_id', $this->id)->where('meta_key', '=', 'user_action')->where('meta_value', '=', 'like')->count(); - - return $likes; - } - - public function dislikes($disliked = null){ - $dislikes = NoteMeta::where('note_id', $this->id)->where('meta_key', '=', 'user_action')->where('meta_value', '=', 'dislike')->count(); - - return $dislikes; - } - - public function flags($flags = null){ - $flags = NoteMeta::where('note_id', $this->id)->where('meta_key', '=', 'user_action')->where('meta_value', '=', 'flag')->count(); - - return $flags; - } - - public function comments(){ - return $this->comments; - } - - /** - * Class Helper Functions - **/ - protected function access($attribute, $value){ - if(isset($value)){ - $this->$attribute = $value; - }else{ - return $this->$attribute; - } - } - - /** - * Class Static Functions - */ - - public static function find($id){ - $es = self::connect(); - - if($id === null){ - throw new Exception('Cannot retrieve annotation with null id'); - } - - $params = array( - 'index' => Config::get('elasticsearch.annotationIndex'), - 'type' => self::TYPE, - 'id' => $id - ); - - $annotation = $es->get($params); - $annotation = new Annotation($id, $annotation['_source']); - - $annotation->setActionCounts(); - - return $annotation; - } - - public static function findWithActions($id, $userid){ - $es = self::connect(); - - if($id === null){ - throw new Exception('Cannot retrieve annotation with null id'); + static public function createFromAnnotatorArray(array $input) + { + if(isset($input['id'])) { + $retval = static::firstOrNew(array('id' => $input['id'])); + } else { + $retval = new static(); } - - $params = array( - 'index' => Config::get('elasticsearch.annotationIndex'), - 'type' => self::TYPE, - 'id' => $id - ); - - - $annotation = $es->get($params); - - $annotation = new Annotation($id, $annotation['_source']); - $annotation->setUserAction($userid); - $annotation->setActionCounts(); - return $annotation; - } - - public static function all($docId){ - $es = self::connect(); - - $params = array( - 'index' => Config::get('elasticsearch.annotationIndex'), - 'type' => self::TYPE, - 'body' => array( - 'query' => array( - 'term' => array('doc' => $docId) - ) - ) - ); - - $results = $es->search($params); - $results = $results['hits']['hits']; - $annotations = array(); - foreach($results as $annotation){ - $toPush = new Annotation($annotation['_id'], $annotation['_source']); - $toPush->setActionCounts(); - - array_push($annotations, $toPush); - } - - return $annotations; - } - - public static function allWithActions($docId, $userId){ - $es = self::connect(); - - $params = array( - 'index' => Config::get('elasticsearch.annotationIndex'), - 'type' => self::TYPE, - 'body' => array( - 'query' => array( - 'term' => array('doc' => $docId) - ) - ) - ); - - $results = $es->search($params); - $results = $results['hits']['hits']; - $annotations = array(); - foreach($results as $annotation){ - $toPush = new Annotation($annotation['_id'], $annotation['_source']); - $toPush->setUserAction($userId); - $toPush->setActionCounts(); - - array_push($annotations, $toPush); - } - - return $annotations; - } - - public static function getMetaCount($id, $action){ - $es = self::connect(); - - if($id === null){ - App::abort(404, 'No note id passed'); - } - - $annotation = Annotation::find($id); - - $action_count = $annotation->$action(); - - return $action_count; - } - - public static function addUserAction($note_id, $user_id, $action){ - $es = self::connect(); - - if($note_id == null || $user_id == null || $action == null){ - throw new Exception('Unable to add user action.'); - } - - $toReturn = array( - 'action' => null, - 'likes' => -1, - 'dislikes' => -1, - 'flags' => -1 - ); - - $annotation = Annotation::find($note_id); - - $meta = NoteMeta::where('user_id', $user_id)->where('note_id', '=', $note_id)->where('meta_key', '=', 'user_action'); - - //This user has no actions on this annotation - if($meta->count() == 0){ - $meta = new NoteMeta(); - $meta->user_id = Auth::user()->id; - $meta->note_id = $note_id; - $meta->meta_key = 'user_action'; - $meta->meta_value = $action; - - $meta->save(); - - $toReturn['action'] = true; - }elseif($meta->count() == 1){ - $meta = $meta->first(); - - //This user has already done this action. Removing the action - if($meta->meta_value == $action){ - $meta->delete(); - - $toReturn['action'] = false; - }else{ - $meta->meta_value = $action; - $meta->save(); - - $toReturn['action'] = true; - } - }else{ - throw new Exception('Multiple user actions were found'); - } - - $toReturn['likes'] = $annotation->likes(); - $toReturn['dislikes'] = $annotation->dislikes(); - $toReturn['flags'] = $annotation->flags(); - - return $toReturn; - } - - protected static function connect(){ - $params['hosts'] = Config::get('elasticsearch.hosts'); - $es = new Elasticsearch\Client($params); - - return $es; - } - - static protected function saveAnnotationModel(array $input) - { + $retval->doc = (int)$input['doc']; - $retval = DBAnnotation::firstOrNew(array( - 'id' => $input['id'] - )); - - if(isset($input['user'])) { + if(isset($input['user']) && is_array($input['user'])) { $retval->user_id = (int)$input['user']['id']; } - $retval->doc = (int)$input['doc']; - $retval->id = $input['id']; - if(isset($input['quote'])) { $retval->quote = $input['quote']; } @@ -461,14 +89,10 @@ static protected function saveAnnotationModel(array $input) $retval->uri = $input['uri']; } - $retval->likes = isset($input['likes']) ? (int)$input['likes'] : 0; - $retval->dislikes = isset($input['dislikes']) ? (int)$input['dislikes'] : 0; - $retval->flags = isset($input['flags']) ? (int)$input['flags'] : 0; - DB::transaction(function() use ($retval, $input) { - + $retval->save(); - + if(isset($input['ranges'])) { foreach($input['ranges'] as $range) { $rangeObj = AnnotationRange::firstByRangeOrNew(array( @@ -476,14 +100,14 @@ static protected function saveAnnotationModel(array $input) 'start_offset' => $range['startOffset'], 'end_offset' => $range['endOffset'] )); - + $rangeObj->start = $range['start']; $rangeObj->end = $range['end']; - + $rangeObj->save(); } } - + if(isset($input['comments']) && is_array($input['comments'])) { foreach($input['comments'] as $comment) { @@ -500,16 +124,16 @@ static protected function saveAnnotationModel(array $input) } $permissions = array(); - + if(isset($input['permissions']) && is_array($input['permissions'])) { - + foreach($input['permissions']['read'] as $userId) { $userId = (int)$userId; if(!isset($permissions[$userId])) { $permissions[$userId] = array('read' => false, 'update' => false, 'delete' => false, 'admin' => false); } - + $permissions[$userId]['read'] = true; } @@ -519,7 +143,7 @@ static protected function saveAnnotationModel(array $input) if(!isset($permissions[$userId])) { $permissions[$userId] = array('read' => false, 'update' => false, 'delete' => false, 'admin' => false); } - + $permissions[$userId]['update'] = true; } @@ -529,7 +153,7 @@ static protected function saveAnnotationModel(array $input) if(!isset($permissions[$userId])) { $permissions[$userId] = array('read' => false, 'update' => false, 'delete' => false, 'admin' => false); } - + $permissions[$userId]['delete'] = true; } @@ -539,42 +163,243 @@ static protected function saveAnnotationModel(array $input) if(!isset($permissions[$userId])) { $permissions[$userId] = array('read' => false, 'update' => false, 'delete' => false, 'admin' => false); } - + $permissions[$userId]['admin'] = true; } } foreach($permissions as $userId => $perms) { $userId = (int)$userId; - + $permissionsObj = AnnotationPermission::firstOrNew(array( - 'annotation_id' => $input['id'], - 'user_id' => $userId + 'annotation_id' => $retval->id, + 'user_id' => $userId )); - + $permissionsObj->read = (int)$perms['read']; $permissionsObj->update = (int)$perms['update']; $permissionsObj->delete = (int)$perms['delete']; $permissionsObj->admin = (int)$perms['admin']; - + $permissionsObj->save(); } - + if(isset($input['tags']) && is_array($input['tags'])) { foreach($input['tags'] as $tag) { + AnnotationTag::where('annotation_id', '=', $retval->id)->delete(); + $tag = AnnotationTag::firstOrNew(array( - 'annotation_id' => $input['id'], - 'tag' => strtolower($tag) + 'annotation_id' => $retval->id, + 'tag' => strtolower($tag) )); $tag->save(); } } - + }); + + return $retval; + + } + + public function toAnnotatorArray() + { + $item = $this->toArray(); + $item['created'] = $item['created_at']; + $item['updated'] = $item['updated_at']; + $item['annotator_schema_version'] = 'v1.0'; + $item['ranges'] = array(); + $item['tags'] = array(); + $item['comments'] = array(); + $item['permissions'] = array( + 'read' => array(), + 'update' => array(), + 'delete' => array(), + 'admin' => array() + ); + + $comments = AnnotationComment::where('annotation_id', '=', $item['id'])->get(); + + foreach($comments as $comment) { + $user = User::find($comment['user_id']); + + $item['comments'][] = array( + 'id' => $comment->id, + 'text' => $comment->text, + 'created' => $comment->created_at->toRFC2822String(), + 'updated' => $comment->updated_at->toRFC2822String(), + 'user' => array( + 'id' => $user->id, + 'user_level' => $user->user_level, + 'email' => $user->email, + 'name' => "{$user->fname} {$user->lname[0]}" + ) + ); + } + + $ranges = AnnotationRange::where('annotation_id', '=', $item['id'])->get(); + + foreach($ranges as $range) { + $item['ranges'][] = array( + 'start' => $range['start'], + 'end' => $range['end'], + 'startOffset' => $range['start_offset'], + 'endOffset' => $range['end_offset'] + ); + } + + $user = User::where('id', '=', $item['user_id'])->first(); + $item['user'] = array_intersect_key($user->toArray(), array_flip(array('id', 'email', 'user_level'))); + $item['user']['name'] = $user->fname . ' ' . $user->lname{0}; + + $item['consumer'] = static::ANNOTATION_CONSUMER; + + $tags = AnnotationTag::where('annotation_id', '=', $item['id'])->get(); + + foreach($tags as $tag) { + $item['tags'][] = $tag->tag; + } + + $permissions = AnnotationPermission::where('annotation_id', '=', $item['id'])->get(); + + foreach($permissions as $perm) { + if($perm->read) { + $item['permissions']['read'][] = $perm['user_id']; + } + + if($perm->update) { + $item['permissions']['update'][] = $perm['user_id']; + } + + if($perm->delete) { + $item['permissions']['delete'][] = $perm['user_id']; + } + + if($perm->admin) { + $item['permissions']['admin'][] = $perm['user_id']; + } + } + + $item['likes'] = $this->likes(); + $item['dislikes'] = $this->dislikes(); + $item['flags'] = $this->flags(); + + $item = array_intersect_key($item, array_flip(array( + 'id', 'annotator_schema_version', 'created', 'updated', + 'text', 'quote', 'uri', 'ranges', 'user', 'consumer', 'tags', + 'permissions', 'likes', 'dislikes', 'flags', 'comments', 'doc' + ))); + + return $item; + + } + static public function loadAnnotationsForAnnotator($docId, $annotationId = null, $userId = null) + { + $annotations = static::where('doc', '=', $docId); + + if(!is_null($annotationId)) { + $annotations->where('id', '=', $annotationId); + } + + if(!is_null($userId)) { + $annotations->where('user_id', '=', $userId); + } + + $annotations = $annotations->get(); + + $retval = array(); + foreach($annotations as $annotation) { + $retval[] = $annotation->toAnnotatorArray(); + } + return $retval; } -} - + + public function updateSearchIndex() + { + } + + public function addOrUpdateComment(array $comment) { + $obj = new AnnotationComment(); + $obj->text = $comment['text']; + $obj->user_id = $comment['user']['id']; + + if(isset($comment['id'])) { + $obj->id = $comment['id']; + } + + $obj->annotation_id = $this->id; + + return $obj->save(); + } + + static public function getMetaCount($id, $action) + { + $annotation = static::where('annotation_id', '=', $id); + + $actionCount = $annotation->$action(); + + return $actionCount; + } + + public function saveUserAction($userId, $action) + { + switch($action) { + case static::ACTION_DISLIKE: + case static::ACTION_LIKE: + case static::ACTION_FLAG: + break; + default: + throw new \InvalidArgumentException("Invalid Action to Add"); + } + + $actionModel = NoteMeta::where('annotation_id', '=', $this->id) + ->where('user_id', '=', $userId) + ->where('meta_key', '=', NoteMeta::TYPE_USER_ACTION) + ->take(1)->first(); + + if(is_null($actionModel)) { + $actionModel = new NoteMeta(); + $actionModel->meta_key = NoteMeta::TYPE_USER_ACTION; + $actionModel->user_id = $userId; + $actionModel->annotation_id = $this->id; + } + + $actionModel->meta_value = $action; + + return $actionModel->save(); + } + + public function likes() + { + $likes = NoteMeta::where('annotation_id', $this->id) + ->where('meta_key', '=', 'user_action') + ->where('meta_value', '=', static::ACTION_LIKE) + ->count(); + + return $likes; + } + + public function dislikes() + { + $dislikes = NoteMeta::where('annotation_id', $this->id) + ->where('meta_key', '=', 'user_action') + ->where('meta_value', '=', static::ACTION_DISLIKE) + ->count(); + + return $dislikes; + } + + public function flags() + { + $flags = NoteMeta::where('annotation_id', $this->id) + ->where('meta_key', '=', 'user_action') + ->where('meta_value', '=', static::ACTION_FLAG) + ->count(); + + return $flags; + } +} \ No newline at end of file diff --git a/app/models/DBAnnotation.php b/app/models/DBAnnotation.php deleted file mode 100644 index 5f944f6f4..000000000 --- a/app/models/DBAnnotation.php +++ /dev/null @@ -1,263 +0,0 @@ -hasMany('AnnotationComment', 'annotation_id'); - } - - public function tags() - { - return $this->hasMany('AnnotationTag', 'annotation_id'); - } - - public function permissions() - { - return $this->hasMany('AnnotationPermission', 'annotation_id'); - } - - static public function loadAnnotationsForAnnotator($docId, $annotationId = null, $userId = null) - { - if(is_null($userId)) { - if(is_null($annotationId)) { - $annotations = static::where('doc', '=', $docId)->get(); - } else { - $annotations = static::where('annotation_id', '=', $annotationId)->get(); - } - } else { - if(!is_null($annotationId)) { - $annotations = array(static::firstWithActions($annotationId, $userId)); - } else { - $annotations = static::where('doc', '=', $docId)->get(); - } - } - - $retval = array(); - foreach($annotations as $annotation) { - - $item = $annotation->toArray(); - $item['created'] = $item['created_at']; - $item['updated'] = $item['updated_at']; - $item['annotator_schema_version'] = 'v1.0'; - $item['ranges'] = array(); - $item['tags'] = array(); - $item['comments'] = array(); - $item['permissions'] = array( - 'read' => array(), - 'update' => array(), - 'delete' => array(), - 'admin' => array() - ); - - $ranges = AnnotationRange::where('annotation_id', '=', $item['id'])->get(); - - foreach($ranges as $range) { - $item['ranges'][] = array( - 'start' => $range['start'], - 'end' => $range['end'], - 'startOffset' => $range['start_offset'], - 'endOffset' => $range['end_offset'] - ); - } - - if(!is_null($userId)) { - $user = User::where('id', '=', $userId)->first(); - $item['user'] = array_intersect_key($user->toArray(), array_flip(array('id', 'email', 'user_level'))); - $item['user']['name'] = $user->fname . ' ' . $user->lname{0}; - } - - $item['consumer'] = "Madison"; - - $tags = AnnotationTag::where('annotation_id', '=', $item['id'])->get(); - - foreach($tags as $tag) { - $items['tags'][] = $tag->tag; - } - - $permissions = AnnotationPermission::where('annotation_id', '=', $item['id'])->get(); - - foreach($permissions as $perm) { - if($perm->read) { - $item['permissions']['read'][] = $perm['user_id']; - } - - if($perm->update) { - $item['permissions']['update'][] = $perm['user_id']; - } - - if($perm->delete) { - $item['permissions']['delete'][] = $perm['user_id']; - } - - if($perm->admin) { - $item['permissions']['admin'][] = $perm['user_id']; - } - } - - $item = array_intersect_key($item, array_flip(array( - 'id', 'annotator_schema_version', 'created', 'updated', - 'text', 'quote', 'uri', 'ranges', 'user', 'consumer', 'tags', - 'permissions', 'likes', 'dislikes', 'flags', 'comments', 'user_action', - 'doc' - ))); - - $retval[] = $item; - } - - return $retval; - } - - static public function firstWithActions($annotationId, $userId) - { - $retval = static::where('id', '=', $annotationId)->first(); - $retval->setUserAction($userId); - $retval->setActionCounts(); - - return $retval; - } - - public function addComment(array $comment) { - $obj = new AnnotationComment(); - $obj->text = $comment['text']; - $obj->user_id = $comment['user']['id']; - $obj->id = $comment['id']; - $obj->annotation_id = $this->id; - return $obj->save(); - } - - static public function allByDocId($docId) - { - $retval = static::where('doc_id', '=', $docId); - - foreach($retval as $annotation) { - $annotation->setActionCounts(); - } - - return $retval; - } - - static public function allWithActions($docId, $userId) { - - $retval = static::where('doc_id', '=', $docId); - - foreach($retval as $annotation) { - $annotation->setUserAction($userId); - $annotation->setActionCounts(); - } - - return $retval; - } - - static public function getMetaCount($id, $action) - { - $annotation = static::where('annotation_id', '=', $id); - - $actionCount = $annotation->$action(); - - return $actionCount; - } - - static public function addUserAction($annotationId, $userId, $action) - { - $retval = array( - 'action' => null, - 'likes' => -1, - 'dislikes' => -1, - 'flags' => -1 - ); - - $annotation = static::where('annotation_id', '=', $annotationId); - - $meta = NoteMeta::where('user_id', $userId) - ->where('note_id', '=', $annotationId) - ->where('meta_key', '=', 'user_action'); - - if($meta->count() > 1) { - throw new Exception("Multiple user actions were found"); - } - - if($meta->count() == 0) { - $meta = new NoteMeta(); - - $meta->user_id = Auth::user()->id; - $meta->note_id = $annotationId; - $meta->meta_key = 'user_action'; - $meta->meta_value = $action; - - $meta->save(); - - $retval['action'] = true; - } else if($meta->count() == 1) { - $emeta = $meta->first(); - - if($meta->meta_value == $action) { - $meta->delete(); - $retval['action'] = false; - } else { - $meta->meta_value = $action; - $meta->save(); - - $retval['action'] = true; - } - } - - $retval['likes'] = $annotation->likes(); - $retval['dislikes'] = $annotation->dislikes(); - $retval['flags'] = $annotation->flags(); - - return $retval; - } - - public function setUserAction($userId) - { - $meta = NoteMeta::where('user_id', $userId) - ->where('note_id', '=', $this->id) - ->where('meta_key', '=', 'user_action'); - - if($meta->count() == 1) { - $this->user_action = $meta->first()->meta_value; - } - } - - public function setActionCounts() - { - $this->likes = $this->likes(); - $this->dislikes = $this->dislikes(); - $this->flags = $this->flags(); - } - - public function likes() - { - $likes = NoteMeta::where('note_id', $this->id) - ->where('meta_key', '=', 'user_action') - ->where('meta_value', '=', 'like') - ->count(); - - return $likes; - } - - public function dislikes() - { - $likes = NoteMeta::where('note_id', $this->id) - ->where('meta_key', '=', 'user_action') - ->where('meta_value', '=', 'dislike') - ->count(); - - return $likes; - } - - public function flags() - { - $likes = NoteMeta::where('note_id', $this->id) - ->where('meta_key', '=', 'user_action') - ->where('meta_value', '=', 'flag') - ->count(); - - return $likes; - } -} \ No newline at end of file diff --git a/app/models/NoteMeta.php b/app/models/NoteMeta.php index dac59a854..b37054427 100644 --- a/app/models/NoteMeta.php +++ b/app/models/NoteMeta.php @@ -5,6 +5,8 @@ class NoteMeta extends Eloquent{ protected $table = 'note_meta'; + const TYPE_USER_ACTION = "user_action"; + public function user(){ return $this->belongsTo('User'); } diff --git a/app/models/OldAnnotation.php b/app/models/OldAnnotation.php new file mode 100644 index 000000000..e7007fa77 --- /dev/null +++ b/app/models/OldAnnotation.php @@ -0,0 +1,580 @@ +id = $id; + + if(isset($source)){ + foreach($source as $key => $value){ + $this->$key = $value; + } + } + + $this->index = Config::get('elasticsearch.annotationIndex'); + + $this->es = self::connect(); + } + + public function addComment($comment){ + $es = $this->es; + + $comment['created'] = Carbon::now('America/New_York')->toRFC2822String(); + $comment['updated'] = Carbon::now('America/New_York')->toRFC2822String(); + + array_push($this->comments, $comment); + + foreach($this->comments as $index => &$comment){ + $comment['id'] = $index + 1; + } + + $retval = $this->update(false); + + $dbComment = new AnnotationComment(); + $dbComment->text = $comment['text']; + $dbComment->user_id = $comment['user']['id']; + $dbComment->id = $comment['id']; + $dbComment->annotation_id = $this->id; + $dbComment->save(); + + return $retval; + } + + public function setUserAction($user_id){ + $meta = NoteMeta::where('user_id', $user_id)->where('note_id', '=', $this->id)->where('meta_key', '=', 'user_action'); + + if($meta->count() == 1){ + $this->user_action = $meta->first()->meta_value; + } + } + + public function setActionCounts(){ + $this->likes = $this->likes(); + $this->dislikes = $this->dislikes(); + $this->flags = $this->flags(); + } + + public function update($updateTimestamp = true){ + $es = $this->es; + + if($updateTimestamp){ + $this->updated = Carbon::now('America/New_York')->toRFC2822String(); + } + + if(isset($body)){ + foreach($body as $name => $value){ + $this->$name = $value; + } + } + + if(isset($body['user_action'])){ + unset($body['user_action']); + } + + $params = array( + 'index' => $this->index, + 'type' => self::TYPE, + 'id' => $this->id, + ); + + $attributes = new ReflectionClass('Annotation'); + $attributes = $attributes->getProperties(ReflectionProperty::IS_PUBLIC); + + $body = array(); + + foreach($attributes as $attribute){ + $name = $attribute->name; + $body[$name] = $this->$name; + } + + $params['body']['doc'] = $body; + + $dbValues = $params['body']; + $dbValues['id'] = $params['id']; + + try{ + $results = $es->update($params); + }catch(Elasticsearch\Common\Exceptions\Missing404Exception $e){ + App::abort(404, 'Id not found'); + }catch(Exception $e){ + App::abort(404, $e->getMessage()); + } + + file_put_contents('/tmp/update.txt', var_export($params, true)); + + static::saveAnnotationModel($dbValues); + + return $results; + } + + public function save(){ + $es = $this->es; + + if(!isset($this->body)){ + throw new Exception('Annotation body not found. Cannot save.'); + } + + $dbValues = $this->body; + + $this->body['created'] = Carbon::now('America/New_York')->toRFC2822String(); + $this->body['updated'] = Carbon::now('America/New_York')->toRFC2822String(); + + $params = array( + 'index' => $this->index, + 'type' => self::TYPE, + 'body' => $this->body + ); + + $results = $es->index($params); + + $dbValues['id'] = $results['_id']; + + static::saveAnnotationModel($dbValues); + + return $results['_id']; + } + + public function delete(){ + $es = self::connect(); + + $params = array( + 'index' => $this->index, + 'type' => self::TYPE, + 'id' => $this->id + ); + + $result = $es->delete($params); + + if($result['ok'] == true){ + $metas = NoteMeta::where('note_id', $this->id); + $metas->delete(); + } + + return $result; + } + + /** + * Accessor Functions + */ + + public function id($id = null){ + return $this->access('id', $id); + } + + public function created($created = null){ + return $this->access('created', $created); + } + + public function updated($updated = null){ + return $this->access('updated', $updated); + } + + public function quote($quote = null){ + return $this->access('quote', $quote); + } + + public function uri($uri = null){ + return $this->access('uri', $uri); + } + + public function ranges($ranges = null){ + return $this->access('ranges', $ranges); + } + + public function tags($tags = null){ + return $this->access('tags', $tags); + } + + public function permissions($permissions = null){ + return $this->access('permissions', $permissions); + } + + public function body($body = null){ + return $this->access('body', $body); + } + + public function text($text = null){ + return $this->access('text', $text); + } + + public function user($user = null){ + return $this->access('user', $user); + } + + public function likes($likes = null){ + $likes = NoteMeta::where('note_id', $this->id)->where('meta_key', '=', 'user_action')->where('meta_value', '=', 'like')->count(); + + return $likes; + } + + public function dislikes($disliked = null){ + $dislikes = NoteMeta::where('note_id', $this->id)->where('meta_key', '=', 'user_action')->where('meta_value', '=', 'dislike')->count(); + + return $dislikes; + } + + public function flags($flags = null){ + $flags = NoteMeta::where('note_id', $this->id)->where('meta_key', '=', 'user_action')->where('meta_value', '=', 'flag')->count(); + + return $flags; + } + + public function comments(){ + return $this->comments; + } + + /** + * Class Helper Functions + **/ + protected function access($attribute, $value){ + if(isset($value)){ + $this->$attribute = $value; + }else{ + return $this->$attribute; + } + } + + /** + * Class Static Functions + */ + + public static function find($id){ + $es = self::connect(); + + if($id === null){ + throw new Exception('Cannot retrieve annotation with null id'); + } + + $params = array( + 'index' => Config::get('elasticsearch.annotationIndex'), + 'type' => self::TYPE, + 'id' => $id + ); + + $annotation = $es->get($params); + $annotation = new Annotation($id, $annotation['_source']); + + $annotation->setActionCounts(); + + return $annotation; + } + + public static function findWithActions($id, $userid){ + $es = self::connect(); + + if($id === null){ + throw new Exception('Cannot retrieve annotation with null id'); + } + + $params = array( + 'index' => Config::get('elasticsearch.annotationIndex'), + 'type' => self::TYPE, + 'id' => $id + ); + + + $annotation = $es->get($params); + + $annotation = new Annotation($id, $annotation['_source']); + $annotation->setUserAction($userid); + $annotation->setActionCounts(); + + return $annotation; + } + + public static function all($docId){ + $es = self::connect(); + + $params = array( + 'index' => Config::get('elasticsearch.annotationIndex'), + 'type' => self::TYPE, + 'body' => array( + 'query' => array( + 'term' => array('doc' => $docId) + ) + ) + ); + + $results = $es->search($params); + $results = $results['hits']['hits']; + $annotations = array(); + foreach($results as $annotation){ + $toPush = new Annotation($annotation['_id'], $annotation['_source']); + $toPush->setActionCounts(); + + array_push($annotations, $toPush); + } + + return $annotations; + } + + public static function allWithActions($docId, $userId){ + $es = self::connect(); + + $params = array( + 'index' => Config::get('elasticsearch.annotationIndex'), + 'type' => self::TYPE, + 'body' => array( + 'query' => array( + 'term' => array('doc' => $docId) + ) + ) + ); + + $results = $es->search($params); + $results = $results['hits']['hits']; + $annotations = array(); + foreach($results as $annotation){ + $toPush = new Annotation($annotation['_id'], $annotation['_source']); + $toPush->setUserAction($userId); + $toPush->setActionCounts(); + + array_push($annotations, $toPush); + } + + return $annotations; + } + + public static function getMetaCount($id, $action){ + $es = self::connect(); + + if($id === null){ + App::abort(404, 'No note id passed'); + } + + $annotation = Annotation::find($id); + + $action_count = $annotation->$action(); + + return $action_count; + } + + public static function addUserAction($note_id, $user_id, $action){ + $es = self::connect(); + + if($note_id == null || $user_id == null || $action == null){ + throw new Exception('Unable to add user action.'); + } + + $toReturn = array( + 'action' => null, + 'likes' => -1, + 'dislikes' => -1, + 'flags' => -1 + ); + + $annotation = Annotation::find($note_id); + + $meta = NoteMeta::where('user_id', $user_id)->where('note_id', '=', $note_id)->where('meta_key', '=', 'user_action'); + + //This user has no actions on this annotation + if($meta->count() == 0){ + $meta = new NoteMeta(); + $meta->user_id = Auth::user()->id; + $meta->note_id = $note_id; + $meta->meta_key = 'user_action'; + $meta->meta_value = $action; + + $meta->save(); + + $toReturn['action'] = true; + }elseif($meta->count() == 1){ + $meta = $meta->first(); + + //This user has already done this action. Removing the action + if($meta->meta_value == $action){ + $meta->delete(); + + $toReturn['action'] = false; + }else{ + $meta->meta_value = $action; + $meta->save(); + + $toReturn['action'] = true; + } + }else{ + throw new Exception('Multiple user actions were found'); + } + + $toReturn['likes'] = $annotation->likes(); + $toReturn['dislikes'] = $annotation->dislikes(); + $toReturn['flags'] = $annotation->flags(); + + return $toReturn; + } + + protected static function connect(){ + $params['hosts'] = Config::get('elasticsearch.hosts'); + $es = new Elasticsearch\Client($params); + + return $es; + } + + static protected function saveAnnotationModel(array $input) + { + + $retval = DBAnnotation::firstOrNew(array( + 'id' => $input['id'] + )); + + if(isset($input['user'])) { + $retval->user_id = (int)$input['user']['id']; + } + + $retval->doc = (int)$input['doc']; + $retval->id = $input['id']; + + if(isset($input['quote'])) { + $retval->quote = $input['quote']; + } + + if(isset($input['text'])) { + $retval->text = $input['text']; + } + + if(isset($input['uri'])) { + $retval->uri = $input['uri']; + } + + $retval->likes = isset($input['likes']) ? (int)$input['likes'] : 0; + $retval->dislikes = isset($input['dislikes']) ? (int)$input['dislikes'] : 0; + $retval->flags = isset($input['flags']) ? (int)$input['flags'] : 0; + + DB::transaction(function() use ($retval, $input) { + + $retval->save(); + + if(isset($input['ranges'])) { + foreach($input['ranges'] as $range) { + $rangeObj = AnnotationRange::firstByRangeOrNew(array( + 'annotation_id' => $retval->id, + 'start_offset' => $range['startOffset'], + 'end_offset' => $range['endOffset'] + )); + + $rangeObj->start = $range['start']; + $rangeObj->end = $range['end']; + + $rangeObj->save(); + } + } + + if(isset($input['comments']) && is_array($input['comments'])) { + foreach($input['comments'] as $comment) { + + $commentObj = AnnotationComment::firstOrNew(array( + 'id' => (int)$comment['id'], + 'annotation_id' => $retval->id, + 'user_id' => (int)$comment['user']['id'] + )); + + $commentObj->text = $comment['text']; + + $commentObj->save(); + } + } + + $permissions = array(); + + if(isset($input['permissions']) && is_array($input['permissions'])) { + + foreach($input['permissions']['read'] as $userId) { + $userId = (int)$userId; + + if(!isset($permissions[$userId])) { + $permissions[$userId] = array('read' => false, 'update' => false, 'delete' => false, 'admin' => false); + } + + $permissions[$userId]['read'] = true; + } + + foreach($input['permissions']['update'] as $userId) { + $userId = (int)$userId; + + if(!isset($permissions[$userId])) { + $permissions[$userId] = array('read' => false, 'update' => false, 'delete' => false, 'admin' => false); + } + + $permissions[$userId]['update'] = true; + } + + foreach($input['permissions']['delete'] as $userId) { + $userId = (int)$userId; + + if(!isset($permissions[$userId])) { + $permissions[$userId] = array('read' => false, 'update' => false, 'delete' => false, 'admin' => false); + } + + $permissions[$userId]['delete'] = true; + } + + foreach($input['permissions']['admin'] as $userId) { + $userId = (int)$userId; + + if(!isset($permissions[$userId])) { + $permissions[$userId] = array('read' => false, 'update' => false, 'delete' => false, 'admin' => false); + } + + $permissions[$userId]['admin'] = true; + } + } + + foreach($permissions as $userId => $perms) { + $userId = (int)$userId; + + $permissionsObj = AnnotationPermission::firstOrNew(array( + 'annotation_id' => $input['id'], + 'user_id' => $userId + )); + + $permissionsObj->read = (int)$perms['read']; + $permissionsObj->update = (int)$perms['update']; + $permissionsObj->delete = (int)$perms['delete']; + $permissionsObj->admin = (int)$perms['admin']; + + $permissionsObj->save(); + } + + if(isset($input['tags']) && is_array($input['tags'])) { + foreach($input['tags'] as $tag) { + + $tag = AnnotationTag::firstOrNew(array( + 'annotation_id' => $input['id'], + 'tag' => strtolower($tag) + )); + + $tag->save(); + } + } + + }); + + return $retval; + } +} + diff --git a/composer.json b/composer.json index 283a4664f..10dd3f93f 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,8 @@ "roumen/sitemap": "dev-master", "elasticsearch/elasticsearch": "~0.4", "illuminate/remote": "4.1.*", - "graham-campbell/markdown": "1.0.*" + "graham-campbell/markdown": "1.0.*", + "doctrine/dbal" : "2.3.*" }, "autoload": { "classmap": [