migration = $factory; } public function getMigrations(Updater $updater) { $migrations = array('# ATTENTION: This update script will execute some more SQL queries than that below as it is necessary to rebuilt some archives #' => false); // update scheduled reports to use new plugin $reportsToReplace = array( 'UserSettings_getBrowserVersion' => 'DevicesDetection_getBrowserVersions', 'UserSettings_getBrowser' => 'DevicesDetection_getBrowsers', 'UserSettings_getOSFamily' => 'DevicesDetection_getOsFamilies', 'UserSettings_getOS' => 'DevicesDetection_getOsVersions', 'UserSettings_getMobileVsDesktop' => 'DevicesDetection_getType', 'UserSettings_getBrowserType' => 'DevicesDetection_getBrowserEngines', 'UserSettings_getWideScreen' => 'UserSettings_getScreenType', ); $reportTable = Common::prefixTable('report'); foreach ($reportsToReplace as $old => $new) { $migrations[] = $this->migration->db->sql("UPDATE $reportTable SET reports = REPLACE(reports, '".$old."', '".$new."')"); } // update dashboard to use new widgets $oldWidgets = array( array('module' => 'UserSettings', 'action' => 'getBrowserVersion', 'params' => array()), array('module' => 'UserSettings', 'action' => 'getBrowser', 'params' => array()), array('module' => 'UserSettings', 'action' => 'getOSFamily', 'params' => array()), array('module' => 'UserSettings', 'action' => 'getOS', 'params' => array()), array('module' => 'UserSettings', 'action' => 'getMobileVsDesktop', 'params' => array()), array('module' => 'UserSettings', 'action' => 'getBrowserType', 'params' => array()), array('module' => 'UserSettings', 'action' => 'getWideScreen', 'params' => array()), ); $newWidgets = array( array('module' => 'DevicesDetection', 'action' => 'getBrowserVersions', 'params' => array()), array('module' => 'DevicesDetection', 'action' => 'getBrowsers', 'params' => array()), array('module' => 'DevicesDetection', 'action' => 'getOsFamilies', 'params' => array()), array('module' => 'DevicesDetection', 'action' => 'getOsVersions', 'params' => array()), array('module' => 'DevicesDetection', 'action' => 'getType', 'params' => array()), array('module' => 'DevicesDetection', 'action' => 'getBrowserEngines', 'params' => array()), array('module' => 'UserSettings', 'action' => 'getScreenType', 'params' => array()), ); $allDashboards = Db::get()->fetchAll(sprintf("SELECT * FROM %s", Common::prefixTable('user_dashboard'))); $dashboardTable = Common::prefixTable('user_dashboard'); $dashboardQuery = "UPDATE $dashboardTable SET layout = ? WHERE iddashboard = ?"; foreach ($allDashboards as $dashboard) { $dashboardLayout = json_decode($dashboard['layout']); $dashboardLayout = DashboardModel::replaceDashboardWidgets($dashboardLayout, $oldWidgets, $newWidgets); $newLayout = json_encode($dashboardLayout); if ($newLayout != $dashboard['layout']) { $migrations[] = $this->migration->db->boundSql($dashboardQuery, array($newLayout, $dashboard['iddashboard'])); } } return $migrations; } public function doUpdate(Updater $updater) { $updater->executeMigrations(__FILE__, $this->getMigrations($updater)); // DeviceDetection upgrade in beta1 timed out on demo #6750 $archiveBlobTables = self::getAllArchiveBlobTables(); foreach ($archiveBlobTables as $table) { self::updateBrowserArchives($table); self::updateOsArchives($table); } } /** * Returns all available archive blob tables * * @return array */ public static function getAllArchiveBlobTables() { if (empty(self::$archiveBlobTables)) { $archiveTables = ArchiveTableCreator::getTablesArchivesInstalled(); self::$archiveBlobTables = array_filter($archiveTables, function ($name) { return ArchiveTableCreator::getTypeFromTableName($name) == ArchiveTableCreator::BLOB_TABLE; }); // sort tables so we have them in order of their date rsort(self::$archiveBlobTables); } return (array) self::$archiveBlobTables; } /** * Find the first day on which DevicesDetection archives were generated * * @return int Timestamp */ public static function getFirstDayOfArchivedDeviceDetectorData() { static $deviceDetectionBlobAvailableDate; if (empty($deviceDetectionBlobAvailableDate)) { $archiveBlobTables = self::getAllArchiveBlobTables(); $deviceDetectionBlobAvailableDate = null; foreach ($archiveBlobTables as $table) { // Look for all day archives and try to find that with the lowest date $deviceDetectionBlobAvailableDate = Db::get()->fetchOne(sprintf("SELECT date1 FROM %s WHERE name = 'DevicesDetection_browserVersions' AND period = 1 ORDER BY date1 ASC LIMIT 1", $table)); if (!empty($deviceDetectionBlobAvailableDate)) { break; } } $deviceDetectionBlobAvailableDate = strtotime($deviceDetectionBlobAvailableDate); } return $deviceDetectionBlobAvailableDate; } /** * Updates all browser archives to new structure * @param string $table * @throws \Exception */ public static function updateBrowserArchives($table) { // rename old UserSettings archives where no DeviceDetection archives exists Db::exec(sprintf("UPDATE IGNORE %s SET name='DevicesDetection_browserVersions' WHERE name = 'UserSettings_browser'", $table)); /* * check dates of remaining (non-day) archives with calculated safe date * archives before or within that week/month/year of that date will be replaced */ $oldBrowserBlobs = Db::get()->fetchAll(sprintf("SELECT * FROM %s WHERE name = 'UserSettings_browser' AND `period` > 1", $table)); foreach ($oldBrowserBlobs as $blob) { // if start date of blob is before calculated date us old usersettings archive instead of already existing DevicesDetection archive if (strtotime($blob['date1']) < self::getFirstDayOfArchivedDeviceDetectorData()) { Db::get()->query(sprintf("DELETE FROM %s WHERE idarchive = ? AND name = ?", $table), array($blob['idarchive'], 'DevicesDetection_browserVersions')); Db::get()->query(sprintf("UPDATE %s SET name = ? WHERE idarchive = ? AND name = ?", $table), array('DevicesDetection_browserVersions', $blob['idarchive'], 'UserSettings_browser')); } } } public static function updateOsArchives($table) { Db::exec(sprintf("UPDATE IGNORE %s SET name='DevicesDetection_osVersions' WHERE name = 'UserSettings_os'", $table)); /* * check dates of remaining (non-day) archives with calculated safe date * archives before or within that week/month/year of that date will be replaced */ $oldOsBlobs = Db::get()->fetchAll(sprintf("SELECT * FROM %s WHERE name = 'UserSettings_os' AND `period` > 1", $table)); foreach ($oldOsBlobs as $blob) { // if start date of blob is before calculated date us old usersettings archive instead of already existing DevicesDetection archive if (strtotime($blob['date1']) < self::getFirstDayOfArchivedDeviceDetectorData()) { Db::get()->query(sprintf("DELETE FROM %s WHERE idarchive = ? AND name = ?", $table), array($blob['idarchive'], 'DevicesDetection_osVersions')); Db::get()->query(sprintf("UPDATE %s SET name = ? WHERE idarchive = ? AND name = ?", $table), array('DevicesDetection_osVersions', $blob['idarchive'], 'UserSettings_os')); } } } }