. */ // 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();