template) $this->template = $this->getPredefinedTemplate(); if(!$this->_parent) $this->setParent($this->getPredefinedParent()); } /** * Get predefined template (template method) * * @return Template * */ protected function getPredefinedTemplate() { return $this->wire()->templates->get('role'); } /** * Get predefined parent page (template method) * * @return Page * */ protected function getPredefinedParent() { return $this->wire()->pages->get($this->wire()->config->rolesPageID); } /** * Does this role have the given permission name, id or object? * * @param string|int|Permission $permission Permission object, name, or id. * @param Page|Template|null $context Optional Page or Template context. * @return bool * @see User::hasPermission() * */ public function hasPermission($permission, $context = null) { $name = $permission; $permission = null; $has = false; if(empty($name)) { // do nothing return false; } else if($name instanceof Page) { $permission = $name; $has = $this->permissions->has($permission); } else if(ctype_digit("$name")) { $name = (int) $name; foreach($this->permissions as $p) { if(((int) $p->id) === $name) { $permission = $p; $has = true; break; } } } else if($name === 'page-add' || $name === 'page-create') { // runtime permissions that don't have associated permission pages if(empty($context)) return false; /** @var Permission $permission */ $permission = $this->wire(new Permission()); $permission->name = $name; } else if(is_string($name)) { $permissions = $this->wire()->permissions; // all permissions if(!$permissions->has($name)) { if(!ctype_alnum(str_replace('-', '', $name))) { $name = $this->wire()->sanitizer->pageName($name); } if($context) { $method = $permissions->getDelegatedMethod($name, $context); if($method) { // non-installed permission delegates to a method call such as $page->editable() return $context->$method(); } } $delegated = $permissions->getDelegatedPermissions(); if(isset($delegated[$name])) $name = $delegated[$name]; } foreach($this->permissions as $p) { if($p->name === $name) { $permission = $p; $has = true; break; } } } if($context instanceof Page || $context instanceof Template) { if(!$permission) $permission = $this->wire()->permissions->get($name); if($permission) { $has = $this->hasPermissionContext($has, $permission, $context); } } return $has; } /** * Return whether the role has the permission within the context of a Page or Template * * @param bool $has Result from the hasPermission() method * @param Permission $permission Permission to check * @param Wire $context Must be a Template or Page * @return bool * */ protected function hasPermissionContext($has, Permission $permission, Wire $context) { if(strpos($permission->name, 'page-') !== 0) return $has; $type = str_replace('page-', '', $permission->name); if(!in_array($type, array('view', 'edit', 'add', 'create'))) $type = 'edit'; $accessTemplate = $context instanceof Page ? $context->getAccessTemplate($type) : $context; if(!$accessTemplate) return false; if(!$accessTemplate->useRoles) return $has; if($permission->name === 'page-view') { if(!$has) return false; $has = $accessTemplate->hasRole($this); return $has; } if($permission->name === 'page-edit' && !$has) return false; switch($permission->name) { case 'page-edit': $has = in_array($this->id, $accessTemplate->editRoles); break; case 'page-create': $has = in_array($this->id, $accessTemplate->createRoles); break; case 'page-add': $has = in_array($this->id, $accessTemplate->addRoles); break; default: // some other page-* permission $rolesPermissions = $accessTemplate->rolesPermissions; if(!isset($rolesPermissions["$this->id"])) return $has; foreach($rolesPermissions["$this->id"] as $permissionID) { $revoke = strpos($permissionID, '-') === 0; if($revoke) $permissionID = ltrim($permissionID, '-'); $permissionID = (int) $permissionID; if($permission->id != $permissionID) continue; if($has) { if($revoke) $has = false; } else { if(!$revoke) $has = true; } break; } } return $has; } /** * Add the given Permission string, id or object. * * This is the same as `$role->permissions->add($permission)` except this one will accept ID or name. * * @param string|int|Permission $permission Permission object, name or id. * @return bool Returns false if permission not recognized, true otherwise * */ public function addPermission($permission) { if(is_string($permission) || is_int($permission)) { $permission = $this->wire()->permissions->get($permission); } if($permission instanceof Permission) { $this->permissions->add($permission); return true; } return false; } /** * Remove the given permission string, id or object. * * This is the same as `$role->permissions->remove($permission)` except this one will accept ID or name. * * @param string|int|Permission $permission Permission object, name or id. * @return bool false if permission not recognized, true otherwise * */ public function removePermission($permission) { if(is_string($permission) || is_int($permission)) { $permission = $this->wire()->permissions->get($permission); } if($permission instanceof Permission) { $this->permissions->remove($permission); return true; } return false; } /** * Return the API variable used for managing pages of this type * * #pw-internal * * @return Roles * */ public function getPagesManager() { return $this->wire()->roles; } }