.
*/
// phpcs:disable PSR1.Files.SideEffects.FoundWithSymbols
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
if (!defined('LOGTIVITY_VERSION')) {
define('LOGTIVITY_VERSION', '3.3.8');
}
class Logtivity
{
public const ACCESS_LOGS = 'view_logs';
public const ACCESS_SETTINGS = 'view_log_settings';
/**
* @var string
*/
protected string $version = LOGTIVITY_VERSION;
/**
* Integrations with other plugins
*
* @var array[]
*/
protected array $integrations = [
WP_DLM::class => 'Download_Monitor',
MeprCtrlFactory::class => 'Memberpress',
Easy_Digital_Downloads::class => 'Easy_Digital_Downloads',
EDD_Software_Licensing::class => 'Easy_Digital_Downloads/Licensing',
EDD_Recurring::class => 'Easy_Digital_Downloads/Recurring',
FrmHooksController::class => 'Formidable',
PMXI_Plugin::class => 'WP_All_Import',
\Code_Snippets\Plugin::class => 'Code_Snippets',
];
/**
* @var bool
*/
protected bool $coreLoaded = false;
public function __construct()
{
$this->loadCore();
$this->activateLoggers();
add_action('upgrader_process_complete', [$this, 'upgradeProcessComplete'], 10, 2);
add_action('activated_plugin', [$this, 'setLogtivityToLoadFirst']);
add_action('admin_notices', [$this, 'welcomeMessage']);
add_action('admin_notices', [$this, 'checkForSiteUrlChange']);
add_action('admin_enqueue_scripts', [$this, 'loadScripts']);
add_action('admin_init', [$this, 'redirectOnActivate']);
add_filter('plugin_action_links_' . plugin_basename(__FILE__), [$this, 'addSettingsLinkFromPluginsPage']);
register_activation_hook(__FILE__, [$this, 'activated']);
}
/**
* @return self
*/
public static function init(): self
{
return new static();
}
/**
* @return void
*/
protected function loadCore(): void
{
if ($this->coreLoaded == false) {
$requires = array_merge(
$this->getFiles(__DIR__ . '/functions'),
$this->getFiles(__DIR__ . '/Base')
);
foreach ($requires as $file) {
require_once $file;
}
$coreFiles = $this->getFiles(__DIR__ . '/Core');
$initClasses = [];
foreach ($coreFiles as $file) {
require_once $file;
$className = basename($file, '.php');
if (is_callable([$className, 'init'])) {
$initClasses[] = $className;
}
}
foreach ($initClasses as $class) {
call_user_func([$class, 'init']);
}
$this->coreLoaded = true;
}
}
/**
* @return void
*/
protected function activateLoggers(): void
{
add_action('plugins_loaded', function () {
$this->loadCore();
$this->updateCheck();
if ($this->defaultLoggingDisabled() == false) {
$this->loadCoreLoggers();
$this->loadIntegrations();
}
});
}
/**
* @param string $path
* @param bool $recurse
* @param string $extension
*
* @return array
*/
protected function getFiles(string $path, bool $recurse = true, string $extension = 'php'): array
{
if (is_dir($path)) {
$files = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
} elseif (is_file($path)) {
return [realpath($path)];
} else {
return [];
}
$list = [];
foreach ($files as $file) {
if ($file->isFile()) {
if ($file->getExtension() == $extension) {
$list[] = $file->getRealPath();
}
} elseif ($recurse) {
$list = array_merge($list, $this->getFiles($file->getRealPath(), $recurse, $extension));
}
}
return $list;
}
/**
* Review updates based on version
*
* @return void
*/
public function updateCheck(): void
{
$currentVersion = get_option('logtivity_version');
if (version_compare($currentVersion, '3.1.6', '<=')) {
$this->checkCapabilities();
}
if ($currentVersion && version_compare($currentVersion, '3.1.7', '<=')) {
// Default for updating sites should be no behavior change
update_option('logtivity_app_verify_url', 0);
}
update_option('logtivity_version', $this->version);
}
/**
* Custom capabilities added prior to v3.1.7
*
* @return void
*/
protected function checkCapabilities(): void
{
$capabilities = array_filter(
array_keys(logtivity_get_capabilities()),
function (string $capability): bool {
return in_array($capability, [Logtivity::ACCESS_LOGS, Logtivity::ACCESS_SETTINGS]);
}
);
if ($administrator = get_role('administrator')) {
if (array_search(Logtivity::ACCESS_LOGS, $capabilities) === false) {
$administrator->add_cap(Logtivity::ACCESS_LOGS);
}
if (array_search(Logtivity::ACCESS_SETTINGS, $capabilities) === false) {
$administrator->add_cap(Logtivity::ACCESS_SETTINGS);
}
}
}
/**
* Is the default Event logging from within the plugin enabled
*
* @return bool
*/
protected function defaultLoggingDisabled(): bool
{
return (bool)(new Logtivity_Options())->getOption('logtivity_disable_default_logging');
}
/**
* @return void
*/
protected function loadCoreLoggers(): void
{
$coreLoggers = $this->getFiles(__DIR__ . '/Loggers/Core');
foreach ($coreLoggers as $logger) {
require_once $logger;
}
}
/**
* @return void
*/
protected function loadIntegrations(): void
{
$loggerFolder = __DIR__ . '/Loggers/';
foreach ($this->integrations as $key => $folder) {
$integrationFolder = $loggerFolder . $folder;
if (class_exists($key)) {
if (is_dir($integrationFolder . '/Base')) {
// Load any base classes
$baseFiles = $this->getFiles($integrationFolder . '/Base');
foreach ($baseFiles as $file) {
require_once $file;
}
}
$files = $this->getFiles($integrationFolder, false);
foreach ($files as $file) {
require_once $file;
}
}
}
}
/**
* Main entry for registering a site using the team API Key
*
* @param ?string $teamApi
* @param ?string $teamName
* @param ?string $siteName
* @param ?string $url
*
* @return null|Logtivity_Response|WP_Error
*/
public static function registerSite(
?string $teamApi,
?string $teamName = null,
?string $siteName = null,
?string $url = null
) {
$logtivityOptions = new Logtivity_Options();
if ($logtivityOptions->getApiKey()) {
$response = new WP_Error(
'logtivity_register_site_error',
__('You have already entered an API Key for this site.', 'logtivity')
);
} elseif ($teamApi) {
$request = [
'method' => 'POST',
'timeout' => 6,
'blocking' => true,
'body' => [
'team_name' => $teamName,
'name' => $siteName ?: get_bloginfo('name'),
'url' => $url ?: home_url(),
],
'cookies' => [],
];
$response = new Logtivity_Response($teamApi, '/sites', $request);
if ($response->code == 200 && $response->error == false) {
$apikey = $response->body['api_key'] ?? null;
$teamName = $response->body['team_name'] ?? '*unknown*';
$created = $response->body['created_at'] ?? null;
$isNew = $response->body['is_new'] ?? null;
if ($apikey) {
$logtivityOptions->update(['logtivity_site_api_key' => $apikey]);
if ($isNew) {
$response->message = sprintf(
'This site has been created on Logtivity for team \'%s\'. Logging is now enabled.',
logtivity_get_app_url(),
$teamName
);
} else {
if ($created) {
$createdTimestamp = strtotime($created);
$creationText = sprintf(
'It was created on %s at %s ',
wp_date(get_option('date_format'), $createdTimestamp),
wp_date(get_option('time_format'), $createdTimestamp)
);
}
$response->message = sprintf(
'This site was found on Logtivity. %sfor the team \'%s\'. Logging is now enabled.',
logtivity_get_app_url(),
$creationText ?? '',
$teamName
);
}
}
}
} else {
$response = new WP_Error('logtivity_missing_data', 'Team API Key is required.');
}
return $response;
}
/**
* @param ?string $action
* @param ?array $meta
* @param ?int $userId
*
* @return Logtivity_Logger
*/
public static function log(?string $action = null, ?array $meta = null, ?int $userId = null): Logtivity_Logger
{
return Logtivity_Logger::log($action, $meta, $userId);
}
/**
* @param WP_Upgrader $upgraderObject
* @param array $options
*
* @return void
*/
public function upgradeProcessComplete(WP_Upgrader $upgraderObject, array $options): void
{
$type = $options['type'] ?? null;
$action = $options['action'] ?? null;
if ($type == 'plugin' && $action == 'update') {
$this->setLogtivityToLoadFirst();
}
}
/**
* @return void
*/
public function setLogtivityToLoadFirst(): void
{
$path = str_replace(WP_PLUGIN_DIR . '/', '', __FILE__);
if ($plugins = get_option('active_plugins')) {
if ($key = array_search($path, $plugins)) {
array_splice($plugins, $key, 1);
array_unshift($plugins, $path);
update_option('active_plugins', $plugins);
}
}
}
/**
* @param array $links
*
* @return string[]
*/
public function addSettingsLinkFromPluginsPage(array $links): array
{
if (apply_filters('logtivity_hide_settings_page', false)) {
return $links;
}
return array_merge(
[
sprintf('Settings', admin_url('admin.php?page=logtivity-settings')),
],
$links
);
}
/**
* @return void
*/
public function activated(): void
{
add_option('logtivity_activate', true);
$this->checkCapabilities();
if (apply_filters('logtivity_hide_settings_page', false)) {
return;
}
set_transient('logtivity-welcome-notice', true, 5);
}
/**
* Redirect to Settings page
*
* @return void
* @since 3.1.11
*
*/
public function redirectOnActivate()
{
if (get_option('logtivity_activate')) {
delete_option('logtivity_activate');
if (!isset($_GET['activate-multi'])) {
$page = (new Logtivity_Options())->isWhiteLabelMode() ? 'lgtvy-logs' : 'logtivity';
wp_redirect(admin_url('admin.php?page=' . $page));
exit;
}
}
}
/**
* @return void
*/
public function welcomeMessage(): void
{
if (get_transient('logtivity-welcome-notice')) {
echo logtivity_view('activation');
delete_transient('logtivity-welcome-notice');
}
}
/**
* @return void
*/
public function checkForSiteUrlChange(): void
{
if (
current_user_can(static::ACCESS_SETTINGS)
&& logtivity_has_site_url_changed()
&& (new Logtivity_Options())->isWhiteLabelMode() == false
&& !get_transient('dismissed-logtivity-site-url-has-changed-notice')
) {
echo logtivity_view('site-url-changed-notice');
}
}
/**
* @return void
*/
public function loadScripts(): void
{
wp_enqueue_style(
'logtivity_google_font_admin_css',
'https://fonts.googleapis.com/css?family=IBM+Plex+Sans:400,500',
false,
$this->version
);
wp_enqueue_style(
'logtivity_admin_css',
plugin_dir_url(__FILE__) . 'assets/admin.css',
['logtivity_google_font_admin_css'],
$this->version
);
wp_enqueue_script(
'logtivity_admin_js',
plugin_dir_url(__FILE__) . 'assets/app.js',
false,
$this->version
);
wp_localize_script('logtivity_admin_js', 'logtivityAdminA11y', [
'loadingLogs' => __('Loading logs...', 'logtivity'),
'loadLogsError' => __('Unable to load logs. Please try again.', 'logtivity'),
]);
}
}
Logtivity::init();