Plans

Parthenon comes with a Plan system. This will allow you to provide a group of limits to a user.

Configuration

Name Type Description
enabled Boolean To define if the plan module is enabled.
subscriber_type string The kind of subscriber team or user
plan array The plans

Plans

The plans are defined with the name of the plan and then it has the field limit that holds the limits for the plan.

The limits is defined by the name of the limit and the and limit as a number and the description.

plan:
  enabled: true
  plan:
    basic:
      limit:
        team_invite:
          limit: 1
          description: "Number of users"
    standard:
      limit:
        team_invite:
          limit: 5
          description: "Number of users"

Counter

One of the parts of ensuring a limit is enforced is knowing how many the user currently has. To handle this we created the CounterInterface

Interface

The interface has two methods.

  • supports - This method defines if this limitable item is supported by this counter. It returns a boolean value.
  • getCount - This returns the count. If you want to make the it unlimited for a plan you can return -1.

    <?php
    
    declare(strict_types=1);
    
    /*
    * Copyright Humbly Arrogant Ltd 2020-2021, all rights reserved.
    */
    
    namespace Parthenon\Plan;
    
    interface CounterInterface
    {
    public function supports(LimitableInterface $limitable): bool;
    
    public function getCount(LimitedUserInterface $user, LimitableInterface $limitable): int;
    }
    

Example

Here is the example

<?php

declare(strict_types=1);

/*
 * Copyright Humbly Arrogant Ltd 2020-2021, all rights reserved.
 */

namespace Parthenon\Plan\Counter;

use Parthenon\Common\Exception\GeneralException;
use Parthenon\Plan\CounterInterface;
use Parthenon\Plan\LimitableInterface;
use Parthenon\Plan\LimitedUserInterface;
use Parthenon\User\Entity\MemberInterface;
use Parthenon\User\Entity\TeamInviteCode;
use Parthenon\User\Repository\TeamInviteCodeRepositoryInterface;
use Parthenon\User\Repository\TeamRepositoryInterface;
use Parthenon\User\Repository\UserRepositoryInterface;

class TeamInviteCounter implements CounterInterface
{
    public function __construct(
        private TeamInviteCodeRepositoryInterface $inviteCodeRepository,
        private UserRepositoryInterface $userRepository,
        private TeamRepositoryInterface $teamRepository
    ) {
    }

    public function supports(LimitableInterface $limitable): bool
    {
        return $limitable instanceof TeamInviteCode;
    }

    public function getCount(LimitedUserInterface $user, LimitableInterface $limitable): int
    {
        if (!$user instanceof MemberInterface) {
            throw new GeneralException('User does not implement MemberInterface');
        }

        $team = $this->teamRepository->getByMember($user);

        $inviteCount = $this->inviteCodeRepository->getUsableInviteCount($team);
        $activeMemberCount = $this->userRepository->getCountForActiveTeamMemebers($team);

        return $inviteCount + $activeMemberCount;
    }
}

Check Limit

To check if a user is allowed to do something we extend the Symfony AuthorizationChecker.

There are two supported attributed

  • create
  • enable

Example


/** @var \Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface $authorizationChecker */
if (!$authorizationChecker->isGranted(TeamInviteCode::AUTH_CHECKER_ATTRIBUTE, $inviteCode)) {
    throw new GeneralException("Not allowed to do this");
}