Skip to content

Instantly share code, notes, and snippets.

@JugurthaK
Created November 4, 2019 12:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JugurthaK/2cfe4b74c26e6880ae515ae807e0890d to your computer and use it in GitHub Desktop.
Save JugurthaK/2cfe4b74c26e6880ae515ae807e0890d to your computer and use it in GitHub Desktop.
<?php
$config = json_decode(file_get_contents(dirname(__FILE__) . "/install.json"), true);
if (!is_array($config)) {
die("[ERROR] Cannot parse JSON file at [". dirname(__FILE__) . "/install.json" ."]\n");
}
define('PIWIK_DOCUMENT_ROOT', $config['document_root']);
if (file_exists(PIWIK_DOCUMENT_ROOT . '/bootstrap.php')) {
require_once PIWIK_DOCUMENT_ROOT . '/bootstrap.php';
}
if (!defined('PIWIK_INCLUDE_PATH')) {
define('PIWIK_INCLUDE_PATH', PIWIK_DOCUMENT_ROOT);
}
require_once PIWIK_INCLUDE_PATH . '/core/bootstrap.php';
if (!Piwik\Common::isPhpCliMode()) {
exit;
}
if (!defined('PIWIK_ENABLE_ERROR_HANDLER') || PIWIK_ENABLE_ERROR_HANDLER) {
Piwik\ErrorHandler::registerErrorHandler();
Piwik\ExceptionHandler::setUp();
}
use Piwik\ErrorHandler;
use Piwik\ExceptionHandler;
use Piwik\FrontController;
use Piwik\Access;
use Piwik\Common;
use Piwik\Plugins\UsersManager\API as APIUsersManager;
use Piwik\Plugins\SitesManager\API as APISitesManager;
use Piwik\Plugins\CoreAdminHome\API as APICoreAdminHome;
use Piwik\Plugins\Marketplace\API as APIMarketplace;
use Piwik\Config;
use Piwik\Filesystem;
use Piwik\DbHelper;
use Piwik\Updater;
use Piwik\Plugin\Manager;
use Piwik\Container\StaticContainer;
use Piwik\Option;
if (!defined('PIWIK_ENABLE_ERROR_HANDLER') || PIWIK_ENABLE_ERROR_HANDLER) {
ErrorHandler::registerErrorHandler();
ExceptionHandler::setUp();
}
FrontController::setUpSafeMode();
$environment = new \Piwik\Application\Environment(null);
try {
$environment->init();
} catch(\Exception $e) {}
$installer = new PiwikCliInstall($config);
$installer->install();
class PiwikCliInstall {
protected $config;
public function __construct($config) {
$this->config = $config;
}
protected function log($text) {
echo date("Y-m-d H:i:s") . " - $text\n";
}
public function install() {
/*
To avoid unnecessary redundant tasks. Run only on one instance operations
that dont generate/update config file (conf)
*/
$this->log('Running Piwik Initial Install Script');
$this->prepare();
$this->initDBConnection();
if(getenv('CF_INSTANCE_INDEX') === "0") {
$this->tableCreation();
$this->createUser();
$this->addWebsite();
}
$this->setTrustedHosts();
$this->finish();
// $this->setGeo();
$this->setPrivacy();
if(getenv('CF_INSTANCE_INDEX') === "0") {
/* It's making call to matomo/piwik domain to activate purchaed plugins */
$this->saveLicenseKey();
}
$this->setupPlugins();
$this->setConfigExtras();
$this->setOptionExtras();
$this->deactivatePlugins();
$this->setPluginSettings();
$this->setArchivingSettings();
}
protected function prepare() {
$this->log('Preparing Cache and Diagnostics');
Filesystem::deleteAllCacheOnUpdate();
$diagnosticService = StaticContainer::get('Piwik\Plugins\Diagnostics\DiagnosticService');
$diagnosticService->runDiagnostics();
}
/**
* Initialises and saves the database connection to Piwik
* [database] should be in config. Should be an array with keys [host], [adapter], [username], [password], [dbname] and [tables_prefix]
*/
protected function initDBConnection() {
$this->log('Initialising Database Connections');
$config = Config::getInstance();
if (array_key_exists('session_save_handler', $this->config)) {
$config->General['session_save_handler'] = $this->config['session_save_handler'];
}
// TODO Salt lookk like making problem with multi servers
// $config->General['salt'] = Common::generateUniqId();
$config->General['installation_in_progress'] = 1;
$config->database = $this->config['database'];
// Connect to the database with retry timeout so any provisioning scripts & DB setup scripts are given a chance
$retries = array(10, 20, 30, 40, 50, 60, 70, 80);
foreach( $retries as $retry_timeout_index => $retry_timeout ) {
try {
DbHelper::isDatabaseConnectionUTF8();
break;
} catch(\Exception $e) {
$this->log("Database connection failed. Retrying in $retry_timeout seconds.");
$this->log($e->getMessage());
sleep($retry_timeout);
}
}
if (!DbHelper::isDatabaseConnectionUTF8()) { // Exception will be thrown if cannot connect
$config->database['charset'] = 'utf8';
}
$config->forceSave();
}
/**
* Performs the initial table creation for Piwik
*/
protected function tableCreation() {
$this->log('Ensuring Tables are Created');
$tablesInstalled = DbHelper::getTablesInstalled();
if (count($tablesInstalled) === 0) {
DbHelper::createTables();
DbHelper::createAnonymousUser();
$this->updateComponents();
}
}
/**
* Creates the default superuser
* [login], [password] and [email] should all be set in the config
*/
protected function createUser() {
$this->log('Ensuring Users get Created');
$config_arr = $this->config;
Access::doAsSuperUser(function () use ($config_arr) {
$api = APIUsersManager::getInstance();
if (!$api->userExists($config_arr['login']) and !$api->userEmailExists($config_arr['email'])) {
$api->addUser($config_arr['login'], $config_arr['password'], $config_arr['email']);
$api->setSuperUserAccess($config_arr['login'], true);
}
});
}
/**
* Sets up the initial website (site ID 1 or (4) ) to track
* [site_name], [site_url] and [base_domain] should all be set in config
*/
protected function addWebsite() {
$this->log('Adding Primary Website');
$primaryWebSiteNotExist = Access::doAsSuperUser(function () {
return empty(APISitesManager::getInstance()->getAllSitesId());
});
if ($primaryWebSiteNotExist) {
$config_arr = $this->config;
$result = Access::doAsSuperUser(function () use ($config_arr) {
return APISitesManager::getInstance()->addSite($config_arr['site_name'], $config_arr['site_url'], 0);
});
}
}
/**
* Sets up the trused hosts (domains that reference the instance)
*/
protected function setTrustedHosts() {
$general = Config::getInstance()->General;
$general['trusted_hosts'] = $this->config['trusted_hosts'];
Config::getInstance()->General = $general;
Config::getInstance()->forceSave();
}
/**
* Finishes the fake installation. Removes 'installation_in_progress' in the config file and updates core.
*/
protected function finish() {
$this->log('Finalising primary install procedure');
Manager::getInstance()->loadPluginTranslations();
Manager::getInstance()->loadActivatedPlugins();
Manager::getInstance()->installLoadedPlugins();
$config = Config::getInstance();
unset($config->General['installation_in_progress']);
unset($config->database['adapter']);
$config->forceSave();
// Put in Activated plugins
Manager::getInstance()->loadActivatedPlugins();
exec("php " . PIWIK_DOCUMENT_ROOT . "/console core:update --yes");
}
/**
* Sets the Geolocation
* [geo_provider] is mandatory. Only correct value implemented is [geoip_pecl]
*/
protected function setGeo() {
$this->log('Setting Geolocation');
Option::set('usercountry.location_provider', $this->config['geo_provider']);
if ( $this->config['geo_provider'] === 'geoip_pecl' ) {
Option::set('geoip.isp_db_url', '');
Option::set('geoip.loc_db_url', 'http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz');
Option::set('geoip.org_db_url', '');
Option::set('geoip.updater_period', 'month');
}
}
/**
* Sets privacy settings
* [privacy] can exist in config. Sub settings are [anonymize_ip] and [honor_do_not_track]
*/
protected function setPrivacy() {
$this->log('Setting up Privacy Rules');
if ( array_key_exists('privacy', $this->config) && is_array($this->config['privacy']) ) {
if ( array_key_exists('anonymize_ip', $this->config['privacy']) ) {
if ($this->config['privacy']['anonymize_ip'] === true) {
Option::set('PrivacyManager.ipAnonymizerEnabled', 1);
Option::set('PrivacyManager.ipAddressMaskLength', 2);
// Avoid using Anonymized Ip For VisitEnrichment ( possible impact on unique visitors)
Option::set('PrivacyManager.useAnonymizedIpForVisitEnrichment', false);
} else {
Option::set('PrivacyManager.ipAnonymizerEnabled', 0);
}
}
if ( array_key_exists('honor_do_not_track', $this->config['privacy']) ) {
if ($this->config['privacy']['honor_do_not_track'] === true) {
Option::set('PrivacyManager.doNotTrackEnabled', 1);
} else {
Option::set('PrivacyManager.doNotTrackEnabled', 0);
}
}
}
}
/**
* Sets extra configuration that is to go directly into the config.ini.php
* [config] can exist. Each Key represents a section in the config file ( value should also be array)
* Each sub-array item in key->value represents the config key and associated setting
*/
protected function setConfigExtras() {
$this->log('Setting up extra configuration');
if (array_key_exists('extras', $this->config) && is_array($this->config['extras'])) {
// 2 level array - section then setting
$config = Config::getInstance();
foreach( $this->config['extras'] as $config_section => $config_settings ) {
foreach($config_settings as $setting_key => $setting_value) {
$config->{$config_section}[$setting_key] = $setting_value;
}
}
$config->forceSave();
}
}
/**
* Setup plugins
* [plugins] in config should be text based and already extracted in the plugins piwik directory
*/
protected function setupPlugins() {
$this->log('Setting up Extra Plugins');
echo exec("php " . PIWIK_DOCUMENT_ROOT . "/console core:clear-caches") . "\n";
if (array_key_exists('plugins', $this->config) && is_array($this->config['plugins'])) {
$config = Config::getInstance();
foreach($config->PluginsInstalled as $pi_arr) {
foreach($pi_arr as $pi) {
$config->Plugins[] = $pi;
}
}
// Now go and activate them
foreach( $this->config['plugins'] as $plugin_txt ) {
echo exec("php " . PIWIK_DOCUMENT_ROOT . "/console plugin:activate " . $plugin_txt) . "\n";
$config->PluginsInstalled[] = $plugin_txt;
$config->Plugins[] = $plugin_txt;
}
$config->forceSave();
// And Update Core
exec("php " . PIWIK_DOCUMENT_ROOT . "/console core:update --yes");
}
}
/**
* Deactivates any default plugins specified
* [deactivate_plugins] in config should be set
*/
protected function deactivatePlugins() {
$this->log('Deactivating unwanted plugins');
if (array_key_exists('deactivate_plugins', $this->config) && is_array($this->config['deactivate_plugins'])) {
foreach ($this->config['deactivate_plugins'] as $plugin_to_deactivate) {
echo exec("php " . PIWIK_DOCUMENT_ROOT . "/console plugin:deactivate " . $plugin_to_deactivate) . "\n";
}
}
}
/**
* This function sets optional extras
* [options] should be set and be key-value in order to use
*/
protected function setOptionExtras() {
$this->log('Setting custom options');
if (array_key_exists('options', $this->config) && is_array($this->config['options'])) {
foreach( $this->config['options'] as $option_key => $option_val ) {
Option::set($option_key, $option_val);
}
}
}
protected function updateComponents() {
$this->log('Updating Components');
Access::getInstance();
return Access::doAsSuperUser(function () {
$updater = new Updater();
$componentsWithUpdateFile = $updater->getComponentUpdates();
if (empty($componentsWithUpdateFile)) {
return false;
}
$result = $updater->updateComponents($componentsWithUpdateFile);
print($result);
return $result;
});
}
/**
* Updates Piwik V3 Plugin Settings.
* Looks for a [plugin_settings] key in config. Config then in key-value form nested under plugin_name
*/
protected function setPluginSettings() {
$this->log('Updating Plugin Settings');
if (array_key_exists('plugin_settings', $this->config)) {
if (class_exists("\\Piwik\\Plugins\\CorePluginsAdmin\\SettingsMetadata")) {
foreach($this->config['plugin_settings'] as $plugin_name => $plugin_settings) {
$this->log("Adding plugin settings for $plugin_name");
$settings = new \Piwik\Settings\Storage\Backend\PluginSettingsTable($plugin_name, "");
$settings->save( $plugin_settings );
}
} else {
$this->log("Cannot update plugin settings - Are you running Piwik 3?");
}
}
}
/**
* Set the archiving settings to disable realtime archiving
*/
protected function setArchivingSettings() {
$this->log('Updating Archiving Settings');
$config_arr = $this->config;
if ( array_key_exists('archiving', $this->config) && is_array($this->config['archiving']) ) {
$archivingSettingsApplied = Access::doAsSuperUser(function () use ($config_arr) {
$archiving = $config_arr['archiving'];
return APICoreAdminHome::getInstance()->setArchiveSettings($archiving['enable_browser_trigger_archiving'], $archiving['today_archive_time_to_live']);
});
}
}
/**
* Save the provided license key for plugins
*/
protected function saveLicenseKey() {
$this->log('Save plugins license Key');
$config_arr = $this->config;
if ( array_key_exists('plugins_license_Key', $this->config) ) {
$licenseKeySaved = Access::doAsSuperUser(function () use ($config_arr) {
return APIMarketplace::getInstance()->saveLicenseKey($config_arr['plugins_license_Key']);
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment