Skip to the content.

← Back to Activities Plugin

5.6.4 Activity Entity Reference

Last Updated: December 3, 2025
Status: Complete
Scope: Activities Plugin - Activity Entity

Comprehensive technical reference for the Activity entity, covering data model, relationships, field definitions, and integration patterns with the authorization system.

Table of Contents

Activity Entity Overview

The Activity entity represents authorization types within KMP that require member authorization for participation. Activities define configuration requirements for member participation, including approval workflows, age restrictions, and permission requirements.

Core Responsibilities:

Location: plugins/Activities/src/Model/Entity/Activity.php
Extends: App\Model\Entity\BaseEntity
Table Class: Activities\Model\Table\ActivitiesTable

Database Schema

Table: activities_activities

The Activity entity maps to the activities_activities database table with the following structure:

Column Type Null Default Notes
id INT(11) NO Auto Primary key, auto-incrementing
name VARCHAR(255) NO   Unique activity identifier
term_length INT(11) NO   Authorization validity in days
activity_group_id INT(11) NO   Foreign key to ActivityGroup
minimum_age TINYINT(2) YES NULL Minimum age requirement
maximum_age TINYINT(2) YES NULL Maximum age requirement
num_required_authorizors TINYINT(2) NO 1 Required approvers for new requests
num_required_renewers TINYINT(2) NO 1 Required approvers for renewals
permission_id INT(11) YES NULL Foreign key to Permission (RBAC)
grants_role_id INT(11) YES NULL Foreign key to Role (auto-granted)
created DATETIME NO   Creation timestamp
created_by INT(11) YES NULL Creator member ID
modified DATETIME YES NULL Last modification timestamp
modified_by INT(11) YES NULL Last modifier member ID
deleted DATETIME YES NULL Soft deletion timestamp

Indexes:

Foreign Keys:

Entity Properties

Core Configuration Properties

name

term_length

activity_group_id

Age Restriction Properties

minimum_age

maximum_age

Approval Workflow Properties

num_required_authorizors

num_required_renewers

Integration Properties

permission_id

grants_role_id

Audit Properties

created

created_by

modified

modified_by

deleted

Relationships

Parent Relationships (belongsTo)

activity_group

permission

role

Child Relationships (hasMany)

authorizations

current_authorizations

pending_authorizations

upcoming_authorizations

previous_authorizations

member_activities

pending_authorizations

Virtual Properties

Virtual properties are computed from related data and appear as entity properties but are not stored in the database.

activity_group_name

grants_role_name

length

Mass Assignment Security

The Activity entity uses CakePHP’s accessible field system to prevent mass assignment vulnerabilities while allowing legitimate field updates.

Accessible Fields

The following fields can be safely mass assigned through newEntity() or patchEntity():

Core Activity Configuration:

Administrative Fields:

Relationship Management:

Protected Fields

The following fields are NOT accessible via mass assignment:

Methods

getApproversQuery()

Discovers members who have permission to authorize this activity within a specified organizational branch.

Signature:

public function getApproversQuery(int $branch_id): \Cake\ORM\Query\SelectQuery

Parameters:

Returns: SelectQuery for eligible approvers

Description: This method is the core integration point between activities and the RBAC authorization system. It uses the activity’s permission_id to identify members with the required permission to authorize this activity within the specified branch.

Implementation Details:

Error Handling:

Usage Examples:

// Get all potential approvers within a branch
$branchApprovers = $activity->getApproversQuery($member->branch_id)->toArray();

// Count available approvers
$approverCount = $activity->getApproversQuery($branchId)->count();
if ($approverCount < $activity->num_required_authorizors) {
    throw new InsufficientApproversException(
        "Insufficient approvers available for activity authorization"
    );
}

// Chain additional query conditions
$seniorApprovers = $activity->getApproversQuery($branchId)
    ->innerJoinWith('MemberRoles.Roles', function ($q) {
        return $q->where(['Roles.name LIKE' => '%Senior%']);
    })
    ->distinct()
    ->toArray();

// Exclude specific approvers (e.g., requestor)
$availableApprovers = $activity->getApproversQuery($member->branch_id)
    ->where(['Members.id !=' => $requestingMember->id])
    ->toArray();

Integration Points:

Performance Notes:

Virtual Property Accessors

The entity provides magic property access to virtual computed properties:

// Access virtual properties
$groupName = $activity->activity_group_name;  // Calls _getActivityGroupName()
$roleName = $activity->grants_role_name;      // Calls _getGrantsRoleName()
$days = $activity->length;                    // Alias for term_length

Magic Method:

Authorization Architecture

Approver Discovery Process

The Activity entity participates in the authorization approval workflow through the approver discovery mechanism:

  1. Activity Configuration:
    • Activity defines required permission via permission_id
    • Activity specifies required approver count: num_required_authorizors
  2. Authorization Request:
    • Member requests authorization for activity
    • System calls getApproversQuery() to identify eligible approvers
    • Approvers filtered by permission and organizational branch
  3. Multi-Level Approval:
    • AuthorizationApproval entities created for each required approver
    • Workflow routes request sequentially through required approvals
    • Final approval triggers authorization activation and role assignment

Age-Based Eligibility

Activities define age restrictions for member participation:

