/**
  * Prepare security- and filter-based restrictions.
  * @access private
  */
 protected function _prepare_restrictions()
 {
     parent::_prepare_restrictions();
     if (!$this->_returns_no_data()) {
         include_once 'webcore/db/query_security.php';
         $restriction = new QUERY_SECURITY_RESTRICTION($this, $this->_user);
         $sql = $restriction->as_sql(array(Privilege_set_folder, Privilege_set_entry, $this->_privilege_set));
         if (!$sql) {
             $this->_set_returns_no_data();
         } else {
             $this->_calculated_restrictions[] = $sql;
         }
     }
 }
 /**
  * Prepare security- and filter-based restrictions.
  * @access private
  */
 protected function _prepare_restrictions()
 {
     parent::_prepare_restrictions();
     if (!$this->_returns_no_data()) {
         $p = $this->_user->permissions();
         $vis = $p->value_for(Privilege_set_folder, Privilege_view);
         $invis = $p->value_for(Privilege_set_folder, Privilege_view_hidden);
         /* The all-denied case is already checked in OBJECT_IN_FOLDER_QUERY. */
         if ($vis == Privilege_always_granted) {
             // all visible folders are returned, regardless of folder permissions
             $join_type = "LEFT";
             // All folders are returned, filtered by user request
             if ($invis == Privilege_always_granted) {
                 if ($this->_filter != All) {
                     $usable = "fldr.state & {$this->_filter} = fldr.state";
                 } else {
                     $usable = '1';
                 }
             } else {
                 if ($invis == Privilege_always_denied) {
                     // all visible folders are returned, regardless of folder permissions
                     // all invisible folders are blocked, regardless of folder permissions
                     $usable = "fldr.state & " . ($this->_filter & ~Invisible) . " = fldr.state";
                     // Disallow any invisible folders
                 } else {
                     // Return all visible folders and only invisible folders with folder-level permissions
                     if ($this->_filter & Visible) {
                         if ($this->_filter & Invisible) {
                             $usable = "((fldr.state & " . Visible . ")" . " OR ((fldr.state & " . Invisible . ") AND (perm.folder_permissions & " . Privilege_view_hidden . ")))" . " AND (fldr.state & {$this->_filter} = fldr.state)";
                         } else {
                             $usable = "(fldr.state & {$this->_filter})";
                         }
                     } else {
                         if ($this->_filter & Invisible) {
                             $usable = "((fldr.state & {$this->_filter} = fldr.state) AND (perm.folder_permissions & " . Privilege_view_hidden . "))";
                         } else {
                             $this->raise('Unreachable state (logic error)', '_prepare_restrictions', 'USER_FOLDER_QUERY');
                         }
                     }
                 }
             }
         } else {
             // only those folders for which folder permissions allow this user are returned
             $join_type = "INNER";
             if ($invis == Privilege_always_denied) {
                 // no invisible folders are returned, regardless of folder permissions
                 $usable = "(fldr.state & " . ($this->_filter & ~Invisible) . " = fldr.state) AND (perm.folder_permissions & " . Privilege_view . ")";
             } else {
                 if ($invis == Privilege_always_granted) {
                     // all folder-granted visible folders and all invisible folders, regardless
                     // of whether invisible is granted (view_folder is sufficient)
                     $usable = "(perm.folder_permissions & " . Privilege_view . ") AND (fldr.state & {$this->_filter} = fldr.state)";
                 } else {
                     // no user-rights case: all visible folders with view_folder permissions
                 }
                 if ($this->_filter & Visible) {
                     if ($this->_filter & Invisible) {
                         $usable = "(perm.folder_permissions & " . Privilege_view . ") AND ((fldr.state & " . Visible . ")" . " OR ((fldr.state & " . Invisible . ") AND (perm.folder_permissions & " . Privilege_view_hidden . ")))" . " AND (fldr.state & {$this->_filter} = fldr.state)";
                     } else {
                         $usable = "(perm.folder_permissions & " . Privilege_view . ") AND (fldr.state & {$this->_filter} = fldr.state)";
                     }
                 } else {
                     if ($this->_filter & Invisible) {
                         $usable = "(perm.folder_permissions & " . Privilege_view . ") AND (perm.folder_permissions & " . Privilege_view_hidden . ") AND (fldr.state & {$this->_filter} = fldr.state)";
                     } else {
                         $this->raise('Unreachable state (logic error)', '_prepare_restrictions', 'USER_FOLDER_QUERY');
                     }
                 }
             }
         }
         if (!$this->_returns_no_data()) {
             $this->add_select("({$usable}) AS usable");
             $this->_usable_restriction = $usable;
             $this->_tables = "{$this->app->table_names->folders} fldr" . " {$join_type} JOIN {$this->app->table_names->folder_permissions} perm ON perm.folder_id = fldr.permissions_id" . " LEFT JOIN {$this->app->table_names->groups} grp on perm.ref_id = grp.id" . " LEFT JOIN {$this->app->table_names->users_to_groups} utg ON utg.group_id = grp.id";
             if ($this->_num_records) {
                 // this query is special and can't use the LIMIT function
                 // so record the number of records elsewhere. The record
                 // count will be limited with '_is_valid_object'
                 $this->_num_folders = $this->_num_records;
                 $this->_first_folder = $this->_first_record;
                 $this->_num_records = 0;
             }
             if ($this->_user->is_anonymous()) {
                 $global_type = Privilege_kind_anonymous;
             } else {
                 $global_type = Privilege_kind_registered;
             }
             $user_id = $this->_user->id;
             $this->_calculated_restrictions[] = "(perm.kind = '{$global_type}')" . " OR ((perm.kind = '" . Privilege_kind_user . "') AND (perm.ref_id = {$user_id}))" . " OR ((perm.kind = '" . Privilege_kind_group . "') AND (perm.ref_id = grp.id) AND (utg.user_id = {$user_id}))";
         }
     }
 }