PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.10.1
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.10.1
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 / Paths.php
matomo / classes / WpMatomo Last commit date
Admin 1 month ago Commands 2 years ago Db 1 year ago Ecommerce 1 month ago Report 2 months ago Site 2 months ago TrackingCode 4 months ago Updater 4 years ago User 2 months ago Workarounds 2 years ago WpStatistics 5 months ago views 1 month ago AIBotTracking.php 4 months ago API.php 2 months ago Access.php 4 years ago AjaxTracker.php 4 months ago Annotations.php 2 months ago Bootstrap.php 10 months ago Capabilities.php 2 months ago Compatibility.php 2 months ago Email.php 2 years ago ErrorNotice.php 1 month ago Feature.php 2 months ago Installer.php 1 month ago Logger.php 1 year ago OptOut.php 1 month ago Paths.php 5 months ago PluginActionLinks.php 2 months ago PluginAdminOverrides.php 2 months ago PluginInit.php 2 months ago PrivacyBadge.php 4 years ago RedirectOnActivation.php 2 months ago Referral.php 2 months ago Roles.php 2 months ago ScheduledTasks.php 2 months ago Settings.php 4 months ago Site.php 3 years ago TrackingCode.php 2 months ago Uninstaller.php 5 months ago Updater.php 10 months ago User.php 4 years ago
Paths.php
257 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 stdClass;
13 use WP_Filesystem_Direct;
14
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit; // if accessed directly
17 }
18
19 class Paths {
20
21 private static $host_init_filesystem = false;
22 private static $host_init_filesystem_succeeded = false;
23
24 public function get_file_system() {
25 if ( ! function_exists( 'WP_Filesystem' ) ) {
26 require_once ABSPATH . '/wp-admin/includes/file.php';
27 }
28
29 if ( ! self::$host_init_filesystem ) {
30 self::$host_init_filesystem = true;
31 self::$host_init_filesystem_succeeded = WP_Filesystem();
32 }
33
34 if ( ! class_exists( '\WP_Filesystem_Direct' ) ) {
35 require_once ABSPATH . '/wp-admin/includes/class-wp-filesystem-base.php';
36 require_once ABSPATH . '/wp-admin/includes/class-wp-filesystem-direct.php';
37 }
38
39 return new WP_Filesystem_Direct( new stdClass() );
40 }
41
42 public function get_host_init_filesystem_succeeded() {
43 return self::$host_init_filesystem_succeeded;
44 }
45
46 public function get_upload_base_url() {
47 $upload_dir = wp_upload_dir();
48 $path_upload_url = $upload_dir['baseurl'];
49
50 return rtrim( $path_upload_url, '/' ) . '/' . MATOMO_UPLOAD_DIR;
51 }
52
53 public function get_upload_base_dir() {
54 $upload_dir = wp_upload_dir();
55 $path_upload_dir = $upload_dir['basedir'];
56 $path_upload_dir = rtrim( $path_upload_dir, '/' ) . '/' . MATOMO_UPLOAD_DIR;
57
58 return $path_upload_dir;
59 }
60
61 public function get_matomo_js_upload_path() {
62 return $this->get_upload_base_dir() . '/' . MATOMO_JS_NAME;
63 }
64
65 public function get_config_ini_path() {
66 return $this->get_upload_base_dir() . '/' . MATOMO_CONFIG_PATH;
67 }
68
69 public function get_tracker_api_rest_api_endpoint() {
70 return path_join( get_rest_url(), API::VERSION . '/' . API::ROUTE_HIT . '/' );
71 }
72
73 public function get_tracker_api_url_in_matomo_dir() {
74 return plugins_url( 'app/matomo.php', MATOMO_ANALYTICS_FILE );
75 }
76
77 public function get_js_tracker_rest_api_endpoint() {
78 return $this->get_tracker_api_rest_api_endpoint();
79 }
80
81 public function get_js_tracker_url_in_matomo_dir() {
82 $paths = new Paths();
83
84 if ( file_exists( $paths->get_matomo_js_upload_path() ) ) {
85 return $this->get_upload_base_url() . '/' . MATOMO_JS_NAME;
86 }
87
88 return plugins_url( 'app/matomo.js', MATOMO_ANALYTICS_FILE );
89 }
90
91 public function get_tmp_dir() {
92 $is_multi_site = function_exists( 'is_multisite' ) && is_multisite();
93
94 $cache_dir_alternative = $this->get_upload_base_dir() . '/tmp';
95 $base_cache_dir = WP_CONTENT_DIR . '/cache';
96 $default_cache_dir = $base_cache_dir . '/' . MATOMO_UPLOAD_DIR;
97
98 if ( ! $is_multi_site &&
99 ( ( is_writable( WP_CONTENT_DIR ) && ! is_dir( $base_cache_dir ) )
100 || is_writable( $base_cache_dir ) ) ) {
101 // we prefer wp-content/cache
102 $cache_dir = $default_cache_dir;
103
104 if ( ! is_dir( $cache_dir ) ) {
105 wp_mkdir_p( $cache_dir );
106 }
107
108 if ( ! is_writable( $cache_dir ) ) {
109 // wasn't made writable for some reason so we prefer to use the upload dir just to be safe
110 $cache_dir = $cache_dir_alternative;
111 }
112 } else {
113 // fallback wp-content/uploads/matomo/tmp if $defaultCacheDir is not writable or if multisite is used
114 // with multisite we need to make sure to cache files per site
115 $cache_dir = $cache_dir_alternative;
116
117 if ( ! is_dir( $cache_dir ) ) {
118 wp_mkdir_p( $cache_dir );
119 }
120 }
121
122 return $cache_dir;
123 }
124
125 /**
126 * parameter matomo_file is required for the unit test cases (when checking with a path including the string matomo)
127 *
128 * @param string $target_dir
129 * @param string $matomo_file
130 *
131 * @return string
132 */
133 public function get_relative_dir_to_matomo( $target_dir, $matomo_file = MATOMO_ANALYTICS_FILE ) {
134 // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
135 return matomo_rel_path( $target_dir, dirname( $matomo_file ) . '/app' );
136 }
137
138 public function get_gloal_upload_dir_if_possible( $file_to_look_for = '' ) {
139 if ( defined( 'MATOMO_GLOBAL_UPLOAD_DIR' ) ) {
140 return MATOMO_GLOBAL_UPLOAD_DIR;
141 }
142
143 $path_upload_dir = $this->get_upload_base_dir();
144
145 if ( ! is_multisite() || is_network_admin() ) {
146 return $path_upload_dir;
147 }
148
149 $global_path_upload_dir = $this->get_global_path_upload_dir_if_matches_site_specific_dir( $path_upload_dir );
150 if ( ! empty( $global_path_upload_dir ) ) {
151 $path_upload_dir = $global_path_upload_dir;
152 } else {
153 // re-implement _wp_upload_dir to find hopefully the upload_dir for the network site
154 $upload_path = trim( get_option( 'upload_path' ) );
155 if ( empty( $upload_path ) || 'wp-content/uploads' === $upload_path ) {
156 $path_upload_dir = WP_CONTENT_DIR . '/uploads';
157 } elseif ( 0 !== strpos( $upload_path, ABSPATH ) ) {
158 // $dir is absolute, $upload_path is (maybe) relative to ABSPATH
159 $path_upload_dir = path_join( ABSPATH, $upload_path );
160 } else {
161 $path_upload_dir = $upload_path;
162 }
163 }
164
165 if ( ! empty( $file_to_look_for ) ) {
166 $file_to_look_for = MATOMO_UPLOAD_DIR . '/' . ltrim( $file_to_look_for, '/' );
167 }
168
169 $path_upload_dir = rtrim( $path_upload_dir, '/' ) . '/';
170 if ( ! empty( $file_to_look_for )
171 && ! file_exists( $path_upload_dir . $file_to_look_for ) ) {
172 // seems we haven't auto detected the right one yet... (or it is not yet installed)
173 // we go up the site upload dir step by step to try and find the network upload dir
174 $parent_dir = $path_upload_dir;
175 do {
176 $parent_dir = dirname( $parent_dir );
177 $parent_dir = rtrim( $parent_dir, '/' ) . '/';
178 // NOTE: file_exists here can trigger an open_basedir warning on some setups
179 // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
180 if ( @file_exists( $parent_dir . $file_to_look_for ) ) {
181 return $parent_dir;
182 }
183 } while ( strpos( $parent_dir, ABSPATH ) === 0 ); // we don't go outside WP dir
184 }
185
186 $path_upload_dir = rtrim( $path_upload_dir, '/' ) . '/' . MATOMO_UPLOAD_DIR;
187
188 return $path_upload_dir;
189 }
190
191 public function clear_assets_dir() {
192 $tmp_dir = $this->get_tmp_dir() . '/assets';
193 if ( $tmp_dir && is_dir( $tmp_dir ) ) {
194 $file_system_direct = $this->get_file_system();
195 $file_system_direct->rmdir( $tmp_dir, true );
196 }
197 }
198
199 public function clear_cache_dir() {
200 $tmp_dir = $this->get_tmp_dir();
201 if ( $tmp_dir
202 && is_dir( $tmp_dir )
203 && is_dir( $tmp_dir . '/cache' ) ) {
204 // we make sure it's a matomo cache dir to not delete something falsely
205 $file_system_direct = $this->get_file_system();
206 $file_system_direct->rmdir( $tmp_dir, true );
207 }
208 }
209
210 public function uninstall() {
211 $this->clear_cache_dir();
212
213 $dir = $this->get_upload_base_dir();
214
215 $file_system_direct = $this->get_file_system();
216 $file_system_direct->rmdir( $dir, true );
217
218 $global_dir = $this->get_upload_base_dir();
219 if ( $global_dir && $global_dir !== $dir ) {
220 $file_system_direct->rmdir( $dir );
221 }
222 }
223
224 /**
225 * Must be called after Paths::get_file_system().
226 *
227 * @return bool
228 */
229 public function is_upload_dir_writable() {
230 $upload_dir = $this->get_upload_base_dir();
231
232 // the WP direct filesystem abstraction may not be available based on user
233 // configuration. in this case, we can't write to the upload dir using WP_Filesystem
234 $is_filesystem_direct_available = defined( 'FS_CHMOD_FILE' );
235 return is_dir( $upload_dir )
236 && is_writable( $upload_dir )
237 && $this->get_host_init_filesystem_succeeded()
238 && $is_filesystem_direct_available;
239 }
240
241 /**
242 * public for tests
243 *
244 * @param string $path_upload_dir
245 * @return string|null
246 */
247 public function get_global_path_upload_dir_if_matches_site_specific_dir( $path_upload_dir ) {
248 $multisite_path_regex = '%sites/(\d)+/' . preg_quote( MATOMO_UPLOAD_DIR, '%' ) . '$%';
249
250 if ( ! preg_match( $multisite_path_regex, $path_upload_dir ) ) {
251 return null;
252 }
253
254 return preg_replace( $multisite_path_regex, '', $path_upload_dir );
255 }
256 }
257