-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add auto-provisioning for matomo #52
base: master
Are you sure you want to change the base?
Conversation
classes/tool/tool_base.php
Outdated
@@ -144,4 +146,13 @@ public function trackurl($urlencode = false, $leadingslash = false): string { | |||
return $trackurl; | |||
} | |||
|
|||
/** | |||
* Override in child to implement. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please flesh this out more with how this should work generically, eg if someone wanted to come and add support for GA later on
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That should be more descriptive now.
classes/form/edit.php
Outdated
@@ -27,6 +27,9 @@ | |||
|
|||
use moodleform; | |||
use tool_webanalytics\plugin_manager; | |||
use tool_webanalytics\record; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are those leftovers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct and now removed.
tool/matomo/README.md
Outdated
- Set the global config settings 'apitoken' and 'apiurl' to enable auto provisioning. These can also be set in config.php e.g: | ||
- `$CFG->forced_plugin_settings['watool_matomo']['apiurl'] = 'https://matomo.org';` | ||
- `$CFG->forced_plugin_settings['watool_matomo']['apitoken'] = 'xxxx';` | ||
- Auto provisioning attempts are made if the current site url has changed since any of the instances were stored. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please flesh this out a bit more, this might only need comments but might be some missing code too. I want to understand what is happened if we roll this auto provisioning out toa pre production side, eg p-client.catalyst-au.net and they get a matomo instance, and then a few months later they go live and the dns changes to moodle.client.com
In this scenario I can see a method called update_site but it isn't actually called from anywhere?
I would expect this to continue using the same matomo id, ie the one instance will seamlessly show stats from before and after the dns change. This should be the same as if the client later changes their domain for marketing reasons, the stats should continue to be seamless.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was previously just creating a new instance on the matomo server when the DNS changed but is now updating the url over the API if the DNS changes, essentially keeping the site id the same. Have fleshed this out in the docs.
Note that when manually adding an instance config on the front end it will also try to create/update over the API if the API config is in the form.
I have also documented these methods in unit tests for the watool_matomo plugin too.
tool/matomo/README.md
Outdated
@@ -0,0 +1,22 @@ | |||
# Matomo (formerly Piwik) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've also realized this is a new readme file. Even though this is specific to the tool_matomo I think this should be a section under the main readme purely to make it easier to find when casually browsing github so you don't have to go dig. We could just cross link the two readmes but this chunk of help is small enough that we can just embed it directly.
In theory if we added this same support to GA and other tools they could all be inline in the main readme
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have moved this to the parent plugin README
5445cbf
to
f4c5caf
Compare
f4c5caf
to
0268e6a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mentioning the issues I've noticed. We'll work on getting these sorted.
<TABLE NAME="watool_matomo_api_error_log" COMMENT="Matomo Track log errors"> | ||
<FIELDS> | ||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/> | ||
<FIELD NAME="endpoint" TYPE="text" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="The name of the endpoint function called during the sync attempt"/> | ||
<FIELD NAME="error" TYPE="text" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="The string given as the error"/> | ||
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/> | ||
</FIELDS> | ||
<KEYS> | ||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/> | ||
</KEYS> | ||
</TABLE> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- This table is missing an upgrade step
- Table name is needlessly long and could cause issues
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree we probably just don't need the table
$request['method'] = 'SitesManager.addSite'; | ||
$request['siteName'] = !empty($sitename) ? $sitename : $SITE->fullname; | ||
$request['timezone'] = !empty($timezone) ? $timezone : core_date::get_server_timezone(); | ||
$request['currency'] = !empty($currency) ? $currency : 'GBP'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fallback currency should be more global
if (!empty($url['scheme'])) { | ||
return $this->config->siteurl; | ||
} | ||
return "https://{$url['path']}"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't look like it would form a proper url
'id' => 'id', | ||
'username' => 'username', | ||
'id' => 'id', | ||
'username' => 'username', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indenting changed to being incorrect
* Otherwise, create a new instance over the API. | ||
* | ||
* @param $client | ||
* @return int siteid if successful, 0 if not. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would recommend clarifying what is returned for already registered sites. This appears to be siteid, so would be "if successful or already registered"
$settings->add( | ||
new admin_setting_heading( | ||
'watool_matomo_autoprovision', | ||
get_string('autoprovision_heading', 'watool_matomo'), | ||
'' | ||
) | ||
); | ||
$settings->add( | ||
new admin_setting_configtext( | ||
'watool_matomo_siteurl', | ||
get_string('apiurl', 'watool_matomo'), | ||
get_string('apiurl_help', 'watool_matomo'), | ||
$CFG->forced_plugin_settings['watool_matomo']['url'] ?? '', | ||
PARAM_URL | ||
) | ||
); | ||
$settings->add( | ||
new admin_setting_configpasswordunmask( | ||
'watool_matomo_token', | ||
get_string('apitoken', 'watool_matomo'), | ||
get_string('apitoken_desc', 'watool_matomo'), | ||
$CFG->forced_plugin_settings['watool_matomo']['token'] ?? '', | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indenting
$category = new admin_category( | ||
'tool_webanalytics', | ||
new lang_string('pluginname', 'tool_webanalytics'), | ||
false | ||
); | ||
$ADMIN->add('tools', $category); | ||
|
||
$externalpage = new admin_externalpage( | ||
'tool_webanalytics_manage', | ||
get_string('pluginname', 'tool_webanalytics'), | ||
new moodle_url('/admin/tool/webanalytics/manage.php') | ||
'tool_webanalytics_manage', | ||
get_string('pluginname', 'tool_webanalytics'), | ||
new moodle_url('/admin/tool/webanalytics/manage.php') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indenting
use curl; | ||
use Exception; | ||
use moodle_url; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
curl and moodle_url aren't used
use tool_webanalytics\tool\tool_interface; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this needed?
$settings = []; | ||
$settings['siteid'] = isset($data->siteid) ? $data->siteid : ''; | ||
$settings['siteid'] = isset($data->siteid) ? $data->siteid : ''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a bit repetitive to me, can this be a $defaults array and then cast the stdClass to an array and merge them and skip all the isset bits?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found a couple of extra issues after more testing
foreach ($records as $record) { | ||
$settings = $record->get_property('settings'); | ||
$name = $record->get_property('name'); | ||
if ((!empty($settings['wwwroot']) && $settings['wwwroot'] === $CFG->wwwroot) || $name === 'auto-provisioned:FAILED') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If $settings['wwwroot'] doesn't exist (which will happen for existing records since this is a new setting) auto provision is allowed for sites that may already have the proper URL set. Right now this will lead to creating a duplicate record due to other mentioned issues.
$request['siteName'] = !empty($sitename) ? $sitename : $SITE->fullname; | ||
$request['timezone'] = !empty($timezone) ? $timezone : core_date::get_server_timezone(); | ||
$request['currency'] = !empty($currency) ? $currency : 'GBP'; | ||
$request = array_merge($request, $this->build_urls_for_request($urls)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the build_urls_for_request function isn't provided with the existing urls (none are passed here), it will override all existing sites with just the updated site. This is problematic for registrations that are connected to multiple site urls. This is used in both registrations and auto provisioning.
$allrecords = $rm->get_all(); | ||
$autoprovisioned = array_filter($allrecords, function($record) { | ||
return preg_match("/^auto-provisioned:/", $record->get_property('name')); | ||
}); | ||
|
||
if ($autoprovisioned = reset($autoprovisioned)) { | ||
$apsettings = $autoprovisioned->get_property('settings'); | ||
$data = $autoprovisioned->export(); | ||
} else { | ||
$data = new stdClass(); | ||
$data->name = 'auto-provisioned:' . uniqid(); | ||
} | ||
|
||
$hasdnschanged = !empty($apsettings['wwwroot']) && $apsettings['wwwroot'] !== $CFG->wwwroot; | ||
|
||
try { | ||
// If the DNS has changed, let's try to update an existing site. | ||
if ($hasdnschanged && $siteid = $client->get_siteid_from_url($apsettings['wwwroot'])) { | ||
$client->update_site($siteid, '', [$CFG->wwwroot]); | ||
} else { | ||
// No site provisioned yet, create a new one. | ||
$siteid = $client->add_site(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is hardcoded to 'auto-provisioned', but if there's no match it goes straight to adding a site, which will create duplicates for sites that have a manual link or have changed the name. Needs some extra checks.
$CFG->forced_plugin_settings['watool_matomo']['url'] ?? '', | ||
PARAM_URL | ||
) | ||
); | ||
$settings->add( | ||
new admin_setting_configpasswordunmask( | ||
'watool_matomo_token', | ||
get_string('apitoken', 'watool_matomo'), | ||
get_string('apitoken_desc', 'watool_matomo'), | ||
$CFG->forced_plugin_settings['watool_matomo']['token'] ?? '', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The defaults don't match the names of the settings that are used elsewhere or in the readme, and the token setting name doesn't match either. It may also be better to not use these as the default so the token can be kept hidden?
$this->config = $config; | ||
$this->settings = $settings; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Properties for these haven't been declared.
This commit contains the ability to auto provision sites based on either a value in the config.php file or via the instance form on the front end.
To auto provision on install or upgrade add a setting
watool_matomo
intoconfig.php
as an array, e.g:Where the apitoken is the
auth_token
of the user that is allowed to do API requests on the Matomo server, and the 'siteurl' is the URL of the Matomo server instance.During install if the above setting is present it will loop through the array and attempt to create a site on the remote Matomo instance per array item. If successful, it create new records locally and stores the siteid, the apitoken, and the siteurl per instance created.
When manually adding a new instance via the front end, an auto provision attempt will be made if the form submission contains both the siteurl and the apitoken. If successful, the siteid is retrieved and stored against the local record. If the form is submitted with a siteid, there will be not attempt to register with the remote server.
Additionally, at the point of submisision the current
CFG->wwwroot
is stored against that instance locally. On page loads that check if the tag should be output, a check is made to see if the currentCFG->wwwroot
matches that stored against the local record. If it does not match, an attempt is made to update the remotely registered instance with the new url. If successful, this new url is then stored locally. This is to allow the remote to track if and when the url of the server changes.