PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 4.0.2
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v4.0.2
5.13.0 5.12.1 5.12.0 5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / classes / WpMatomo / ScheduledTasks.php
matomo / classes / WpMatomo Last commit date
Admin 5 years ago Commands 5 years ago Db 5 years ago Ecommerce 5 years ago Report 6 years ago Site 5 years ago TrackingCode 5 years ago Updater 5 years ago User 5 years ago views 6 years ago API.php 5 years ago Access.php 6 years ago AjaxTracker.php 5 years ago Annotations.php 6 years ago Bootstrap.php 6 years ago Capabilities.php 6 years ago Compatibility.php 6 years ago Email.php 5 years ago Installer.php 5 years ago Logger.php 5 years ago OptOut.php 6 years ago Paths.php 6 years ago PrivacyBadge.php 6 years ago Referral.php 6 years ago Roles.php 6 years ago ScheduledTasks.php 5 years ago Settings.php 5 years ago Site.php 6 years ago TrackingCode.php 5 years ago Uninstaller.php 6 years ago Updater.php 5 years ago User.php 6 years ago
ScheduledTasks.php
329 lines
1 <?php
2 /**
3 * Matomo - free/libre analytics platform
4 *
5 * @link https://matomo.org
6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7 * @package matomo
8 */
9
10 namespace WpMatomo;
11
12 use Piwik\Config;
13 use Piwik\CronArchive;
14 use Piwik\Filesystem;
15 use Piwik\Option;
16 use Piwik\Plugins\GeoIp2\GeoIP2AutoUpdater;
17 use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2;
18 use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2\Php;
19 use Piwik\Plugins\UserCountry\LocationProvider;
20 use WpMatomo\Site\Sync as SiteSync;
21 use WpMatomo\User\Sync as UserSync;
22
23 if ( ! defined( 'ABSPATH' ) ) {
24 exit; // if accessed directly
25 }
26
27 class ScheduledTasks {
28 const EVENT_SYNC = 'matomo_scheduled_sync';
29 const EVENT_DISABLE_ADDHANDLER = 'matomo_scheduled_disable_addhandler';
30 const EVENT_ARCHIVE = 'matomo_scheduled_archive';
31 const EVENT_GEOIP = 'matomo_scheduled_geoipdb';
32 const EVENT_UPDATE = 'matomo_update_core';
33
34 const KEY_BEFORE_CRON = 'before-cron-';
35 const KEY_AFTER_CRON = 'after-cron-';
36
37 /**
38 * @var Settings
39 */
40 private $settings;
41
42 /**
43 * @var Logger
44 */
45 private $logger;
46
47 public function __construct( Settings $settings ) {
48 $this->settings = $settings;
49 $this->logger = new Logger();
50 }
51
52 public function add_weekly_schedule( $schedules ) {
53 $schedules['matomo_monthly'] = array(
54 'interval' => 60 * 60 * 24 * 30,
55 'display' => __( 'Monthly', 'matomo' ),
56 );
57
58 return $schedules;
59 }
60
61 public function schedule() {
62 add_action( self::EVENT_UPDATE, array( $this, 'perform_update' ) );
63 add_filter( 'cron_schedules', array( $this, 'add_weekly_schedule' ) );
64
65 $self = $this;
66 $event_priority = 10;
67
68 foreach ( $this->get_all_events() as $event_name => $event_config ) {
69 if ( ! wp_next_scheduled( $event_name ) ) {
70 wp_schedule_event( time(), $event_config['interval'], $event_name );
71 }
72
73 // logging last execution start time
74 add_action(
75 $event_name,
76 function () use ( $self, $event_name ) {
77 $self->set_last_time_before_cron( $event_name, time() );
78 },
79 $event_priority / 2,
80 $accepted_args = 0
81 );
82
83 // actual event
84 add_action( $event_name, array( $this, $event_config['method'] ), $event_priority, $accepted_args = 0 );
85
86 // logging last execution end time
87 add_action(
88 $event_name,
89 function () use ( $self, $event_name ) {
90 $self->set_last_time_after_cron( $event_name, time() );
91 },
92 $event_priority * 2,
93 $accepted_args = 0
94 );
95 }
96
97 register_deactivation_hook( MATOMO_ANALYTICS_FILE, array( $this, 'uninstall' ) );
98 }
99
100 public function get_last_time_before_cron( $event_name ) {
101 return get_option( Settings::OPTION_PREFIX . self::KEY_BEFORE_CRON . $event_name );
102 }
103
104 public function set_last_time_before_cron( $event_name, $time ) {
105 // we use settings prefix so data automatically gets removed when uninstalling
106 update_option( Settings::OPTION_PREFIX . self::KEY_BEFORE_CRON . $event_name, $time );
107 }
108
109 public function get_last_time_after_cron( $event_name ) {
110 return get_option( Settings::OPTION_PREFIX . self::KEY_AFTER_CRON . $event_name );
111 }
112
113 public function set_last_time_after_cron( $event_name, $time ) {
114 // we use settings prefix so data automatically gets removed when uninstalling
115 update_option( Settings::OPTION_PREFIX . self::KEY_AFTER_CRON . $event_name, $time );
116 }
117
118 public function get_all_events() {
119 $events = array(
120 self::EVENT_SYNC => array(
121 'name' => 'Sync users & sites',
122 'interval' => 'daily',
123 'method' => 'sync',
124 ),
125 self::EVENT_ARCHIVE => array(
126 'name' => 'Archive',
127 'interval' => 'hourly',
128 'method' => 'archive',
129 ),
130 self::EVENT_GEOIP => array(
131 'name' => 'Update GeoIP DB',
132 'interval' => 'matomo_monthly',
133 'method' => 'update_geo_ip2_db',
134 ),
135 );
136 if ($this->settings->should_disable_addhandler()) {
137 $events[self::EVENT_DISABLE_ADDHANDLER] = array(
138 'name' => 'Disable AddHandler',
139 'interval' => 'hourly',
140 'method' => 'disable_add_handler',
141 );
142 }
143 return $events;
144 }
145
146 public function disable_add_handler($forceUndo = false)
147 {
148 $disable_addhandler = $this->settings->should_disable_addhandler();
149 if ($disable_addhandler) {
150 $this->logger->log( 'Scheduled tasks disabling addhandler' );
151 try {
152 Bootstrap::do_bootstrap();
153
154 $files = Filesystem::globr(dirname(MATOMO_ANALYTICS_FILE), '.htaccess');
155 foreach ($files as $file) {
156 if (is_readable($file)) {
157 $content = file_get_contents($file);
158 $search = 'AddHandler';
159 $replace = '# AddHandler';
160 if ($forceUndo) {
161 $search = '# AddHandler';
162 $replace = 'AddHandler';
163 }
164 if (strpos($content, $search) !== false && ($forceUndo || strpos($content,$replace) === false)) {
165 if (is_writeable($file)) {
166 $content = str_replace($search, $replace, $content);
167 @file_put_contents($file, $content);
168 } else {
169 $this->logger->log('Cannot update file as not writable ' . $file);
170 }
171 }
172 }
173 }
174 } catch ( \Exception $e ) {
175 $this->logger->log_exception( 'disable_addhandler', $e );
176 throw $e;
177 }
178 }
179 }
180
181 private function check_try_update()
182 {
183 try {
184 $installer = new Installer( $this->settings );
185 if ( $installer->looks_like_it_is_installed() ) {
186 $updater = new Updater( $this->settings );
187 $updater->update_if_needed();
188 }
189 } catch ( \Exception $e ) {
190 // we don't want to rethrow exception otherwise some other blogs might never sync
191 $this->logger->log_exception( 'check_try_update', $e );
192 }
193 }
194
195 public function perform_update() {
196 $this->logger->log( 'Scheduled tasks perform update' );
197
198 try {
199 $updater = new Updater( $this->settings );
200 $updater->update();
201 } catch ( \Exception $e ) {
202 $this->logger->log_exception( 'cron_update', $e );
203 throw $e;
204 }
205 }
206
207 public function update_geo_ip2_db() {
208 $this->logger->log( 'Scheduled tasks update geoip database' );
209 try {
210 Bootstrap::do_bootstrap();
211
212 $maxmind_license = $this->settings->get_global_option('maxmind_license_key');
213 if (empty($maxmind_license)) {
214 $db_url = GeoIp2::getDbIpLiteUrl();
215 } else {
216 $db_url = 'https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&suffix=tar.gz&license_key=' . $maxmind_license;
217 }
218
219 Option::set( GeoIP2AutoUpdater::LOC_URL_OPTION_NAME, $db_url);
220 $updater = new GeoIP2AutoUpdater();
221 $updater->update();
222 if ( LocationProvider::getCurrentProviderId() !== Php::ID && LocationProvider::getProviderById( Php::ID ) ) {
223 LocationProvider::setCurrentProvider( Php::ID );
224 }
225 } catch ( \Exception $e ) {
226 $this->logger->log_exception( 'update_geoip2', $e );
227 throw $e;
228 }
229 }
230
231 public function sync() {
232 $this->check_try_update();
233
234 $this->logger->log( 'Scheduled tasks sync all sites and users' );
235
236 try {
237 $site = new SiteSync( $this->settings );
238 $site->sync_all();
239 $user = new UserSync();
240 $user->sync_all();
241 } catch ( \Exception $e ) {
242 $this->logger->log_exception( 'cron_sync', $e );
243 throw $e;
244 }
245 }
246
247 public function archive( $force = false, $throw_exception = true ) {
248 $this->check_try_update();
249
250 if ( defined( 'MATOMO_DISABLE_WP_ARCHIVING' ) && MATOMO_DISABLE_WP_ARCHIVING ) {
251 return;
252 }
253
254 $this->logger->log( 'Scheduled tasks archive data' );
255
256 try {
257 Bootstrap::do_bootstrap();
258 } catch ( \Exception $e ) {
259 $this->logger->log_exception( 'archive_bootstrap', $e );
260 throw $e;
261 }
262
263 $archiver = new CronArchive();
264 $archiver->concurrentRequestsPerWebsite = 1;
265 $archiver->maxConcurrentArchivers = 1;
266
267 if ( $force ) {
268 $archiver->shouldArchiveAllSites = true;
269 $archiver->disableScheduledTasks = true;
270 }
271
272 if ( is_multisite() ) {
273 if ( is_network_admin() ) {
274 return; // nothing to archive
275 } else {
276 $blog_id = get_current_blog_id();
277 $idsite = Site::get_matomo_site_id( $blog_id );
278 if ( ! empty( $idsite ) ) {
279 $archiver->shouldArchiveSpecifiedSites = array( $idsite );
280 } else {
281 // there is no site mapped to it so there's no point in archiving it
282 return;
283 }
284 }
285 }
286
287 try {
288 $archiver->main();
289
290 $archive_errors = $archiver->getErrors();
291
292 } catch ( \Exception $e ) {
293 $this->logger->log_exception( 'archive_main' , $e);
294 $archive_errors = $archiver->getErrors();
295
296 if (!empty($archive_errors)) {
297 $message = '';
298 foreach ($archiver->getErrors() as $error) {
299 $message .= var_export($error, 1) . ' ';
300 }
301 $message = new \Exception(trim($message));
302 $this->logger->log_exception('archive_errors', $message);
303 }
304
305 if ($throw_exception) {
306 throw $e;
307 } else {
308 $archive_errors[] = $e->getMessage();
309 }
310 }
311
312 return $archive_errors;
313 }
314
315 public function uninstall() {
316 $this->logger->log( 'Scheduled tasks uninstall all events' );
317
318 foreach ( $this->get_all_events() as $event_name => $config ) {
319 $timestamp = wp_next_scheduled( $event_name );
320 if ( $timestamp ) {
321 wp_unschedule_event( $timestamp, $event_name );
322 }
323 }
324 foreach ( $this->get_all_events() as $event_name => $config ) {
325 wp_clear_scheduled_hook( $event_name );
326 }
327 }
328 }
329