User Activity by Xon

User Activity by Xon 2.13.4

No permission to download
Hello Xon,

I have only now noticed that Redis and Caching are necessary and recommended for this addon. I don't use either (Redis is not possible on my managed server). Nevertheless, the addon works. Should I still uninstall it?
 
This add-on works without redis, but it comes down to how busy your site is. With a few visitors that will be fine, but the busier the site the more I recommend using a caching backend.
 
Ok, then I'm reassured. We currently never have more than 3000 unique users per day. On its own server. That shouldn't be a problem I guess. Does the add-on cause an increase in data that I should delete at regular intervals?

Two questions, Xon: Zend OPcache is running on our server. Could you also cache your add-on with it? I also use Cloudflare. Maybe User Activity
data caching also works with CF?

Best regards
 
"opcache" only caches php bytcode, not user data. Cloudflare cache the entire page. These are different from XF's caching system
 
I get this when trying to upgrade from XF1:

ErrorException: Batch install error: [E_WARNING] ZipArchive::open(): Empty string as source

src/XF/Service/AddOnArchive/Extractor.php:36

Generated by: Alfa1
May 1, 2021 at 8:53 AM

Stack trace

#0 [internal function]: XF::handlePhpError(2, '[E_WARNING] Zip...', '/home/nginx/dom...', 36, Array)
#1 src/XF/Service/AddOnArchive/Extractor.php(36): ZipArchive->open('')
#2 src/XF/Service/AddOnArchive/Extractor.php(56): XF\Service\AddOnArchive\Extractor->open()
#3 src/XF/Service/AddOnArchive/Extractor.php(125): XF\Service\AddOnArchive\Extractor->zip()
#4 src/XF/Job/AddOnInstallBatch.php(176): XF\Service\AddOnArchive\Extractor->copyFiles(NULL, 0, Object(XF\Timer))
#5 src/XF/Job/AddOnInstallBatch.php(81): XF\Job\AddOnInstallBatch->stepCopy(Object(XF\Timer))
#6 src/XF/Job/Manager.php(258): XF\Job\AddOnInstallBatch->run(8)
#7 src/XF/Job/Manager.php(200): XF\Job\Manager->runJobInternal(Array, 8)
#8 src/XF/Job/Manager.php(116): XF\Job\Manager->runJobEntry(Array, 8)
#9 src/XF/Admin/Controller/Tools.php(120): XF\Job\Manager->runByIds(Array, 8)
#10 src/XF/Mvc/Dispatcher.php(350): XF\Admin\Controller\Tools->actionRunJob(Object(XF\Mvc\ParameterBag))
#11 src/XF/Mvc/Dispatcher.php(257): XF\Mvc\Dispatcher->dispatchClass('XF:Tools', 'RunJob', Object(XF\Mvc\RouteMatch), Object(SV\UserMentionsImprovements\XF\Admin\Controller\Tools), NULL)
#12 src/XF/Mvc/Dispatcher.php(113): XF\Mvc\Dispatcher->dispatchFromMatch(Object(XF\Mvc\RouteMatch), Object(SV\UserMentionsImprovements\XF\Admin\Controller\Tools), NULL)
#13 src/XF/Mvc/Dispatcher.php(55): XF\Mvc\Dispatcher->dispatchLoop(Object(XF\Mvc\RouteMatch))
#14 src/XF/App.php(2326): XF\Mvc\Dispatcher->run()
#15 src/XF.php(488): XF\App->run()
#16 admin.php(13): XF::runApp('XF\\Admin\\App')
#17 {main}

Request state

array(4) {
["url"] => string(33) "/xf/admin.php?tools/run-job"
["referrer"] => string(61) "-xf/admin.php?tools/run-job"
["_GET"] => array(1) {
["tools/run-job"] => string(0) ""
}
["_POST"] => array(3) {
["_xfRedirect"] => string(96) "-xf/admin.php?add-ons/install-from-archive-complete&batch_id=9"
["_xfToken"] => string(8) "********"
["only_ids"] => string(3) "143"
}
}
 
Nothing about the add-ons zips are special, they are made via XenForo's add-on builder using php7.4. The only reference to that error message is a stupidly old version of XenForo & likely php.

What version of php are you using?
 
I think I've discovered a little bug:
If a node does have a node_name set, the activity is not being tracked as param node_id ist not set in this caes when calling XF\Repository\SessionActivity::updateSessionActivity

Would it be possible to add a setting to choose the location for template forum_view?
Could probably use the existing setting with some rewording.

Code:
<h3 class="block-minorHeader">{{ phrase('svUserActivity_users_who_are_viewing_this_x', {'content_type': $contentTypePhrase|to_lower}) }}</h3>
It seems impossible to properly translate this into german:
In german, the first letter of the content type name needs to be uppercase as it is a noun.

Furthermore, translation depends on the grammatical gender ("genus") of the noun - Thema (thread) for example is neutral whereas conversation is female (if translated as Unterhaltung or Konversation).

