add piwik installation
This commit is contained in:
parent
90aa4ef157
commit
8c5d4f0c31
3197 changed files with 563902 additions and 0 deletions
61
www/analytics/core/AssetManager/UIAsset.php
Normal file
61
www/analytics/core/AssetManager/UIAsset.php
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\AssetManager;
|
||||
|
||||
use Exception;
|
||||
|
||||
abstract class UIAsset
|
||||
{
|
||||
abstract public function validateFile();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getAbsoluteLocation();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getRelativeLocation();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getBaseDirectory();
|
||||
|
||||
/**
|
||||
* Removes the previous file if it exists.
|
||||
* Also tries to remove compressed version of the file.
|
||||
*
|
||||
* @see ProxyStaticFile::serveStaticFile(serveFile
|
||||
* @throws Exception if the file couldn't be deleted
|
||||
*/
|
||||
abstract public function delete();
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @throws \Exception
|
||||
*/
|
||||
abstract public function writeContent($content);
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getContent();
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
abstract public function exists();
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
abstract public function getModificationDate();
|
||||
}
|
||||
63
www/analytics/core/AssetManager/UIAsset/InMemoryUIAsset.php
Normal file
63
www/analytics/core/AssetManager/UIAsset/InMemoryUIAsset.php
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\AssetManager\UIAsset;
|
||||
|
||||
use Exception;
|
||||
use Piwik\AssetManager\UIAsset;
|
||||
|
||||
class InMemoryUIAsset extends UIAsset
|
||||
{
|
||||
private $content;
|
||||
|
||||
public function validateFile()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public function getAbsoluteLocation()
|
||||
{
|
||||
throw new Exception('invalid operation');
|
||||
}
|
||||
|
||||
public function getRelativeLocation()
|
||||
{
|
||||
throw new Exception('invalid operation');
|
||||
}
|
||||
|
||||
public function getBaseDirectory()
|
||||
{
|
||||
throw new Exception('invalid operation');
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$this->content = null;
|
||||
}
|
||||
|
||||
public function exists()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function writeContent($content)
|
||||
{
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
public function getContent()
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
public function getModificationDate()
|
||||
{
|
||||
throw new Exception('invalid operation');
|
||||
}
|
||||
}
|
||||
113
www/analytics/core/AssetManager/UIAsset/OnDiskUIAsset.php
Normal file
113
www/analytics/core/AssetManager/UIAsset/OnDiskUIAsset.php
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\AssetManager\UIAsset;
|
||||
|
||||
use Exception;
|
||||
use Piwik\AssetManager\UIAsset;
|
||||
|
||||
class OnDiskUIAsset extends UIAsset
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $baseDirectory;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $relativeLocation;
|
||||
|
||||
/**
|
||||
* @param string $baseDirectory
|
||||
* @param string $fileLocation
|
||||
*/
|
||||
function __construct($baseDirectory, $fileLocation)
|
||||
{
|
||||
$this->baseDirectory = $baseDirectory;
|
||||
$this->relativeLocation = $fileLocation;
|
||||
}
|
||||
|
||||
public function getAbsoluteLocation()
|
||||
{
|
||||
return $this->baseDirectory . '/' . $this->relativeLocation;
|
||||
}
|
||||
|
||||
public function getRelativeLocation()
|
||||
{
|
||||
return $this->relativeLocation;
|
||||
}
|
||||
|
||||
public function getBaseDirectory()
|
||||
{
|
||||
return $this->baseDirectory;
|
||||
}
|
||||
|
||||
public function validateFile()
|
||||
{
|
||||
if (!$this->assetIsReadable())
|
||||
throw new Exception("The ui asset with 'href' = " . $this->getAbsoluteLocation() . " is not readable");
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
if ($this->exists()) {
|
||||
|
||||
if (!unlink($this->getAbsoluteLocation()))
|
||||
throw new Exception("Unable to delete merged file : " . $this->getAbsoluteLocation() . ". Please delete the file and refresh");
|
||||
|
||||
// try to remove compressed version of the merged file.
|
||||
@unlink($this->getAbsoluteLocation() . ".deflate");
|
||||
@unlink($this->getAbsoluteLocation() . ".gz");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function writeContent($content)
|
||||
{
|
||||
$this->delete();
|
||||
|
||||
$newFile = @fopen($this->getAbsoluteLocation(), "w");
|
||||
|
||||
if (!$newFile)
|
||||
throw new Exception ("The file : " . $newFile . " can not be opened in write mode.");
|
||||
|
||||
fwrite($newFile, $content);
|
||||
|
||||
fclose($newFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
return file_get_contents($this->getAbsoluteLocation());
|
||||
}
|
||||
|
||||
public function exists()
|
||||
{
|
||||
return $this->assetIsReadable();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
private function assetIsReadable()
|
||||
{
|
||||
return is_readable($this->getAbsoluteLocation());
|
||||
}
|
||||
|
||||
public function getModificationDate()
|
||||
{
|
||||
return filemtime($this->getAbsoluteLocation());
|
||||
}
|
||||
}
|
||||
54
www/analytics/core/AssetManager/UIAssetCacheBuster.php
Normal file
54
www/analytics/core/AssetManager/UIAssetCacheBuster.php
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
* @method static \Piwik\AssetManager\UIAssetCacheBuster getInstance()
|
||||
*/
|
||||
namespace Piwik\AssetManager;
|
||||
|
||||
use Piwik\Plugin\Manager;
|
||||
use Piwik\Singleton;
|
||||
use Piwik\Version;
|
||||
|
||||
class UIAssetCacheBuster extends Singleton
|
||||
{
|
||||
/**
|
||||
* Cache buster based on
|
||||
* - Piwik version
|
||||
* - Loaded plugins (name and version)
|
||||
* - Super user salt
|
||||
* - Latest
|
||||
*
|
||||
* @param string[] $pluginNames
|
||||
* @return string
|
||||
*/
|
||||
public function piwikVersionBasedCacheBuster($pluginNames = false)
|
||||
{
|
||||
$masterFile = PIWIK_INCLUDE_PATH . '/.git/refs/heads/master';
|
||||
$currentGitHash = file_exists($masterFile) ? @file_get_contents($masterFile) : null;
|
||||
|
||||
$pluginNames = !$pluginNames ? Manager::getInstance()->getLoadedPluginsName() : $pluginNames;
|
||||
sort($pluginNames);
|
||||
|
||||
$pluginsInfo = '';
|
||||
foreach ($pluginNames as $pluginName) {
|
||||
$plugin = Manager::getInstance()->getLoadedPlugin($pluginName);
|
||||
$pluginsInfo .= $plugin->getPluginName() . $plugin->getVersion() . ',';
|
||||
}
|
||||
|
||||
$cacheBuster = md5($pluginsInfo . PHP_VERSION . Version::VERSION . trim($currentGitHash));
|
||||
return $cacheBuster;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
public function md5BasedCacheBuster($content)
|
||||
{
|
||||
return md5($content);
|
||||
}
|
||||
}
|
||||
70
www/analytics/core/AssetManager/UIAssetCatalog.php
Normal file
70
www/analytics/core/AssetManager/UIAssetCatalog.php
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\AssetManager;
|
||||
|
||||
class UIAssetCatalog
|
||||
{
|
||||
/**
|
||||
* @var UIAsset[]
|
||||
*/
|
||||
private $uiAssets = array();
|
||||
|
||||
/**
|
||||
* @var UIAssetCatalogSorter
|
||||
*/
|
||||
private $catalogSorter;
|
||||
|
||||
/**
|
||||
* @param UIAssetCatalogSorter $catalogSorter
|
||||
*/
|
||||
function __construct($catalogSorter)
|
||||
{
|
||||
$this->catalogSorter = $catalogSorter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UIAsset $uiAsset
|
||||
*/
|
||||
public function addUIAsset($uiAsset)
|
||||
{
|
||||
if(!$this->assetAlreadyInCatalog($uiAsset)) {
|
||||
|
||||
$this->uiAssets[] = $uiAsset;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UIAsset[]
|
||||
*/
|
||||
public function getAssets()
|
||||
{
|
||||
return $this->uiAssets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UIAssetCatalog
|
||||
*/
|
||||
public function getSortedCatalog()
|
||||
{
|
||||
return $this->catalogSorter->sortUIAssetCatalog($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UIAsset $uiAsset
|
||||
* @return boolean
|
||||
*/
|
||||
private function assetAlreadyInCatalog($uiAsset)
|
||||
{
|
||||
foreach($this->uiAssets as $existingAsset)
|
||||
if($uiAsset->getAbsoluteLocation() == $existingAsset->getAbsoluteLocation())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
59
www/analytics/core/AssetManager/UIAssetCatalogSorter.php
Normal file
59
www/analytics/core/AssetManager/UIAssetCatalogSorter.php
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\AssetManager;
|
||||
|
||||
class UIAssetCatalogSorter
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $priorityOrder;
|
||||
|
||||
/**
|
||||
* @param string[] $priorityOrder
|
||||
*/
|
||||
function __construct($priorityOrder)
|
||||
{
|
||||
$this->priorityOrder = $priorityOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UIAssetCatalog $uiAssetCatalog
|
||||
* @return UIAssetCatalog
|
||||
*/
|
||||
public function sortUIAssetCatalog($uiAssetCatalog)
|
||||
{
|
||||
$sortedCatalog = new UIAssetCatalog($this);
|
||||
foreach ($this->priorityOrder as $filePattern) {
|
||||
|
||||
$assetsMatchingPattern = array_filter($uiAssetCatalog->getAssets(), function($uiAsset) use ($filePattern) {
|
||||
return preg_match('~^' . $filePattern . '~', $uiAsset->getRelativeLocation());
|
||||
});
|
||||
|
||||
foreach($assetsMatchingPattern as $assetMatchingPattern) {
|
||||
$sortedCatalog->addUIAsset($assetMatchingPattern);
|
||||
}
|
||||
}
|
||||
|
||||
$this->addUnmatchedAssets($uiAssetCatalog, $sortedCatalog);
|
||||
|
||||
return $sortedCatalog;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UIAssetCatalog $uiAssetCatalog
|
||||
* @param UIAssetCatalog $sortedCatalog
|
||||
*/
|
||||
private function addUnmatchedAssets($uiAssetCatalog, $sortedCatalog)
|
||||
{
|
||||
foreach ($uiAssetCatalog->getAssets() as $uiAsset) {
|
||||
$sortedCatalog->addUIAsset($uiAsset);
|
||||
}
|
||||
}
|
||||
}
|
||||
119
www/analytics/core/AssetManager/UIAssetFetcher.php
Normal file
119
www/analytics/core/AssetManager/UIAssetFetcher.php
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\AssetManager;
|
||||
|
||||
use Piwik\AssetManager\UIAsset\OnDiskUIAsset;
|
||||
use Piwik\Theme;
|
||||
|
||||
abstract class UIAssetFetcher
|
||||
{
|
||||
/**
|
||||
* @var UIAssetCatalog
|
||||
*/
|
||||
protected $catalog;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fileLocations = array();
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
protected $plugins;
|
||||
|
||||
/**
|
||||
* @var Theme
|
||||
*/
|
||||
private $theme;
|
||||
|
||||
/**
|
||||
* @param string[] $plugins
|
||||
* @param Theme $theme
|
||||
*/
|
||||
function __construct($plugins, $theme)
|
||||
{
|
||||
$this->plugins = $plugins;
|
||||
$this->theme = $theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getPlugins()
|
||||
{
|
||||
return $this->plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* $return UIAssetCatalog
|
||||
*/
|
||||
public function getCatalog()
|
||||
{
|
||||
if($this->catalog == null)
|
||||
$this->createCatalog();
|
||||
|
||||
return $this->catalog;
|
||||
}
|
||||
|
||||
abstract protected function retrieveFileLocations();
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
abstract protected function getPriorityOrder();
|
||||
|
||||
private function createCatalog()
|
||||
{
|
||||
$this->retrieveFileLocations();
|
||||
|
||||
$this->initCatalog();
|
||||
|
||||
$this->populateCatalog();
|
||||
|
||||
$this->sortCatalog();
|
||||
}
|
||||
|
||||
private function initCatalog()
|
||||
{
|
||||
$catalogSorter = new UIAssetCatalogSorter($this->getPriorityOrder());
|
||||
$this->catalog = new UIAssetCatalog($catalogSorter);
|
||||
}
|
||||
|
||||
private function populateCatalog()
|
||||
{
|
||||
foreach ($this->fileLocations as $fileLocation) {
|
||||
|
||||
$newUIAsset = new OnDiskUIAsset($this->getBaseDirectory(), $fileLocation);
|
||||
$this->catalog->addUIAsset($newUIAsset);
|
||||
}
|
||||
}
|
||||
|
||||
private function sortCatalog()
|
||||
{
|
||||
$this->catalog = $this->catalog->getSortedCatalog();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function getBaseDirectory()
|
||||
{
|
||||
// served by web server directly, so must be a public path
|
||||
return PIWIK_USER_PATH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Theme
|
||||
*/
|
||||
public function getTheme()
|
||||
{
|
||||
return $this->theme;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\AssetManager\UIAssetFetcher;
|
||||
|
||||
use Piwik\AssetManager\UIAssetFetcher;
|
||||
use Piwik\Piwik;
|
||||
use string;
|
||||
|
||||
class JScriptUIAssetFetcher extends UIAssetFetcher
|
||||
{
|
||||
|
||||
protected function retrieveFileLocations()
|
||||
{
|
||||
|
||||
if(!empty($this->plugins)) {
|
||||
|
||||
/**
|
||||
* Triggered when gathering the list of all JavaScript files needed by Piwik
|
||||
* and its plugins.
|
||||
*
|
||||
* Plugins that have their own JavaScript should use this event to make those
|
||||
* files load in the browser.
|
||||
*
|
||||
* JavaScript files should be placed within a **javascripts** subdirectory in your
|
||||
* plugin's root directory.
|
||||
*
|
||||
* _Note: While you are developing your plugin you should enable the config setting
|
||||
* `[Debug] disable_merged_assets` so JavaScript files will be reloaded immediately
|
||||
* after every change._
|
||||
*
|
||||
* **Example**
|
||||
*
|
||||
* public function getJsFiles(&$jsFiles)
|
||||
* {
|
||||
* $jsFiles[] = "plugins/MyPlugin/javascripts/myfile.js";
|
||||
* $jsFiles[] = "plugins/MyPlugin/javascripts/anotherone.js";
|
||||
* }
|
||||
*
|
||||
* @param string[] $jsFiles The JavaScript files to load.
|
||||
*/
|
||||
Piwik::postEvent('AssetManager.getJavaScriptFiles', array(&$this->fileLocations), null, $this->plugins);
|
||||
}
|
||||
|
||||
$this->addThemeFiles();
|
||||
}
|
||||
|
||||
protected function addThemeFiles()
|
||||
{
|
||||
$theme = $this->getTheme();
|
||||
if(!$theme) {
|
||||
return;
|
||||
}
|
||||
if(in_array($theme->getThemeName(), $this->plugins)) {
|
||||
|
||||
$jsInThemes = $this->getTheme()->getJavaScriptFiles();
|
||||
|
||||
if(!empty($jsInThemes)) {
|
||||
|
||||
foreach($jsInThemes as $jsFile) {
|
||||
|
||||
$this->fileLocations[] = $jsFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getPriorityOrder()
|
||||
{
|
||||
return array(
|
||||
'libs/jquery/jquery.js',
|
||||
'libs/jquery/jquery-ui.js',
|
||||
'libs/jquery/jquery.browser.js',
|
||||
'libs/',
|
||||
'plugins/CoreHome/javascripts/require.js',
|
||||
'plugins/Zeitgeist/javascripts/piwikHelper.js',
|
||||
'plugins/Zeitgeist/javascripts/',
|
||||
'plugins/CoreHome/javascripts/uiControl.js',
|
||||
'plugins/CoreHome/javascripts/broadcast.js',
|
||||
'plugins/CoreHome/javascripts/', // load CoreHome JS before other plugins
|
||||
'plugins/',
|
||||
'tests/',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\AssetManager\UIAssetFetcher;
|
||||
|
||||
use Piwik\AssetManager\UIAssetFetcher;
|
||||
|
||||
class StaticUIAssetFetcher extends UIAssetFetcher
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $priorityOrder;
|
||||
|
||||
function __construct($fileLocations, $priorityOrder, $theme)
|
||||
{
|
||||
parent::__construct(array(), $theme);
|
||||
|
||||
$this->fileLocations = $fileLocations;
|
||||
$this->priorityOrder = $priorityOrder;
|
||||
}
|
||||
|
||||
protected function retrieveFileLocations()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected function getPriorityOrder()
|
||||
{
|
||||
return $this->priorityOrder;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\AssetManager\UIAssetFetcher;
|
||||
|
||||
use Piwik\AssetManager\UIAssetFetcher;
|
||||
use Piwik\Piwik;
|
||||
|
||||
class StylesheetUIAssetFetcher extends UIAssetFetcher
|
||||
{
|
||||
protected function getPriorityOrder()
|
||||
{
|
||||
return array(
|
||||
'libs/',
|
||||
'plugins/CoreHome/stylesheets/color_manager.css', // must be before other Piwik stylesheets
|
||||
'plugins/Zeitgeist/stylesheets/base.less',
|
||||
'plugins/Zeitgeist/stylesheets/',
|
||||
'plugins/',
|
||||
'plugins/Dashboard/stylesheets/dashboard.less',
|
||||
'tests/',
|
||||
);
|
||||
}
|
||||
|
||||
protected function retrieveFileLocations()
|
||||
{
|
||||
/**
|
||||
* Triggered when gathering the list of all stylesheets (CSS and LESS) needed by
|
||||
* Piwik and its plugins.
|
||||
*
|
||||
* Plugins that have stylesheets should use this event to make those stylesheets
|
||||
* load.
|
||||
*
|
||||
* Stylesheets should be placed within a **stylesheets** subdirectory in your plugin's
|
||||
* root directory.
|
||||
*
|
||||
* **Example**
|
||||
*
|
||||
* public function getStylesheetFiles(&$stylesheets)
|
||||
* {
|
||||
* $stylesheets[] = "plugins/MyPlugin/stylesheets/myfile.less";
|
||||
* $stylesheets[] = "plugins/MyPlugin/stylesheets/myotherfile.css";
|
||||
* }
|
||||
*
|
||||
* @param string[] &$stylesheets The list of stylesheet paths.
|
||||
*/
|
||||
Piwik::postEvent('AssetManager.getStylesheetFiles', array(&$this->fileLocations));
|
||||
|
||||
$this->addThemeFiles();
|
||||
}
|
||||
|
||||
protected function addThemeFiles()
|
||||
{
|
||||
$themeStylesheet = $this->getTheme()->getStylesheet();
|
||||
|
||||
if($themeStylesheet) {
|
||||
$this->fileLocations[] = $themeStylesheet;
|
||||
}
|
||||
}
|
||||
}
|
||||
209
www/analytics/core/AssetManager/UIAssetMerger.php
Normal file
209
www/analytics/core/AssetManager/UIAssetMerger.php
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\AssetManager;
|
||||
|
||||
use Piwik\AssetManager\PiwikLessCompiler;
|
||||
use Piwik\AssetManager\UIAsset\StylesheetUIAsset;
|
||||
use Piwik\AssetManager;
|
||||
|
||||
abstract class UIAssetMerger
|
||||
{
|
||||
/**
|
||||
* @var UIAssetFetcher
|
||||
*/
|
||||
private $assetFetcher;
|
||||
|
||||
/**
|
||||
* @var UIAsset
|
||||
*/
|
||||
private $mergedAsset;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $mergedContent;
|
||||
|
||||
/**
|
||||
* @var UIAssetCacheBuster
|
||||
*/
|
||||
protected $cacheBuster;
|
||||
|
||||
/**
|
||||
* @param UIAsset $mergedAsset
|
||||
* @param UIAssetFetcher $assetFetcher
|
||||
* @param UIAssetCacheBuster $cacheBuster
|
||||
*/
|
||||
function __construct($mergedAsset, $assetFetcher, $cacheBuster)
|
||||
{
|
||||
$this->mergedAsset = $mergedAsset;
|
||||
$this->assetFetcher = $assetFetcher;
|
||||
$this->cacheBuster = $cacheBuster;
|
||||
}
|
||||
|
||||
public function generateFile()
|
||||
{
|
||||
if(!$this->shouldGenerate())
|
||||
return;
|
||||
|
||||
$this->mergedContent = $this->getMergedAssets();
|
||||
|
||||
$this->postEvent($this->mergedContent);
|
||||
|
||||
$this->adjustPaths();
|
||||
|
||||
$this->addPreamble();
|
||||
|
||||
$this->writeContentToFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getMergedAssets();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function generateCacheBuster();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getPreamble();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getFileSeparator();
|
||||
|
||||
/**
|
||||
* @param UIAsset $uiAsset
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function processFileContent($uiAsset);
|
||||
|
||||
/**
|
||||
* @param string $mergedContent
|
||||
*/
|
||||
abstract protected function postEvent(&$mergedContent);
|
||||
|
||||
protected function getConcatenatedAssets()
|
||||
{
|
||||
if(empty($this->mergedContent))
|
||||
$this->concatenateAssets();
|
||||
|
||||
return $this->mergedContent;
|
||||
}
|
||||
|
||||
private function concatenateAssets()
|
||||
{
|
||||
$mergedContent = '';
|
||||
|
||||
foreach ($this->getAssetCatalog()->getAssets() as $uiAsset) {
|
||||
|
||||
$uiAsset->validateFile();
|
||||
$content = $this->processFileContent($uiAsset);
|
||||
|
||||
$mergedContent .= $this->getFileSeparator() . $content;
|
||||
}
|
||||
|
||||
$this->mergedContent = $mergedContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
protected function getPlugins()
|
||||
{
|
||||
return $this->assetFetcher->getPlugins();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UIAssetCatalog
|
||||
*/
|
||||
protected function getAssetCatalog()
|
||||
{
|
||||
return $this->assetFetcher->getCatalog();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
private function shouldGenerate()
|
||||
{
|
||||
if(!$this->mergedAsset->exists())
|
||||
return true;
|
||||
|
||||
return !$this->isFileUpToDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
private function isFileUpToDate()
|
||||
{
|
||||
$f = fopen($this->mergedAsset->getAbsoluteLocation(), 'r');
|
||||
$firstLine = fgets($f);
|
||||
fclose($f);
|
||||
|
||||
if (!empty($firstLine) && trim($firstLine) == trim($this->getCacheBusterValue())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Some CSS file in the merge, has changed since last merged asset was generated
|
||||
// Note: we do not detect changes in @import'ed LESS files
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
private function isMergedAssetsDisabled()
|
||||
{
|
||||
return AssetManager::getInstance()->isMergedAssetsDisabled();
|
||||
}
|
||||
|
||||
private function adjustPaths()
|
||||
{
|
||||
$theme = $this->assetFetcher->getTheme();
|
||||
// During installation theme is not yet ready
|
||||
if($theme) {
|
||||
$this->mergedContent = $this->assetFetcher->getTheme()->rewriteAssetsPathToTheme($this->mergedContent);
|
||||
}
|
||||
}
|
||||
|
||||
private function writeContentToFile()
|
||||
{
|
||||
$this->mergedAsset->writeContent($this->mergedContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function getCacheBusterValue()
|
||||
{
|
||||
if(empty($this->cacheBusterValue))
|
||||
$this->cacheBusterValue = $this->generateCacheBuster();
|
||||
|
||||
return $this->cacheBusterValue;
|
||||
}
|
||||
|
||||
private function addPreamble()
|
||||
{
|
||||
$this->mergedContent = $this->getPreamble() . $this->mergedContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
private function shouldCompareExistingVersion()
|
||||
{
|
||||
return $this->isMergedAssetsDisabled();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\AssetManager\UIAssetMerger;
|
||||
|
||||
use Piwik\AssetManager\UIAsset;
|
||||
use Piwik\AssetManager\UIAssetCacheBuster;
|
||||
use Piwik\AssetManager\UIAssetFetcher\JScriptUIAssetFetcher;
|
||||
use Piwik\AssetManager\UIAssetMerger;
|
||||
use Piwik\AssetManager;
|
||||
use Piwik\AssetManager\UIAssetMinifier;
|
||||
use Piwik\Piwik;
|
||||
|
||||
class JScriptUIAssetMerger extends UIAssetMerger
|
||||
{
|
||||
/**
|
||||
* @var UIAssetMinifier
|
||||
*/
|
||||
private $assetMinifier;
|
||||
|
||||
/**
|
||||
* @param UIAsset $mergedAsset
|
||||
* @param JScriptUIAssetFetcher $assetFetcher
|
||||
* @param UIAssetCacheBuster $cacheBuster
|
||||
*/
|
||||
function __construct($mergedAsset, $assetFetcher, $cacheBuster)
|
||||
{
|
||||
parent::__construct($mergedAsset, $assetFetcher, $cacheBuster);
|
||||
|
||||
$this->assetMinifier = UIAssetMinifier::getInstance();
|
||||
}
|
||||
|
||||
protected function getMergedAssets()
|
||||
{
|
||||
$concatenatedAssets = $this->getConcatenatedAssets();
|
||||
|
||||
return str_replace("\n", "\r\n", $concatenatedAssets);
|
||||
}
|
||||
|
||||
protected function generateCacheBuster()
|
||||
{
|
||||
$cacheBuster = $this->cacheBuster->piwikVersionBasedCacheBuster($this->getPlugins());
|
||||
return "/* Piwik Javascript - cb=" . $cacheBuster . "*/\r\n";
|
||||
}
|
||||
|
||||
protected function getPreamble()
|
||||
{
|
||||
return $this->getCacheBusterValue();
|
||||
}
|
||||
|
||||
protected function postEvent(&$mergedContent)
|
||||
{
|
||||
$plugins = $this->getPlugins();
|
||||
|
||||
if(!empty($plugins)) {
|
||||
|
||||
/**
|
||||
* Triggered after all the JavaScript files Piwik uses are minified and merged into a
|
||||
* single file, but before the merged JavaScript is written to disk.
|
||||
*
|
||||
* Plugins can use this event to modify merged JavaScript or do something else
|
||||
* with it.
|
||||
*
|
||||
* @param string $mergedContent The minified and merged JavaScript.
|
||||
*/
|
||||
Piwik::postEvent('AssetManager.filterMergedJavaScripts', array(&$mergedContent), null, $plugins);
|
||||
}
|
||||
}
|
||||
|
||||
public function getFileSeparator()
|
||||
{
|
||||
return PHP_EOL;
|
||||
}
|
||||
|
||||
protected function processFileContent($uiAsset)
|
||||
{
|
||||
$content = $uiAsset->getContent();
|
||||
|
||||
if (!$this->assetMinifier->isMinifiedJs($content))
|
||||
$content = $this->assetMinifier->minifyJs($content);
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\AssetManager\UIAssetMerger;
|
||||
|
||||
use Exception;
|
||||
use Piwik\AssetManager\UIAsset;
|
||||
use Piwik\AssetManager\UIAssetMerger;
|
||||
use Piwik\Piwik;
|
||||
use lessc;
|
||||
|
||||
class StylesheetUIAssetMerger extends UIAssetMerger
|
||||
{
|
||||
/**
|
||||
* @var lessc
|
||||
*/
|
||||
private $lessCompiler;
|
||||
|
||||
function __construct($mergedAsset, $assetFetcher, $cacheBuster)
|
||||
{
|
||||
parent::__construct($mergedAsset, $assetFetcher, $cacheBuster);
|
||||
|
||||
$this->lessCompiler = self::getLessCompiler();
|
||||
}
|
||||
|
||||
protected function getMergedAssets()
|
||||
{
|
||||
foreach($this->getAssetCatalog()->getAssets() as $uiAsset) {
|
||||
|
||||
$content = $uiAsset->getContent();
|
||||
if (false !== strpos($content, '@import')) {
|
||||
$this->lessCompiler->addImportDir(dirname($uiAsset->getAbsoluteLocation()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $this->lessCompiler->compile($this->getConcatenatedAssets());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return lessc
|
||||
* @throws Exception
|
||||
*/
|
||||
private static function getLessCompiler()
|
||||
{
|
||||
if (!class_exists("lessc")) {
|
||||
throw new Exception("Less was added to composer during 2.0. ==> Execute this command to update composer packages: \$ php composer.phar install");
|
||||
}
|
||||
$less = new lessc();
|
||||
return $less;
|
||||
}
|
||||
|
||||
protected function generateCacheBuster()
|
||||
{
|
||||
$fileHash = $this->cacheBuster->md5BasedCacheBuster($this->getConcatenatedAssets());
|
||||
return "/* compile_me_once=$fileHash */";
|
||||
}
|
||||
|
||||
protected function getPreamble()
|
||||
{
|
||||
return $this->getCacheBusterValue() . "\n"
|
||||
. "/* Piwik CSS file is compiled with Less. You may be interested in writing a custom Theme for Piwik! */\n";
|
||||
}
|
||||
|
||||
protected function postEvent(&$mergedContent)
|
||||
{
|
||||
/**
|
||||
* Triggered after all less stylesheets are compiled to CSS, minified and merged into
|
||||
* one file, but before the generated CSS is written to disk.
|
||||
*
|
||||
* This event can be used to modify merged CSS.
|
||||
*
|
||||
* @param string $mergedContent The merged and minified CSS.
|
||||
*/
|
||||
Piwik::postEvent('AssetManager.filterMergedStylesheets', array(&$mergedContent));
|
||||
}
|
||||
|
||||
public function getFileSeparator()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
protected function processFileContent($uiAsset)
|
||||
{
|
||||
return $this->rewriteCssPathsDirectives($uiAsset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrite css url directives
|
||||
* - rewrites paths defined relatively to their css/less definition file
|
||||
* - rewrite windows directory separator \\ to /
|
||||
*
|
||||
* @param UIAsset $uiAsset
|
||||
* @return string
|
||||
*/
|
||||
private function rewriteCssPathsDirectives($uiAsset)
|
||||
{
|
||||
static $rootDirectoryLength = null;
|
||||
if (is_null($rootDirectoryLength)) {
|
||||
$rootDirectoryLength = self::countDirectoriesInPathToRoot($uiAsset);
|
||||
}
|
||||
|
||||
$baseDirectory = dirname($uiAsset->getRelativeLocation());
|
||||
$content = preg_replace_callback(
|
||||
"/(url\(['\"]?)([^'\")]*)/",
|
||||
function ($matches) use ($rootDirectoryLength, $baseDirectory) {
|
||||
|
||||
$absolutePath = realpath(PIWIK_USER_PATH . "/$baseDirectory/" . $matches[2]);
|
||||
|
||||
if($absolutePath) {
|
||||
|
||||
$relativePath = substr($absolutePath, $rootDirectoryLength);
|
||||
|
||||
$relativePath = str_replace('\\', '/', $relativePath);
|
||||
|
||||
return $matches[1] . $relativePath;
|
||||
|
||||
} else {
|
||||
return $matches[1] . $matches[2];
|
||||
}
|
||||
},
|
||||
$uiAsset->getContent()
|
||||
);
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UIAsset $uiAsset
|
||||
* @return int
|
||||
*/
|
||||
protected function countDirectoriesInPathToRoot($uiAsset)
|
||||
{
|
||||
$rootDirectory = realpath($uiAsset->getBaseDirectory());
|
||||
|
||||
if ($rootDirectory != PATH_SEPARATOR
|
||||
&& substr_compare($rootDirectory, PATH_SEPARATOR, -1)) {
|
||||
$rootDirectory .= PATH_SEPARATOR;
|
||||
}
|
||||
$rootDirectoryLen = strlen($rootDirectory);
|
||||
return $rootDirectoryLen;
|
||||
}
|
||||
}
|
||||
66
www/analytics/core/AssetManager/UIAssetMinifier.php
Normal file
66
www/analytics/core/AssetManager/UIAssetMinifier.php
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
* @method static \Piwik\AssetManager\UIAssetMinifier getInstance()
|
||||
*/
|
||||
namespace Piwik\AssetManager;
|
||||
|
||||
use Exception;
|
||||
use Piwik\Singleton;
|
||||
use JShrink\Minifier;
|
||||
|
||||
class UIAssetMinifier extends Singleton
|
||||
{
|
||||
const MINIFIED_JS_RATIO = 100;
|
||||
|
||||
protected function __construct()
|
||||
{
|
||||
self::validateDependency();
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indicates if the provided JavaScript content has already been minified or not.
|
||||
* The heuristic is based on a custom ratio : (size of file) / (number of lines).
|
||||
* The threshold (100) has been found empirically on existing files :
|
||||
* - the ratio never exceeds 50 for non-minified content and
|
||||
* - it never goes under 150 for minified content.
|
||||
*
|
||||
* @param string $content Contents of the JavaScript file
|
||||
* @return boolean
|
||||
*/
|
||||
public function isMinifiedJs($content)
|
||||
{
|
||||
$lineCount = substr_count($content, "\n");
|
||||
if ($lineCount == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$contentSize = strlen($content);
|
||||
|
||||
$ratio = $contentSize / $lineCount;
|
||||
|
||||
return $ratio > self::MINIFIED_JS_RATIO;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
public function minifyJs($content)
|
||||
{
|
||||
return Minifier::minify($content);
|
||||
}
|
||||
|
||||
private static function validateDependency()
|
||||
{
|
||||
if (!class_exists("JShrink\\Minifier"))
|
||||
throw new Exception("JShrink could not be found, maybe you are using Piwik from git and need to have update Composer. <br>php composer.phar update");
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue