diff --git a/app.json b/app.json index 13304176f3..447b91099d 100644 --- a/app.json +++ b/app.json @@ -10,6 +10,7 @@ "logo": "http://www.ushahidi.com/assets/img/favicon.ico", "success_url": "/", "addons": [ - "cleardb" + "cleardb", + "scheduler" ] } diff --git a/application/classes/Log/Raven.php b/application/classes/Log/Raven.php index 9b68106960..07dcb44196 100644 --- a/application/classes/Log/Raven.php +++ b/application/classes/Log/Raven.php @@ -53,21 +53,17 @@ public function write(array $messages) { // Write each message into the log file // Format: time --- level: body - $this->raven->getIdent( - $this->raven->captureException($message['additional']['exception']) - ); + $this->raven->captureException($message['additional']['exception']); } else { // Write each message into the log file // Format: time --- level: body - $this->raven->getIdent( - $this->raven->captureMessage( - $this->format_message($message), - $message, - [ - 'level' => $this->mapRavenLevel($message['level']) - ], - $message['trace'] - ) + $this->raven->captureMessage( + $this->format_message($message), + $message, + [ + 'level' => $this->mapRavenLevel($message['level']) + ], + $message['trace'] ); } } diff --git a/application/classes/Ushahidi/Core.php b/application/classes/Ushahidi/Core.php index f0785a268d..7e6840329f 100644 --- a/application/classes/Ushahidi/Core.php +++ b/application/classes/Ushahidi/Core.php @@ -467,7 +467,9 @@ public static function init() $di->set('repository.post.point', $di->lazyNew('Ushahidi_Repository_Post_Point')); $di->set('repository.post.relation', $di->lazyNew('Ushahidi_Repository_Post_Relation')); $di->set('repository.post.text', $di->lazyNew('Ushahidi_Repository_Post_Text')); + $di->set('repository.post.description', $di->lazyNew('Ushahidi_Repository_Post_Description')); $di->set('repository.post.varchar', $di->lazyNew('Ushahidi_Repository_Post_Varchar')); + $di->set('repository.post.title', $di->lazyNew('Ushahidi_Repository_Post_Title')); $di->set('repository.post.media', $di->lazyNew('Ushahidi_Repository_Post_Media')); // The post value repo factory @@ -482,7 +484,9 @@ public static function init() 'point' => $di->lazyGet('repository.post.point'), 'relation' => $di->lazyGet('repository.post.relation'), 'text' => $di->lazyGet('repository.post.text'), + 'description' => $di->lazyGet('repository.post.description'), 'varchar' => $di->lazyGet('repository.post.varchar'), + 'title' => $di->lazyGet('repository.post.title'), 'media' => $di->lazyGet('repository.post.media'), ], ]; @@ -612,6 +616,8 @@ public static function init() $di->set('validator.post.point', $di->lazyNew('Ushahidi_Validator_Post_Point')); $di->set('validator.post.relation', $di->lazyNew('Ushahidi_Validator_Post_Relation')); $di->set('validator.post.varchar', $di->lazyNew('Ushahidi_Validator_Post_Varchar')); + $di->set('validator.post.video', $di->lazyNew('Ushahidi_Validator_Post_Video')); + $di->set('validator.post.title', $di->lazyNew('Ushahidi_Validator_Post_Title')); $di->set('validator.post.media', $di->lazyNew('Ushahidi_Validator_Post_Media')); $di->params['Ushahidi_Validator_Post_Media'] = [ 'media_repo' => $di->lazyGet('repository.media') @@ -630,7 +636,9 @@ public static function init() 'point' => $di->lazyGet('validator.post.point'), 'relation' => $di->lazyGet('validator.post.relation'), 'varchar' => $di->lazyGet('validator.post.varchar'), + 'title' => $di->lazyGet('validator.post.title'), 'media' => $di->lazyGet('validator.post.media'), + 'video' => $di->lazyGet('validator.post.video'), ], ]; diff --git a/application/classes/Ushahidi/Formatter/Post/CSV.php b/application/classes/Ushahidi/Formatter/Post/CSV.php index 8cb614b43c..899a5af7ac 100644 --- a/application/classes/Ushahidi/Formatter/Post/CSV.php +++ b/application/classes/Ushahidi/Formatter/Post/CSV.php @@ -42,8 +42,6 @@ protected function generateCSVRecords($records) // Sort the columns from the heading so that they match with the record keys ksort($heading); - Kohana::$log->add(Log::INFO, print_r($heading, true)); - // Send response as CSV download header('Access-Control-Allow-Origin: *'); header('Content-Type: text/csv; charset=utf-8'); diff --git a/application/classes/Ushahidi/Repository/Post/Description.php b/application/classes/Ushahidi/Repository/Post/Description.php new file mode 100644 index 0000000000..8e077c74c3 --- /dev/null +++ b/application/classes/Ushahidi/Repository/Post/Description.php @@ -0,0 +1,32 @@ + + * @package Ushahidi\Application + * @copyright 2014 Ushahidi + * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) + */ + +use Ushahidi\Core\Entity\PostValue; +use Ushahidi\Core\Entity\PostValueRepository; + +class Ushahidi_Repository_Post_Description extends Ushahidi_Repository_Post_Text +{ + public function getAllForPost($post_id, Array $include_attributes = []) + { + return []; + } + // DeleteRepository + // This value should be immutable and unchangeable + public function createValue($value, $form_attribute_id, $post_id) + { + return 0; + } + + public function updateValue($id, $value) + { + return 0; + } +} diff --git a/application/classes/Ushahidi/Repository/Post/Title.php b/application/classes/Ushahidi/Repository/Post/Title.php new file mode 100644 index 0000000000..9e13a2fe34 --- /dev/null +++ b/application/classes/Ushahidi/Repository/Post/Title.php @@ -0,0 +1,30 @@ + + * @package Ushahidi\Application + * @copyright 2014 Ushahidi + * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) + */ + +use Ushahidi\Core\Entity\PostValue; +use Ushahidi\Core\Entity\PostValueRepository; + +class Ushahidi_Repository_Post_Title extends Ushahidi_Repository_Post_Varchar +{ + public function getAllForPost($post_id, Array $include_attributes = []) + { + return []; + } + public function createValue($value, $form_attribute_id, $post_id) + { + return 0; + } + + public function updateValue($id, $value) + { + return 0; + } +} diff --git a/application/classes/Ushahidi/Repository/Post/Value.php b/application/classes/Ushahidi/Repository/Post/Value.php index 9c1db707e9..aac659efcc 100644 --- a/application/classes/Ushahidi/Repository/Post/Value.php +++ b/application/classes/Ushahidi/Repository/Post/Value.php @@ -64,7 +64,6 @@ public function getAllForPost($post_id, Array $include_attributes = []) } $results = $query->execute($this->db); - return $this->getCollection($results->as_array()); } diff --git a/application/classes/Ushahidi/Validator/Form/Attribute/Update.php b/application/classes/Ushahidi/Validator/Form/Attribute/Update.php index 5700c08e2e..f2968dfdff 100644 --- a/application/classes/Ushahidi/Validator/Form/Attribute/Update.php +++ b/application/classes/Ushahidi/Validator/Form/Attribute/Update.php @@ -51,7 +51,8 @@ protected function getRules() 'location', 'number', 'relation', - 'upload' + 'upload', + 'video' ]]], ], 'type' => [ @@ -65,7 +66,9 @@ protected function getRules() 'datetime', 'link', 'relation', - 'media' + 'media', + 'title', + 'description' ]]], ], 'required' => [ diff --git a/application/classes/Ushahidi/Validator/Post/Title.php b/application/classes/Ushahidi/Validator/Post/Title.php new file mode 100644 index 0000000000..31b793a4c8 --- /dev/null +++ b/application/classes/Ushahidi/Validator/Post/Title.php @@ -0,0 +1,23 @@ + + * @package Ushahidi\Application + * @copyright 2014 Ushahidi + * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) + */ + +class Ushahidi_Validator_Post_Title extends Ushahidi_Validator_Post_Varchar +{ + protected function validate($value) + { + if (!is_scalar($value)) { + return 'scalar'; + } + if (!Valid::max_length($value, 255)) { + return 'max_length'; + } + } +} diff --git a/application/classes/Ushahidi/Validator/Post/Video.php b/application/classes/Ushahidi/Validator/Post/Video.php new file mode 100644 index 0000000000..412e28ea10 --- /dev/null +++ b/application/classes/Ushahidi/Validator/Post/Video.php @@ -0,0 +1,25 @@ + + * @package Ushahidi\Application + * @copyright 2016 Ushahidi + * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) + */ +class Ushahidi_Validator_Post_Video extends Ushahidi_Validator_Post_ValueValidator +{ + protected function validate($value) + { + if (!Valid::url($value)) { + return 'url'; + } + if (!$this->checkVideoTypes($value)) { + return 'video_type'; + } + } + + protected function checkVideoTypes($value) { + return (strpos($value, 'youtube') !== false || strpos($value, 'vimeo') !== false); + } +} diff --git a/application/messages/post.php b/application/messages/post.php index c1f84a08d8..88428126b5 100644 --- a/application/messages/post.php +++ b/application/messages/post.php @@ -35,5 +35,6 @@ 'lat' => 'the field :param1 must contain a valid latitude', 'lon' => 'the field :param1 must contain a valid longitude', 'url' => 'The field :param1 must be a url, Given: :param2', + 'video_type' => 'The field :param1 must be either a youtube or vimeo url, Given: :param2', ] ]; diff --git a/application/tests/datasets/ushahidi/Base.yml b/application/tests/datasets/ushahidi/Base.yml index 4b45517880..65247d29b2 100644 --- a/application/tests/datasets/ushahidi/Base.yml +++ b/application/tests/datasets/ushahidi/Base.yml @@ -73,6 +73,13 @@ forms: description: "Missing persons" require_approval: 0 everyone_can_create: 0 + - + id: 3 + name: "Video Embed" + type: "report" + description: "Test video embed" + require_approval: 0 + everyone_can_create: 0 form_roles: - id: 1 @@ -95,6 +102,10 @@ form_stages: id: 4 form_id: 2 label: "Main" + - + id: 5 + form_id: 3 + label: "Post" form_attributes: - id: 1 @@ -133,10 +144,10 @@ form_attributes: id: 4 label: "Description" key: "description" - type: "text" + type: "description" input: "textarea" required: 0 - priority: 2 + priority: 0 options: "" cardinality: 1 form_stage_id: 1 @@ -260,6 +271,29 @@ form_attributes: cardinality: 0 config: '[]' form_stage_id: 1 + - + id: 16 + label: "Video" + key: "video_field" + type: "video" + input: "video" + required: 0 + options: '[]' + priority: 5 + cardinality: 0 + config: '[]' + form_stage_id: 5 + - + id: 17 + label: "Title" + key: "title" + type: "title" + input: "text" + required: 0 + priority: 0 + options: "" + cardinality: 1 + form_stage_id: 1 posts: - id: 1 @@ -605,7 +639,7 @@ post_varchar: value: "some-string" - id: 7 - post_id: 105 + post_id: 106 form_attribute_id: 1 value: "some-string" - diff --git a/application/tests/features/api.posts.feature b/application/tests/features/api.posts.feature index 101d5b87d4..8dd04435ae 100644 --- a/application/tests/features/api.posts.feature +++ b/application/tests/features/api.posts.feature @@ -422,6 +422,54 @@ Feature: Testing the Posts API And the "user.id" property equals "2" Then the guzzle status code should be 200 + @create + Scenario: Creating a new Post with Title And Description values silently ignore them + Given that I want to make a new "Post" + And that the request "data" is: + """ + { + "form":1, + "title":"Test post", + "author_realname": "Robbie Mackay", + "author_email": "someotherrobbie@test.com", + "type":"report", + "status":"draft", + "locale":"en_US", + "values": + { + "title": ["test"], + "description": ["description"], + "full_name":["David Kobia"], + "description":["Skinny, homeless Kenyan last seen in the vicinity of the greyhound station"], + "date_of_birth":[], + "missing_date":["2016-05-31T00:00:00.000Z"], + "last_location":["atlanta"], + "last_location_point":[{ + "lat":33.755, + "lon":-84.39 + }], + "geometry_test":["POLYGON((0 0,1 1,2 2,0 0))"], + "missing_status":["believed_missing"], + "links":[ + "http://google.com", + "http://facebook.com" + ] + }, + "tags":["explosion"], + "completed_stages":[1] + } + """ + When I request "/posts" + Then the response is JSON + And the response has a "id" property + And the type of the "id" property is "numeric" + And the response does not have a "values.title" property + And the response does not have a "values.description" property + And the "title" property equals "Test post" + And the response has a "status" property + And the "status" property equals "draft" + Then the guzzle status code should be 200 + @update Scenario: Updating a Post Given that I want to update a "Post" @@ -1247,22 +1295,22 @@ Feature: Testing the Posts API And the "count" property equals "1" Then the guzzle status code should be 200 - @update - Scenario: Users can assign roles to restrict publication of their posts - Given that I want to update a "Post" - And that its "id" is "105" - And that the request "Authorization" header is "Bearer testbasicuser2" - And that the request "data" is: - """ - { - "published_to":["admin"] - } - """ - When I request "/posts" - Then the guzzle status code should be 200 - And the response is JSON - And the "published_to" property contains "admin" - And the response has an "id" property + @update + Scenario: Users can assign roles to restrict publication of their posts + Given that I want to update a "Post" + And that its "id" is "105" + And that the request "Authorization" header is "Bearer testbasicuser2" + And that the request "data" is: + """ + { + "published_to":["admin"] + } + """ + When I request "/posts" + Then the guzzle status code should be 200 + And the response is JSON + And the "published_to" property contains "admin" + And the response has an "id" property @create Scenario: Creating a new Post with invalid location latitude @@ -1348,6 +1396,58 @@ Feature: Testing the Posts API And the "errors.1.title" property equals "the field Last Location (point) must contain a valid longitude" Then the guzzle status code should be 422 + @create + Scenario: Creating a new Post with invalid video field type + Given that I want to make a new "Post" + And that the request "data" is: + """ + { + "form":3, + "title":"Test video post", + "author_realname": "Robbie Mackay", + "author_email": "someotherrobbie@test.com", + "type":"report", + "status":"draft", + "locale":"en_US", + "values": + { + "video_field":["https://www.yourtube.com/watch/12345"] + } + } + """ + When I request "/posts" + Then the response is JSON + And the response has an "errors" property + And the response has an "errors.1.title" property + And the "errors.1.title" property equals "The field Video must be either a youtube or vimeo url, Given: https://www.yourtube.com/watch/12345" + Then the guzzle status code should be 422 + + @create + Scenario: Creating a new Post with invalid video url + Given that I want to make a new "Post" + And that the request "data" is: + """ + { + "form":3, + "title":"Test video post", + "author_realname": "Robbie Mackay", + "author_email": "someotherrobbie@test.com", + "type":"report", + "status":"draft", + "locale":"en_US", + "values": + { + "video_field":["not a url"] + } + } + """ + When I request "/posts" + Then the response is JSON + And the response has an "errors" property + And the response has an "errors.1.title" property + And the "errors.1.title" property equals "The field Video must be a url, Given: not a url" + Then the guzzle status code should be 422 + @update Scenario: Updating a Post with invalid latitude Given that I want to update a "Post" diff --git a/application/tests/features/forms/api.attributes.feature b/application/tests/features/forms/api.attributes.feature index c2546e278d..a329f561f3 100644 --- a/application/tests/features/forms/api.attributes.feature +++ b/application/tests/features/forms/api.attributes.feature @@ -175,7 +175,7 @@ Feature: Testing the Form Attributes API Then the response is JSON And the response has a "count" property And the type of the "count" property is "numeric" - And the "count" property equals "17" + And the "count" property equals "18" Then the guzzle status code should be 200 Scenario: Listing All Attributes @@ -184,7 +184,7 @@ Feature: Testing the Form Attributes API Then the response is JSON And the response has a "count" property And the type of the "count" property is "numeric" - And the "count" property equals "17" + And the "count" property equals "19" Then the guzzle status code should be 200 Scenario: Search for point attributes diff --git a/composer.json b/composer.json index 005e4c01d6..39cf48cb5e 100644 --- a/composer.json +++ b/composer.json @@ -47,7 +47,7 @@ "satooshi/php-coveralls": "^2.0@dev", "henrikbjorn/phpspec-code-coverage": "~2.0", "ramsey/uuid": "^3.4.1", - "sentry/sentry": "^0.22.0" + "sentry/sentry": "~1.5" }, "require-dev": { "behat/behat": "~2.5.2", diff --git a/composer.lock b/composer.lock index e37f5530dc..c150c6fef9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "023cd1767a81c7b7c94345c43132cc23", - "content-hash": "794fdfbb194b5bf89423e857c351fb61", + "hash": "32655a8026b42180ced79f5cd11e82ae", + "content-hash": "0d86c0e3da72c4f08bc4a6869b6e9686", "packages": [ { "name": "abraham/twitteroauth", @@ -3049,16 +3049,16 @@ }, { "name": "sentry/sentry", - "version": "0.22.0", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-php.git", - "reference": "49d4c0c4f2c298c9f15a07416debb5352a209b79" + "reference": "2a92076ffc6c3f193f2736c9ce75d26705bb48b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/49d4c0c4f2c298c9f15a07416debb5352a209b79", - "reference": "49d4c0c4f2c298c9f15a07416debb5352a209b79", + "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/2a92076ffc6c3f193f2736c9ce75d26705bb48b7", + "reference": "2a92076ffc6c3f193f2736c9ce75d26705bb48b7", "shasum": "" }, "require": { @@ -3071,7 +3071,7 @@ }, "require-dev": { "friendsofphp/php-cs-fixer": "^1.8.0", - "phpunit/phpunit": "^4.6.6" + "phpunit/phpunit": "^4.8 || ^5.0" }, "bin": [ "bin/sentry" @@ -3079,7 +3079,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "0.22.x-dev" + "dev-master": "1.6.x-dev" } }, "autoload": { @@ -3103,7 +3103,7 @@ "log", "logging" ], - "time": "2016-06-23 19:41:24" + "time": "2016-11-01 18:46:47" }, { "name": "shadowhand/email", diff --git a/migrations/20161110175958_update_post_title_desc.php b/migrations/20161110175958_update_post_title_desc.php new file mode 100644 index 0000000000..652b1b147c --- /dev/null +++ b/migrations/20161110175958_update_post_title_desc.php @@ -0,0 +1,56 @@ +getAdapter()->getConnection(); + + $rows = $this->fetchAll( + "SELECT id + FROM form_stages + WHERE type = 'post'" + ); + + $insert = $pdo->prepare( + "INSERT into + form_attributes + (`label`, `type`, `required`, `priority`, `cardinality`, `input`, `key`, `form_stage_id`) + VALUES + ('Title', 'title', 1, 0, 0, 'varchar', :title_key, :title_form_stage_id), + ('Description', 'description', 1, 0, 0, 'text', :desc_key, :desc_form_stage_id)" + ); + + foreach ($rows as $row) { + $uuid = Uuid::uuid4(); + $title_key = $uuid->toString(); + $uuid = Uuid::uuid4(); + $desc_key = $uuid->toString(); + + $insert->execute( + [ + ':title_form_stage_id' => $row['id'], + ':desc_form_stage_id' => $row['id'], + ':title_key' => $title_key, + ':desc_key' => $desc_key + ] + ); + } + } + + /** + * Migrate Down. + */ + public function down() + { + $this->execute("DELETE from form_attributes where type = 'title'"); + $this->execute("DELETE from form_attributes where type = 'description'"); + } +}