Would it be possible to change this so an individual phrase is being used for each content type?
That would allow to translate this properly :)
 
Last edited:
I think I've discovered a little bug:
If a node does have a node_name set, the activity is not being tracked as param node_id ist not set in this caes when calling XF\Repository\SessionActivity::updateSessionActivity
The code actually extracts the observed node_id(s) from the Response's View::getParam variables, and doesn't actually parse it out of the arguments that go into the action.

This pattern allows the code to only run & extract user activity if the user has permission to view the relevant content.

Would it be possible to add a setting to choose the location for template forum_view?
Could probably use the existing setting with some rewording.
The code for viewing user activity in a container (vs the thread/conversation/etc) wasn't an initial goal and was only added after a paid request.

Moving the actual code yourself is very simple;
HTML:
<xf:macro template="UA_ViewContainer_macros"
          name="UserActivity"
          arg-contentTypePhrase="{{ phrase('forum') }}"
          arg-records="{$UA_Records}"/>

This impacts a few places, "Adds activity containers (list)" template mods for a number of categories/nodes/etc, and then wiring up a style property or option. These really should be style properties, but migrating from options to style properties is frustrating and annoying, so I haven't done that.

I'm open to pull requests on github however.

Code:
<h3 class="block-minorHeader">{{ phrase('svUserActivity_users_who_are_viewing_this_x', {'content_type': $contentTypePhrase|to_lower}) }}</h3>
It seems impossible to properly translate this into german:
In german, the first letter of the content type name needs to be uppercase as it is a noun.

Furthermore, translation depends on the grammatical gender ("genus") of the noun - Thema (thread) for example is neutral whereas conversation is female (if translated as Unterhaltung or Konversation).

Would it be possible to change this so an individual phrase is being used for each content type?
That would allow to translate this properly :)
My recommendation is just translate svUserActivity_users_who_are_viewing_this_x as not actually mentioning the current content type which is one thing I've actually been considering.

I'm open to a PR on github if you want to go through all the effort to write essentially every template modification and create about dozen new phrases.
 
The code actually extracts the observed node_id(s) from the Response's View::getParam variables, and doesn't actually parse it out of the arguments that go into the action.
Hmm, maybe I am missing smth.?

