PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 4.13.3
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v4.13.3
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 / app / core / Updates / 4.0.0-b1.php
matomo / app / core / Updates Last commit date
3.12.0-b1.php 5 years ago 3.12.0-b7.php 5 years ago 4.0.0-b1.php 4 years ago 4.0.0-b3.php 4 years ago 4.0.0-rc3.php 4 years ago 4.0.0-rc4.php 4 years ago 4.0.1-b1.php 4 years ago 4.0.4-b1.php 4 years ago 4.1.2-b1.php 5 years ago 4.1.2-b2.php 4 years ago 4.10.0-b1.php 3 years ago 4.11.0-b1.php 3 years ago 4.11.0-rc2.php 3 years ago 4.12.0-b1.php 3 years ago 4.12.0-b2.php 3 years ago 4.12.0-b3.php 3 years ago 4.12.0-b4.php 3 years ago 4.3.0-b3.php 4 years ago 4.3.0-b4.php 4 years ago 4.3.0-rc2.php 4 years ago 4.4.0-b1.php 4 years ago 4.5.0-b1.php 4 years ago 4.6.0-b1.php 4 years ago 4.6.0-b4.php 4 years ago 4.6.2-rc2.php 4 years ago 4.7.0-b2.php 4 years ago 4.7.1-b1.php 4 years ago 5.0.0-b1.php 4 years ago
4.0.0-b1.php
314 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 *
8 */
9
10 namespace Piwik\Updates;
11
12 use Piwik\DataAccess\TableMetadata;
13 use Piwik\Updater\Migration\Custom as CustomMigration;
14 use Piwik\Db;
15 use Piwik\DbHelper;
16 use Piwik\Plugin\Manager;
17 use Piwik\Plugins\CoreAdminHome\Commands\MigrateTokenAuths;
18 use Piwik\Plugins\CoreHome\Columns\Profilable;
19 use Piwik\Plugins\CoreHome\Columns\VisitorSecondsSinceFirst;
20 use Piwik\Plugins\CoreHome\Columns\VisitorSecondsSinceOrder;
21 use Piwik\Plugins\Installation\ServerFilesGenerator;
22 use Piwik\Plugins\PagePerformance\Columns\TimeDomCompletion;
23 use Piwik\Plugins\PagePerformance\Columns\TimeDomProcessing;
24 use Piwik\Plugins\PagePerformance\Columns\TimeNetwork;
25 use Piwik\Plugins\PagePerformance\Columns\TimeOnLoad;
26 use Piwik\Plugins\PagePerformance\Columns\TimeServer;
27 use Piwik\Plugins\PagePerformance\Columns\TimeTransfer;
28 use Piwik\Common;
29 use Piwik\Config;
30 use Piwik\Plugins\UserCountry\LocationProvider;
31 use Piwik\Plugins\VisitorInterest\Columns\VisitorSecondsSinceLast;
32 use Piwik\SettingsPiwik;
33 use Piwik\Updater;
34 use Piwik\Updates as PiwikUpdates;
35 use Piwik\Updater\Migration\Factory as MigrationFactory;
36
37 /**
38 * Update for version 4.0.0-b1.
39 */
40 class Updates_4_0_0_b1 extends PiwikUpdates
41 {
42 /**
43 * @var MigrationFactory
44 */
45 private $migration;
46
47 public function __construct(MigrationFactory $factory)
48 {
49 $this->migration = $factory;
50 }
51
52 public function getMigrations(Updater $updater)
53 {
54 $tableMetadata = new TableMetadata();
55
56 $columnsToAdd = [];
57
58 $migrations = [];
59
60 $domain = Config::getLocalConfigPath() === Config::getDefaultLocalConfigPath() ? '' : Config::getHostname();
61 $domainArg = !empty($domain) ? "--matomo-domain=". escapeshellarg($domain) . " " : '';
62 $toString = sprintf('./console %score:matomo4-migrate-token-auths', $domainArg);
63 $custom = new CustomMigration(array(MigrateTokenAuths::class, 'migrate'), $toString);
64
65 $migrations[] = $custom;
66
67 // invalidations table
68 $migrations[] = $this->migration->db->createTable('archive_invalidations', [
69 'idinvalidation' => 'BIGINT UNSIGNED NOT NULL AUTO_INCREMENT',
70 'idarchive' => 'INTEGER UNSIGNED NULL',
71 'name' => 'VARCHAR(255) NOT NULL',
72 'idsite' => 'INTEGER NOT NULL',
73 'date1' => 'DATE NOT NULL',
74 'date2' => 'DATE NOT NULL',
75 'period' => 'TINYINT UNSIGNED NOT NULL',
76 'ts_invalidated' => 'DATETIME NOT NULL',
77 'status' => 'TINYINT(1) UNSIGNED DEFAULT 0',
78 'report' => 'VARCHAR(255) NULL',
79 ], ['idinvalidation']);
80
81 $migrations[] = $this->migration->db->addIndex('archive_invalidations', ['idsite', 'date1', 'period'], 'index_idsite_dates_period_name');
82
83 $migrations[] = $this->migration->db->dropColumn('user', 'alias');
84
85 // prevent possible duplicates when shorting session id
86 $migrations[] = $this->migration->db->sql('DELETE FROM `' . Common::prefixTable('session') . '` WHERE length(id) > 190');
87
88 $migrations[] = $this->migration->db->changeColumnType('session', 'id', 'VARCHAR(191)');
89 $migrations[] = $this->migration->db->changeColumnType('site_url', 'url', 'VARCHAR(190)');
90 $migrations[] = $this->migration->db->changeColumnType('option', 'option_name', 'VARCHAR(191)');
91
92 $migrations[] = $this->migration->db->changeColumnType('log_action', 'name', 'VARCHAR(4096)');
93 $migrations[] = $this->migration->db->changeColumnType('log_conversion', 'url', 'VARCHAR(4096)');
94 $migrations[] = $this->migration->db->changeColumn('log_link_visit_action', 'interaction_position', 'pageview_position', 'MEDIUMINT UNSIGNED DEFAULT NULL');
95
96 $customTrackerPluginActive = false;
97 if (in_array('CustomPiwikJs', Config::getInstance()->Plugins['Plugins'])) {
98 $customTrackerPluginActive = true;
99 }
100
101 $migrations[] = $this->migration->plugin->activate('BulkTracking');
102 $migrations[] = $this->migration->plugin->deactivate('CustomPiwikJs');
103 $migrations[] = $this->migration->plugin->uninstall('CustomPiwikJs');
104
105 if ($customTrackerPluginActive) {
106 $migrations[] = $this->migration->plugin->activate('CustomJsTracker');
107 }
108
109 // Prepare all installed tables for utf8mb4 conversions. e.g. make some indexed fields smaller so they don't exceed the maximum key length
110 $allTables = DbHelper::getTablesInstalled();
111
112 foreach ($allTables as $table) {
113 if (preg_match('/archive_/', $table) == 1) {
114 $tableNameUnprefixed = Common::unprefixTable($table);
115 $migrations[] = $this->migration->db->changeColumnType($tableNameUnprefixed, 'name', 'VARCHAR(190)');
116 }
117 }
118
119 // Move the site search fields of log_visit out of custom variables into their own fields
120 $columnsToAdd['log_link_visit_action']['search_cat'] = 'VARCHAR(200) NULL';
121 $columnsToAdd['log_link_visit_action']['search_count'] = 'INTEGER(10) UNSIGNED NULL';
122
123 // replace days to ... dimensions w/ seconds dimensions
124 foreach (['log_visit', 'log_conversion'] as $table) {
125 $columnsToAdd[$table]['visitor_seconds_since_first'] = VisitorSecondsSinceFirst::COLUMN_TYPE;
126 $columnsToAdd[$table]['visitor_seconds_since_order'] = VisitorSecondsSinceOrder::COLUMN_TYPE;
127 }
128 $columnsToAdd['log_visit']['visitor_seconds_since_last'] = VisitorSecondsSinceLast::COLUMN_TYPE;
129 $columnsToAdd['log_visit']['profilable'] = Profilable::COLUMN_TYPE;
130 $columnsToAdd['log_link_visit_action'][TimeDomCompletion::COLUMN_NAME] = TimeDomCompletion::COLUMN_TYPE;
131 $columnsToAdd['log_link_visit_action'][TimeDomProcessing::COLUMN_NAME] = TimeDomProcessing::COLUMN_TYPE;
132 $columnsToAdd['log_link_visit_action'][TimeNetwork::COLUMN_NAME] = TimeNetwork::COLUMN_TYPE;
133 $columnsToAdd['log_link_visit_action'][TimeOnLoad::COLUMN_NAME] = TimeOnLoad::COLUMN_TYPE;
134 $columnsToAdd['log_link_visit_action'][TimeServer::COLUMN_NAME] = TimeServer::COLUMN_TYPE;
135 $columnsToAdd['log_link_visit_action'][TimeTransfer::COLUMN_NAME] = TimeTransfer::COLUMN_TYPE;
136
137 $columnsToMaybeAdd = ['revenue', 'revenue_discount', 'revenue_shipping', 'revenue_subtotal', 'revenue_tax'];
138 $columnsLogConversion = $tableMetadata->getColumns(Common::prefixTable('log_conversion'));
139 foreach ($columnsToMaybeAdd as $columnToMaybeAdd) {
140 if (!in_array($columnToMaybeAdd, $columnsLogConversion, true)) {
141 $columnsToAdd['log_conversion'][$columnToMaybeAdd] = 'DOUBLE NULL DEFAULT NULL';
142 }
143 }
144
145 foreach ($columnsToAdd as $table => $columns) {
146 $migrations[] = $this->migration->db->addColumns($table, $columns);
147
148 foreach ($columns as $columnName => $columnType) {
149 $optionKey = 'version_' . $table . '.' . $columnName;
150 $optionValue = $columnType;
151
152 if ($table == 'log_visit' && isset($columnsToAdd['log_conversion'][$columnName])) {
153 $optionValue .= '1'; // column is in log_conversion too
154 }
155
156 $migrations[] = $this->migration->db->sql("INSERT IGNORE INTO `" . Common::prefixTable('option')
157 . "` (option_name, option_value) VALUES ('$optionKey', '$optionValue')");
158 }
159 }
160
161 if (Manager::getInstance()->isPluginInstalled('CustomVariables')) {
162 $visitActionTable = Common::prefixTable('log_link_visit_action');
163 $migrations[] = $this->migration->db->sql("UPDATE $visitActionTable SET search_cat = if(custom_var_k4 = '_pk_scat', custom_var_v4, search_cat), search_count = if(custom_var_k5 = '_pk_scount', custom_var_v5, search_count) WHERE custom_var_k4 = '_pk_scat' or custom_var_k5 = '_pk_scount'");
164 }
165
166 if ($this->usesGeoIpLegacyLocationProvider()) {
167 // activate GeoIp2 plugin for users still using GeoIp2 Legacy (others might have it disabled on purpose)
168 $migrations[] = $this->migration->plugin->activate('GeoIp2');
169 }
170
171 // remove old options
172 $migrations[] = $this->migration->db->sql('DELETE FROM `' . Common::prefixTable('option') . '` WHERE option_name IN ("geoip.updater_period", "geoip.loc_db_url", "geoip.isp_db_url", "geoip.org_db_url")');
173
174 // init seconds_to_... columns
175 $logVisitColumns = $tableMetadata->getColumns(Common::prefixTable('log_visit'));
176 $hasDaysColumnInVisit = in_array('visitor_days_since_first', $logVisitColumns);
177
178 if ($hasDaysColumnInVisit) {
179 $migrations[] = $this->migration->db->sql("UPDATE " . Common::prefixTable('log_visit')
180 . " SET visitor_seconds_since_first = visitor_days_since_first * 86400,
181 visitor_seconds_since_order = visitor_days_since_order * 86400,
182 visitor_seconds_since_last = visitor_days_since_last * 86400");
183 }
184
185 $logConvColumns = $tableMetadata->getColumns(Common::prefixTable('log_conversion'));
186 $hasDaysColumnInConv = in_array('visitor_days_since_first', $logConvColumns);
187
188 if ($hasDaysColumnInConv) {
189 $migrations[] = $this->migration->db->sql("UPDATE " . Common::prefixTable('log_conversion')
190 . " SET visitor_seconds_since_first = visitor_days_since_first * 86400,
191 visitor_seconds_since_order = visitor_days_since_order * 86400");
192 }
193
194 // remove old days_to_... columns
195 $migrations[] = $this->migration->db->dropColumns('log_visit', [
196 'config_gears',
197 'config_director',
198 'visitor_days_since_first',
199 'visitor_days_since_order',
200 'visitor_days_since_last',
201 ]);
202 $migrations[] = $this->migration->db->dropColumns('log_conversion', [
203 'visitor_days_since_first',
204 'visitor_days_since_order',
205 ]);
206
207 $config = Config::getInstance();
208
209 if (!empty($config->mail['type']) && $config->mail['type'] === 'Crammd5') {
210 $migrations[] = $this->migration->config->set('mail', 'type', 'Cram-md5');
211 }
212
213 // keep piwik_ignore for existing installs
214 $migrations[] = $this->migration->config->set('Tracker', 'ignore_visits_cookie_name', 'piwik_ignore');
215
216 $migrations[] = $this->migration->plugin->activate('PagePerformance');
217 if (!Manager::getInstance()->isPluginActivated('CustomDimensions')) {
218 $migrations[] = $this->migration->plugin->activate('CustomDimensions');
219 }
220
221 $configTableLimit = Config::getInstance()->getFromLocalConfig('General')['datatable_archiving_maximum_rows_custom_variables'] ?? null;
222 $configSubTableLimit = Config::getInstance()->getFromLocalConfig('General')['datatable_archiving_maximum_rows_subtable_custom_variables'] ?? null;
223
224 if ($configTableLimit) {
225 $migrations[] = $this->migration->config->set('General', 'datatable_archiving_maximum_rows_custom_dimensions', $configTableLimit);
226 }
227 if ($configSubTableLimit) {
228 $migrations[] = $this->migration->config->set('General', 'datatable_archiving_maximum_rows_subtable_custom_dimensions', $configSubTableLimit);
229 }
230
231 return $migrations;
232 }
233
234 public function doUpdate(Updater $updater)
235 {
236 $salt = SettingsPiwik::getSalt();
237 $sessions = Db::fetchAll('SELECT id from ' . Common::prefixTable('session'));
238
239 foreach ($sessions as $session) {
240 if (!empty($session['id']) && mb_strlen($session['id']) != 128) {
241 $bind = [ hash('sha512', $session['id'] . $salt), $session['id'] ];
242 try {
243 Db::query(sprintf('UPDATE %s SET id = ? WHERE id = ?', Common::prefixTable('session')), $bind);
244 } catch (\Exception $e) {
245 // ignore possible duplicate key errors
246 }
247 }
248 }
249
250 $updater->executeMigrations(__FILE__, $this->getMigrations($updater));
251
252 if ($this->usesGeoIpLegacyLocationProvider()) {
253 // switch to default provider if GeoIp Legacy was still in use
254 LocationProvider::setCurrentProvider(LocationProvider\DefaultProvider::ID);
255 }
256
257 // eg the case when not updating from most recent Matomo 3.X and when not using the UI updater
258 // afterwards the should receive a notification that the plugins are outdated
259 self::ensureCorePluginsThatWereMovedToMarketplaceCanBeUpdated();
260 ServerFilesGenerator::createFilesForSecurity();
261 }
262
263 public static function ensureCorePluginsThatWereMovedToMarketplaceCanBeUpdated()
264 {
265 $plugins = ['Provider', 'CustomVariables'];
266 $pluginManager = Manager::getInstance();
267 foreach ($plugins as $plugin) {
268 if ($pluginManager->isPluginThirdPartyAndBogus($plugin)) {
269 $pluginDir = Manager::getPluginDirectory($plugin);
270
271 if (is_dir($pluginDir) &&
272 file_exists($pluginDir . '/' . $plugin . '.php')
273 && !file_exists($pluginDir . '/plugin.json')
274 && is_writable($pluginDir)) {
275 file_put_contents($pluginDir . '/plugin.json', '{
276 "name": "'.$plugin.'",
277 "description": "'.$plugin.'",
278 "version": "3.14.1",
279 "theme": false,
280 "require": {
281 "piwik": ">=3.0.0,<4.0.0-b1"
282 },
283 "authors": [
284 {
285 "name": "Matomo",
286 "email": "hello@matomo.org",
287 "homepage": "https:\/\/matomo.org"
288 }
289 ],
290 "homepage": "https:\/\/matomo.org",
291 "license": "GPL v3+",
292 "keywords": ["'.$plugin.'"]
293 }');
294 // otherwise cached information might be used and it won't be loaded otherwise within same request
295 $pluginObj = $pluginManager->loadPlugin($plugin);
296 $pluginObj->reloadPluginInformation();
297 $pluginManager->unloadPlugin($pluginObj); // prevent any events being posted to it somehow
298 }
299 }
300 }
301 }
302
303 protected function usesGeoIpLegacyLocationProvider()
304 {
305 $currentProvider = LocationProvider::getCurrentProviderId();
306
307 return in_array($currentProvider, [
308 'geoip_pecl',
309 'geoip_php',
310 'geoip_serverbased',
311 ]);
312 }
313 }
314