Download the PHP package goldnead/statamic-teams without Composer

On this page you can find all versions of the php package goldnead/statamic-teams. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package statamic-teams

Teams for Statamic

Workspaces with members. A team is a choir, a company, a household: people are in it with a role that counts in that team only, they come in by invitation link or join code, and access or a purchase can belong to the team instead of one person.

Works with Statamic's file users and Eloquent users alike.

Requirements

Installation

Optional, when email-templates is installed:

The Control Panel lists teams under Users → Teams. Permissions: view teams, manage teams, manage teams settings.

Usage

In Antlers, {{ teams:switch_form }}, {{ teams:members }}, {{ teams:invite_form }} and {{ teams:join_form }} cover the usual account pages (see "Front end").

Concepts

Team Goldnead\Teams\Models\Team: id, uuid, name, type (team, personal, or your own), owner_id, join_method (invitation_only, join_code), join_code, settings, billing.
Membership One user in one team: role, meta (free fields, e.g. a voice part), is_current, joined_at. Users are stored by string key, so UUIDs (file users) and integers (Eloquent) both work.
Invitation Addressed to an email, with a role and meta copied onto the membership. Expires (default 7 days), is bound to its address, works once. Inviting the same address again replaces the link.
Role Global roles start from teams.roles; changes made in the CP (table team_global_roles) win, and each can be reset to the config. A team can add or adjust roles for itself (team_roles); a team role with a global handle replaces it for that team. owner holds every permission and cannot be removed from the last owner.

Nobody hands out more than they hold. Whoever assigns a role, invites into it or removes someone holding it must hold every permission of that role; a role with * and the owner role only by an owner. Changing one's own role, and demoting or removing an owner, is an owner's business. The last-owner check runs inside the write's transaction with the owner rows locked. The same rule covers editing someone else's membership fields (updateMemberMeta).

An invitation grants what its sender may still give. On acceptance, the person who invited must still be in the team and hold every permission of the invited role. If not, the invitation is not refused (the invitee acted in good faith) but grants only default_role; the team can raise it. Invitations from the CP or an import (no sender) keep their role.

Managing roles

In the CP, Teams → Roles lists the global roles with one column per permission, and creates, renames, changes, resets and deletes them (core publish form with a checkbox per permission). The team page has a Roles panel: every role that applies there, marked Global or This team, and roles created or adjusted for that team only. Both need the Statamic permission manage team roles; manage teams is not enough.

The rules hold for every caller, CP and API alike:

When a change takes effect. Global and team roles are read once per request or queue job and kept for its duration; every write through the addon empties that store. A long-running job (one job that loops for minutes) therefore works with the roles as they were when it read them first. Call app(\Goldnead\Teams\Support\GlobalRoleStore::class)->flush() and app(\Goldnead\Teams\Support\TeamRoleStore::class)->flush() where it must see changes made meanwhile. Only a missing team_global_roles table (migration not run) falls back to the config; any other database error is thrown, so a deleted or narrowed role never gets its config permissions back by accident.

Nobody is put into a team without consent: the Control Panel and the front end invite, they do not add. Teams::addMember() exists for code that has its own consent (an import, a checkout).

Public API

Everything goes through the facade Goldnead\Teams\Facades\Teams (root: Goldnead\Teams\TeamsManager). These are the operations statamic-app-api exposes as JSON.

Methods that change something take an optional $actor. With an actor (the signed-in user), the actor's role in the team must allow it. Without an actor the call is trusted (CP, console, import). A refusal is a Goldnead\Teams\Exceptions\TeamsException with a stable reason and an HTTP status():

reason status
not_member 403 actor or user is not in the team
forbidden 403 the role does not allow it
already_member 422
invitation_not_found 404
invitation_expired, invitation_used, invitation_revoked 410
invitation_wrong_email 403 account email differs from the invited one
join_code_invalid 404
join_disabled 403 team does not accept codes
unknown_role, last_owner, already_owner, personal_team, team_mismatch, team_required 422
import_collision 409 a fixed id belongs to another team
read_only 423
role_exists, role_protected, unknown_permission, wildcard_not_allowed, invalid_role_handle 422 role editor
role_in_use 409 details: members, invitations
role_handle_in_teams 409 details.teams: [{id, name}]
anything a join guard returns, e.g. team_full 422

TeamsException::toArray() (the JSON body) is {reason, message}, plus details where a reason has them.

$user is anything that names a user: a Statamic user, an Authenticatable, or its id.

Roles over app-api. statamic-app-api does not expose role management yet. An endpoint for it is a thin controller in the shape of its TeamController::changeRole(): resolve the team the caller is a member of, then pass the signed-in user as $actor, so the team permission manage team roles and the no-escalation rule apply:

A TeamsException answers with its status() and toArray(). Global roles are not for app-api: with an actor, every global call is forbidden.

Team offers hasMember($user), roleOf($user), membershipOf($user), isOwner($user), isPersonal(), isReadOnly(), allowsJoinCode(), setting($key) and summary() (the fields events and APIs carry; never the join code).

Current team middleware

The team is read from the X-Team-ID header, team_id in query or body, and the route parameters {team} / {team_id}, by id or uuid (all configurable under teams.current). Two sources that point to different teams: 422. A team the user is not in, or one that does not exist: 403. Afterwards Teams::current() returns the team.

Without a named team, mixed mode falls back to the user's current team. With teams.current.fallback_to_current = false the request has no team, and Teams::currentOrFail() answers 422 (team_required).

