Skip to content

Commit

Permalink
Feature/add review workflow toggle (ushahidi#1318)
Browse files Browse the repository at this point in the history
* Add require_approval to Form entity
* Add everyone_can_create to Form entity
* Add form_roles table to record roles which can_create posts in a survey
* Update post authorizer to honor who can create for each form
* Update post validator to check status based on required approval settings
* Add new tests
* Architecture: Give validators access to full entity as well as changes.
  - Avoids nasty overrides in UpdatePost to pass needed info to validator
* Add auto-publish for forms that don't require approval
  - Posts added to a form with `require_approval` set to false will be created with `status` = ‘published’.

Refs ushahidi#1282
  • Loading branch information
zhalloran authored and rjmackay committed Sep 2, 2016
1 parent 0e70f47 commit e726641
Show file tree
Hide file tree
Showing 38 changed files with 1,358 additions and 276 deletions.
51 changes: 51 additions & 0 deletions application/classes/Controller/Api/Forms/Roles.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');

/**
* Ushahidi API Forms Roles Controller
*
* @author Ushahidi Team <[email protected]>
* @package Ushahidi\Application\Controllers
* @copyright 2013 Ushahidi
* @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3)
*/

class Controller_API_Forms_Roles extends Ushahidi_Rest {

protected $_action_map = array
(
Http_Request::GET => 'get',
Http_Request::PUT => 'put', // Typically Update..
Http_Request::OPTIONS => 'options'
);

protected function _scope()
{
return 'forms';
}

protected function _resource()
{
return 'form_roles';
}

// Ushahidi_Rest
public function action_get_index_collection()
{
parent::action_get_index_collection();

$this->_usecase->setIdentifiers($this->request->param());
$this->_usecase->setFilters($this->request->query() + [
'form_id' => $this->request->param('form_id')
]);
}

// Ushahidi_Rest
public function action_put_index_collection()
{
$this->_usecase = service('factory.usecase')
->get($this->_resource(), 'update_collection')
->setIdentifiers($this->_identifiers())
->setPayload($this->_payload());
}

}
12 changes: 12 additions & 0 deletions application/classes/Ushahidi/Core.php
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,10 @@ public static function init()
'create' => $di->lazyNew('Ushahidi_Validator_Form_Attribute_Create'),
'update' => $di->lazyNew('Ushahidi_Validator_Form_Attribute_Update'),
];
$di->params['Ushahidi\Factory\ValidatorFactory']['map']['form_roles'] = [
'create' => $di->lazyNew('Ushahidi_Validator_Form_Role_Create'),
'update_collection' => $di->lazyNew('Ushahidi_Validator_Form_Role_Update'),
];
$di->params['Ushahidi\Factory\ValidatorFactory']['map']['form_stages'] = [
'create' => $di->lazyNew('Ushahidi_Validator_Form_Stage_Create'),
'update' => $di->lazyNew('Ushahidi_Validator_Form_Stage_Update'),
Expand Down Expand Up @@ -275,6 +279,7 @@ public static function init()
'dataproviders' => $di->lazyNew('Ushahidi_Formatter_Dataprovider'),
'forms' => $di->lazyNew('Ushahidi_Formatter_Form'),
'form_attributes' => $di->lazyNew('Ushahidi_Formatter_Form_Attribute'),
'form_roles' => $di->lazyNew('Ushahidi_Formatter_Form_Role'),
'form_stages' => $di->lazyNew('Ushahidi_Formatter_Form_Stage'),
'layers' => $di->lazyNew('Ushahidi_Formatter_Layer'),
'media' => $di->lazyNew('Ushahidi_Formatter_Media'),
Expand All @@ -301,6 +306,7 @@ public static function init()
'dataprovider',
'form',
'form_attribute',
'form_role',
'form_stage',
'layer',
'media',
Expand Down Expand Up @@ -400,6 +406,7 @@ public static function init()
$di->set('repository.contact', $di->lazyNew('Ushahidi_Repository_Contact'));
$di->set('repository.dataprovider', $di->lazyNew('Ushahidi_Repository_Dataprovider'));
$di->set('repository.form', $di->lazyNew('Ushahidi_Repository_Form'));
$di->set('repository.form_role', $di->lazyNew('Ushahidi_Repository_Form_Role'));
$di->set('repository.form_stage', $di->lazyNew('Ushahidi_Repository_Form_Stage'));
$di->set('repository.form_attribute', $di->lazyNew('Ushahidi_Repository_Form_Attribute'));
$di->set('repository.layer', $di->lazyNew('Ushahidi_Repository_Layer'));
Expand Down Expand Up @@ -446,6 +453,7 @@ public static function init()
$di->params['Ushahidi_Repository_Post'] = [
'form_attribute_repo' => $di->lazyGet('repository.form_attribute'),
'form_stage_repo' => $di->lazyGet('repository.form_stage'),
'form_repo' => $di->lazyGet('repository.form'),
'post_value_factory' => $di->lazyGet('repository.post_value_factory'),
'bounding_box_factory' => $di->newFactory('Util_BoundingBox'),
'tag_repo' => $di->lazyGet('repository.tag')
Expand Down Expand Up @@ -579,6 +587,10 @@ public static function init()
$di->setter['Ushahidi_Validator_Form_Stage_Update'] = [
'setFormRepo' => $di->lazyGet('repository.form'),
];
$di->setter['Ushahidi_Validator_Form_Role_Update'] = [
'setFormRepo' => $di->lazyGet('repository.form'),
'setRoleRepo' => $di->lazyGet('repository.role'),
];
$di->setter['Ushahidi_Validator_Media_Create'] = [
'setMaxBytes' => $di->lazy(function() {
return \Kohana::$config->load('media.max_upload_bytes');
Expand Down
31 changes: 31 additions & 0 deletions application/classes/Ushahidi/Formatter/Form/Role.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');

/**
* Ushahidi API Formatter for Form Role
*
* @author Ushahidi Team <[email protected]>
* @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\Traits\FormatterAuthorizerMetadata;

class Ushahidi_Formatter_Form_Role extends Ushahidi_Formatter_API
{
use FormatterAuthorizerMetadata;

public function __invoke($entity)
{
$data = [
'id' => $entity->id,
'url' => URL::site('forms/' . $entity->form_id . '/roles/' . $entity->id, Request::current()),
'form_id' => $entity->form_id,
'role_id' => $entity->role_id,
];

$data = $this->add_metadata($data, $entity);

return $data;
}
}
157 changes: 100 additions & 57 deletions application/classes/Ushahidi/Repository/Form.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,62 +15,105 @@
use Ushahidi\Core\SearchData;

class Ushahidi_Repository_Form extends Ushahidi_Repository implements
FormRepository
FormRepository
{
// Ushahidi_Repository
protected function getTable()
{
return 'forms';
}

// CreateRepository
// ReadRepository
public function getEntity(Array $data = null)
{
return new Form($data);
}

// SearchRepository
public function getSearchFields()
{
return ['parent', 'q' /* LIKE name */];
}

// Ushahidi_Repository
protected function setSearchConditions(SearchData $search)
{
$query = $this->search_query;

if ($search->parent) {
$query->where('parent_id', '=', $search->parent);
}

if ($search->q) {
// Form text searching
$query->where('name', 'LIKE', "%{$search->q}%");
}
}

// CreateRepository
public function create(Entity $entity)
{
// todo ensure default group is created
return parent::create($entity->setState(['created' => time()]));
}

// UpdateRepository
public function update(Entity $entity)
{
return parent::update($entity->setState(['updated' => time()]));
}

/**
* Get total count of entities
* @param Array $where
* @return int
*/
public function getTotalCount(Array $where = [])
{
return $this->selectCount($where);
}
// Ushahidi_Repository
protected function getTable()
{
return 'forms';
}

// CreateRepository
// ReadRepository
public function getEntity(Array $data = null)
{
if (isset($data["id"])) {
$can_create = $this->getRolesThatCanCreatePosts($data['id']);
$data = $data + [
'can_create' => $can_create['roles'],
];
}
return new Form($data);
}

// SearchRepository
public function getSearchFields()
{
return ['parent', 'q' /* LIKE name */];
}

// Ushahidi_Repository
protected function setSearchConditions(SearchData $search)
{
$query = $this->search_query;

if ($search->parent) {
$query->where('parent_id', '=', $search->parent);
}

if ($search->q) {
// Form text searching
$query->where('name', 'LIKE', "%{$search->q}%");
}
}

// CreateRepository
public function create(Entity $entity)
{
// todo ensure default group is created

return parent::create($entity->setState(['created' => time()]));
}

// UpdateRepository
public function update(Entity $entity)
{
return parent::update($entity->setState(['updated' => time()]));
}

/**
* Get total count of entities
* @param Array $where
* @return int
*/
public function getTotalCount(Array $where = [])
{
return $this->selectCount($where);
}

/**
* Get `everyone_can_create` and list of roles that have access to post to the form
* @param $form_id
* @return Array
*/
public function getRolesThatCanCreatePosts($form_id)
{
$query = DB::select('forms.everyone_can_create', 'roles.name')
->distinct(TRUE)
->from('forms')
->join('form_roles', 'LEFT')
->on('forms.id', '=', 'form_roles.form_id')
->join('roles', 'LEFT')
->on('roles.id', '=', 'form_roles.role_id')
->where('forms.id', '=', $form_id);

$results = $query->execute($this->db)->as_array();

$everyone_can_create = (count($results) == 0 ? 1 : $results[0]['everyone_can_create']);

$roles = [];

foreach($results as $role) {
if (!is_null($role['name'])) {
$roles[] = $role['name'];
}
}

return [
'everyone_can_create' => $everyone_can_create,
'roles' => $roles,
];

}

}
98 changes: 98 additions & 0 deletions application/classes/Ushahidi/Repository/Form/Role.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');

/**
* Ushahidi Form Role Repository
*
* @author Ushahidi Team <[email protected]>
* @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\Data;
use Ushahidi\Core\Entity;
use Ushahidi\Core\SearchData;
use Ushahidi\Core\Entity\FormRole;
use Ushahidi\Core\Entity\FormRoleRepository;

class Ushahidi_Repository_Form_Role extends Ushahidi_Repository implements
FormRoleRepository
{
// Ushahidi_Repository
protected function getTable()
{
return 'form_roles';
}

// CreateRepository
// ReadRepository
public function getEntity(Array $data = null)
{
return new FormRole($data);
}

// SearchRepository
public function getSearchFields()
{
return ['form_id', 'roles'];
}

// Ushahidi_Repository
protected function setSearchConditions(SearchData $search)
{
$query = $this->search_query;

if ($search->form_id) {
$query->where('form_id', '=', $search->form_id);
}

if ($search->roles) {
$query->where('role_id', 'in', $search->roles);
}
}

// FormRoleRepository
public function updateCollection(Array $entities)
{
if (empty($entities)) {
return;
}

// Delete all existing form roles records
// Assuming all entites have the same form id
$this->deleteAllForForm(current($entities)->form_id);

$query = DB::insert($this->getTable())
->columns(array_keys(current($entities)->asArray()));

foreach($entities as $entity) {
$query->values($entity->asArray());
}

$query->execute($this->db);

return $entities;
}

// FormRoleRepository
public function getByForm($form_id)
{
$query = $this->selectQuery(compact($form_id));
$results = $query->execute($this->db);

return $this->getCollection($results->as_array());
}

// ValuesForFormRoleRepository
public function deleteAllForForm($form_id)
{
return $this->executeDelete(compact('form_id'));
}

// FormRoleRepository
public function existsInFormRole($role_id, $form_id)
{
return (bool) $this->selectCount(compact('role_id', 'form_id'));
}

}
Loading

0 comments on commit e726641

Please sign in to comment.