I'm coming back to this question after some time because I feel like I have a bit more knowledge to be able to tackle it. Starting from Andy's pseudo-code, this is what I've got and it seems to be working ok, but I wonder if there's a better way to do it.
I also wonder if I need to code a bit more defensively. I guess this runs on every request, so I'm not sure if it's something that could be optimized. The tags are added to the user after purchasing a membership through our Commerce store (in another module.)
Andy mentioned setting it up as a Twig filter but I haven't got to that point yet.
$user = Craft::$app->getUser()->getIdentity();
if (!$user) {
return;
}
$loyalty = 0;
$currentYear = date('Y');
$previousYear = null;
$years = Tag::find()->groupId(1)->relatedTo($user)->all();
arsort($years);
foreach ($years as $year) {
if ($year->title == $currentYear) {
$loyalty++;
$previousYear = bcsub($year->title, 1);
}
if (!empty($previousYear)) {
if ($year->title == $previousYearMinusOne) {
$loyalty++;
$previousYear = bcsub($year->title, 1);
}
}
}
$user->setFieldValue('loyalty', $loyalty);
Craft::$app->getElements()->saveElement($user);
I'd appreciate any tips!