ChoirLive keeps its API names and behaviour with:

Front end

Antlers tags, all working on the current team unless team="id or uuid" is given:

Inside {{ teams:members }}, remove_url and role_url are set only when the signed-in user may use them (post role to role_url).

The forms post to /!/statamic-teams/… (route names statamic.teams.forms.*). A request that wants JSON gets JSON with reason on refusal. redirect="…" is followed only for a path on this site. Joining by code is limited to 10 attempts per hour per account and 30 per address (teams.routes.join_limits). The link in the invitation mail opens /teams/invitations/{token} (view teams::invitation, publish with --tag=teams-views): a guest is sent to teams.invitations.login_url first; accepting is a POST from that page, so a mail scanner following the link accepts nothing.

Entitlements

A team is the subject team:<id> (Team::MORPH_ALIAS, registered in the morph map unless the host already maps team). Grant access to a team like to anything else:

Check a member:

Teams registers itself with entitlements (Entitlements::extendSubjects(), from entitlements 150b5f2 on) as a subject expander. Then entitlements itself counts a user's teams, for grants and for limits, without going through Teams::allows():

A subject is expanded only when its type names a user: user, the auth model's class (ChoirLive: App\Models\User) and its morph alias, plus teams.entitlements.user_types. An email or a team subject is never expanded; a team id is not a user id. Expansion applies to reads only; a refund against a person never touches the team's grant (entitlements' rule).

Payments

Payments has no customer model: the buyer is email, name, country on the payment, the billing address sits in payments.meta.address. Teams::checkout() fills exactly those from the team's billing fields (company, name, email, line1, line2, postal_code, city, country, vat_id), names the team as $details['for'] (payments ≥ eb8bfb6: the grant, renewals, refunds and the subscription then belong to the team) and carries meta.team_id, meta.team_uuid, meta.paid_by, meta.address (as fields) and meta.vat_id. The same details work for Subscriptions::start(); Teams::checkoutBuyer() and Teams::checkoutDetails() return them.

VAT ID. Stored on the team as entered and not verified there (the CP says so). With statamic-invoices installed, the checkout asks its BuyerAdmission::check() (VIES, cached) and freezes the answer as meta.vat_id_check, which the invoice prints. Without invoices no check is claimed.

Required: the payer is a member holding manage billing in the team. Otherwise Teams::checkout() throws TeamsException (not_member or forbidden) and no checkout starts. Pass the signed-in user as payer; only system code (a CP action, a job) may pass none.

Mails

Key (teams.mail.*) Template slug To Default
invitation teams-invitation invited address on
member_joined teams-member-joined the team's owners on
member_removed teams-member-removed whoever was removed by someone else on
role_changed teams-role-changed the member off

With email-templates, the CP entry wins; without it, or before teams:mail-templates, the shipped text (lang/*/mail.php) is sent. Variables per mail are listed on the Wiring page.

With an email-templates version that has the template registry, each mail is registered there (occasion, event, placeholders with label and example, default text): the template list then shows "Sent on: Teams: …" and Live Preview fills in the examples. Older versions get the defaults through the email-templates.sources import tag instead.

Events

Every event extends Goldnead\Teams\Events\TeamEvent with a stable handle() and a payload() of ids and plain fields (no tokens, no join codes):

teams.team.created, teams.team.updated, teams.team.deleted, teams.team.ownership_transferred, teams.member.joined (via: created, added, invitation, join_code), teams.member.left (reason: left, removed), teams.member.role_changed, teams.invitation.sent, teams.invitation.accepted, teams.invitation.revoked, teams.role.created, teams.role.updated (changes: label, permissions), teams.role.deleted (reassigned_to, reassigned).

Role events carry role (handle, label, permissions, scope) and team, which is null for a global role (then team_type is null too, a flow filtered on a team type does not fire, and the activity entry has no subject). Members moved by a deletion each fire teams.member.role_changed as well.

Every payload carries team_type at the top level (personal, team or a type of your own), the same value as team.type.

Personal teams are created, not joined. Creating a personal team (on registration with personal.create_on_registration, or through Teams::personalTeam()) fires teams.team.created with team_type = personal and no teams.member.joined for its owner. A regular team still announces its founder as the first member (via = created). Since 0.2.0; before, every registration on a site with personal teams fired member.joined.

With statamic-automations each is a trigger (group "Teams") with one setting, Team type: empty fires for every team, a type fires only for teams of that type. In webhook-manager, filter on team_type in the payload. With statamic-webhook-manager a webhook trigger (source type team), with statamic-activity an entry (subject team:<id>). Teams → Wiring in the CP shows, per event, its mail and how many enabled flows and webhooks listen.

Importing teams

Teams::import(array $data) or php please teams:import teams.json [--dry-run] (a JSON list, one transaction). Idempotent by uuid, no events, no mails.

A plain token is hashed on the way in, so links already in someone's inbox keep working. An unknown role stops the import with nothing written.

Settings

Under Settings → Addon settings (with statamic-brand-context): invitation lifetime, matching email, join code length, personal team on registration, and the four mail switches. Everything else in config/teams.php (php artisan vendor:publish --tag=teams-config).

License

Proprietary, part of the goldnead suite license. See LICENSE.md.


All versions of statamic-teams with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
laravel/framework Version ^12.40|^13.0
statamic/cms Version ^6.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package goldnead/statamic-teams contains the following files

Loading the files please wait ...