// Example: Youth activity (age 13-17)
$activity->minimum_age = 13;
$activity->maximum_age = 17;

// Example: Adult activity (age 18+)
$activity->minimum_age = 18;
$activity->maximum_age = null;  // No upper limit

Validation Point: Authorization request workflow validates member age before processing

Role Grant Integration

Upon authorization approval, the Activity can automatically grant a role to the member:

  1. Configuration: grants_role_id set to target Role
  2. Activation: When authorization becomes active (status = “Approved”)
  3. Assignment: ActiveWindowManager grants role to member automatically
  4. Removal: Role removed if authorization revoked or expires

Note: Role assignment is automatic via ActiveWindow integration; no manual role management needed

Renewal vs. New Request

Activities support both new requests and renewal requests with potentially different approval requirements:

Usage Examples

Activity Creation

// Create new heavy weapons combat activity
$activity = $activitiesTable->newEntity([
    'name' => 'Heavy Weapons Authorization',
    'term_length' => 1095,  // 3 years in days
    'activity_group_id' => $combatGroupId,
    'minimum_age' => 18,
    'maximum_age' => null,  // No upper age limit
    'num_required_authorizors' => 2,  // Requires 2 approvers
    'num_required_renewers' => 2,     // Same for renewals
    'permission_id' => $marshalPermissionId,
    'grants_role_id' => $fighterRoleId
]);
$activitiesTable->save($activity);

Approver Discovery

// Find members authorized to approve activity within branch
$approversQuery = $activity->getApproversQuery($branchId);
$approvers = $approversQuery->toArray();

// Validate sufficient approvers available
if (count($approvers) < $activity->num_required_authorizors) {
    throw new \Exception("Insufficient approvers for authorization workflow");
}

// Send approval requests
foreach ($approvers as $approver) {
    $authorizationManager->sendApprovalRequest($authorization, $approver);
}

Member Eligibility Check

// Check age-based eligibility before allowing authorization request
if ($member->age !== null) {
    $minimumMet = $activity->minimum_age === null || 
                 $member->age >= $activity->minimum_age;
    $maximumMet = $activity->maximum_age === null || 
                 $member->age <= $activity->maximum_age;
    
    if (!$minimumMet || !$maximumMet) {
        throw new \Exception(
            "Member age {$member->age} not eligible for {$activity->name}"
        );
    }
}

Activity Configuration Query

// Load activity with all relationships for admin interface
$activity = $activitiesTable->find()
    ->contain([
        'ActivityGroup',
        'Permission',
        'Role',
        'CurrentAuthorizations' => function ($q) {
            return $q->contain(['Member']);
        },
        'PendingAuthorizations' => function ($q) {
            return $q->contain(['Member']);
        }
    ])
    ->where(['Activities.id' => $activityId])
    ->first();

Activity Statistics

// Get authorization statistics for activity
$activity = $activitiesTable->get($activityId, [
    'contain' => [
        'CurrentAuthorizations',
        'PendingAuthorizations',
        'UpcomingAuthorizations'
    ]
]);

$stats = [
    'current_count' => count($activity->current_authorizations),
    'pending_count' => count($activity->pending_authorizations),
    'upcoming_count' => count($activity->upcoming_authorizations),
];

ActivitiesTable Utility Methods

The ActivitiesTable class provides static utility methods for authorization permission checking. These methods support navigation display, workflow entry validation, and access control.

canAuthorizeActivity()

Checks if a user can authorize a specific activity based on their permissions.

Signature:

public static function canAuthorizeActivity($user, int $activityId): bool

Parameters:

Returns: bool - True if user can authorize the activity, false otherwise

Usage Examples:

// Controller authorization check
if (!ActivitiesTable::canAuthorizeActivity($this->getIdentity(), $activityId)) {
    throw new ForbiddenException('Insufficient permissions');
}

// Workflow entry validation
if (ActivitiesTable::canAuthorizeActivity($currentUser, $activity->id)) {
    $authorizationManager->processApproval($authorization, $currentUser);
}

// UI conditional display
if (ActivitiesTable::canAuthorizeActivity($this->identity, $activity->id)) {
    echo $this->Html->link('Authorize', ['action' => 'authorize', $activity->id]);
}

canAuhtorizeAnyActivity()

Checks if a user has authorization permissions for any activities in the system.

Signature:

public static function canAuhtorizeAnyActivity($user): bool

Parameters:

Returns: bool - True if user can authorize any activities, false otherwise

Usage Examples:

// Navigation queue display
if (ActivitiesTable::canAuhtorizeAnyActivity($this->getIdentity())) {
    $pendingCount = $this->getIdentity()->getPendingApprovalsCount();
    echo $this->Html->link("Authorization Queue ({$pendingCount})", 
        ['plugin' => 'Activities', 'controller' => 'AuthorizationApprovals']);
}

// Dashboard widget conditional
if (ActivitiesTable::canAuhtorizeAnyActivity($currentUser)) {
    echo $this->element('Activities.authorization_queue_widget');
}

// Redirect unauthorized users
if (!ActivitiesTable::canAuhtorizeAnyActivity($this->getIdentity())) {
    $this->Flash->error('You do not have authorization permissions');
    return $this->redirect(['controller' => 'Members', 'action' => 'view']);
}

Performance Notes:


Source Files