Presence tracking no longer loads profile data from Play unnecessarily [*]
Fixes
WP_Query in get_active_slack_users() with a direct query against the presence table, removing the blog switch and the profile post loadrecord_user_presence() that fetched slack_status and slack_handle from post meta; values already in the presence table row are used directlyairtable_uuid, email, and full_name from the Play blog in post_presence_to_iti(); skip the load entirely when post_id is 0Presence cron scheduling now runs once on upgrade rather than on every admin request [*]
Fixes
schedule_slack_presence_cron_event() at 14.2.1 so it runs once per installation on upgrade, not on every admin requestBot users tracked in presence table and membership events record last-seen date [*]
New
process_bot_user() — bots are now upserted directly into the presence table on user_change events, using post_id = 0 since bots have no profile; op is set to create or update based on whether a row already existsImprovements
process_activity_event() from process_user_event() so that team_join and user_change events also update the member’s last_seen_dateFixes
is_bot early-return from process_team_join() and process_user_change() — bot events are now intercepted in process_user_event() before reaching those methods, so the guards were dead codeSlim cached ventures and add a cache-warming CLI command [*]
New
warm-profile-transients WP-CLI command to bust and rewrite all profile, team, organisation, and venture caches; dry-run by default, --letsgo executes the bust and rewrite and reports object countsSIA_Ariel_Transient_Service::bust_transient_variants_in_all_blogs() — runs a LIKE-based bust on every blog, complementing the existing bust_transient_in_all_blogs() which only deletes exact-keyed transientsImprovements
SIA_Website properties (active_plugins, country_user, maintainer) and heavy nested team collections (hosts, organizations, teamMembers) from venture objects before serialization, reducing the size of profile and team-member transientsFixes
warm-profile-transients --letsgo now correctly busts all get_blog_profiles variants; previously called bust_transient_in_all_blogs which deleted the bare key but not the parametered variants like _include_inactive_0last_seen_date and last_seen_source in the ITI webhook payload when processing team_join and user_change events; previously these fields were absent, causing Airtable to clear the stored values on every membership updateUnify Slack member data in the presence table [*]
New
backfill-slack-presence-meta CLI command to populate the new columns from existing profile meta for all members with a non-blank Slack ID; dry-run by default, --letsgo executes and reports totalsslack_status, slack_handle, and slack_type columns to wp_slack_user_presenceslack_status and slack_handle to the presence table on every presence upsert in record_user_presence()slack_status, slack_handle, and slack_type to the presence table when processing team_join and user_change events; slack_type is only available from the live Slack user object so it is not backfilled by the migration commandImprovements
upgrade_to_13_6_0() to setup_slack_presence_tracking() to describe its role rather than its versionFix access-log polling failures and add totals to the CLI output [*]
Improvements
poll-slack-presence output: “X of Y members seen today”Fixes
WP_Error (instead of NULL) when the token is missing or the Slack API returns an error; the poll-slack-presence CLI command now surfaces these as a fatal error messageFix access-log pagination so all of today’s entries are found [*]
Fixes
poll_access_logs() from cursor-based to page-based pagination, which is what team.accessLogs actually uses; add an early-exit once a page contains no today entries, since logs are sorted newest-firstKeep a local record of when each Slack member was last seen [*]
Active members who have not interacted with Slack in the past 14 days can now be identified automatically. The Events API captures real interactions, and a nightly access-log poll catches members who only open the app without posting or reacting.
New
wp_slack_user_presence table on plugin activation to store each active member’s last-seen date, the source that recorded it, and when the access log poll last ran for that userSIA_Ariel_Slack_Presence::get_active_slack_users() to query all profiles with slack_status = 'active' and a slack_id, returning a map of Slack user ID to profile post ID; result is cached for the request lifetimerecord_user_presence( $slack_id, $source ) to upsert today’s date into the presence table, skipping inactive users and honouring a once-per-day gate to avoid redundant writespoll_access_logs() to call team.accessLogs with cursor-based pagination for members not already seen today, recording access-log presence and stamping last_polled for all active usersget_inactive_users( $days = 14 ) to return all active members whose last-seen date is older than the threshold or who have no presence record yetmessage.*, reaction_added, file_created, and member_joined_channel events in process_event() and route each to process_activity_event(), which calls record_user_presence with source event; bot messages and deletions are skippedSLACK_NET_CRM_APP_ACCESSLOGS_USER_TOKEN constant for the user OAuth token (admin scope) required by team.accessLogspoll_access_logs as a daily WP-Cron job at 23:00 UTC on the Play blog; applied automatically on first page load after deployment via maybe_upgrade(); unschedule on deactivationpoll-slack-presence CLI command: dry-run lists active members not yet seen today; --letsgo runs the poll and shows the post-poll outcome for each user (✅ seen today, ❌ not in logs, or ⏸️ in dry-run)post_presence_to_iti() to POST a presence update to the ITI Airtable webhook after each successful upsert; payload mirrors process_team_join/process_user_change structure and includes last_seen_date and last_seen_sourceEnrich IT Infrastructure payload with Slack member type and full name [*]
Improvements
slack_type (resolved from user flags: Bot, Single-Channel Guest, Multi-Channel Guest, Primary Owner, Owner, Admin, Member) and slack_full_name (from profile.real_name)airtable_uuid and email are sent as NULL in those casesget_slack_user_type() to resolve Slack member type from user object flagsslack_full_name in the sync-slack-users-to-iti CLI payload (from $profile->full_name); slack_type is sent as NULL since the profile does not store itImport Slack workspace members from a CSV export [*]
New
import-slack-users-from-csv CLI command in SIA_Ariel_WP_CLI: reads a Slack admin member CSV export (userid, username, email, status), looks up each row by email, and writes slack_id, slack handle, and slack_status to the matching profile; dry-run by default, --letsgo to execute; bots (non-U/W user IDs) and rows without an email or user ID are skippedFixes
AIRTABLE_ITI_APP_ID env var to AIRTABLE_ITI_REPORTS_APP_ID in constants.phpDEBUG_ITI to DEBUG_ITI_REPORTS and AIRTABLE_ITI_REQUEST_TOKEN to AIRTABLE_ITI_REPORTS_REQUEST_TOKEN in post_slack_user_to_airtable_iti_webhook()json_decode result with is_array() before accessing message keys in fetch()Sync all Slack workspace members to IT Infrastructure on demand [*]
New
sync-slack-users-to-iti CLI command in SIA_Ariel_WP_CLI: queries all profiles with a slack_id, builds the same payload as process_user_change, and calls post_slack_user_to_airtable_iti_webhook for each; dry-run by default, --letsgo to execute, --quiet to suppress outputMake the Slack users connection name more specific
Fixes
AIRTABLE_ITI_SLACK_SUFFIX to AIRTABLE_ITI_SLACK_USERS_SUFFIX in constants.php and update its reference in post_slack_user_to_airtable_iti_webhook()Sync Slack membership changes to member profiles
When a new member joins the Slack workspace, or when an existing member’s account is updated or deactivated, their profile is automatically kept in sync and IT Infrastructure is notified in real time.
New
AIRTABLE_ITI_BASE_URL and AIRTABLE_ITI_SLACK_SUFFIX constants and post_slack_user_to_airtable_iti_webhook() in SIA_Ariel_Remote_Abstract to POST Slack user data to the IT Infrastructure Airtable baseSIA_Ariel_Slack_Event_Listener::process_user_event() as a category dispatcher that collects processor output and calls the ITI webhook; process_event() routes to it for all user-related event typesprocess_team_join(): looks up the profile by email, writes slack_id, slack handle, and slack_status = 'active' to profile meta, and returns the ITI payloadprocess_user_change(): keeps slack_id, slack handle, and slack_status in sync on every user mutation, and returns the ITI payloadprocess_event() switch to dispatch on event->type instead of the raw event objectFix fatal error in has_community_role() when community role is empty
Fixes
null/empty $communityRoles in SIA_Team_Member::has_community_role() before passing to in_array()Normalize Team hosts exportable to Net/CRM
New
SIA_Profiles_Public::TEAMS_POST_TYPE_MACHINE_NAME to NETCRM_Entity::normalize_data() to send airtable_uuids back to Net/CRMListen to Slack team events and send to IT Infrastructure
Create the boilerplate that gets the webhooks authorized.
New
SIA_Ariel_Slack_Event_Listener loaded by SIA_Ariel::load_dependencies()SIA_Ariel_Public::$SlackEventListenerSIA_Ariel::define_public_hooks()Enrich and adapt parameters posted to Website Reports
Match level names, add an expected service, and use component to reflect the plugin (i.e. software component)
New
SIA_Ariel_Remote_Abstract::$softwareComponentName property that’s processed from $plugin_nameSIA_Ariel_Remote_Abstractpost_website_network_activity_to_airtable_webhook()SIA_Ariel_Remote_Abstract::post_website_network_activity_to_airtable_webhookSIA_Ariel_Remote_Abstract::post_website_network_activity_to_airtable_webhook)_**
Fix sending Scaling Lead member the invite to empty email address
Improvements
SIA_Ariel_Messaging_Repository::scalingLeadTeamMemberPlayEmailInvite()Fixes
SIA_Team_Member::sendPlayInvite() in the non-SIA Passport caseSend emails to a specified invite_email paramenter for SIA Passports
Invited users with SIA Passports don’t have access to them yet and need to be invited on a different email.
New
SIA_Team_Member::sendPlayInvite() and when present use it to when calling the SIA_Ariel_Messaging_Repository::passportTeamMemberPlayEmailInvite()invite_email parameter from CRUD_User::create() to the entity using the trait’s sendPlayInvite() methodSIA_Team_Member::has_sia_passport() helper method using the SIA_Ariel_Public::is_sia_passport() staticSIA_Ariel_WP_CLI::team_member_send_invite() method to the necessary invite_email parameterSend automatic customized invites for CRUD create candidate and host team members
Create a messaging repository to compose, for now, invite emails. When it’s a passport user account, consider access credentials when including sections regarding the Playbook and Slack.
Add SIA Passport user creation and custom invite creation when a Team member object is created via the REST API and its CRUD User trait.
New
SIA_Team_Member::sendPlayInvite() to make use of the new messaging repository, have a specific behavior for SIA Passport users, and use a $simulate parameterSIA_Team_Member as buildSignature()$accessCredentials property to SIA_Team_Member mirroring the usage in SIA_Profile, and separate as a method set_accessLevels() used both by the contructor and after a profile change in CRUD_UserCRUD_User::update() when updating the profile and making use of the new SIA_Team_Member::set_accessLevels()inviteType and a specific ‘PASSWORDLESS-ACCOUNT’ temporary_password in the CRUD_User::create() outputCRUD_User::create()scalingLeadTeamMemberPlayEmailInvite()) and passport (passportTeamMemberPlayEmailInvite()) in SIA_Ariel_Messaging_Repository, based on the sender user and the subject $teamMemberObject, loaded by SIA_Ariel::load_dependencies()SIA_Team_Member::sendPlayInvite() and replace with a call to the SIA_Ariel_Messaging_RepositorySLACK_SIGNING_BASE_URL and GOOGLE_WORKSPACE_SIGNING_BASE_URL in constants.php grabbing values from .env, used to build URLs in email invites by the messaging repositorySIA_Ariel_Repository::getAccessRootUrl(), used to compose invite emailsImprovements
POST ‘create’ operation by checking there’s a Profile post id sent and the Profile can be loaded in SIA_Ariel_REST::team_member()email property during the POST ‘create’ operation SIA_Ariel_REST::team_member()SIA_Ariel_REST::team_member()SIA_Ariel_Public::is_sia_passport()disconnect-team-member calling SIA_Ariel_WP_CLI::disconnect_team_member_from_profile() and removing the connection between a user account and a profile to be able to restart the creation processinvite-team-member calling SIA_Ariel_WP_CLI::team_member_send_invite() to be able to read an output of SIA_Team_Member::sendPlayInvite()PLAY_URL using the WANDA_DOMAIN in constants.php, used to be included in invites$args by using the admin email’s user in CRUD_Entity::create()Fixes
POST ‘create’ operation outcome in SIA_Ariel_REST::profile()Add the profile deactivation functionality to CRUD profiles
Ensure cache busting when only a meta field is changed, in this case the value of the “active” field.
CRUD_Entity::update() active field in responses from SIA_Ariel_REST::profile()Send automatic invites for CRUD create scaling lead team members
When requested, send an invite to Scaling lead profile user from CRUD_User::create()
New
SIA_Team_Member::$inviteSent, directly picking up the value from the $profile propertySIA_Team_Member::sendPlayInvite() and track the outcome in $inviteSentCRUD_User::create() and include it in the response of SIA_Ariel_REST::team_member() POST methodTeamMember::sendPlayInvite() calling back SIA_Ariel_WP_CLI::team_member_send_invite()Create users for Profiles via REST
Provide the GET, PATCH, POST endpoint and callback for adding a Team member user account, or update it.
New
CRUD_User, with create() (Creates a new WordPress user account and, upon success, instantiates self and returns it.) and update() (Update user meta values, depending in provided properties) and include it from SIA_Ariel::load_dependencies()CRUD_User trait in SIA_Team_MemberSIA_Team_Member::__construct(): $profilePostId and $usernamecreate() method: SIA_Team_Member::$temporary_passwordplay/team_member WP REST Route with SIA_Ariel_REST::team_member() callbackSIA_Ariel_REST::request_is_well_formed() to pass through user focused requestsSIA_Ariel_REST::get_request_callback()constants.php the profile community role constant setting (brought verbatim from SIA Profiles) in SIA_Ariel::set_profile_role_constants() to prevent needing not yet defined values for role conversiondescription is now a SIA_Organization exportable (SIA Profiles 15.12.0), normalize value by removing HTML in NETCRM_Entity::normalize_data()Fixes
post_status instead of creating only “pending” posts in CRUD_Entity::create()defined() in CRUD_Entity::update()CRUD_Entity::update() and use WP meta update function, otherwise use ACF field methodsInclude the post status in the REST response
New
post_status in all POST and PATCH success responses for CRUD entities from SIA_Ariel_RESTIntegrate Profile in the Net/CRM framework and improve CLI
New
SIA_Ariel_Public::maybe_send_data_to_netcrm() hooked to wp_after_insert_post since 10.0.0SIA_Ariel_Remote_Abstract::post_netcrm_data_to_airtable_webhook()AIRTABLE_NETCRM_PROFILES_SUFFIX in constants.phpSIA_Ariel_WP_CLI to send a single entityImprovements
send-netcrm-data into send-all-of-post-type-to-netcrm for clarityCreate a CLI command to post all organizations’ data to Net/CRM
New
SIA_Ariel_WP_CLICreate the framework to send data to Net/CRM
Provide a standardized posting method via a new Trait, and processing from the remote abstract. Requests are tokenized, formatted, and sent forward to an Airtable webhook defined as a constant.
To prevent infinite loops, when updating a CRUD entity via API, set a constant that blocks processing in the method hooked to the Wordpress update hook.
New
SIA_Ariel_Remote_Abstract::post_netcrm_data_to_airtable_webhook()NETCRM_Entity, for now providing only one method: post_data_to_netcrm(), and loaded from SIA_Ariel::load_dependencies()AIRTABLE_NETCRM_ORGANIZATIONS_SUFFIX and AIRTABLE_NETCRM_BASE_URL in constants.phpwp_after_insert_post in SIA_Ariel::define_public_hooks() to send update to Net/CRM via SIA_Ariel_Public::maybe_send_data_to_netcrm()DOING_API_ENTITY_UPDATE in CRUD_Entity::create() and CRUD_Entity::update() and checking it in SIA_Ariel_Public::maybe_send_data_to_netcrm()SIA_Ariel_REST::request_is_well_formed() to ensure there are no crossed wiresComVo report phase identifier in remote abstract
New
SIA_Ariel::get_site_slug()SIA_Ariel::is_development_domain()$args in SIA_Ariel_Remote_Abstract::post_community_voting_data_to_airtable_webhook()Staging is an International website
New
STAGING_BLOG_ID in constants.phpSIA_Ariel::is_staging()SIA_Ariel_Public::wsl_hook_alter_provider_config() has a team case for stagingBring the CRUD Trait closer to production
Better guard clauses and extensible to Profile, an entity that doesn’t have a “name” like Organization.
Fixes
environment property is set in CRUD_Entity methods to not throw useless Warningsstaging to prevent Fatal triggered by array returnsKick-start the CRUD API for Play entity operations
New enpoints for team, profile, and organization using GET for retrieval, POST for creation, and PATCH for updates via a new CRUD trait.
New
SIA_Ariel_REST::$RESTRoutesPOST and PATCH as allowed methods for WP Rest Request routes in SIA_Ariel_Rest::register_rest_routes()Bearer authorization in SIA_Ariel_Rest::request_is_authorized() that validates a token against the .env token using the new get_bearer_token() RegExp extractor$method (GET, POST, PATCH) matches the body of the request in SIA_Ariel_Rest::request_is_well_formed()create() and update() operations in CRUD_Entity included from SIA_Ariel::load_dependencies()Improvements
SIA_Ariel_Rest::request_is_valid() method used for A&AP related method that will followDon’t add empty parameters to transient names
Improvements
null parameter is no longer added to the suffix in SIA_Ariel_Transient_Service::get_transient_name()Remote abstract handlers to Mailjet API
Subscribe a contact to an audience & add a contact to one or more lists. In the case of duplicates, especially during adding contacts to lists, when the Mailjet “error” contains specific text, treat it as a success.
New
SIA_Ariel_Remote_Abstract::subscribe_contact_to_mailjet_list() that takes a list id and contact data and posts to the Mailjet APISIA_Ariel_Remote_Abstract::subscribe_contact_to_mailjet_audience() that takes a contact data and posts to the Mailjet APISIA_Ariel_Remote_Abstract::post_to_mailjet() which – belonging in a separate class – takes a single argument, prepares the request, and passes it forward to SIA_Ariel_Remote_Abstract->fetch()constants.phpAdd ComVo daily summary new args to doc comment
Improvements
type and date params of summary in DocBlock of SIA_Ariel_Remote_Abstract::post_community_voting_data_to_airtable_webhook()Include ComVo daily summary creation in the remote
Improvements
SIA_Ariel_Remote_Abstract::post_community_voting_data_to_airtable_webhook() and switch case and a new webhook endpoint constant in constant.phpInclude ComVo votes creation in the remote
Improvements
$args['slug'] when votes are sent (each has its own) in the SIA_Ariel_Remote_Abstract::post_community_voting_data_to_airtable_webhook()Include ComVo project updates in the remote
Add a readiness describer to the repo and adjust the Airtable posting remote for project updates.
New
SIA_Ariel_Repository::describe_readiness()IS_READY 200 and IS_NOT_READY 403 to constants.phpImprovements
$args['state'] in the SIA_Ariel_Remote_Abstract::post_community_voting_data_to_airtable_webhook()Provide Project Voting with a remote for posting to the ComVo Reports Airtable base
New
SIA_Ariel_Remote_Abstract::post_community_voting_data_to_airtable_webhook()SIA_Ariel_Repository::describe_status(), added in the new class-sia-ariel-repository.php included in SIA_Ariel::load_dependencies()AIRTABLE_COMVO_BASE_URL) using the app specific AIRTABLE_COMVO_REPORTS_APP_ID .env and webhook suffixes to constants.phpFixes
AIRTABLE_WNA_ACTIVITY_ENDPOINT Airtable app specific string into .env as AIRTABLE_WNA_APP_ID and load it in constants.php via env()Reduced scope of replacement of Google WSL provider with Login with SIA Passport
In order to let other plugins hook into the rendering of WSL provider names, replace Google with Login with SIA Passport only when necessary: login page and non-team blogs.
Other plugins hook into the provider name render to change the login modal, present on other pages
Improvements
wsl_render_auth_widget_alter_provider_name filtering to only non-team blogs or the wp-login.php page in SIA_Ariel_Public::wsl_provider_name()mmlr_wls_action_params filter in SIA_Ariel::define_public_hooks()Add a registration url property to the A&AP class
New
SIA_AAP::$registration_url and, in the constructor, if there are no issue and the SIA_AAP::$url is set, append “user/register” to itSend Host Privacy policy and Imprint page URLs to the A&AP
New
imprint-host and privacy-policy-host to the switch as triggers in SIA_Ariel_Admin::send_application_platform_importable_from_post() hooked to save_postimprint_url and privacy_policy_url in the list of constants sent to the local A&AP from SIA_AAP::set_application_platform_constant_importables() Send the Host contact page post URL to the A&AP
New
contact_url in the list of constants sent to the local A&AP from SIA_AAP::set_application_platform_constant_importables() Send post dependant or constant importables to A&AP
When the application landing page is updated, send its title. Provide a method to send constant importables, like the site email, to A&AP.
New
about-application-host post, in SIA_Ariel_Admin::send_application_platform_importable_from_post() hooked to save_post in SIA_Ariel::define_admin_hooks()SIA_AAP::set_application_platform_constant_importables()Send importable variables to A&AP when Implementation or Stencil options are saved
When the Implementation options page is saved, pass config values through to the A&AP class to POST to the website’s repsective platform in the mapped language. When Stencil options are updated, iterate through website to do the same thing.
New
SIA_Ariel_Remote_Abstract::post_importable_variable_to_country_aap() that sends importables to the A&AP endpoint as formatted dataSIA_AAP::$importablesSIA_AAP::update_application_platform_importables() that takes a $content and optionally $ISO639Language as parameters, formats the data, and passes is to SIA_Ariel_Remote_Abstract::run() with the post_importable_variable_to_country_aap function as a parameterSIA_Ariel_Admin::update_english_application_platforms_importables() to iterate websites’ AAPs and use their formatterSIA_Ariel_Admin::update_application_platform_importables()that takes an $updatedConfig parameter, finds the local website’s AAPs, formats SIA_Publishing_Config data as array, and sends it to the formattersaved_implementation_options to saved_implementation_options and update_english_application_platforms_importables to saved_stencil_options in SIA_Ariel::define_admin_hooks()Fix empty transient value while setting a transient in AJAX calls
New
$value instead of FALSE while setting a transient during an AJAX call from SIA_Ariel_Transient_Service::setTransient() New mirosite identifier helper
SIA_Ariel::is_microsite() to identify at once is_summit() and is_retreat()Fix empty A&AP card ‘details’ notice
$details exists when adding to $cardAtts in SIA_AAP::get_state_card()Mature A&AP cache busting connected to sitemaps
Introduce the notion of cacheable properties in the AAP objects, and when they are changed, bust sitemap and static caches.
SIA_AAP::cacheable property to store data that shows on other pagesSIA_AAP::majorUpdate() method that takes the old AAP object and compares submodules data that is also shown on other pagesSIA_AAP::__bust_cache() that empties transients and, when the update is major, , also bust sitemaps cache by calling SIA_Publishing_Sitemap::__bust_cache() for both the AAP’s team blog id and the international blog idSIA_AAP shown between the application close and announcement (after which it becomes “Overdue”)SIA_Ariel_REST::store_country_aap_data()New shorthands for the retreat and summit blogs
SIA_Ariel::is_retreat() and SIA_Ariel::is_summit()Improve transient management, especially busting
SIA_Ariel_REST::store_country_aap_data()SIA_Website $team and $maintainer from transientsSIA_Ariel_Transient_Service::bust_transient_variants() using a partial name LIKE%% query SIA_Ariel_Transient_Service::listTransients()SIA_Ariel_Transient_Service::setTransient()$network parameter to SIA_Ariel_Transient_Service::bust_transient() in order to reuse it for site (“network”) transientsSIA_Ariel_Transient_Service::bust_network_transient() that passes parameters to bust_transient() with the $network parameter set to TRUEbust_network_transients() to SIA_Ariel_Transient_Service::bust_transient_in_all_blogs() in order to clarify its purpose and actually not use it anywhereIntroduce the concept of critical posts for a SIA Website
page_for_privacy_policy, page_on_front, and page_for_posts properties that load the blog options in SIA_Website::__construct()SIA_Website::post_is_critical() with a $postId parameter that checks if it’s one of the above Allow members of suspended organizations to log into Play
SIA_Ariel_Public::block_access_for_inactive_accounts()SIA_Team_Member::can_edit_team() to use the SIA_Team::$licensingStatus propertyAdd a helper checking a team member can update a licensing status
Check if a specific Organization’s licensing status can be edited by the current team member to replace checking each status with each permission.
SIA_Team_Member::can_manage_organization_with_status() that takes a status as a parameter and checks it against the which types of organizations the current user can manageCreate an activity repository that posts service updates to Airtable
Isolate all existing event processors into the new Activity repository to be used by other plugins, and send the service name in the event to adapt to the new Network Activity event structure.
SIA_Ariel_Activity_Repository) to contain all methods related to posting activity events to Airtable SIA_Ariel_Remote_Abstract::post_website_network_activity_to_airtable_webhook()post_event() shorthand out of SIA_Ariel_Remote_Abstract and into SIA_Ariel_Activity_RepositorySIA_Publishing_Public and into SIA_Ariel_Activity_RepositoryInclude stylesheet, active plugins, and is_restricted in Website class websites CLI reports
New shorthand to get a website’s state
SIA_Website::validate_website() to simplify repeated checks whether the website is maintained or its license New shorthand for posting to Airtable and refined logs
SIA_Ariel_Remote_Abstract::post_event() to not have every call from instantiating a new object from the classSIA_Ariel_Remote_Abstract::post_website_network_activity_to_airtable_webhook()post_website_network_activity_to_airtable_webhook() when in production or when the DEBUG_ACTIVITY_LOG environment value is not TRUE$sia_website is stale by generating data o n the fly in SIA_Ariel_Remote_Abstract::post_website_network_activity_to_airtable_webhook()Add a method to post to an Airtable base webhook
Send activity updates to the Airtable automation triggered by a webhook. The webhook accepts JSON and includes a custom “security” token picked up from .env
POSTs updates to be processed by an Airtable automation: SIA_Ariel_Remote_Abstract::post_website_network_activity_to_airtable_webhook() AIRTABLE_WNA_ACTIVITY_ENDPOINT pointing to Website Activity webhookProvide a single site transient buster
SIA_Ariel_Transient_Service::bust_transient() to only bust local transientsbust_network_transients() and only do the blog looping and passing parameters to the method aboveSIA_Team_Member::$off_limits_post_ids propertyCreate a transient management service
SIA_Ariel_Transient_Service with 2 methods: get_transient_name()) depending on class, function, and arguments bust_transient()) across the network provided for other plugins to call when state changesSIA_Ariel::get_websites() moved over from SIA_Profiles and SIA_Ariel::get_blog_ids()SIA_Ariel_Admin::bust_site_transients() hooked to: wp_insert_site, wp_delete_site, and wp_update_siteMove WSL login filters from Parlament
SIA_Ariel_Public::display_wsl_widget() and SIA_Ariel_Public::wsl_provider_name()Provide a switch to check current blog in the stack
SIA_Ariel::is_switched_from() checking in the stack if we originally started from the queried blog idbool param to SIA_Ariel::is_play() using the above to ensure that we’re not saying yes during a switch for profiles Suggest a profile REST route with an empty callback
SIA_Profiles_Public::is_playbook() instead of own SIA_Ariel::is_play().New permission to manage board members
SIA_Team_Member::can() and map it to manage_sites for now;Add the language property to SIA SIA_Website
$language in SIA_Website::__construct() via get_blog_option() for 'WP_LANG'.Refactor REST API calls to use Bearer authentication
SIA_Ariel_Remote_AbstractSIA_Ariel_Remote_Abstract::request_is_valid()SIA_Ariel_Remote_Abstract throw a WP_Error if the .env constant is not setDefine a LICENSOR_ORGANIZATION_POST_ID constant for SIA gGmbH
Expand the SIA_Website class to include ISO2 and sia.click url and link
SIA_Website::get_ISO2() method adapted from SIA_Team$shortUrl and $shortLink propertiesInclude country user in the Sites network admin report and fix admin email
Get archival data from AAP API and use salted authorization tokens using the .env salt and tokens
Parametrize Ariel::is... and ensure SIA_Ariel_Public::initialize_sia_website() doesn’t perform double duty
New status constants
New REST route to show Application & Assessment data
Allow Communications Coordinator user role to edit own organization
edit_own_organization permission in SIA_Team_Member::can(), return TRUE for users with the “communications_coordinator” role Check if a team member belongs to an organization and can edit it
SIA_Team_Member::user_is_member_of_organization() methodSIA_Team_Member::can() and check if a user is holds either “Coordinator” or “Organizational lead” community rolesSIA_Team_Member::get_user_organization() method to get a user’s organization (can be only one)SIA_Team_Member::can_edit_organization() helperFix incorrect empty community role values from team member profile by stopping to try to chain SIA_Team_Member::get() with SIA_Post_Interface::get() which only gets values of WP_Post
New SIA_Website class to hold license details
Improve permission check in SIA_Team_Member::can() when global $current_team_member is already set
Filter mmlr_wls_action_params to only show Google as Wordpress Social Login provider
Migrate the WSL config alter hook from Deployment
First version as Ariel
Return country name after AAP REST; Improve error messages
Add a WANDA_DOMAIN constant from env() and re-use in other URL constants
Fix not adding the “slug” key to AAP meta.
Pivot to using ISO2 in AAP REST.
Fix not sending AAP REST error text.
Fix only recording AAP REST data only for active teams.
Fix check for Restricted Site Access being enabled.
Create a REST endpoint for adding A&AP data to teams
New umbrella manage_implementation_partners permission.
Provide static methods to verify blog purpose (stencil, team, management).
Switch the Team member profile permissions to default capabilities.
Improve creation of profiles that don’t use Passports
Fix lack or return from get_sia_profile and improve yet another edge case: valid profile, missing org.
Integrate access levels to support Profiles, Play, and themes.