Check whether a user has access to view discussions in a particular category.

@since 2.0.18
@example $UserModel->GetCategoryViewPermission($UserID, $CategoryID).

@param $Sender UserModel.
@return bool Whether user has permission.
485494
public function UserModel_GetCategoryViewPermission_Create($Sender) {
      static $PermissionModel = NULL;


      $UserID = ArrayValue(0, $Sender->EventArguments, '');
		$CategoryID = ArrayValue(1, $Sender->EventArguments, '');
      $Permission = GetValue(2, $Sender->EventArguments, 'Vanilla.Discussions.View');
		if ($UserID && $CategoryID) {
         if ($PermissionModel === NULL)
            $PermissionModel = new PermissionModel();
         
         $Category = CategoryModel::Categories($CategoryID);
         if ($Category)
            $PermissionCategoryID = $Category['PermissionCategoryID'];
         else
            $PermissionCategoryID = -1;
         
         $Result = $PermissionModel->GetUserPermissions($UserID, $Permission, 'Category', 'PermissionCategoryID', 'CategoryID', $PermissionCategoryID);
         return (GetValue($Permission, GetValue(0, $Result), FALSE)) ? TRUE : FALSE;
      }
      return FALSE;
   }
766879
public function can_view_post(stdClass $user, discussion_entity $discussion, post_entity $post) : bool {
        if (!$this->can_view_post_shell($user, $post)) {
            return false;
        }

        $forum = $this->get_forum();
        $forumrecord = $this->get_forum_record();
        $discussionrecord = $this->get_discussion_record($discussion);
        $postrecord = $this->get_post_record($post);
        $coursemodule = $forum->get_course_module_record();
        return forum_user_can_see_post($forumrecord, $discussionrecord, $postrecord, $user, $coursemodule, false);
    }
531218
public function hasPermission($recipient, $permission)
    {

        if ($recipient instanceof Group) {
            $check = true;
            foreach ($recipient->getLogins() as $login) {
                if ($this->hasLoginPermission($login, $permission) === false) {
                    $check = false;
                }
            }

            return $check;
        } else {
            return $this->hasLoginPermission($recipient, $permission);
        }
    }
376810
public function check_permissions() {
        $context = context_module::instance($this->cm->id);
        return has_capability('mod/glossary:exportentry', $context)
            || ($this->entry->userid == $this->user->id && has_capability('mod/glossary:exportownentry', $context));
    }
716255
public function access($permission, $user_id = null)
    {
        if ($this->isSuperadmin($user_id)) {
            return true;
        }

        if ($permission === GC_PERM_SUPERADMIN) {
            return false;
        }

        return in_array($permission, $this->getPermissions($user_id));
    }
716741
protected function canAccess()
    {
        if ($this->formRequest->user()->isAdmin() || $this->formRequest->user()->isUser()) {
            return true;
        }

        return $this->formRequest->user()->canDo('message.message.view');
    }
540884
public function DiscussionController_InsideCommentMeta_Handler($Sender, $Args) {      
      // Signed in users only. No guest reporting!
      if (Gdn::Session()->UserID)
         $this->AddFlagButton($Sender, $Args);
   }
1223696
public function CategoriesController_Render_Before($Sender) {      
      $Sender->ShowOptions = FALSE;
      SaveToConfig('Vanilla.AdminCheckboxes.Use', FALSE, FALSE);
      $this->AddButton($Sender, 'Discussion');
      $this->DiscussionsClickable($Sender);      
   }
84934
public function inherit($requester, $controlled, $perms = "*") {
		$permission = $this->_classes['permission'];
		return $permission::allow($requester, $controlled, $perms, 0);
	}
482704
public function hasBlocked(Model $recipient): bool
    {
        return $this->getFriendship($recipient)->status === Status::BLOCKED;
    }
219204
public static function CategoryPermissions($Escape = FALSE) {
      if(is_null(self::$_CategoryPermissions)) {
         $Session = Gdn::Session();
         
         if((is_object($Session->User) && $Session->User->Admin)) {
            self::$_CategoryPermissions = TRUE;
			} elseif(C('Garden.Permissions.Disabled.Category')) {
				if($Session->CheckPermission('Vanilla.Discussions.View'))
					self::$_CategoryPermissions = TRUE;
				else
					self::$_CategoryPermissions = array(); // no permission
         } else {
            $SQL = Gdn::SQL();
            
            $Categories = CategoryModel::Categories();
            $IDs = array();
            
            foreach ($Categories as $ID => $Category) {
               if ($Category['PermsDiscussionsView']) {
                  $IDs[] = $ID;
               }
            }

            // Check to see if the user has permission to all categories. This is for speed.
            $CategoryCount = count($Categories);
            
            if (count($IDs) == $CategoryCount)
               self::$_CategoryPermissions = TRUE;
            else {
               self::$_CategoryPermissions = array();
               foreach($IDs as $ID) {
                  self::$_CategoryPermissions[] = ($Escape ? '@' : '').$ID;
               }
            }
         }
      }
      
      return self::$_CategoryPermissions;
   }
1066164
public function hasBlockedBeingFollowedBy(Model $sender)
    {
        return $this->followers()->whereFollowedBy($sender)->whereStatus(Status::BLOCKED)->exists();
    }
