Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
      • Traits
    • Reflection
    • Security
    • Tokenizer
    • Utils
  • Tracy
    • Bridges
      • Nette
  • none

Classes

  • Identity
  • Passwords
  • Permission
  • SimpleAuthenticator
  • User

Interfaces

  • IAuthenticator
  • IAuthorizator
  • IIdentity
  • IResource
  • IRole
  • IUserStorage

Exceptions

  • AuthenticationException
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://nette.org)
  5:  * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  6:  */
  7: 
  8: namespace Nette\Security;
  9: 
 10: use Nette;
 11: 
 12: 
 13: /**
 14:  * Access control list (ACL) functionality and privileges management.
 15:  *
 16:  * This solution is mostly based on Zend_Acl (c) Zend Technologies USA Inc. (http://www.zend.com), new BSD license
 17:  *
 18:  * @copyright  Copyright (c) 2005, 2007 Zend Technologies USA Inc.
 19:  */
 20: class Permission implements IAuthorizator
 21: {
 22:     use Nette\SmartObject;
 23: 
 24:     /** @var array  Role storage */
 25:     private $roles = [];
 26: 
 27:     /** @var array  Resource storage */
 28:     private $resources = [];
 29: 
 30:     /** @var array  Access Control List rules; whitelist (deny everything to all) by default */
 31:     private $rules = [
 32:         'allResources' => [
 33:             'allRoles' => [
 34:                 'allPrivileges' => [
 35:                     'type' => self::DENY,
 36:                     'assert' => null,
 37:                 ],
 38:                 'byPrivilege' => [],
 39:             ],
 40:             'byRole' => [],
 41:         ],
 42:         'byResource' => [],
 43:     ];
 44: 
 45:     /** @var mixed */
 46:     private $queriedRole;
 47: 
 48:     private $queriedResource;
 49: 
 50: 
 51:     /********************* roles ****************d*g**/
 52: 
 53: 
 54:     /**
 55:      * Adds a Role to the list. The most recently added parent
 56:      * takes precedence over parents that were previously added.
 57:      * @param  string
 58:      * @param  string|array
 59:      * @throws Nette\InvalidArgumentException
 60:      * @throws Nette\InvalidStateException
 61:      * @return static
 62:      */
 63:     public function addRole($role, $parents = null)
 64:     {
 65:         $this->checkRole($role, false);
 66:         if (isset($this->roles[$role])) {
 67:             throw new Nette\InvalidStateException("Role '$role' already exists in the list.");
 68:         }
 69: 
 70:         $roleParents = [];
 71: 
 72:         if ($parents !== null) {
 73:             if (!is_array($parents)) {
 74:                 $parents = [$parents];
 75:             }
 76: 
 77:             foreach ($parents as $parent) {
 78:                 $this->checkRole($parent);
 79:                 $roleParents[$parent] = true;
 80:                 $this->roles[$parent]['children'][$role] = true;
 81:             }
 82:         }
 83: 
 84:         $this->roles[$role] = [
 85:             'parents' => $roleParents,
 86:             'children' => [],
 87:         ];
 88: 
 89:         return $this;
 90:     }
 91: 
 92: 
 93:     /**
 94:      * Returns true if the Role exists in the list.
 95:      * @param  string
 96:      * @return bool
 97:      */
 98:     public function hasRole($role)
 99:     {
100:         $this->checkRole($role, false);
101:         return isset($this->roles[$role]);
102:     }
103: 
104: 
105:     /**
106:      * Checks whether Role is valid and exists in the list.
107:      * @param  string
108:      * @param  bool
109:      * @throws Nette\InvalidStateException
110:      * @return void
111:      */
112:     private function checkRole($role, $throw = true)
113:     {
114:         if (!is_string($role) || $role === '') {
115:             throw new Nette\InvalidArgumentException('Role must be a non-empty string.');
116: 
117:         } elseif ($throw && !isset($this->roles[$role])) {
118:             throw new Nette\InvalidStateException("Role '$role' does not exist.");
119:         }
120:     }
121: 
122: 
123:     /**
124:      * Returns all Roles.
125:      * @return array
126:      */
127:     public function getRoles()
128:     {
129:         return array_keys($this->roles);
130:     }
131: 
132: 
133:     /**
134:      * Returns existing Role's parents ordered by ascending priority.
135:      * @param  string
136:      * @return array
137:      */
138:     public function getRoleParents($role)
139:     {
140:         $this->checkRole($role);
141:         return array_keys($this->roles[$role]['parents']);
142:     }
143: 
144: 
145:     /**
146:      * Returns true if $role inherits from $inherit. If $onlyParents is true,
147:      * then $role must inherit directly from $inherit.
148:      * @param  string
149:      * @param  string
150:      * @param  bool
151:      * @throws Nette\InvalidStateException
152:      * @return bool
153:      */
154:     public function roleInheritsFrom($role, $inherit, $onlyParents = false)
155:     {
156:         $this->checkRole($role);
157:         $this->checkRole($inherit);
158: 
159:         $inherits = isset($this->roles[$role]['parents'][$inherit]);
160: 
161:         if ($inherits || $onlyParents) {
162:             return $inherits;
163:         }
164: 
165:         foreach ($this->roles[$role]['parents'] as $parent => $foo) {
166:             if ($this->roleInheritsFrom($parent, $inherit)) {
167:                 return true;
168:             }
169:         }
170: 
171:         return false;
172:     }
173: 
174: 
175:     /**
176:      * Removes the Role from the list.
177:      *
178:      * @param  string
179:      * @throws Nette\InvalidStateException
180:      * @return static
181:      */
182:     public function removeRole($role)
183:     {
184:         $this->checkRole($role);
185: 
186:         foreach ($this->roles[$role]['children'] as $child => $foo) {
187:             unset($this->roles[$child]['parents'][$role]);
188:         }
189: 
190:         foreach ($this->roles[$role]['parents'] as $parent => $foo) {
191:             unset($this->roles[$parent]['children'][$role]);
192:         }
193: 
194:         unset($this->roles[$role]);
195: 
196:         foreach ($this->rules['allResources']['byRole'] as $roleCurrent => $rules) {
197:             if ($role === $roleCurrent) {
198:                 unset($this->rules['allResources']['byRole'][$roleCurrent]);
199:             }
200:         }
201: 
202:         foreach ($this->rules['byResource'] as $resourceCurrent => $visitor) {
203:             if (isset($visitor['byRole'])) {
204:                 foreach ($visitor['byRole'] as $roleCurrent => $rules) {
205:                     if ($role === $roleCurrent) {
206:                         unset($this->rules['byResource'][$resourceCurrent]['byRole'][$roleCurrent]);
207:                     }
208:                 }
209:             }
210:         }
211: 
212:         return $this;
213:     }
214: 
215: 
216:     /**
217:      * Removes all Roles from the list.
218:      *
219:      * @return static
220:      */
221:     public function removeAllRoles()
222:     {
223:         $this->roles = [];
224: 
225:         foreach ($this->rules['allResources']['byRole'] as $roleCurrent => $rules) {
226:             unset($this->rules['allResources']['byRole'][$roleCurrent]);
227:         }
228: 
229:         foreach ($this->rules['byResource'] as $resourceCurrent => $visitor) {
230:             foreach ($visitor['byRole'] as $roleCurrent => $rules) {
231:                 unset($this->rules['byResource'][$resourceCurrent]['byRole'][$roleCurrent]);
232:             }
233:         }
234: 
235:         return $this;
236:     }
237: 
238: 
239:     /********************* resources ****************d*g**/
240: 
241: 
242:     /**
243:      * Adds a Resource having an identifier unique to the list.
244:      *
245:      * @param  string
246:      * @param  string
247:      * @throws Nette\InvalidArgumentException
248:      * @throws Nette\InvalidStateException
249:      * @return static
250:      */
251:     public function addResource($resource, $parent = null)
252:     {
253:         $this->checkResource($resource, false);
254: 
255:         if (isset($this->resources[$resource])) {
256:             throw new Nette\InvalidStateException("Resource '$resource' already exists in the list.");
257:         }
258: 
259:         if ($parent !== null) {
260:             $this->checkResource($parent);
261:             $this->resources[$parent]['children'][$resource] = true;
262:         }
263: 
264:         $this->resources[$resource] = [
265:             'parent' => $parent,
266:             'children' => [],
267:         ];
268: 
269:         return $this;
270:     }
271: 
272: 
273:     /**
274:      * Returns true if the Resource exists in the list.
275:      * @param  string
276:      * @return bool
277:      */
278:     public function hasResource($resource)
279:     {
280:         $this->checkResource($resource, false);
281:         return isset($this->resources[$resource]);
282:     }
283: 
284: 
285:     /**
286:      * Checks whether Resource is valid and exists in the list.
287:      * @param  string
288:      * @param  bool
289:      * @throws Nette\InvalidStateException
290:      * @return void
291:      */
292:     private function checkResource($resource, $throw = true)
293:     {
294:         if (!is_string($resource) || $resource === '') {
295:             throw new Nette\InvalidArgumentException('Resource must be a non-empty string.');
296: 
297:         } elseif ($throw && !isset($this->resources[$resource])) {
298:             throw new Nette\InvalidStateException("Resource '$resource' does not exist.");
299:         }
300:     }
301: 
302: 
303:     /**
304:      * Returns all Resources.
305:      * @return array
306:      */
307:     public function getResources()
308:     {
309:         return array_keys($this->resources);
310:     }
311: 
312: 
313:     /**
314:      * Returns true if $resource inherits from $inherit. If $onlyParents is true,
315:      * then $resource must inherit directly from $inherit.
316:      *
317:      * @param  string
318:      * @param  string
319:      * @param  bool
320:      * @throws Nette\InvalidStateException
321:      * @return bool
322:      */
323:     public function resourceInheritsFrom($resource, $inherit, $onlyParent = false)
324:     {
325:         $this->checkResource($resource);
326:         $this->checkResource($inherit);
327: 
328:         if ($this->resources[$resource]['parent'] === null) {
329:             return false;
330:         }
331: 
332:         $parent = $this->resources[$resource]['parent'];
333:         if ($inherit === $parent) {
334:             return true;
335: 
336:         } elseif ($onlyParent) {
337:             return false;
338:         }
339: 
340:         while ($this->resources[$parent]['parent'] !== null) {
341:             $parent = $this->resources[$parent]['parent'];
342:             if ($inherit === $parent) {
343:                 return true;
344:             }
345:         }
346: 
347:         return false;
348:     }
349: 
350: 
351:     /**
352:      * Removes a Resource and all of its children.
353:      *
354:      * @param  string
355:      * @throws Nette\InvalidStateException
356:      * @return static
357:      */
358:     public function removeResource($resource)
359:     {
360:         $this->checkResource($resource);
361: 
362:         $parent = $this->resources[$resource]['parent'];
363:         if ($parent !== null) {
364:             unset($this->resources[$parent]['children'][$resource]);
365:         }
366: 
367:         $removed = [$resource];
368:         foreach ($this->resources[$resource]['children'] as $child => $foo) {
369:             $this->removeResource($child);
370:             $removed[] = $child;
371:         }
372: 
373:         foreach ($removed as $resourceRemoved) {
374:             foreach ($this->rules['byResource'] as $resourceCurrent => $rules) {
375:                 if ($resourceRemoved === $resourceCurrent) {
376:                     unset($this->rules['byResource'][$resourceCurrent]);
377:                 }
378:             }
379:         }
380: 
381:         unset($this->resources[$resource]);
382:         return $this;
383:     }
384: 
385: 
386:     /**
387:      * Removes all Resources.
388:      * @return static
389:      */
390:     public function removeAllResources()
391:     {
392:         foreach ($this->resources as $resource => $foo) {
393:             foreach ($this->rules['byResource'] as $resourceCurrent => $rules) {
394:                 if ($resource === $resourceCurrent) {
395:                     unset($this->rules['byResource'][$resourceCurrent]);
396:                 }
397:             }
398:         }
399: 
400:         $this->resources = [];
401:         return $this;
402:     }
403: 
404: 
405:     /********************* defining rules ****************d*g**/
406: 
407: 
408:     /**
409:      * Allows one or more Roles access to [certain $privileges upon] the specified Resource(s).
410:      * If $assertion is provided, then it must return true in order for rule to apply.
411:      *
412:      * @param  string|string[]|null
413:      * @param  string|string[]|null
414:      * @param  string|string[]|null
415:      * @param  callable    assertion
416:      * @return static
417:      */
418:     public function allow($roles = self::ALL, $resources = self::ALL, $privileges = self::ALL, $assertion = null)
419:     {
420:         $this->setRule(true, self::ALLOW, $roles, $resources, $privileges, $assertion);
421:         return $this;
422:     }
423: 
424: 
425:     /**
426:      * Denies one or more Roles access to [certain $privileges upon] the specified Resource(s).
427:      * If $assertion is provided, then it must return true in order for rule to apply.
428:      *
429:      * @param  string|string[]|null
430:      * @param  string|string[]|null
431:      * @param  string|string[]|null
432:      * @param  callable    assertion
433:      * @return static
434:      */
435:     public function deny($roles = self::ALL, $resources = self::ALL, $privileges = self::ALL, $assertion = null)
436:     {
437:         $this->setRule(true, self::DENY, $roles, $resources, $privileges, $assertion);
438:         return $this;
439:     }
440: 
441: 
442:     /**
443:      * Removes "allow" permissions from the list in the context of the given Roles, Resources, and privileges.
444:      *
445:      * @param  string|string[]|null
446:      * @param  string|string[]|null
447:      * @param  string|string[]|null
448:      * @return static
449:      */
450:     public function removeAllow($roles = self::ALL, $resources = self::ALL, $privileges = self::ALL)
451:     {
452:         $this->setRule(false, self::ALLOW, $roles, $resources, $privileges);
453:         return $this;
454:     }
455: 
456: 
457:     /**
458:      * Removes "deny" restrictions from the list in the context of the given Roles, Resources, and privileges.
459:      *
460:      * @param  string|string[]|null
461:      * @param  string|string[]|null
462:      * @param  string|string[]|null
463:      * @return static
464:      */
465:     public function removeDeny($roles = self::ALL, $resources = self::ALL, $privileges = self::ALL)
466:     {
467:         $this->setRule(false, self::DENY, $roles, $resources, $privileges);
468:         return $this;
469:     }
470: 
471: 
472:     /**
473:      * Performs operations on Access Control List rules.
474:      * @param  bool  operation add?
475:      * @param  bool  type
476:      * @param  string|string[]|null
477:      * @param  string|string[]|null
478:      * @param  string|string[]|null
479:      * @param  callable    assertion
480:      * @throws Nette\InvalidStateException
481:      * @return static
482:      */
483:     protected function setRule($toAdd, $type, $roles, $resources, $privileges, $assertion = null)
484:     {
485:         // ensure that all specified Roles exist; normalize input to array of Roles or null
486:         if ($roles === self::ALL) {
487:             $roles = [self::ALL];
488: 
489:         } else {
490:             if (!is_array($roles)) {
491:                 $roles = [$roles];
492:             }
493: 
494:             foreach ($roles as $role) {
495:                 $this->checkRole($role);
496:             }
497:         }
498: 
499:         // ensure that all specified Resources exist; normalize input to array of Resources or null
500:         if ($resources === self::ALL) {
501:             $resources = [self::ALL];
502: 
503:         } else {
504:             if (!is_array($resources)) {
505:                 $resources = [$resources];
506:             }
507: 
508:             foreach ($resources as $resource) {
509:                 $this->checkResource($resource);
510:             }
511:         }
512: 
513:         // normalize privileges to array
514:         if ($privileges === self::ALL) {
515:             $privileges = [];
516: 
517:         } elseif (!is_array($privileges)) {
518:             $privileges = [$privileges];
519:         }
520: 
521:         if ($toAdd) { // add to the rules
522:             foreach ($resources as $resource) {
523:                 foreach ($roles as $role) {
524:                     $rules = &$this->getRules($resource, $role, true);
525:                     if (count($privileges) === 0) {
526:                         $rules['allPrivileges']['type'] = $type;
527:                         $rules['allPrivileges']['assert'] = $assertion;
528:                         if (!isset($rules['byPrivilege'])) {
529:                             $rules['byPrivilege'] = [];
530:                         }
531:                     } else {
532:                         foreach ($privileges as $privilege) {
533:                             $rules['byPrivilege'][$privilege]['type'] = $type;
534:                             $rules['byPrivilege'][$privilege]['assert'] = $assertion;
535:                         }
536:                     }
537:                 }
538:             }
539: 
540:         } else { // remove from the rules
541:             foreach ($resources as $resource) {
542:                 foreach ($roles as $role) {
543:                     $rules = &$this->getRules($resource, $role);
544:                     if ($rules === null) {
545:                         continue;
546:                     }
547:                     if (count($privileges) === 0) {
548:                         if ($resource === self::ALL && $role === self::ALL) {
549:                             if ($type === $rules['allPrivileges']['type']) {
550:                                 $rules = [
551:                                     'allPrivileges' => [
552:                                         'type' => self::DENY,
553:                                         'assert' => null,
554:                                         ],
555:                                     'byPrivilege' => [],
556:                                 ];
557:                             }
558:                             continue;
559:                         }
560:                         if ($type === $rules['allPrivileges']['type']) {
561:                             unset($rules['allPrivileges']);
562:                         }
563:                     } else {
564:                         foreach ($privileges as $privilege) {
565:                             if (isset($rules['byPrivilege'][$privilege]) &&
566:                                 $type === $rules['byPrivilege'][$privilege]['type']
567:                             ) {
568:                                 unset($rules['byPrivilege'][$privilege]);
569:                             }
570:                         }
571:                     }
572:                 }
573:             }
574:         }
575:         return $this;
576:     }
577: 
578: 
579:     /********************* querying the ACL ****************d*g**/
580: 
581: 
582:     /**
583:      * Returns true if and only if the Role has access to [certain $privileges upon] the Resource.
584:      *
585:      * This method checks Role inheritance using a depth-first traversal of the Role list.
586:      * The highest priority parent (i.e., the parent most recently added) is checked first,
587:      * and its respective parents are checked similarly before the lower-priority parents of
588:      * the Role are checked.
589:      *
590:      * @param  string|null|IRole  $role
591:      * @param  string|null|IResource  $resource
592:      * @param  string|null  $privilege
593:      * @throws Nette\InvalidStateException
594:      * @return bool
595:      */
596:     public function isAllowed($role = self::ALL, $resource = self::ALL, $privilege = self::ALL)
597:     {
598:         $this->queriedRole = $role;
599:         if ($role !== self::ALL) {
600:             if ($role instanceof IRole) {
601:                 $role = $role->getRoleId();
602:             }
603:             $this->checkRole($role);
604:         }
605: 
606:         $this->queriedResource = $resource;
607:         if ($resource !== self::ALL) {
608:             if ($resource instanceof IResource) {
609:                 $resource = $resource->getResourceId();
610:             }
611:             $this->checkResource($resource);
612:         }
613: 
614:         do {
615:             // depth-first search on $role if it is not 'allRoles' pseudo-parent
616:             if ($role !== null && ($result = $this->searchRolePrivileges($privilege === self::ALL, $role, $resource, $privilege)) !== null) {
617:                 break;
618:             }
619: 
620:             if ($privilege === self::ALL) {
621:                 if ($rules = $this->getRules($resource, self::ALL)) { // look for rule on 'allRoles' psuedo-parent
622:                     foreach ($rules['byPrivilege'] as $privilege => $rule) {
623:                         if (($result = $this->getRuleType($resource, null, $privilege)) === self::DENY) {
624:                             break 2;
625:                         }
626:                     }
627:                     if (($result = $this->getRuleType($resource, null, null)) !== null) {
628:                         break;
629:                     }
630:                 }
631:             } else {
632:                 if (($result = $this->getRuleType($resource, null, $privilege)) !== null) { // look for rule on 'allRoles' pseudo-parent
633:                     break;
634: 
635:                 } elseif (($result = $this->getRuleType($resource, null, null)) !== null) {
636:                     break;
637:                 }
638:             }
639: 
640:             $resource = $this->resources[$resource]['parent']; // try next Resource
641:         } while (true);
642: 
643:         $this->queriedRole = $this->queriedResource = null;
644:         return $result;
645:     }
646: 
647: 
648:     /**
649:      * Returns real currently queried Role. Use by assertion.
650:      * @return mixed
651:      */
652:     public function getQueriedRole()
653:     {
654:         return $this->queriedRole;
655:     }
656: 
657: 
658:     /**
659:      * Returns real currently queried Resource. Use by assertion.
660:      * @return mixed
661:      */
662:     public function getQueriedResource()
663:     {
664:         return $this->queriedResource;
665:     }
666: 
667: 
668:     /********************* internals ****************d*g**/
669: 
670: 
671:     /**
672:      * Performs a depth-first search of the Role DAG, starting at $role, in order to find a rule
673:      * allowing/denying $role access to a/all $privilege upon $resource.
674:      * @param  bool  all (true) or one?
675:      * @param  string
676:      * @param  string
677:      * @param  string  only for one
678:      * @return mixed  null if no applicable rule is found, otherwise returns ALLOW or DENY
679:      */
680:     private function searchRolePrivileges($all, $role, $resource, $privilege)
681:     {
682:         $dfs = [
683:             'visited' => [],
684:             'stack' => [$role],
685:         ];
686: 
687:         while (($role = array_pop($dfs['stack'])) !== null) {
688:             if (isset($dfs['visited'][$role])) {
689:                 continue;
690:             }
691:             if ($all) {
692:                 if ($rules = $this->getRules($resource, $role)) {
693:                     foreach ($rules['byPrivilege'] as $privilege2 => $rule) {
694:                         if ($this->getRuleType($resource, $role, $privilege2) === self::DENY) {
695:                             return self::DENY;
696:                         }
697:                     }
698:                     if (($type = $this->getRuleType($resource, $role, null)) !== null) {
699:                         return $type;
700:                     }
701:                 }
702:             } else {
703:                 if (($type = $this->getRuleType($resource, $role, $privilege)) !== null) {
704:                     return $type;
705: 
706:                 } elseif (($type = $this->getRuleType($resource, $role, null)) !== null) {
707:                     return $type;
708:                 }
709:             }
710: 
711:             $dfs['visited'][$role] = true;
712:             foreach ($this->roles[$role]['parents'] as $roleParent => $foo) {
713:                 $dfs['stack'][] = $roleParent;
714:             }
715:         }
716:         return null;
717:     }
718: 
719: 
720:     /**
721:      * Returns the rule type associated with the specified Resource, Role, and privilege.
722:      * @param  string|null  $resource
723:      * @param  string|null  $role
724:      * @param  string|null  $privilege
725:      * @return bool|null  null if a rule does not exist or assertion fails, otherwise returns ALLOW or DENY
726:      */
727:     private function getRuleType($resource, $role, $privilege)
728:     {
729:         if (!$rules = $this->getRules($resource, $role)) {
730:             return null;
731:         }
732: 
733:         if ($privilege === self::ALL) {
734:             if (isset($rules['allPrivileges'])) {
735:                 $rule = $rules['allPrivileges'];
736:             } else {
737:                 return null;
738:             }
739:         } elseif (!isset($rules['byPrivilege'][$privilege])) {
740:             return null;
741: 
742:         } else {
743:             $rule = $rules['byPrivilege'][$privilege];
744:         }
745: 
746:         if ($rule['assert'] === null || call_user_func($rule['assert'], $this, $role, $resource, $privilege)) {
747:             return $rule['type'];
748: 
749:         } elseif ($resource !== self::ALL || $role !== self::ALL || $privilege !== self::ALL) {
750:             return null;
751: 
752:         } elseif ($rule['type'] === self::ALLOW) {
753:             return self::DENY;
754: 
755:         } else {
756:             return self::ALLOW;
757:         }
758:     }
759: 
760: 
761:     /**
762:      * Returns the rules associated with a Resource and a Role, or null if no such rules exist.
763:      * If the $create parameter is true, then a rule set is first created and then returned to the caller.
764:      * @param  string|null  $resource
765:      * @param  string|null  $role
766:      * @param  bool
767:      * @return array|null
768:      */
769:     private function &getRules($resource, $role, $create = false)
770:     {
771:         $null = null;
772:         if ($resource === self::ALL) {
773:             $visitor = &$this->rules['allResources'];
774:         } else {
775:             if (!isset($this->rules['byResource'][$resource])) {
776:                 if (!$create) {
777:                     return $null;
778:                 }
779:                 $this->rules['byResource'][$resource] = [];
780:             }
781:             $visitor = &$this->rules['byResource'][$resource];
782:         }
783: 
784:         if ($role === self::ALL) {
785:             if (!isset($visitor['allRoles'])) {
786:                 if (!$create) {
787:                     return $null;
788:                 }
789:                 $visitor['allRoles']['byPrivilege'] = [];
790:             }
791:             return $visitor['allRoles'];
792:         }
793: 
794:         if (!isset($visitor['byRole'][$role])) {
795:             if (!$create) {
796:                 return $null;
797:             }
798:             $visitor['byRole'][$role]['byPrivilege'] = [];
799:         }
800: 
801:         return $visitor['byRole'][$role];
802:     }
803: }
804: 
Nette 2.4-20180918 API API documentation generated by ApiGen 2.8.0