| <?php |
|
|
| |
| |
| |
| |
| |
| |
|
|
| namespace Piwik\Plugin\Dimension; |
|
|
| use Piwik\CacheId; |
| use Piwik\Cache as PiwikCache; |
| use Piwik\Columns\Dimension; |
| use Piwik\Common; |
| use Piwik\DataTable; |
| use Piwik\Db; |
| use Piwik\DbHelper; |
| use Piwik\Plugin\Manager as PluginManager; |
| use Piwik\Tracker\Request; |
| use Piwik\Tracker\Visitor; |
| use Piwik\Tracker\Action; |
| use Piwik\Plugin; |
| use Exception; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| abstract class VisitDimension extends Dimension |
| { |
| public const INSTALLER_PREFIX = 'log_visit.'; |
|
|
| protected $dbTableName = 'log_visit'; |
| protected $category = 'General_Visitors'; |
|
|
| public function install() |
| { |
| if (empty($this->columnType) || empty($this->columnName)) { |
| return array(); |
| } |
|
|
| $changes = array( |
| $this->dbTableName => array("ADD COLUMN `$this->columnName` $this->columnType"), |
| ); |
|
|
| if ($this->isHandlingLogConversion()) { |
| $changes['log_conversion'] = array("ADD COLUMN `$this->columnName` $this->columnType"); |
| } |
|
|
| return $changes; |
| } |
|
|
| |
| |
| |
| |
| |
| public function update() |
| { |
| if (!$this->columnType) { |
| return array(); |
| } |
|
|
| $conversionColumns = DbHelper::getTableColumns(Common::prefixTable('log_conversion')); |
|
|
| $changes = array(); |
|
|
| $changes[$this->dbTableName] = array("MODIFY COLUMN `$this->columnName` $this->columnType"); |
|
|
| $handlingConversion = $this->isHandlingLogConversion(); |
| $hasConversionColumn = array_key_exists($this->columnName, $conversionColumns); |
|
|
| if ($hasConversionColumn && $handlingConversion) { |
| $changes['log_conversion'] = array("MODIFY COLUMN `$this->columnName` $this->columnType"); |
| } elseif (!$hasConversionColumn && $handlingConversion) { |
| $changes['log_conversion'] = array("ADD COLUMN `$this->columnName` $this->columnType"); |
| } elseif ($hasConversionColumn && !$handlingConversion) { |
| $changes['log_conversion'] = array("DROP COLUMN `$this->columnName`"); |
| } |
|
|
| return $changes; |
| } |
|
|
| |
| |
| |
| |
| public function getVersion() |
| { |
| return $this->columnType . $this->isHandlingLogConversion(); |
| } |
|
|
| private function isHandlingLogConversion() |
| { |
| if (empty($this->columnName) || empty($this->columnType)) { |
| return false; |
| } |
|
|
| return $this->hasImplementedEvent('onAnyGoalConversion'); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| public function uninstall() |
| { |
| if (empty($this->columnName) || empty($this->columnType)) { |
| return; |
| } |
|
|
| try { |
| $sql = "ALTER TABLE `" . Common::prefixTable($this->dbTableName) . "` DROP COLUMN `$this->columnName`"; |
| Db::exec($sql); |
| } catch (Exception $e) { |
| if (!Db::get()->isErrNo($e, '1091')) { |
| throw $e; |
| } |
| } |
|
|
| try { |
| if (!$this->isHandlingLogConversion()) { |
| return; |
| } |
|
|
| $sql = "ALTER TABLE `" . Common::prefixTable('log_conversion') . "` DROP COLUMN `$this->columnName`"; |
| Db::exec($sql); |
| } catch (Exception $e) { |
| if (!Db::get()->isErrNo($e, '1091')) { |
| throw $e; |
| } |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| public function getRequiredVisitFields() |
| { |
| return array(); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function onNewVisit(Request $request, Visitor $visitor, $action) |
| { |
| return false; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function onExistingVisit(Request $request, Visitor $visitor, $action) |
| { |
| return false; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function onConvertedVisit(Request $request, Visitor $visitor, $action) |
| { |
| return false; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function onAnyGoalConversion(Request $request, Visitor $visitor, $action) |
| { |
| return false; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function shouldForceNewVisit(Request $request, Visitor $visitor, ?Action $action = null) |
| { |
| return false; |
| } |
|
|
| |
| |
| |
| |
| public static function getAllDimensions() |
| { |
| $cacheId = CacheId::pluginAware('VisitDimensions'); |
| $cache = PiwikCache::getTransientCache(); |
|
|
| if (!$cache->contains($cacheId)) { |
| $plugins = PluginManager::getInstance()->getPluginsLoadedAndActivated(); |
| $instances = array(); |
|
|
| foreach ($plugins as $plugin) { |
| foreach (self::getDimensions($plugin) as $instance) { |
| $instances[] = $instance; |
| } |
| } |
|
|
| $instances = self::sortDimensions($instances); |
|
|
| $cache->save($cacheId, $instances); |
| } |
|
|
| return $cache->fetch($cacheId); |
| } |
|
|
| |
| |
| |
| |
| public static function sortDimensions($dimensions) |
| { |
| $sorted = array(); |
| $exists = array(); |
|
|
| |
| foreach ($dimensions as $index => $dimension) { |
| $fields = $dimension->getRequiredVisitFields(); |
| if (empty($fields)) { |
| $sorted[] = $dimension; |
| $exists[] = $dimension->getColumnName(); |
| unset($dimensions[$index]); |
| } |
| } |
|
|
| |
| |
| $dependencies = array(); |
| foreach ($dimensions as $dimension) { |
| $dependencies[$dimension->getColumnName()] = $dimension->getRequiredVisitFields(); |
| } |
|
|
| foreach ($dependencies as $column => $fields) { |
| foreach ($fields as $key => $field) { |
| if (empty($dependencies[$field]) && !in_array($field, $exists)) { |
| |
| unset($dependencies[$column][$key]); |
| } elseif (!empty($dependencies[$field]) && in_array($column, $dependencies[$field])) { |
| throw new Exception("Circular reference detected for required field $field in dimension $column"); |
| } |
| } |
| } |
|
|
| $count = 0; |
| while (count($dimensions) > 0) { |
| $count++; |
| if ($count > 1000) { |
| foreach ($dimensions as $dimension) { |
| $sorted[] = $dimension; |
| } |
| break; |
| } |
| foreach ($dimensions as $key => $dimension) { |
| $fields = $dependencies[$dimension->getColumnName()]; |
| if (count(array_intersect($fields, $exists)) === count($fields)) { |
| $sorted[] = $dimension; |
| $exists[] = $dimension->getColumnName(); |
| unset($dimensions[$key]); |
| } |
| } |
| } |
|
|
| return $sorted; |
| } |
|
|
| |
| |
| |
| |
| |
| public static function getDimensions(Plugin $plugin) |
| { |
| $dimensions = $plugin->findMultipleComponents('Columns', '\\Piwik\\Plugin\\Dimension\\VisitDimension'); |
| $instances = array(); |
|
|
| foreach ($dimensions as $dimension) { |
| $instances[] = new $dimension(); |
| } |
|
|
| return $instances; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function sortStaticListByUsage(array $array, DataTable $table, string $keyColumn, int $maxValuesToReturn): array |
| { |
| |
| foreach ($array as $k => $v) { |
| $array[$k] = ['count' => 0, 'name' => $v]; |
| } |
| $array['xx'] = ['count' => 0, 'name' => 'Unknown']; |
|
|
| foreach ($table->getRows() as $row) { |
| if (isset($row[$keyColumn])) { |
| if (isset($array[$row[$keyColumn]])) { |
| $array[$row[$keyColumn]]['count']++; |
| } else { |
| $array['xx']['count']++; |
| } |
| } |
| } |
| |
| uasort($array, function ($a, $b) { |
| return $a <=> $b; |
| }); |
| $array = array_reverse($array, true); |
|
|
| |
| $flat = []; |
| $i = 0; |
| foreach ($array as $k => $v) { |
| $flat[$k] = $v['name']; |
| $i++; |
| if ($i == ($maxValuesToReturn)) { |
| break; |
| } |
| } |
|
|
| return array_values($flat); |
| } |
| } |
|
|