PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 4.4.1
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v4.4.1
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 / Installer.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 RedirectOnActivation.php 5 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
Installer.php
356 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\Common;
13 use Piwik\Config;
14 use Piwik\Container\StaticContainer;
15 use Piwik\DbHelper;
16 use Piwik\Exception\NotYetInstalledException;
17 use Piwik\Plugin\API as PluginApi;
18 use Piwik\SettingsPiwik;
19 use WpMatomo\Site\Sync;
20
21 if ( ! defined( 'ABSPATH' ) ) {
22 exit; // if accessed directly
23 }
24
25 class Installer {
26
27 const OPTION_NAME_INSTALL_DATE = 'matomo-install-date';
28 const OPTION_NAME_INSTALL_VERSION = 'matomo-install-version';
29
30 /**
31 * @var Settings
32 */
33 private $settings;
34
35 /**
36 * @var Logger
37 */
38 private $logger;
39
40 public function __construct( Settings $settings ) {
41 $this->settings = $settings;
42 $this->logger = new Logger();
43 }
44
45 public function register_hooks() {
46 add_action( 'activate_matomo', array( $this, 'install' ) );
47 }
48
49 public function looks_like_it_is_installed() {
50 $paths = new Paths();
51 $config_file = $paths->get_config_ini_path();
52
53 $config_dir = dirname( $config_file );
54 if ( ! is_dir( $config_dir ) ) {
55 wp_mkdir_p( $config_dir );
56 }
57
58 return file_exists( $config_file );
59 }
60
61 public static function is_intalled() {
62 try {
63 Bootstrap::do_bootstrap();
64
65 return SettingsPiwik::isMatomoInstalled();
66 } catch ( NotYetInstalledException $e ) {
67 // not yet installed.... we will need to install it
68 }
69
70 return false;
71 }
72
73 public function can_be_installed() {
74 $paths = new Paths();
75 $upload_dir = $paths->get_upload_base_dir();
76
77 return is_writable( $upload_dir ) || is_writable( dirname( $upload_dir ) );
78 }
79
80 public function install() {
81 if ( ! $this->can_be_installed() ) {
82 return false;
83 }
84
85 try {
86 // prevent session related errors during install making it more stable
87 if ( ! defined( 'PIWIK_ENABLE_SESSION_START' ) ) {
88 define( 'PIWIK_ENABLE_SESSION_START', false );
89 }
90
91 Bootstrap::do_bootstrap();
92
93 if ( ! SettingsPiwik::isMatomoInstalled() || ! $this->looks_like_it_is_installed() ) {
94 throw new NotYetInstalledException( 'Not yet installed' );
95 }
96
97 return false;
98 } catch ( NotYetInstalledException $e ) {
99 $this->logger->log( 'Matomo is not yet installed... installing now' );
100
101 $db_info = $this->create_db();
102 $this->create_config( $db_info );
103
104 // we're scheduling another update in case there are some dimensions to be updated or anything
105 // it is possible that because the plugins need to be reloaded etc that those updates are not executed right
106 // away but need an actual reload and cache clearance etc
107 wp_schedule_single_event( time() + 30, ScheduledTasks::EVENT_UPDATE );
108
109 // to set up geoip in the background later... don't want this to influence the install
110 wp_schedule_single_event( time() + 35, ScheduledTasks::EVENT_GEOIP );
111
112 // in case something fails with website or user creation
113 // also to set up all the other users
114 wp_schedule_single_event( time() + 45, ScheduledTasks::EVENT_SYNC );
115
116 update_option(self::OPTION_NAME_INSTALL_DATE, time());
117 $plugin_data = get_plugin_data( MATOMO_ANALYTICS_FILE, $markup = false, $translate = false );
118 if ( ! empty( $plugin_data['Version'] )) {
119 update_option( self::OPTION_NAME_INSTALL_VERSION, $plugin_data['Version'] );
120 }
121
122 $this->create_website();
123 $this->create_user(); // we sync users as early as possible to make sure things are set up correctly
124 $this->install_tracker();
125
126 try {
127 $this->logger->log( 'Matomo will now init the environment' );
128 $environment = new \Piwik\Application\Environment( null );
129 $environment->init();
130 } catch ( \Exception $e ) {
131 $this->logger->log( 'Ignoring error environment init' );
132 $this->logger->log_exception( 'install_env_init', $e );
133 }
134
135 try {
136 // should load and install plugins
137 $this->logger->log( 'Matomo will now init the front controller and install plugins etc' );
138 \Piwik\FrontController::unsetInstance(); // make sure we're loading the latest instance
139 $controller = \Piwik\FrontController::getInstance();
140 $controller->init();
141 } catch ( \Exception $e ) {
142 $this->logger->log( 'Ignoring error frontcontroller init' );
143 $this->logger->log_exception( 'install_front_init', $e );
144 }
145
146 try {
147 // sync user now again after installing plugins...
148 // before eg the users_language table would not have been available yet
149 $this->create_user();
150 } catch ( \Exception $e ) {
151 $this->logger->log_exception( 'install_create_user', $e );
152 }
153
154 try {
155 // update plugins if there are any
156 $this->update_components();
157 } catch ( \Exception $e ) {
158 $this->logger->log_exception( 'install_update_comp', $e );
159 }
160
161 $this->logger->log( 'Recording version and url' );
162
163 DbHelper::recordInstallVersion();
164
165 $this->set_matomo_url();
166
167 $this->logger->log( 'Emptying some caches' );
168
169 \Piwik\Singleton::clearAll();
170 PluginApi::unsetAllInstances();
171 \Piwik\Cache::flushAll();
172
173 $this->logger->log( 'Matomo install finished' );
174 }
175
176 return true;
177 }
178
179 public function set_matomo_url()
180 {
181 // note that the full url might not be possible to be set if the cron is executed on cli and it maybe doesn't have
182 // the host or if a plugin overwrites the constant of WP_PLUGIN_URL which is used in plugins_url() to not include domain
183 // see https://www.google.com/url?q=https://wordpress.org/support/topic/no-metrics-showing/%23topic-14362043-replies&source=gmail&ust=1620409922890000&usg=AFQjCNHyzG5-9v0A8bjg8aLVVbYSWxkTxg
184
185 $matomo_url = SettingsPiwik::getPiwikUrl();
186 $plugins_url = plugins_url( 'app', MATOMO_ANALYTICS_FILE );
187 // need to make sure to update plugins url if it changes eg if installed somewhere else or domain changes
188
189 if ($matomo_url
190 && $plugins_url === $matomo_url
191 && parse_url($matomo_url, PHP_URL_SCHEME)
192 && parse_url($matomo_url, PHP_URL_HOST)
193 ) {
194 // if currently no scheme or host is set then we'll make sure to overwrite it
195 return;
196 }
197
198 if (!$plugins_url) {
199 return;
200 }
201
202 $has_host = parse_url($plugins_url, PHP_URL_HOST);
203
204 if (!$has_host) {
205 return;
206 }
207
208 $has_scheme = parse_url($plugins_url, PHP_URL_SCHEME);
209
210 if (!$has_scheme) {
211 return;
212 }
213
214 SettingsPiwik::overwritePiwikUrl( $plugins_url );
215 }
216
217 private function install_tracker() {
218 $this->logger->log( 'Matomo is now installing the tracker' );
219 // making sure the tracker will be created in the wp uploads directory
220 $updater = StaticContainer::get( 'Piwik\Plugins\CustomJsTracker\TrackerUpdater' );
221 $updater->update();
222 }
223
224 private function create_db() {
225 $this->logger->log( 'Matomo will now create the database' );
226
227 try {
228 $db_infos = self::get_db_infos();
229 $config = Config::getInstance();
230 if (isset($config)) {
231 $db_infos = array_merge($config->database, $db_infos);
232 }
233 $config->database = $db_infos;
234
235 DbHelper::checkDatabaseVersion();
236 } catch ( \Exception $e ) {
237 $message = sprintf( 'Database info detection failed with %s in %s:%s.', $e->getMessage(), $e->getFile(), $e->getLine() );
238 throw new \Exception( $message, $e->getCode(), $e );
239 }
240
241 $tables_installed = DbHelper::getTablesInstalled();
242 if ( count( $tables_installed ) > 0 ) {
243 // todo define behaviour... might need to ask user how to proceed... but ideally we add check to
244 // see if all tables are there and if so, reuse them...
245 return $db_infos;
246 }
247 DbHelper::createTables();
248 DbHelper::createAnonymousUser();
249 $this->update_components();
250
251 return $db_infos;
252 }
253
254 private function create_config( $db_info ) {
255 $this->logger->log( 'Matomo is now creating the config' );
256 $domain = home_url();
257 $general = array(
258 'trusted_hosts' => array( $domain ),
259 'salt' => Common::generateUniqId(),
260 );
261 $config = Config::getInstance();
262 $path = $config->getLocalPath();
263 if ( ! is_dir( dirname( $path ) ) ) {
264 wp_mkdir_p( dirname( $path ) );
265 }
266 $db_default = array();
267 $general_default = array();
268 if ( $config->database ) {
269 $db_default = $config->database;
270 }
271 if ( $config->General ) {
272 $general_default = $config->General;
273 }
274 $config->database = array_merge( $db_default, $db_info );
275 $config->General = array_merge( $general_default, $general );
276 $config->forceSave();
277
278 $mode = 0664;
279 @chmod( $config->getLocalPath(), $mode );
280 }
281
282 private function create_website() {
283 $sync = new Sync( $this->settings );
284
285 return $sync->sync_current_site();
286 }
287
288 private function create_user() {
289 $sync = new User\Sync();
290
291 $sync->sync_current_users();
292 }
293
294 /**
295 * @param array $default params
296 * @return array
297 */
298 public static function get_db_infos( $default = array() ) {
299 global $wpdb;
300
301 $socket = '';
302 $host_data = null;
303 $host = null;
304 $port = 3306;
305 if (method_exists($wpdb, 'parse_db_host')) {
306 // WP 4.9+
307 $host_data = $wpdb->parse_db_host( DB_HOST );
308 if ($host_data) {
309 list( $host, $port, $socket, $is_ipv6 ) = $host_data;
310 if (!$port && !$socket) {
311 $port = 3306;
312 }
313 }
314 }
315
316 if (!$host_data || !$host) {
317 // WP 4.8 and older
318 // in case DB credentials change in wordpress, we need to apply these changes here as well on demand
319 $hostParts = explode(':', DB_HOST);
320 $host = $hostParts[0];
321 if (count($hostParts) === 2 && is_numeric($hostParts[1])) {
322 $port = $hostParts[1];
323 } else {
324 $port = 3306;
325 }
326 }
327
328 $charset = $wpdb->charset ? $wpdb->charset : 'utf8';
329
330 $database = array(
331 'host' => $host,
332 'port' => $port,
333 'username' => DB_USER,
334 'password' => DB_PASSWORD,
335 'dbname' => DB_NAME,
336 'charset' => $charset,
337 'tables_prefix' => $wpdb->prefix . MATOMO_DATABASE_PREFIX,
338 'adapter' => 'WordPress',
339 );
340 if (!empty($socket)) {
341 $database['unix_socket'] = $socket;
342 }
343 $database = array_merge($default, $database);
344
345 return $database;
346 }
347
348 private function update_components() {
349 $this->logger->log( 'Matomo will now trigger an update' );
350 Updater::unlock(); // make sure the update can be executed
351 $updater = new Updater( $this->settings );
352 $updater->update();
353 }
354
355 }
356