<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; }
#msg ul, pre { overflow: auto; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<title>[GlotPress] [458] trunk:
Move validator permissions interface to project and add GP_Validator_Permission thing to make working with them easier </title>
</head>
<body>
<div id="msg">
<dl>
<dt>Revision</dt> <dd>458</dd>
<dt>Author</dt> <dd>nbachiyski</dd>
<dt>Date</dt> <dd>2010-04-05 17:07:27 +0000 (Mon, 05 Apr 2010)</dd>
</dl>
<h3>Log Message</h3>
<pre>Move validator permissions interface to project and add GP_Validator_Permission thing to make working with them easier </pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkcssstylecss">trunk/css/style.css</a></li>
<li><a href="#trunkgpincludesadvancedpermissionsphp">trunk/gp-includes/advanced-permissions.php</a></li>
<li><a href="#trunkgpincludesgpphp">trunk/gp-includes/gp.php</a></li>
<li><a href="#trunkgpincludesroutesprojectphp">trunk/gp-includes/routes/project.php</a></li>
<li><a href="#trunkgpincludesroutestranslationphp">trunk/gp-includes/routes/translation.php</a></li>
<li><a href="#trunkgpincludesroutesphp">trunk/gp-includes/routes.php</a></li>
<li><a href="#trunkgpincludestemplatephp">trunk/gp-includes/template.php</a></li>
<li><a href="#trunkgpincludesthingphp">trunk/gp-includes/thing.php</a></li>
<li><a href="#trunkgpincludesthingspermissionphp">trunk/gp-includes/things/permission.php</a></li>
<li><a href="#trunkgpincludesthingsprojectphp">trunk/gp-includes/things/project.php</a></li>
<li><a href="#trunkgptemplatesprojectphp">trunk/gp-templates/project.php</a></li>
<li><a href="#trunkgptemplatestranslationsphp">trunk/gp-templates/translations.php</a></li>
<li><a href="#trunkttest_permissionsphp">trunk/t/test_permissions.php</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkgpincludesthingsvalidatorpermissionphp">trunk/gp-includes/things/validator-permission.php</a></li>
<li><a href="#trunkgptemplatesprojectpermissionsphp">trunk/gp-templates/project-permissions.php</a></li>
</ul>
<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkgptemplatestranslationsetpermissionsphp">trunk/gp-templates/translation-set-permissions.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkcssstylecss"></a>
<div class="modfile"><h4>Modified: trunk/css/style.css (457 => 458)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/css/style.css        2010-04-05 12:50:17 UTC (rev 457)
+++ trunk/css/style.css        2010-04-05 17:07:27 UTC (rev 458)
</span><span class="lines">@@ -379,10 +379,10 @@
</span><span class="cx"> .actionlist a:active {
</span><span class="cx"> color: red;
</span><span class="cx"> }
</span><del>-#translation-set-permissions .user {
</del><ins>+.permissions .user {
</ins><span class="cx"> font-weight: bold;
</span><span class="cx"> }
</span><del>-#translation-set-permissions .permission-action {
</del><ins>+.permissions .permission-action {
</ins><span class="cx"> font-style: italic;
</span><span class="cx"> color: #999;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkgpincludesadvancedpermissionsphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/advanced-permissions.php (457 => 458)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/advanced-permissions.php        2010-04-05 12:50:17 UTC (rev 457)
+++ trunk/gp-includes/advanced-permissions.php        2010-04-05 17:07:27 UTC (rev 458)
</span><span class="lines">@@ -15,11 +15,11 @@
</span><span class="cx">         return false;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-function gp_recurse_project_locale_set_slug_permissions( $verdict, $args ) {
-        if ( !( !$verdict && $args['object_type'] == 'project|locale|set-slug' && $args['object_id'] && $args['user'] ) ) {
</del><ins>+function gp_recurse_validator_permission( $verdict, $args ) {
+        if ( !( !$verdict && $args['object_type'] == GP::$validator_permission->object_type && $args['object_id'] && $args['user'] ) ) {
</ins><span class="cx">                 return $verdict;
</span><span class="cx">         }
</span><del>-        list( $project_id, $locale_slug, $set_slug ) = explode( '|', $args['object_id'] );
</del><ins>+        list( $project_id, $locale_slug, $set_slug ) = GP::$validator_permission->project_id_locale_slug_set_slug( $args['object_id'] );
</ins><span class="cx">         $project = GP::$project->get( $project_id );
</span><span class="cx">         if ( $project->parent_project_id ) {
</span><span class="cx">                 return $args['user']->can( $args['action'], $args['object_type'], $project->parent_project_id.'|'.$locale_slug.'|'.$set_slug );
</span><span class="lines">@@ -28,7 +28,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx">
</span><del>-function gp_route_translation_set_permissions_to_parent_project( $verdict, $args ) {
</del><ins>+function gp_route_translation_set_permissions_to_validator_permissions( $verdict, $args ) {
</ins><span class="cx">         if ( !( $verdict == 'no-verdict' && $args['action'] == 'approve' && $args['object_type'] == 'translation-set'
</span><span class="cx">                         && $args['object_id'] && $args['user'] ) ) {
</span><span class="cx">                 return $verdict;
</span><span class="lines">@@ -37,10 +37,11 @@
</span><span class="cx">                 $set = $args['extra']['set'];
</span><span class="cx">         else
</span><span class="cx">                 $set = GP::$translation_set->get( $args['object_id'] );
</span><del>-        return $args['user']->can( 'approve', 'project|locale|set-slug', $set->project_id.'|'.$set->locale.'|'.$set->slug );
</del><ins>+        return $args['user']->can( 'approve', GP::$validator_permission->object_type,
+                GP::$validator_permission->object_id( $set->project_id, $set->locale, $set->slug ) );
</ins><span class="cx">         
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> add_filter( 'can_user', 'gp_recurse_project_permissions', 10, 2 );
</span><del>-add_filter( 'can_user', 'gp_recurse_project_locale_set_slug_permissions', 10, 2 );
-add_filter( 'pre_can_user', 'gp_route_translation_set_permissions_to_parent_project', 10, 2 );
</del><ins>+add_filter( 'can_user', 'gp_recurse_validator_permission', 10, 2 );
+add_filter( 'pre_can_user', 'gp_route_translation_set_permissions_to_validator_permissions', 10, 2 );
</ins></span></pre></div>
<a id="trunkgpincludesgpphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/gp.php (457 => 458)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/gp.php        2010-04-05 12:50:17 UTC (rev 457)
+++ trunk/gp-includes/gp.php        2010-04-05 17:07:27 UTC (rev 458)
</span><span class="lines">@@ -5,6 +5,7 @@
</span><span class="cx">         static $user;
</span><span class="cx">         static $translation_set;
</span><span class="cx">         static $permission;
</span><ins>+        static $validator_permission;
</ins><span class="cx">         static $translation;
</span><span class="cx">         static $original;
</span><span class="cx">         // other singletons
</span></span></pre></div>
<a id="trunkgpincludesroutesprojectphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/routes/project.php (457 => 458)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/routes/project.php        2010-04-05 12:50:17 UTC (rev 457)
+++ trunk/gp-includes/routes/project.php        2010-04-05 17:07:27 UTC (rev 458)
</span><span class="lines">@@ -47,7 +47,7 @@
</span><span class="cx">                 $this->can_or_redirect( 'write', 'project', $project->id );
</span><span class="cx">
</span><span class="cx">                 $format = gp_array_get( GP::$formats, gp_post( 'format', 'po' ), null );
</span><del>-                if ( !$format ) $this->redirect_with_error( __('No such format.') );;
</del><ins>+                if ( !$format ) $this->redirect_with_error( __('No such format.') );
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">                 if ( !is_uploaded_file( $_FILES['import-file']['tmp_name'] ) ) {
</span><span class="lines">@@ -132,4 +132,66 @@
</span><span class="cx">                         gp_redirect( gp_url_project( $project, '_edit' ) );
</span><span class="cx">                 }
</span><span class="cx">         }
</span><ins>+        
+        function permissions_get( $project_path ) {
+                $project = GP::$project->by_path( $project_path );
+                if ( !$project ) gp_tmpl_404();
+                $this->can_or_redirect( 'write', 'project', $project->id );
+                $path_to_root = array_slice( $project->path_to_root(), 1 );
+                $permissions = GP::$validator_permission->by_project_id( $project->id );
+                $parent_permissions = array();
+                foreach( $path_to_root as $parent_project ) {
+                        $this_parent_permissions = GP::$validator_permission->by_project_id( $parent_project->id );
+                        foreach( $this_parent_permissions as $permission ) {
+                                $permission->project = $parent_project;
+                        }
+                        $parent_permissions = array_merge( $parent_permissions, (array)$this_parent_permissions );
+                }
+                // we can't join on users table
+                foreach( array_merge( (array)$permissions, (array)$parent_permissions ) as $permission ) {
+                        $permission->user = GP::$user->get( $permission->user_id );
+                }
+                $this->tmpl( 'project-permissions', get_defined_vars() );
+        }
+
+        function permissions_post( $project_path ) {
+                $project = GP::$project->by_path( $project_path );
+                if ( !$project ) gp_tmpl_404();
+                $this->can_or_redirect( 'write', 'project', $project->id );
+                if ( 'add-validator' == gp_post( 'action' ) ) {
+                        $user = GP::$user->by_login( gp_post( 'user_login' ) );
+                        if ( !$user ) {
+                                $this->redirect_with_error( __('User wasn&#8217;t found!'), gp_url_current() );
+                        }
+                        $new_permission = new GP_Validator_Permission( array(
+                                'user_id' => $user->id,
+                                'action' => 'approve',
+                                'project_id' => $project->id,
+                                'locale_slug' => gp_post( 'locale' ),
+                                'set_slug' => gp_post( 'set-slug' ),
+                        ) );
+                        $this->validate_or_redirect( $new_permission, gp_url_current() );
+                        $permission = GP::$validator_permission->create( $new_permission );
+                        $permission?
+                                $this->notices[] = __('Validator was added.') : $this->errors[] = __('Error in adding validator.');
+                }
+                gp_redirect( gp_url_current() );
+        }
+        
+        function permissions_delete( $project_path, $permission_id ) {
+                $project = GP::$project->by_path( $project_path );
+                if ( !$project ) gp_tmpl_404();
+                $this->can_or_redirect( 'write', 'project', $project->id );
+                $permission = GP::$permission->get( $permission_id );
+                if ( $permission ) {
+                        if ( $permission->delete() ) {
+                                $this->notices[] = __('Permission was deleted.');
+                        } else {
+                                $this->errors[] = __('Error in deleting permission!');
+                        }
+                } else {
+                        $this->errors[] = __('Permission wasn&#8217;t found!');
+                }
+                gp_redirect( gp_url_project( $project, array( '_permissions' ) ) );
+        }        
</ins><span class="cx"> }
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkgpincludesroutestranslationphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/routes/translation.php (457 => 458)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/routes/translation.php        2010-04-05 12:50:17 UTC (rev 457)
+++ trunk/gp-includes/routes/translation.php        2010-04-05 17:07:27 UTC (rev 458)
</span><span class="lines">@@ -248,66 +248,7 @@
</span><span class="cx">                         $this->notices[] = sprintf( __('%d fuzzy translation from Google Translate were added.' ), $ok );
</span><span class="cx">                 }
</span><span class="cx">         }
</span><del>-        
-
-        function permissions_post( $project_path, $locale_slug, $translation_set_slug ) {
-                $project = GP::$project->by_path( $project_path );
-                $locale = GP_Locales::by_slug( $locale_slug );
-                $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $translation_set_slug, $locale_slug );
-                if ( !$project || !$locale || !$translation_set ) gp_tmpl_404();
-                $this->can_or_redirect( 'write', 'project', $project->id );
-                if ( 'add-approver' == gp_post( 'action' ) ) {
-                        $user = GP::$user->by_login( gp_post( 'user_login' ) );
-                        if ( $user ) {
-                                $res = GP::$permission->create( array(
-                                        'user_id' => $user->id,
-                                        'action' => 'approve',
-                                        'object_type' => 'translation-set',
-                                        'object_id' => $translation_set->id,
-                                ) );
-                                $res?
-                                        $this->notices[] = 'Validator was added.' :
-                                        $this->errors[] = 'Error in adding validator.';
-                        } else {
-                                $this->errors[] = 'User wasn&#8217;t found!';
-                        }
-                }
-                gp_redirect( gp_url_current() );
-        }
-        
-        function permissions_get( $project_path, $locale_slug, $translation_set_slug ) {
-                $project = GP::$project->by_path( $project_path );
-                $locale = GP_Locales::by_slug( $locale_slug );
-                $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $translation_set_slug, $locale_slug );
-                if ( !$project || !$locale || !$translation_set ) gp_tmpl_404();
-                $this->can_or_redirect( 'write', 'project', $project->id );
-                $permissions = GP::$permission->by_translation_set_id( $translation_set->id );
-                // we can't join on users table
-                foreach( (array)$permissions as $permission ) {
-                        $permission->user = GP::$user->get( $permission->user_id );
-                }
-                $this->tmpl( 'translation-set-permissions', get_defined_vars() );
-        }
-        
-        function permissions_delete( $project_path, $locale_slug, $translation_set_slug, $permission_id ) {
-                $project = GP::$project->by_path( $project_path );
-                $locale = GP_Locales::by_slug( $locale_slug );
-                $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $translation_set_slug, $locale_slug );
-                if ( !$project || !$locale || !$translation_set ) gp_tmpl_404();
-                $this->can_or_redirect( 'write', 'project', $project->id );
-                $permission = GP::$permission->get( $permission_id );
-                if ( $permission ) {
-                        if ( $permission->delete() ) {
-                                $this->notices[] = 'Permissin was deleted.';
-                        } else {
-                                $this->errors[] = 'Error in deleting permission!';
-                        }
-                } else {
-                        $this->errors[] = 'Permission wasn&#8217;t found!';
-                }
-                gp_redirect( gp_url_project( $project, array( $locale->slug, $translation_set->slug, '_permissions' ) ) );
-        }
-        
</del><ins>+                        
</ins><span class="cx">         function discard_warning( $project_path, $locale_slug, $translation_set_slug ) {
</span><span class="cx">                 $project = GP::$project->by_path( $project_path );
</span><span class="cx">                 $locale = GP_Locales::by_slug( $locale_slug );
</span></span></pre></div>
<a id="trunkgpincludesroutesphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/routes.php (457 => 458)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/routes.php        2010-04-05 12:50:17 UTC (rev 457)
+++ trunk/gp-includes/routes.php        2010-04-05 17:07:27 UTC (rev 458)
</span><span class="lines">@@ -53,6 +53,11 @@
</span><span class="cx">                         "post:/$project/_delete" => array('GP_Route_Project', 'delete_post'),
</span><span class="cx">
</span><span class="cx">                         "post:/$project/_personal" => array('GP_Route_Project', 'personal_options_post'),
</span><ins>+                        
+                        "get:/$project/_permissions" => array('GP_Route_Project', 'permissions_get'),
+                        "post:/$project/_permissions" => array('GP_Route_Project', 'permissions_post'),
+                        "get:/$project/_permissions/_delete/$dir" => array('GP_Route_Project', 'permissions_delete'),
+                        
</ins><span class="cx">
</span><span class="cx">                         "get:/$projects" => array('GP_Route_Project', 'index'),
</span><span class="cx">                         "get:/$projects/_new" => array('GP_Route_Project', 'new_get'),
</span><span class="lines">@@ -64,9 +69,6 @@
</span><span class="cx">                         "post:/$project/$locale/$dir" => array('GP_Route_Translation', 'translations_post'),
</span><span class="cx">                         "get:/$project/$locale/$dir/import-translations" => array('GP_Route_Translation', 'import_translations_get'),
</span><span class="cx">                         "post:/$project/$locale/$dir/import-translations" => array('GP_Route_Translation', 'import_translations_post'),
</span><del>-                        "get:/$project/$locale/$dir/_permissions" => array('GP_Route_Translation', 'permissions_get'),
-                        "post:/$project/$locale/$dir/_permissions" => array('GP_Route_Translation', 'permissions_post'),
-                        "get:/$project/$locale/$dir/_permissions/_delete/$dir" => array('GP_Route_Translation', 'permissions_delete'),
</del><span class="cx">                         "post:/$project/$locale/$dir/_discard-warning" => array('GP_Route_Translation', 'discard_warning'),
</span><span class="cx">                         "/$project/$locale/$dir/export-translations" => array('GP_Route_Translation', 'export_translations_get'),
</span><span class="cx">                         // keep this one at the bottom of the project, because it will catch anything starting with project
</span></span></pre></div>
<a id="trunkgpincludestemplatephp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/template.php (457 => 458)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/template.php        2010-04-05 12:50:17 UTC (rev 457)
+++ trunk/gp-includes/template.php        2010-04-05 17:07:27 UTC (rev 458)
</span><span class="lines">@@ -163,4 +163,12 @@
</span><span class="cx"> function gp_attrs_add_class( $attrs, $class_name ) {
</span><span class="cx">         $attrs['class'] = isset( $attrs['class'] )? $attrs['class'] . ' ' . $class_name : $class_name;
</span><span class="cx">         return $attrs;
</span><ins>+}
+
+function gp_locales_dropdown( $name_and_id, $selected_slug = '', $attrs = array() ) {
+        $options = array( '' => '&mdash; Locale &mdash;' );
+        foreach( GP_Locales::locales() as $locale ) {
+                $options[$locale->slug] = sprintf( '%s &ndash; %s', $locale->slug, $locale->english_name );
+        }
+        return gp_select( $name_and_id, $options, $selected_slug, $attrs );
</ins><span class="cx"> }
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkgpincludesthingphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/thing.php (457 => 458)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/thing.php        2010-04-05 12:50:17 UTC (rev 457)
+++ trunk/gp-includes/thing.php        2010-04-05 17:07:27 UTC (rev 458)
</span><span class="lines">@@ -3,6 +3,7 @@
</span><span class="cx">         
</span><span class="cx">         var $table = null;
</span><span class="cx">         var $field_names = array();
</span><ins>+        var $non_db_field_names = array();
</ins><span class="cx">         var $errors = array();
</span><span class="cx">         var $validation_rules = null;
</span><span class="cx">         var $per_page = 30;
</span><span class="lines">@@ -24,7 +25,7 @@
</span><span class="cx">                 if ( isset( self::$validation_rules_by_class[$this->class] ) ) {
</span><span class="cx">                         $this->validation_rules = &self::$validation_rules_by_class[$this->class];
</span><span class="cx">                 } else {
</span><del>-                        $this->validation_rules = new GP_Validation_Rules( $this->field_names );
</del><ins>+                        $this->validation_rules = new GP_Validation_Rules( array_merge( $this->field_names, $this->non_db_field_names ) );
</ins><span class="cx">                         // we give the rules as a parameter here solely as a syntax sugar
</span><span class="cx">                         $this->restrict_fields( $this->validation_rules );
</span><span class="cx">                         self::$validation_rules_by_class[$this->class] = &$this->validation_rules;
</span><span class="lines">@@ -186,8 +187,9 @@
</span><span class="cx">
</span><span class="cx">         function get( $thing_or_id ) {
</span><span class="cx">                 global $gpdb;
</span><del>-                if ( is_object( $thing_or_id ) ) $thing_or_id = $thing_or_id->id;
-                return $this->coerce( $gpdb->get_row( $gpdb->prepare( "SELECT * FROM $this->table WHERE `id` = '%s'", $thing_or_id ) ) );
</del><ins>+                if ( !$thing_or_id ) return false;
+                $id = is_object( $thing_or_id )? $thing_or_id->id : $thing_or_id;
+                return $this->find_one( array( 'id' => $id ) );
</ins><span class="cx">         }
</span><span class="cx">
</span><span class="cx">         function save( $args = null ) {
</span><span class="lines">@@ -305,15 +307,20 @@
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         function sql_from_conditions( $conditions ) {
</span><del>-                $conditions = array_map( array( &$this, 'sql_condition_from_php_value' ), $conditions );
-                $string_conditions = array();
-                foreach( $conditions as $field => $sql_condition ) {
-                        if ( is_array( $sql_condition ) )
-                                $string_conditions[] = '('. implode( ' OR ', array_map( lambda( '$cond', '"$field $cond"', compact('field') ), $sql_condition ) ) . ')';
-                        else
-                                $string_conditions[] = "$field $sql_condition";
</del><ins>+                if ( is_string( $conditions ) ) {
+                        $conditions;
+                } elseif ( is_array( $conditions ) ) {
+                        $conditions = array_map( array( &$this, 'sql_condition_from_php_value' ), $conditions );
+                        $string_conditions = array();
+                        foreach( $conditions as $field => $sql_condition ) {
+                                if ( is_array( $sql_condition ) )
+                                        $string_conditions[] = '('. implode( ' OR ', array_map( lambda( '$cond', '"$field $cond"', compact('field') ), $sql_condition ) ) . ')';
+                                else
+                                        $string_conditions[] = "$field $sql_condition";
+                        }
+                        $conditions = implode( ' AND ', $string_conditions );
</ins><span class="cx">                 }
</span><del>-                return implode( ' AND ', $string_conditions );
</del><ins>+                return $this->apply_default_conditions( $conditions );
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         function select_all_from_conditions( $conditions ) {
</span><span class="lines">@@ -359,4 +366,11 @@
</span><span class="cx">         function like_escape_printf( $s ) {
</span><span class="cx">                 return str_replace( '%', '%%', like_escape( $s ) );
</span><span class="cx">         }
</span><ins>+        
+        function apply_default_conditions( $conditions_str ) {
+                $conditions = array();
+                if ( isset( $this->default_conditions ) ) $conditions[] = $this->default_conditions;
+                if ( $conditions_str ) $conditions[] = $conditions_str;
+                return implode( ' AND ', $conditions );
+        }
</ins><span class="cx"> }
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkgpincludesthingspermissionphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/things/permission.php (457 => 458)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/things/permission.php        2010-04-05 12:50:17 UTC (rev 457)
+++ trunk/gp-includes/things/permission.php        2010-04-05 17:07:27 UTC (rev 458)
</span><span class="lines">@@ -15,14 +15,5 @@
</span><span class="cx">                 }
</span><span class="cx">                 return $args;
</span><span class="cx">         }
</span><del>-        
-        function by_translation_set_id( $translation_set_id ) {
-                return $this->many( "SELECT * FROM $this->table WHERE object_type='translation-set' AND object_id = %d", $translation_set_id );
-        }
-        
-        function by_project_id_locale_slug_set_slug( $project_id, $locale_slug, $set_slug = 'default' ) {
-                return $this->many( "SELECT * FROM $this->table WHERE object_type='project|locale|set' AND object_id = %s",
-                        $project_id.'|'.$locale_slug.'|'.$set_slug );
-        }
</del><span class="cx"> }
</span><span class="cx"> GP::$permission = new GP_Permission();
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkgpincludesthingsprojectphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-includes/things/project.php (457 => 458)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/things/project.php        2010-04-05 12:50:17 UTC (rev 457)
+++ trunk/gp-includes/things/project.php        2010-04-05 17:07:27 UTC (rev 458)
</span><span class="lines">@@ -35,7 +35,6 @@
</span><span class="cx">         function after_create() {
</span><span class="cx">                 // TODO: pass some args to pre/after_create?
</span><span class="cx">                 if ( is_null( $this->update_path() ) ) return false;
</span><del>-                if ( !$this->copy_permissions_from_parent() ) return false;
</del><span class="cx">         }
</span><span class="cx">
</span><span class="cx">         // Field handling
</span><span class="lines">@@ -80,19 +79,6 @@
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        function copy_permissions_from_parent() {
-                if ( !$this->parent_project_id ) return true;
-                $permissions = GP::$permission->find( array( 'action' => 'write', 'object_type' => 'project', 'object_id' => $this->parent_project_id ) );
-                if ( !is_array( $permissions ) ) return false;
-                foreach( $permissions as $permission ) {
-                        if ( !GP::$permission->create( array( 'user_id' => $permission->user_id, 'action' => 'write',
-                                        'object_type' => 'project', 'object_id' => $this->id ) ) ) {
-                                return false;
-                        }
-                }
-                return true;
-        }
-
</del><span class="cx">         /**
</span><span class="cx">          * Regenrate the paths of all projects from its parents slugs
</span><span class="cx">          */
</span></span></pre></div>
<a id="trunkgpincludesthingsvalidatorpermissionphp"></a>
<div class="addfile"><h4>Added: trunk/gp-includes/things/validator-permission.php (0 => 458)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-includes/things/validator-permission.php         (rev 0)
+++ trunk/gp-includes/things/validator-permission.php        2010-04-05 17:07:27 UTC (rev 458)
</span><span class="lines">@@ -0,0 +1,50 @@
</span><ins>+<?php
+class GP_Validator_Permission extends GP_Permission {
+
+        var $table_basename = 'permissions';
+        var $field_names = array( 'id', 'user_id', 'action', 'object_type', 'object_id' );
+        var $non_db_field_names = array( 'project_id', 'locale_slug', 'set_slug' );
+        var $non_updatable_attributes = array( 'id', );
+
+        function restrict_fields( $permission ) {
+                $permission->project_id_should_not_be('empty');
+                $permission->locale_slug_should_not_be('empty');
+                $permission->user_id_should_not_be('empty');
+                $permission->action_should_not_be('empty');
+                $permission->set_slug_should_not_be('empty');
+        }
+        
+        function set_fields( $db_object ) {
+                parent::set_fields( $db_object );
+                if ( $this->object_id ) {
+                        list( $this->project_id, $this->locale_slug, $this->set_slug ) = $this->project_id_locale_slug_set_slug( $this->object_id );
+                }
+                $this->object_type = 'project|locale|set-slug';
+                $this->default_conditions = "object_type = '".$this->object_type."'";
+        }
+
+        function prepare_fields_for_save( $args ) {
+                $args = (array)$args;
+                $args['object_type'] = $this->object_type;                
+                if ( gp_array_get( $args, 'project_id' ) && gp_array_get( $args, 'locale_slug' )
+                                 && gp_array_get( $args, 'set_slug' ) && !gp_array_get( $args, 'object_id' ) ) {
+                        $args['object_id'] = $this->object_id( $args['project_id'], $args['locale_slug'], $args['set_slug'] );
+                }
+                $args = parent::prepare_fields_for_save( $args );                
+                return $args;
+        }
+        
+        function project_id_locale_slug_set_slug( $object_id ) {
+                return explode( '|', $object_id );
+        }
+        
+        function object_id( $project_id, $locale_slug, $set_slug = 'default' ) {
+                return implode( '|', array( $project_id, $locale_slug, $set_slug ) );
+        }
+        
+        function by_project_id( $project_id ) {
+                $project_id = (int)$project_id;
+                return $this->find_many( "object_id LIKE '$project_id|%'" );
+        }
+}
+GP::$validator_permission = new GP_Validator_Permission();
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/gp-includes/things/validator-permission.php
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:eol-style
</span><span class="cx"> + native
</span></span></pre></div>
<a id="trunkgptemplatesprojectpermissionsphpfromrev454trunkgptemplatestranslationsetpermissionsphp"></a>
<div class="copfile"><h4>Copied: trunk/gp-templates/project-permissions.php (from rev 454, trunk/gp-templates/translation-set-permissions.php) (0 => 458)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-templates/project-permissions.php         (rev 0)
+++ trunk/gp-templates/project-permissions.php        2010-04-05 17:07:27 UTC (rev 458)
</span><span class="lines">@@ -0,0 +1,66 @@
</span><ins>+<?php
+gp_title( sprintf( __( 'Permissions &lt; %s &lt; GlotPress' ), $project->name ) );
+gp_breadcrumb( array(
+        gp_link_project_get( $project, $project->name ),
+        __('Permissions')
+) );
+gp_tmpl_header();
+?>
+<h2><?php _e('Permissions'); ?></h2>
+<h3 id="validators"><?php _e('Validators'); ?></h3>
+        <?php if ( $permissions ): ?>
+        <?php if ( $parent_permissions ): ?>
+<h4 id="validators"><?php _e('Validators for this project'); ?></h4>
+        <?php endif; ?>
+<ul class="permissions">
+        <?php foreach( $permissions as $permission ): ?>
+                <li>
+                        <span class="permission-action"><?php _e('user'); ?></span>
+                        <span class="user"><?php echo esc_html( $permission->user->user_login ); ?></span>
+                        <span class="permission-action">can <?php echo esc_html( $permission->action ); ?> strings with locale</span>
+                        <span class="user"><?php echo esc_html( $permission->locale_slug ); ?></span>
+                        <span class="permission-action">and slug</span>
+                        <span class="user"><?php echo esc_html( $permission->set_slug ); ?></span>
+                        <a href="<?php echo gp_url_join( gp_url_current(), '_delete/'.$permission->id ); ?>" class="action delete"><?php _e('Remove'); ?></a>
+                </li>
+        <? endforeach; ?>
+</ul>        
+        <?php endif; ?>
+        <?php if ( $parent_permissions ): ?>
+<h4 id="validators"><?php _e('Validators for parent projects'); ?></h4>
+<ul class="permissions">                
+                <?php foreach( $parent_permissions as $permission ): ?>
+                        <li>
+                                <span class="permission-action"><?php _e('user'); ?></span>
+                                <span class="user"><?php echo esc_html( $permission->user->user_login ); ?></span>
+                                <span class="permission-action">can <?php echo esc_html( $permission->action ); ?> strings with locale</span>
+                                <span class="user"><?php echo esc_html( $permission->locale_slug ); ?></span>
+                                <span class="permission-action">and slug</span>
+                                <span class="user"><?php echo esc_html( $permission->set_slug ); ?></span>
+                                <span class="permission-action">in the project </span>
+                                <span class="user"><?php gp_link_project( $permission->project, esc_html( $permission->project->name ) ); ?></span>
+                        </li>
+                <? endforeach; ?>
+</ul>                                
+        <?php endif; ?>
+        <?php if ( !$permissions && !$parent_permissions ): ?>
+                <strong><?php _e('No validators defined for this project.'); ?></strong>
+        <?php endif; ?>
+<form action="" method="post" class="secondary">
+        <h3><?php _e('Add a validator for this project'); ?></h3>
+        <dl>
+                <dt><label for="user_login"><?php _e('Username:'); ?></label></dt>
+                <dd><input type="text" name="user_login" value="" id="user_login" /></dd>
+                <dt><label for="locale"><?php _e('Locale:'); ?></label></dt>
+                <dd><?php echo gp_locales_dropdown( 'locale' ); ?></dd>
+                <dt><label for="set-slug"><?php _e('Translation set slug:'); ?></label></dt>
+                <dd><input type="text" name="set-slug" value="default" id="set-slug" /></dd>
+                                
+                <dt>
+                        <input type="submit" name="submit" value="<?php echo esc_attr(__('Add &rarr;')); ?>" id="submit" />
+                        <input type="hidden" name="action" value="add-validator" />
+                </dt>
+</form>
+<?php
+echo gp_js_focus_on('user_login');
+gp_tmpl_footer();
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkgptemplatesprojectphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-templates/project.php (457 => 458)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-templates/project.php        2010-04-05 12:50:17 UTC (rev 457)
+++ trunk/gp-templates/project.php        2010-04-05 17:07:27 UTC (rev 458)
</span><span class="lines">@@ -74,6 +74,7 @@
</span><span class="cx"> <?php if ( $can_write ): ?>
</span><span class="cx">         <p class="secondary actionlist">
</span><span class="cx">                 <?php gp_link( gp_url_project( $project, 'import-originals' ), __( 'Import originals' ) ); ?> &bull;
</span><ins>+                <?php gp_link( gp_url_project( $project, array( '_permissions' ) ), __('Permissions') ); ?> &bull;
</ins><span class="cx">                 <?php gp_link( gp_url_project( '', '_new', array('parent_project_id' => $project->id) ), __('Create a New Sub-Project') ); ?> &bull;
</span><span class="cx">                 <?php gp_link( gp_url( '/sets/_new', array( 'project_id' => $project->id ) ), __('Create a New Translation Set') ); ?>
</span><span class="cx">         </p>
</span></span></pre></div>
<a id="trunkgptemplatestranslationsetpermissionsphp"></a>
<div class="delfile"><h4>Deleted: trunk/gp-templates/translation-set-permissions.php (457 => 458)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-templates/translation-set-permissions.php        2010-04-05 12:50:17 UTC (rev 457)
+++ trunk/gp-templates/translation-set-permissions.php        2010-04-05 17:07:27 UTC (rev 458)
</span><span class="lines">@@ -1,41 +0,0 @@
</span><del>-<?php
-gp_title( sprintf( __( 'Permissions &lt; %s &lt; %s &lt; GlotPress' ), $translation_set->name, $project->name ) );
-gp_breadcrumb( array(
-        gp_link_project_get( $project, $project->name ),
-        $locale->english_name,
-        'default' != $translation_set->slug? $translation_set->name : '',
-        __('Permissions')
-) );
-gp_tmpl_header();
-?>
-<h2><?php _e('Permissions'); ?></h2>
-<ul id="translation-set-permissions">
-        <?php foreach( $permissions as $permission ): ?>
-                <li>
-                        <span class="permission-action"><?php _e('user'); ?></span>
-                        <span class="user"><?php echo esc_html( $permission->user->user_login ); ?></span>
-                        <span class="permission-action">can <?php echo esc_html( $permission->action ); ?></span>
-                        <a href="<?php echo gp_url_join( gp_url_current(), '_delete/'.$permission->id ); ?>" class="action delete"><?php _e('Remove'); ?></a>
-                </li>
-        <? endforeach; ?>
-
-        <?php if ( !$permissions ): ?>
-                <strong><?php _e('No validators defined for this translation set.'); ?></strong>
-        <?php endif; ?>
-</ul>
-
-<form action="" method="post" class="secondary">
-        <h3><?php _e('Add a validator for this translation set'); ?></h3>
-        <p>
-                <label for="user_login"><?php _e('Username:'); ?></label>
-                <input type="text" name="user_login" value="" id="user_login" />
-        </p>
-        <p>
-                <input type="submit" name="submit" value="<?php echo esc_attr(__('Add &rarr;')); ?>" id="submit" />
-        </p>
-        
-        <input type="hidden" name="action" value="add-approver" />
-</form>
-<?php
-echo gp_js_focus_on('user_login');
-gp_tmpl_footer();
</del><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkgptemplatestranslationsphp"></a>
<div class="modfile"><h4>Modified: trunk/gp-templates/translations.php (457 => 458)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/gp-templates/translations.php        2010-04-05 12:50:17 UTC (rev 457)
+++ trunk/gp-templates/translations.php        2010-04-05 17:07:27 UTC (rev 458)
</span><span class="lines">@@ -149,9 +149,6 @@
</span><span class="cx">                 if ( $can_approve ) {
</span><span class="cx">                         $footer_links[] = gp_link_get( gp_url_project( $project, array( $locale->slug, $translation_set->slug, 'import-translations' ) ), __('Import translations') );
</span><span class="cx">                 }
</span><del>-                if ( $can_write ) {
-                 $footer_links[] = gp_link_get( gp_url_project( $project, array( $locale->slug, $translation_set->slug, '_permissions' ) ), __('Permissions') );
-                }
</del><span class="cx">                 if ( GP::$user->logged_in() ) {
</span><span class="cx">                         $export_url = gp_url_project( $project, array( $locale->slug, $translation_set->slug, 'export-translations' ) );
</span><span class="cx">                         $export_link = gp_link_get( $export_url , __('Export'), array('id' => 'export', 'filters' => add_query_arg( array( 'filters' => $filters ), $export_url ) ) );
</span></span></pre></div>
<a id="trunkttest_permissionsphp"></a>
<div class="modfile"><h4>Modified: trunk/t/test_permissions.php (457 => 458)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/t/test_permissions.php        2010-04-05 12:50:17 UTC (rev 457)
+++ trunk/t/test_permissions.php        2010-04-05 17:07:27 UTC (rev 458)
</span><span class="lines">@@ -35,8 +35,8 @@
</span><span class="cx">                 $this->assertFalse( (bool)$user->can( 'write', 'project', $other->id ) );
</span><span class="cx">         }
</span><span class="cx">
</span><del>-        function test_recursive_project_locale_set_slug_permissions() {
-                $object_type = 'project|locale|set-slug';
</del><ins>+        function test_recursive_validator_permissions() {
+                $object_type = GP::$validator_permission->object_type;
</ins><span class="cx">                 $action = 'whetever';
</span><span class="cx">                 $user = GP::$user->create( array( 'user_login' => 'gugu', 'user_email' => 'gugu@gugu.net' ) );
</span><span class="cx">                 
</span><span class="lines">@@ -44,10 +44,12 @@
</span><span class="cx">                 $root = GP::$project->create( array( 'name' => 'Root', 'slug' => 'root', 'path' => 'root') );
</span><span class="cx">                 $sub = GP::$project->create( array( 'name' => 'Sub', 'slug' => 'sub', 'parent_project_id' => $root->id, 'path' => 'root/sub' ) );
</span><span class="cx">                 
</span><del>-                GP::$permission->create( array( 'user_id' => $user->id, 'action' => 'whatever',
-                        'object_type' => $object_type, 'object_id' => $root->id.'|bg|default' ) );
-                $this->assertTrue( (bool)$user->can( 'whatever', $object_type, $root->id.'|bg|default' ) );
-                $this->assertTrue( (bool)$user->can( 'whatever', $object_type, $sub->id.'|bg|default' ) );
</del><ins>+                GP::$validator_permission->create( array( 'user_id' => $user->id, 'action' => 'whatever',
+                        'project_id' => $root->id, 'locale_slug' => 'bg', 'set_slug' => 'default' ) );
+                        
+                $this->assertTrue( (bool)$user->can( 'whatever', $object_type, GP::$validator_permission->object_id( $root->id, 'bg', 'default' ) ) );
+                $this->assertTrue( (bool)$user->can( 'whatever', $object_type, GP::$validator_permission->object_id( $sub->id, 'bg', 'default' ) ) );
+                $this->assertTrue( (bool)$user->can( 'whatever', $object_type, GP::$validator_permission->object_id( $sub->id, 'bg', 'default' ) ) );
</ins><span class="cx">                 $this->assertFalse( (bool)$user->can( 'other', $object_type, $sub->id.'|bg|default' ) );
</span><span class="cx">                 $this->assertFalse( (bool)$user->can( 'whatever', $object_type, $sub->id.'|en|default' ) );
</span><span class="cx">                 $this->assertFalse( (bool)$user->can( 'whatever', $object_type, $sub->id.'|bg|slug' ) );
</span><span class="lines">@@ -61,8 +63,8 @@
</span><span class="cx">                 $root = GP::$project->create( array( 'name' => 'Root', 'slug' => 'root', 'path' => 'root') );
</span><span class="cx">                 $sub = GP::$project->create( array( 'name' => 'Sub', 'slug' => 'sub', 'parent_project_id' => $root->id, 'path' => 'root/sub' ) );
</span><span class="cx">
</span><del>-                GP::$permission->create( array( 'user_id' => $user->id, 'action' => 'approve',
-                        'object_type' => 'project|locale|set-slug', 'object_id' => $root->id.'|bg|default' ) );
</del><ins>+                GP::$validator_permission->create( array( 'user_id' => $user->id, 'action' => 'approve',
+                        'project_id' => $root->id, 'locale_slug' => 'bg', 'set_slug' => 'default' ) );
</ins><span class="cx">                 
</span><span class="cx">                 $set_root_bg = GP::$translation_set->create( array( 'name' => 'Set', 'slug' => 'default', 'project_id' => $root->id, 'locale' => 'bg') );
</span><span class="cx">                 $set_sub_bg = GP::$translation_set->create( array( 'name' => 'Set', 'slug' => 'default', 'project_id' => $sub->id, 'locale' => 'bg') );
</span></span></pre>
</div>
</div>
</body>
</html>