From 5b50afdcafd150186ea5c7b0e1cad98065590b35 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Fri, 28 Aug 2026 18:44:28 +0000
Subject: [PATCH] =A few more phpStorm suggestions, mainly in PHPDocs

---
 inc/integrations/services/Umami.php |  209 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 207 insertions(+), 2 deletions(-)

diff --git a/inc/integrations/services/Umami.php b/inc/integrations/services/Umami.php
index ebc22df..b67bc45 100644
--- a/inc/integrations/services/Umami.php
+++ b/inc/integrations/services/Umami.php
@@ -1,8 +1,9 @@
 <?php
 namespace JVBase\integrations\services;
 use JVBase\integrations\Admin;
-use JVBase\integrations\Instance;
+use JVBase\Instance;
 use JVBase\integrations\Integrations;
+use JVBase\registrar\Registrar;
 
 if (!defined('ABSPATH')) {
 	exit;
@@ -11,8 +12,212 @@
 class Umami extends Integrations
 {
 	use Admin, Instance;
+
+	protected function __construct()
+	{
+		$this->service_name = 'umami';
+		$this->title = 'umami';
+		$this->icon = 'chart-line';
+
+		$this->defineFields();
+		$this->defineInstructions();
+
+		parent::__construct();
+		$this->defineTables();
+	}
+
+	protected function defineFields(): void
+	{
+		$id = $this->addField('website_id', 'Website ID', 'text', 'manage_options');
+		$id->setHint('Found in your Umami dashboard under Settings->Websites');
+		$id->setRequired();
+
+		$api_url = $this->addField('api_url', 'API URL', 'text', 'manage_options');
+		$api_url->setHint('Your Umami server URL. Leave blank if using umami.is cloud service.');
+
+		$api_token = $this->addField('api_token', 'API Token (Optional)', 'text', 'manage_options');
+		$api_token->setSubType('password');
+		$api_token->setHint('Required only if you want to retrieve analytics data for dashboards.');
+	}
+	protected function defineInstructions():void
+	{
+		$this->instructions = [
+			'Login to your <a href="https://cloud.umami.is/settings/websites" target="_blank">umami.is</a> account, select your website, and copy the website ID'
+		];
+	}
+
+	protected function defineTables():void
+	{
+		//TODO: Once we have an actual umami setup, we can store the fetched data here for reference
+		//Ideally, we have the type (term, user, post), WP ID, created_date, and count
+	}
+
 	protected function initialize(): void
 	{
-		// TODO: Implement initialize() method.
+		// Add tracking script to frontend
+		add_action('wp_head', [$this, 'renderTrackingScript'], 5);
+
+		// Schedule data collection if API is configured
+		if ($this->getApiToken()) {
+			add_action('jvb_daily_umami_collection', [$this, 'collectDailyData']);
+
+			if (!wp_next_scheduled('jvb_daily_umami_collection')) {
+				wp_schedule_event(time(), 'daily', 'jvb_daily_umami_collection');
+			}
+		}
 	}
+
+	public function renderTrackingScript():void
+	{
+		if (JVB_TESTING || !$this->isSetUp() || is_admin()) {
+			return;
+		}
+
+		$script_url = $this->getTrackingScriptUrl();
+		if (!$this->getWebsiteID() || empty($script_url)) {
+			return;
+		}
+
+		echo sprintf(
+			'<link rel="preconnect" href="https://%s"/>' . "\n",
+			esc_attr(parse_url($script_url, PHP_URL_HOST))
+		);
+
+		$attributes = [
+			'defer',
+			sprintf(
+				'src="%s"',
+				esc_url($script_url)
+			),
+			sprintf(
+				'data-website-id="%s"',
+				esc_attr($this->getWebsiteID())
+			)
+		];
+
+		$tags = $this->getCurrentTag();
+		if (!empty($tags)) {
+			$attributes[] = $tags;
+		}
+
+		echo sprintf(
+			'<script %s></script>',
+			implode(' ', $attributes)
+		);
+
+		$this->outputCustomEvent();
+	}
+		protected function getCurrentTag():string
+		{
+			$contentTax = array_map('jvbCheckBase', Registrar::withFeature('is_content', 'term'));
+			if (!empty($contentTax) && is_tax($contentTax)) {
+				$tax = get_queried_object();
+				$reg = Registrar::getInstance($tax->taxonomy);
+				return 'data-tag="'.$reg->getUmamiEvent().'"';
+			}
+
+			$profiles = array_map('jvbCheckBase', Registrar::withFeature('profile_link'));
+			if (!empty($profiles) && is_singular($profiles)) {
+				$usr = get_queried_object();
+				$reg = Registrar::getInstance($usr->post_type);
+				return 'data-tag="'.$reg->getUmamiEvent().'"';
+			}
+
+			return '';
+		}
+
+		protected function outputCustomEvent():void
+		{
+			$args = [];
+			$event = false;
+			$contentTax = array_map('jvbCheckBase', Registrar::withFeature('is_content', 'term'));
+			if (!empty($contentTax) && is_tax($contentTax)) {
+				$tax = get_queried_object();
+				$reg = Registrar::getInstance($tax->taxonomy);
+
+				$event = $reg->getUmamiEvent();
+				$args = [
+					'id'	=> $tax->term_id,
+				];
+				if ($reg->isOwnable()) {
+					$owners = jvbGetTermOwners($tax->term_id);
+					if (!empty($owners)) {
+						$args['owners'] = $owners;
+					}
+				}
+			}
+
+			$profiles = array_map('jvbCheckBase', Registrar::withFeature('profile_link'));
+			if (!empty($profiles) && is_singular($profiles)) {
+				$usr = get_queried_object();
+				$reg = Registrar::getInstance($usr->post_type);
+				$event = $reg->getUmamiEvent();
+
+				global $post;
+				$args['id'] = get_the_ID();
+				$args['owner_id'] = $post->post_author;
+			}
+
+			if ($event && !empty($args)) {
+				echo sprintf(
+					'<script defer>umami.track(event_name: %s, data: %s);</script>',
+					$event,
+					json_encode($args)
+				);
+			}
+		}
+
+	/*********************************************************
+	 * UTILITY
+	 *********************************************************/
+	public function getWebsiteID(): string|false
+	{
+		return $this->loadCredentials()['website_id']??false;
+	}
+	protected function getApiUrl():string|false
+	{
+		$api = $this->loadCredentials()['api_url'];
+		return empty($api) ? false : $api;
+	}
+	protected function getApiToken():string|false
+	{
+		$api = $this->loadCredentials()['api_token'];
+		return empty($api) ? false : $api;
+	}
+	protected function getTrackingScriptUrl():string
+	{
+		if ($this->getApiUrl()) {
+			return rtrim($this->getApiUrl(), '/').'/script.js';
+		}
+		// Default to Umami cloud
+		return 'https://cloud.umami.is/script.js';
+	}
+
+	public function buildEvent(string $event, array $args = []):string
+	{
+		$base = 'data-umami-event';
+		$out = [
+			$base	=> esc_attr($event),
+		];
+
+		foreach ($args as $k => $v) {
+			$out[$base.$k] = esc_attr(jvbNoBase($v));
+		}
+
+		return $this->attributesToString($out);
+	}
+
+		protected function attributesToString(array $attributes):string
+		{
+			$strings = [];
+			foreach ($attributes as $key => $value) {
+				$strings[] = sprintf(
+					'%s="%s"',
+					$key,
+					$value
+				);
+			}
+
+			return implode(' ', $strings);
+		}
 }

--
Gitblit v1.10.0