22declare(strict_types=1);
32use
function spl_object_id;
47 private array $rootPermissions;
50 private array $attachments = [];
53 private array $permissions = [];
59 private ObjectSet $permissionRecalculationCallbacks;
66 $this->permissionRecalculationCallbacks =
new ObjectSet();
68 $this->rootPermissions = $basePermissions;
74 $name = $name->getName();
76 $this->rootPermissions[$name] = $grant;
81 unset($this->rootPermissions[$name instanceof
Permission ? $name->getName() : $name]);
82 $this->recalculatePermissions();
86 return isset($this->permissions[$name instanceof
Permission ? $name->getName() : $name]);
91 $name = $name->getName();
94 if($this->isPermissionSet($name)){
95 return $this->permissions[$name]->getValue();
105 if(!$plugin->isEnabled()){
106 throw new PluginException(
"Plugin " . $plugin->getDescription()->getName() .
" is disabled");
110 $this->attachments[spl_object_id($result)] = $result;
111 if($name !==
null && $value !==
null){
112 $result->setPermission($name, $value);
115 $result->subscribePermissible($this);
117 $this->recalculatePermissions();
122 public function removeAttachment(PermissionAttachment $attachment) : void{
123 if(isset($this->attachments[spl_object_id($attachment)])){
124 unset($this->attachments[spl_object_id($attachment)]);
125 $attachment->unsubscribePermissible($this);
127 $this->recalculatePermissions();
134 Timings::$permissibleCalculation->startTiming();
136 $permManager = PermissionManager::getInstance();
137 $permManager->unsubscribeFromAllPermissions($this);
138 $oldPermissions = $this->permissions;
139 $this->permissions = [];
141 foreach(Utils::stringifyKeys($this->rootPermissions) as $name => $isGranted){
142 $perm = $permManager->getPermission($name);
144 throw new \LogicException(
"Unregistered root permission $name");
147 $permManager->subscribeToPermission($name, $this);
148 $this->calculateChildPermissions($perm->getChildren(), !$isGranted,
null, $this->permissions[$name]);
151 foreach($this->attachments as $attachment){
152 $this->calculateChildPermissions($attachment->getPermissions(),
false, $attachment,
null);
156 Timings::$permissibleCalculationDiff->time(
function() use ($oldPermissions, &$diff) :
void{
157 foreach($this->permissions as $permissionAttachmentInfo){
158 $name = $permissionAttachmentInfo->getPermission();
159 if(!isset($oldPermissions[$name])){
160 $diff[$name] =
false;
161 }elseif($oldPermissions[$name]->getValue() !== $permissionAttachmentInfo->getValue()){
164 unset($oldPermissions[$name]);
167 foreach($oldPermissions as $permissionAttachmentInfo){
168 $diff[$permissionAttachmentInfo->getPermission()] = $permissionAttachmentInfo->getValue();
172 Timings::$permissibleCalculationCallback->time(
function() use ($diff) : void{
173 if(count($diff) > 0){
174 foreach($this->permissionRecalculationCallbacks as $closure){
180 Timings::$permissibleCalculation->stopTiming();
188 private function calculateChildPermissions(array $children,
bool $invert, ?PermissionAttachment $attachment, ?PermissionAttachmentInfo $parent) : void{
189 $permManager = PermissionManager::getInstance();
190 foreach(Utils::stringifyKeys($children) as $name => $v){
191 $perm = $permManager->getPermission($name);
192 $value = ($v xor $invert);
193 $this->permissions[$name] =
new PermissionAttachmentInfo($name, $attachment, $value, $parent);
194 $permManager->subscribeToPermission($name, $this);
196 if($perm instanceof Permission){
197 $this->calculateChildPermissions($perm->getChildren(), !$value, $attachment, $this->permissions[$name]);
212 return $this->permissions;
215 public function destroyCycles() : void{
217 $this->permissions = [];
218 foreach($this->attachments as $attachment){
219 $attachment->unsubscribePermissible($this);
221 $this->attachments = [];
222 $this->permissionRecalculationCallbacks->clear();
getPermissionRecalculationCallbacks()
isPermissionSet(Permission|string $name)
addAttachment(Plugin $plugin, ?string $name=null, ?bool $value=null)
unsetBasePermission(Permission|string $name)
getEffectivePermissions()
hasPermission(Permission|string $name)
__construct(array $basePermissions)
setBasePermission(Permission|string $name, bool $grant)