PHP:
class SessionActivity extends XFCP_SessionActivity
{
    /**
     * @param int $userId
     * @param $ip
     * @param string $controller
     * @param string $action
     * @param array $params
     * @param string $viewState enum('valid','error')
     * @param string $robotKey
     */
    public function updateSessionActivity($userId, $ip, $controller, $action, array $params, $viewState, $robotKey)
    {
        /** @var \SV\UserActivity\Repository\UserActivity $userActivityRepo */
        $userActivityRepo = \XF::repository('SV\UserActivity:UserActivity');
        $visitor = \XF::visitor();
        if ($userActivityRepo->isLogging() && $viewState == 'valid' && $userId === $visitor->user_id)
        {
            $handler = $userActivityRepo->getHandler($controller);
            if (!empty($handler))
            {
                $requiredKey = $handler['id'];
                if (!empty($params[$requiredKey]))
                {
                    $userActivityRepo->bufferTrackViewerUsage($handler['type'], $params[$requiredKey], $handler['activeKey']);
                }

So when this is called for a forum, $handler would be
Code:
[
    'controller' => 'XF\Pub\Controller\Forum',
    'type'       => 'node',
    'id'         => 'node_id',
    'actions'    => ['forum'],
    'activeKey'  => 'forum',
]

As $handler is not empty it would take $handler['id'] (= node_id) as the $requiredKey to look up in $params.

But if the node does have a node_name set, $params['node_id'] would be empty as only $params['node_name'] ist set in this case so $userActivityRepo->bufferTrackViewerUsage never does get called?
 
As $handler is not empty it would take $handler['id'] (= node_id) as the $requiredKey to look up in $params.

But if the node does have a node_name set, $params['node_id'] would be empty as only $params['node_name'] ist set in this case so $userActivityRepo->bufferTrackViewerUsage never does get called?
After more review, this does looks to be a bug. There where some XF2.0 like handling which wasn't updated to XF2.1 too.

Both should be fixed for the next version.
 
Not sure if this is working as designed or a bug?

Settings
Prune chance = 1
Fill factor = 0
Thread contribute limit = 1
Track user activity = Thread, Forum, Category
Display user list = Thread, Forum
Display viewer counts = Index Page Forums, Category View, Sub forum list
Track guests = yes
Track robots = yes

I am the only user that is active and I am viewing a forum with several sub-forums.
I click on every sub-forum link to open in a new tab, close those new tabs again and afterwards refresh the page.

Now every sub forum does show one visitor, although there effectively is none.
 
The user activity buckets by the online time (ie ~15 minute blocks) to show users as "active" and doesn't actually care about logging out of if you close the tab.

This is more of a performance thing as you really only notice it with low activity numbers.
 
Xon updated User Activity by Xon with a new update entry:

2.9.0 - Feature & bugfix update

  • php 7+ type hinting
  • Force global namespace for functions which are known to be optimizable to bytecode in php, or known global functions to avoid a current namespace lookup for the function.
  • Fix forum activity not registering as expected when a node_name is set on the forum
  • Fix logging XF2.1+ reaction events as thread activity & remove old XF2.0 like handling for posts.
  • Replace single svUserActivity_users_who_are_viewing_this_x phrase with various...

Read the rest of this update entry...
 
Getting a ton of these since update

  • LogicException: Macro public:UA_ViewContainer_macros :: UserActivity() error: Macro argument contentTypePhrase is required and no value was provided
  • src/XF/Template/Templater.php:896
  • Generated by: Unknown account
  • Aug 24, 2021 at 7:13 AM
 
Getting a ton of these since update

  • LogicException: Macro public:UA_ViewContainer_macros :: UserActivity() error: Macro argument contentTypePhrase is required and no value was provided
  • src/XF/Template/Templater.php:896
  • Generated by: Unknown account
  • Aug 24, 2021 at 7:13 AM
Is this just during the upgrade if so that is expected.

Otherwise I need the stack trace.
 
Even after

Stack trace​

#0 src/XF/Template/MacroState.php(60): XF\Template\Templater->mergeMacroArguments(Array, Array, Array)
#1 src/XF/Template/Templater.php(789): XF\Template\MacroState->getAvailableVars(Object(SV\StandardLib\XF\Template\Templater), Array, Array)
#2 internal_data/code_cache/templates/l1/s12/public/thread_view.php(948): XF\Template\Templater->callMacro('UA_ViewContaine...', 'UserActivity', Array, Array)
#3 src/XF/Template/Templater.php(1644): XF\Template\Templater->{closure}(Object(SV\StandardLib\XF\Template\Templater), Array, Object(XF\Template\ExtensionSet))
#4 src/XF/Template/Template.php(24): XF\Template\Templater->renderTemplate('thread_view', Array)
#5 src/XF/Mvc/Renderer/Html.php(48): XF\Template\Template->render()
#6 src/XF/Mvc/Dispatcher.php(458): XF\Mvc\Renderer\Html->renderView('XF:Thread\\View', 'public:thread_v...', Array)
#7 src/XF/Mvc/Dispatcher.php(440): XF\Mvc\Dispatcher->renderView(Object(XF\Mvc\Renderer\Html), Object(XF\Mvc\Reply\View))
#8 src/XF/Mvc/Dispatcher.php(400): XF\Mvc\Dispatcher->renderReply(Object(XF\Mvc\Renderer\Html), Object(XF\Mvc\Reply\View))
#9 src/XF/Mvc/Dispatcher.php(58): XF\Mvc\Dispatcher->render(Object(XF\Mvc\Reply\View), 'html')
#10 src/XF/App.php(2344): XF\Mvc\Dispatcher->run()
#11 src/XF.php(512): XF\App->run()
#12 index.php(20): XF::runApp('XF\\Pub\\App')
#13 {main}
 
Even after

Stack trace​

#0 src/XF/Template/MacroState.php(60): XF\Template\Templater->mergeMacroArguments(Array, Array, Array)
#1 src/XF/Template/Templater.php(789): XF\Template\MacroState->getAvailableVars(Object(SV\StandardLib\XF\Template\Templater), Array, Array)
#2 internal_data/code_cache/templates/l1/s12/public/thread_view.php(948): XF\Template\Templater->callMacro('UA_ViewContaine...', 'UserActivity', Array, Array)
#3 src/XF/Template/Templater.php(1644): XF\Template\Templater->{closure}(Object(SV\StandardLib\XF\Template\Templater), Array, Object(XF\Template\ExtensionSet))
#4 src/XF/Template/Template.php(24): XF\Template\Templater->renderTemplate('thread_view', Array)
#5 src/XF/Mvc/Renderer/Html.php(48): XF\Template\Template->render()
#6 src/XF/Mvc/Dispatcher.php(458): XF\Mvc\Renderer\Html->renderView('XF:Thread\\View', 'public:thread_v...', Array)
#7 src/XF/Mvc/Dispatcher.php(440): XF\Mvc\Dispatcher->renderView(Object(XF\Mvc\Renderer\Html), Object(XF\Mvc\Reply\View))
#8 src/XF/Mvc/Dispatcher.php(400): XF\Mvc\Dispatcher->renderReply(Object(XF\Mvc\Renderer\Html), Object(XF\Mvc\Reply\View))
#9 src/XF/Mvc/Dispatcher.php(58): XF\Mvc\Dispatcher->render(Object(XF\Mvc\Reply\View), 'html')
#10 src/XF/App.php(2344): XF\Mvc\Dispatcher->run()
#11 src/XF.php(512): XF\App->run()
#12 index.php(20): XF::runApp('XF\\Pub\\App')
#13 {main}
Check that the UA_ViewContainer_macros template isn't out of date, as it you probably have customizations which need merging.
 
Top Bottom