Restrictions in GAC provide an additional layer of access control beyond basic permissions. While permissions determine what modules a user can access, restrictions define the conditions under which that access is valid (e.g., time periods, specific entities, IP addresses).
Apply to all entities in the system, stored separately and cached independently.
// Global restrictions (GAC.php:456-458)$entityType = '3'; // Global entity type$entityId = '0'; // Irrelevant for global$roleIds = []; // No roles for global
Control access based on time periods with support for wildcards:
// Date restriction methods (ByDate.php:8-13)protected array $methods = [ 'before' => 'before', // Allow before a date 'in_range' => 'inRange', // Allow within date range 'out_range' => 'outRange', // Allow outside date range 'after' => 'after', // Allow after a date];
// Before method (ByDate.php:21-44)public function before(array $internalData, array $externalData) : bool { // Validate and format date if ($this->validateDataIntegrity($internalData, ['d' => ['string']])) { $internalData['d'] = $this->formatDate($internalData['d']); } // Check if current date is before restriction date if ($externalData['date'] >= $internalData['d']) { return false; // Access denied } return true; // Access allowed}
// In range method (ByDate.php:51-75)public function inRange(array $internalData, array $externalData) : bool { // Requires start and end dates if ($this->validateDataIntegrity($internalData, ['sd' => ['string'], 'ed' => ['string']])) { $internalData['sd'] = $this->formatDate($internalData['sd']); $internalData['ed'] = $this->formatDate($internalData['ed']); } // Check if date is within range if (!($externalData['date'] >= $internalData['sd'] && $externalData['date'] <= $internalData['ed'])) { return false; } return true;}
// Format date with wildcards (ByDate.php:147-156)function formatDate(string $date, bool $toTime = true) : string|int { $currentDate = date('Y-m-d'); $currentDate = explode('-', $currentDate); // Replace wildcards with current values $date = str_replace('%Y', $currentDate['0'], $date); // Year $date = str_replace('%M', $currentDate['1'], $date); // Month $date = str_replace('%D', $currentDate['2'], $date); // Day return $toTime ? strtotime($date) : $date;}
Date Wildcard Examples
// Restrict access until end of current year['d' => '%Y-12-31']// Restrict to current month only['sd' => '%Y-%M-01', 'ed' => '%Y-%M-31']// Allow access starting tomorrow['d' => '%Y-%M-%D'] // Will be evaluated daily
$gac->setEntity('user', $userId);$restrictions = $gac->getRestrictions();// Check if a restriction category existsif ($restrictions->has('by_date')) { // User has date restrictions}
// Register method (Restrictions.php:72-77)public static function register(string $alias, string $className): void { if (!is_subclass_of($className, Restriction::class)) { throw new \InvalidArgumentException( 'The class "' . $className . '" must extend the base Restriction class.' ); } self::$restrictionMap[$alias] = $className;}
-- Restrictions query (DatabaseAdapter.php:86-93)SELECT a.id, a.entity_type, a.entity_id, c.code AS category_code, b.code AS type_code, a.dataFROM `gac_restriction` AS a INNER JOIN `gac_restriction_method` AS b ON a.restriction_method_id = b.idINNER JOIN `gac_restriction_category` AS c ON b.restriction_category_id = c.idWHERE ((a.entity_type = ? AND a.entity_id = ?) OR (a.entity_type = '0' AND a.entity_id = ?)) -- RolesAND a.deleted_at IS NULLAND a.is_disabled = '0'