1012661
protected static function can_contact_user(int $recipientid, int $senderid) : bool {
        if (has_capability('moodle/site:messageanyuser', \context_system::instance(), $senderid) ||
            $recipientid == $senderid) {
            // The sender has the ability to contact any user across the entire site or themselves.
            return true;
        }

        // The initial value of $cancontact is null to indicate that a value has not been determined.
        $cancontact = null;

        if (self::is_blocked($recipientid, $senderid)) {
            // The recipient has specifically blocked this sender.
            $cancontact = false;
        }

        $sharedcourses = null;
        if (null === $cancontact) {
            // There are three user preference options:
            // - Site: Allow anyone not explicitly blocked to contact me;
            // - Course members: Allow anyone I am in a course with to contact me; and
            // - Contacts: Only allow my contacts to contact me.
            //
            // The Site option is only possible when the messagingallusers site setting is also enabled.

            $privacypreference = self::get_user_privacy_messaging_preference($recipientid);
            if (self::MESSAGE_PRIVACY_SITE === $privacypreference) {
                // The user preference is to allow any user to contact them.
                // No need to check anything else.
                $cancontact = true;
            } else {
                // This user only allows their own contacts, and possibly course peers, to contact them.
                // If the users are contacts then we can avoid the more expensive shared courses check.
                $cancontact = self::is_contact($senderid, $recipientid);

                if (!$cancontact && self::MESSAGE_PRIVACY_COURSEMEMBER === $privacypreference) {
                    // The users are not contacts and the user allows course member messaging.
                    // Check whether these two users share any course together.
                    $sharedcourses = enrol_get_shared_courses($recipientid, $senderid, true);
                    $cancontact = (!empty($sharedcourses));
                }
            }
        }

        if (false === $cancontact) {
            // At the moment the users cannot contact one another.
            // Check whether the messageanyuser capability applies in any of the shared courses.
            // This is intended to allow teachers to message students regardless of message settings.

            // Note: You cannot use empty($sharedcourses) here because this may be an empty array.
            if (null === $sharedcourses) {
                $sharedcourses = enrol_get_shared_courses($recipientid, $senderid, true);
            }

            foreach ($sharedcourses as $course) {
                // Note: enrol_get_shared_courses will preload any shared context.
                if (has_capability('moodle/site:messageanyuser', \context_course::instance($course->id), $senderid)) {
                    $cancontact = true;
                    break;
                }
            }
        }

        return $cancontact;
    }
102635
public function grantAccess($roleOrPermission, UserInterface $user = null)
    {
        $user = $user ? : $this->currentUser();

        if (is_array($roleOrPermission) && $this->grantAccessByRoles($roleOrPermission, $user)) {
            return true;
        } else if (is_array($roleOrPermission) && $this->grantAccessByPermissions($roleOrPermission, $user)) {
            return true;
        } else if ($this->grantAccessByRole($roleOrPermission, $user)) {
            return true;
        } else if ($this->grantAccessByPermission($roleOrPermission, $user)) {
            return true;
        }

        return false;
    }
726314
protected function voteForUser(UserInterface $subject, UserInterface $user)
    {
        foreach ($subject->getGroups() as $group) {
            if (!$group->isDeleted() && $this->canActOnSite($group->getSite()->getSiteId(), $user)) {
                return true;
            }
        }

        return false;
    }
1089997
public function ProfileController_Discussions_Create($Sender, $UserReference = '', $Username = '', $Page = '', $UserID = '') {
		$Sender->EditMode(FALSE);
		
      // Tell the ProfileController what tab to load
		$Sender->GetUserInfo($UserReference, $Username, $UserID);
      $Sender->_SetBreadcrumbs(T('Discussions'), UserUrl($Sender->User, '', 'discussions'));
      $Sender->SetTabView('Discussions', 'Profile', 'Discussions', 'Vanilla');
		$Sender->CountCommentsPerPage = C('Vanilla.Comments.PerPage', 30);
      
      list($Offset, $Limit) = OffsetLimit($Page, Gdn::Config('Vanilla.Discussions.PerPage', 30));
      
      $DiscussionModel = new DiscussionModel();
      $Discussions = $DiscussionModel->GetByUser($Sender->User->UserID, $Limit, $Offset);
      $CountDiscussions = $Offset + $DiscussionModel->LastDiscussionCount + 1;
      $Sender->DiscussionData = $Sender->SetData('Discussions', $Discussions);
      
      // Build a pager
      $PagerFactory = new Gdn_PagerFactory();
      $Sender->Pager = $PagerFactory->GetPager('MorePager', $Sender);
      $Sender->Pager->MoreCode = 'More Discussions';
      $Sender->Pager->LessCode = 'Newer Discussions';
      $Sender->Pager->ClientID = 'Pager';
      $Sender->Pager->Configure(
         $Offset,
         $Limit,
         $CountDiscussions,
         UserUrl($Sender->User, '', 'discussions').'?page={Page}'
      );
      
      // Deliver JSON data if necessary
      if ($Sender->DeliveryType() != DELIVERY_TYPE_ALL && $Offset > 0) {
         $Sender->SetJson('LessRow', $Sender->Pager->ToString('less'));
         $Sender->SetJson('MoreRow', $Sender->Pager->ToString('more'));
         $Sender->View = 'discussions';
      }
      
      // Set the HandlerType back to normal on the profilecontroller so that it fetches it's own views
      $Sender->HandlerType = HANDLER_TYPE_NORMAL;
      
      // Do not show discussion options
      $Sender->ShowOptions = FALSE;
      
      if ($Sender->Head) {
         // These pages offer only duplicate content to search engines and are a bit slow.
         $Sender->Head->AddTag('meta', array('name' => 'robots', 'content' => 'noindex,noarchive'));
      }
      
      // Render the ProfileController
      $Sender->Render();
   }
313585
public function canBrowse()
    {
        $viewer = get_viewer();

        if ($viewer->admin() || $viewer->eql($this->actor)) {
            return true;
        }

        return false;
    }