/**
  * @group Plugins
  */
 public function test_AddAndGet_AnotherSegment()
 {
     $name = 'name';
     $definition = 'searches>1,visitIp!=127.0.0.1';
     $idSegment = API::getInstance()->add($name, $definition, $idSite = 1, $autoArchive = 1, $enabledAllUsers = 1);
     $this->assertEquals($idSegment, 1);
     // Testing get()
     $segment = API::getInstance()->get($idSegment);
     $expected = array('idsegment' => '1', 'name' => $name, 'definition' => $definition, 'login' => 'superUserLogin', 'enable_all_users' => '1', 'enable_only_idsite' => '1', 'auto_archive' => '1', 'ts_last_edit' => null, 'deleted' => '0');
     unset($segment['ts_created']);
     $this->assertEquals($segment, $expected);
     // There is a segment to process for this particular site
     $model = Factory::getModel('Piwik\\Plugins\\SegmentEditor');
     $segments = $model->getSegmentsToAutoArchive($idSite);
     unset($segments[0]['ts_created']);
     $this->assertEquals($segments, array($expected));
     // There is no segment to process for a non existing site
     try {
         $model->getSegmentsToAutoArchive(33);
         $this->fail();
     } catch (Exception $e) {
         // expected
     }
     // There is no segment to process across all sites
     $segments = $model->getSegmentsToAutoArchive($idSite = false);
     $this->assertEquals($segments, array());
 }
Beispiel #2
0
    public function test_makeLogVisitsQueryString_whenSegment()
    {
        $model = Factory::getModel('Piwik\\Plugins\\Live');
        list($sql, $bind) = $model->makeLogVisitsQueryString($idSite = 1, $period = 'month', $date = '2010-01-01', $segment = 'customVariablePageName1==Test', $offset = 0, $limit = 100, $visitorId = 'abc', $minTimestamp = false, $filterSortOrder = false);
        $expectedSql = ' SELECT sub.* FROM
                (

                    SELECT log_inner.*
                    FROM (
                        SELECT log_visit.*
                        FROM ' . Common::prefixTable('log_visit') . ' AS log_visit
                          LEFT JOIN ' . Common::prefixTable('log_link_visit_action') . ' AS log_link_visit_action
                          ON log_link_visit_action.idvisit = log_visit.idvisit
                        WHERE ( log_visit.idsite in (?)
                          AND log_visit.idvisitor = ?
                          AND log_visit.visit_last_action_time >= ?
                          AND log_visit.visit_last_action_time <= ? )
                          AND ( log_link_visit_action.custom_var_k1 = ? )
                        ORDER BY idsite, visit_last_action_time DESC
                        LIMIT 100
                        ) AS log_inner
                    ORDER BY idsite, visit_last_action_time DESC
                    LIMIT 100
                 ) AS sub
                 GROUP BY sub.idvisit
                 ORDER BY sub.visit_last_action_time DESC
        ';
        $expectedBind = array('1', Common::hex2bin('abc'), '2010-01-01 00:00:00', '2010-02-01 00:00:00', 'Test');
        $this->assertEquals(SegmentTest::removeExtraWhiteSpaces($expectedSql), SegmentTest::removeExtraWhiteSpaces($sql));
        $this->assertEquals(SegmentTest::removeExtraWhiteSpaces($expectedBind), SegmentTest::removeExtraWhiteSpaces($bind));
    }
Beispiel #3
0
 public function insertAll($rows)
 {
     $generic = Factory::getGeneric();
     $rowsSql = array();
     foreach ($rows as $row) {
         $values = array();
         foreach ($row as $name => $value) {
             if (is_null($value)) {
                 $values[] = 'NULL';
             } else {
                 if (is_numeric($value)) {
                     $values[] = $value;
                 } else {
                     if (!ctype_print($value)) {
                         $values[] = $generic->bin2dbRawInsert($value);
                     } else {
                         if (is_bool($value)) {
                             $values[] = $value ? '1' : '0';
                         } else {
                             $values[] = "'{$value}'";
                         }
                     }
                 }
             }
         }
         $rowsSql[] = "(" . implode(',', $values) . ")";
     }
     $sql = 'INSERT INTO ' . $this->table . ' VALUES ' . implode(',', $rowsSql);
     $this->db->query($sql);
 }
Beispiel #4
0
 /**
  * @param array $config
  */
 public function __construct($config)
 {
     $this->config = $config;
     $this->maxLifetime = ini_get('session.gc_maxlifetime');
     $this->model = Factory::getModel(__NAMESPACE__);
     $this->model->setConfig($config);
 }
 /**
  *  uses tracker db
  */
 public function insertNew($goal)
 {
     $Generic = Factory::getGeneric($this->db);
     // pg is throwing error when empty values are given for 'FLOAT' columns
     if (empty($goal['revenue'])) {
         unset($goal['revenue']);
     }
     if (empty($goal['revenue_subtotal'])) {
         unset($goal['revenue_subtotal']);
     }
     if (empty($goal['revenue_tax'])) {
         unset($goal['revenue_tax']);
     }
     if (empty($goal['revenue_shipping'])) {
         unset($goal['revenue_shipping']);
     }
     if (empty($goal['revenue_discount'])) {
         unset($goal['revenue_discount']);
     }
     $fields = implode(', ', array_keys($goal));
     $bindFields = Common::getSqlStringFieldsArray($goal);
     $goal['idvisitor'] = $Generic->bin2db($goal['idvisitor']);
     $sql = 'INSERT INTO ' . $this->table . '( ' . $fields . ' ) ' . 'VALUES ( ' . $bindFields . ' ) ';
     $bind = array_values($goal);
     $result = $Generic->insertIgnore($sql, $bind);
     return $result;
 }
Beispiel #6
0
 public function purgeUnused($dimensionMetadataProvider)
 {
     $this->dimensionMetadataProvider = $dimensionMetadataProvider;
     // get current max visit ID in log tables w/ idaction references.
     $maxIds = $this->getMaxIdsInLogTables();
     $this->generic = Factory::getGeneric($this->db);
     $this->createTempTable();
     // do large insert (inserting everything before maxIds) w/o locking tables...
     $this->insertActionsToKeep($maxIds, $deleteOlderThanMax = true);
     // ... then do small insert w/ locked tables to minimize the amount of time tables are locked.
     $this->generic->beginTransaction();
     $this->lockLogTables($this->generic);
     $this->insertActionsToKeep($maxIds, $deleteOlderThanMax = false);
     // Mysql uses 'INSERT IGNORE' which is not available on pgsql 9.1.
     // We can do the generic->insertIgnore, but checking for exception for every
     // single query can be a time taking endeavour. To avoid, 'INSERT's are
     // carried on normally. Before deleting unused actions, we will remove
     // duplicate rows from the temporary table.
     $this->deleteDuplicatesFromTempTable();
     // delete before unlocking tables so there's no chance a new log row that references an
     // unused action will be inserted.
     $this->deleteUnusedActions();
     // unlock the log tables. In pgsql, locks are released on commit/rollback
     $this->generic->commit();
     $this->generic = null;
 }
 public function updateConversions($values, $idvisit)
 {
     $Generic = Factory::getGeneric($this->db);
     $binary_columns = array('idvisitor');
     foreach ($binary_columns as $bc) {
         if (array_key_exists($bc, $values)) {
             $values[$bc] = $Generic->bin2db($values[$bc]);
         }
     }
     $updateParts = $sqlBind = array();
     foreach ($values as $name => $value) {
         // Case where bind parameters don't work
         if (strpos($value, $name) !== false) {
             //$name = 'visit_total_events'
             //$value = 'visit_total_events + 1';
             $updateParts[] = " {$name} = {$value} ";
         } else {
             $updateParts[] = $name . " = ?";
             $sqlBind[] = $value;
         }
     }
     array_push($sqlBind, $idvisit);
     $sql = 'UPDATE ' . $this->table . ' SET ' . implode(', ', $updateParts) . ' ' . 'WHERE idvisit = ?';
     $result = $this->db->query($sql, $sqlBind);
 }
 public function __construct($processNewSegmentsFrom, Model $segmentEditorModel = null, Cache $segmentListCache = null, Date $now = null, LoggerInterface $logger = null)
 {
     $this->processNewSegmentsFrom = $processNewSegmentsFrom;
     $this->segmentEditorModel = $segmentEditorModel ?: Factory::getModel('Piwik\\Plugins\\SegmentEditor');
     $this->segmentListCache = $segmentListCache ?: new Transient();
     $this->now = $now ?: Date::factory('now');
     $this->logger = $logger ?: StaticContainer::get('Psr\\Log\\LoggerInterface');
 }
 public function getCronArchiveTokenAuth(&$tokens)
 {
     $model = Factory::getModel(__NAMESPACE__);
     $superUsers = $model->getUsersHavingSuperUserAccess();
     foreach ($superUsers as $superUser) {
         $tokens[] = $superUser['token_auth'];
     }
 }
 /**
  * Constructor.
  *
  * @param ArchiveInvalidator $invalidator
  * @param DuplicateActionRemover $duplicateActionRemover
  * @param Actions $actionsAccess
  * @param LoggerInterface $logger
  */
 public function __construct(ArchiveInvalidator $invalidator = null, DuplicateActionRemover $duplicateActionRemover = null, Actions $actionsAccess = null, LoggerInterface $logger = null)
 {
     parent::__construct();
     $this->archiveInvalidator = $invalidator ?: new ArchiveInvalidator();
     $this->duplicateActionRemover = $duplicateActionRemover ?: Factory::getModel('Piwik\\Plugins\\CoreAdminHome\\Model', 'DuplicateActionRemover');
     $this->actionsAccess = $actionsAccess ?: new Actions();
     $this->logger = $logger ?: StaticContainer::get('Psr\\Log\\LoggerInterface');
 }
Beispiel #11
0
 protected function loadSettings()
 {
     $SiteSetting = Factory::getDAO('site_setting');
     $settings = $SiteSetting->getByIdsite($this->idSite);
     $flat = array();
     foreach ($settings as $setting) {
         $flat[$setting['setting_name']] = unserialize($setting['setting_value']);
     }
     return $flat;
 }
Beispiel #12
0
 /**
  * Performs a batch insert into a specific table by iterating through the data
  *
  * NOTE: you should use tableInsertBatch() which will fallback to this function if LOAD DATA INFILE not available
  *
  * @param string $tableName PREFIXED table name! you must call Common::prefixTable() before passing the table name
  * @param array $fields array of unquoted field names
  * @param array $values array of data to be inserted
  * @param bool $ignoreWhenDuplicate Ignore new rows that contain unique key values that duplicate old rows
  */
 public static function tableInsertBatchIterate($tableName, $fields, $values, $ignoreWhenDuplicate = true)
 {
     $isArchive = strpos($tableName, 'archive');
     if ($isArchive === false) {
         $Generic = Factory::getGeneric();
         $Generic->insertIgnoreBatch($tableName, $fields, $values, $ignoreWhenDuplicate);
     } else {
         // archive_blob_* tables need special handling for the "value" column
         $Archive = Factory::getDAO('archive');
         $Archive->insertIgnoreBatch($tableName, $fields, $values, $ignoreWhenDuplicate);
     }
 }
Beispiel #13
0
 function __construct($processor)
 {
     parent::__construct($processor);
     if ($processor->getParams()->getSite()->isEcommerceEnabled()) {
         $this->maximumRowsInDataTableLevelZero = self::MAX_ROWS_WHEN_ECOMMERCE;
         $this->maximumRowsInSubDataTable = self::MAX_ROWS_WHEN_ECOMMERCE;
     } else {
         $this->maximumRowsInDataTableLevelZero = Config::getInstance()->General['datatable_archiving_maximum_rows_custom_variables'];
         $this->maximumRowsInSubDataTable = Config::getInstance()->General['datatable_archiving_maximum_rows_subtable_custom_variables'];
     }
     $this->Generic = Factory::getGeneric();
 }
Beispiel #14
0
 protected function invalidatedArchiveIdRows($archiveTable, $idSites)
 {
     $sql = "SELECT idsite, date1, date2, period, name,\n                       STRING_AGG(idarchive || '.' || value, ','  ORDER BY ts_archived DESC) as archives\n                  FROM {$archiveTable}\n                 WHERE name LIKE 'done%'\n                   AND value IN (" . ArchiveWriter::DONE_INVALIDATED . ',' . ArchiveWriter::DONE_OK . ',' . ArchiveWriter::DONE_OK_TEMPORARY . ")\n                   AND idsite IN (" . implode(',', $idSites) . ")\n                 GROUP BY idsite, date1, date2, period, name";
     $rows = $this->db->fetchAll($sql);
     if ($this->isBlob($archiveTable)) {
         $Generic = Factory::getGeneric();
         foreach ($rows as &$row) {
             $parts = explode('.', $row['archives']);
             $row['archives'] = $parts[0] . '.' . $Generic->db2bin($parts[1]);
         }
     }
     return $rows;
 }
 public function __construct(Model $model = null, Date $purgeCustomRangesOlderThan = null, LoggerInterface $logger = null)
 {
     # Overriding the $model object injected by the DI container.
     # DI Container injects the Model class irrespective of the database used
     # (Mysql or Pgsql). Also, it doesn't set the Db object on the Model
     # class.
     $this->model = Factory::getModel('Piwik\\DataAccess');
     $this->purgeCustomRangesOlderThan = $purgeCustomRangesOlderThan ?: self::getDefaultCustomRangeToPurgeAgeThreshold();
     $this->yesterday = Date::factory('yesterday');
     $this->today = Date::factory('today');
     $this->now = time();
     $this->logger = $logger ?: StaticContainer::get('Psr\\Log\\LoggerInterface');
 }
 /**
  * Records the layout in the DB for the given user.
  *
  * @param string $login
  * @param int $idDashboard
  * @param string $layout
  */
 public function saveLayout($login, $idDashboard, $layout)
 {
     $generic = Factory::getGeneric($this->db);
     $sql = 'SELECT * FROM ' . $this->table . ' ' . 'WHERE login = ? AND iddashboard = ? FOR UPDATE';
     $row = $this->db->query($sql, array($login, $idDashboard));
     if ($row) {
         $sql = 'UPDATE ' . $this->table . ' SET ' . ' layout = ? ' . 'WHERE login = ? AND iddashboard = ?';
         $bind = array($layout, $login, $idDashboard);
     } else {
         $sql = 'INSERT INTO ' . $this->table . '(login, iddashboard, layout) ' . 'VALUES (?, ?, ?)';
         $bind = array($login, $idDashboard, $layout);
     }
     $this->db->query($sql, $bind);
 }
Beispiel #17
0
 public function getAllSiteUrls()
 {
     $model = Factory::getModel(__NAMESPACE__);
     $siteIds = $model->getSitesId();
     $siteUrls = array();
     if (empty($siteIds)) {
         return array();
     }
     foreach ($siteIds as $siteId) {
         $siteId = (int) $siteId;
         $siteUrls[$siteId] = $model->getSiteUrlsFromId($siteId);
     }
     return $siteUrls;
 }
 public function setForUser($login, $languageCode)
 {
     $generic = Factory::getGeneric($this->db);
     $generic->beginTransaction();
     $sql = 'SELECT login, language FROM ' . $this->table . ' ' . 'WHERE login = ?';
     $row = $this->db->fetchRow($sql, array($login));
     if ($row) {
         $sql = 'UPDATE ' . $this->table . ' SET ' . ' language = ? ' . 'WHERE login = ?';
         $this->db->query($sql, array($languageCode, $login));
     } else {
         $this->db->insert($this->table, array('login' => $login, 'language' => $languageCode));
     }
     $generic->commit();
 }
 public function setUp()
 {
     parent::setUp();
     \Piwik\Plugin\Manager::getInstance()->loadPlugin('UsersManager');
     \Piwik\Plugin\Manager::getInstance()->installLoadedPlugins();
     // setup the access layer
     FakeAccess::setIdSitesView(array(1, 2));
     FakeAccess::setIdSitesAdmin(array(3, 4));
     //finally we set the user as a Super User by default
     FakeAccess::$superUser = true;
     FakeAccess::$superUserLogin = '******';
     $this->api = API::getInstance();
     $this->model = Factory::getModel('Piwik\\Plugins\\UsersManager');
 }
 public function fetchAll()
 {
     $generic = Factory::getGeneric();
     $generic->checkByteaOutput();
     $sql = 'SELECT *, idvisitor::text AS idvisitor_text FROM ' . $this->table;
     $rows = $this->db->fetchAll($sql);
     while (list($k, $row) = each($rows)) {
         if (!empty($row['idvisitor'])) {
             $rows[$k]['idvisitor'] = $generic->db2bin($row['idvisitor_text']);
         }
         unset($rows[$k]['idvisitor_text']);
     }
     reset($rows);
     return $rows;
 }
Beispiel #21
0
 /**
  * Get / allocate / reserve a new id for the current sequence. Important: Getting the next id will fail in case
  * no such sequence exists. Make sure to create one if needed, see {@link create()}.
  *
  * @return int
  * @throws Exception
  */
 public function getNextId()
 {
     $Generic = Factory::getGeneric($this->db);
     $Generic->beginTransaction();
     $sql = 'UPDATE ' . $this->table . ' SET value = value + 1 WHERE name = ?';
     $result = $this->db->query($sql, array($this->name));
     $rowCount = $result->rowCount();
     if (1 !== $rowCount) {
         $Generic->rollback();
         throw new \Exception("Sequence '" . $this->name . "' not found.");
     }
     $createdId = $this->getCurrentId();
     $Generic->commit();
     return (int) $createdId;
 }
Beispiel #22
0
 public function upsert($idSite, $settingName, $settingValue)
 {
     $Generic = Factory::getGeneric();
     $Generic->beginTransaction();
     $sql = "SELECT * FROM {$this->table} WHERE idsite = ? AND setting_name = ? FOR UPDATE";
     $row = $this->db->fetchOne($sql, array($idSite, $settingName));
     if ($row) {
         $sql = "UPDATE {$this->table} SET\n                    setting_value = ?\n                    WHERE idsite = ? AND setting_name = ?";
         $this->db->query($sql, array($settingValue, $idSite, $settingName));
     } else {
         $sql = "INSERT INTO {$this->table} (idsite, setting_name, setting_value) VALUES (?, ?, ?)";
         $this->db->query($sql, array($idSite, $settingName, $settingValue));
     }
     $Generic->commit();
 }
 /**
  *  recordProfiling
  *
  *  Makes an entry in the table for the query if query does not exist.
  *  If the query exists, the row will be update.
  *  The query column has a unique key.
  *  Uses tracker db
  *  @param string $query
  *  @param int    $count
  *  @param string $time
  *  @return void
  */
 public function recordProfiling($query, $count, $time)
 {
     $generic = Factory::getGeneric($this->db);
     $generic->beginTransaction();
     $sql = 'SELECT query, count, sum_time_ms ' . 'FROM ' . $this->table . ' ' . 'WHERE query = ? FOR UPDATE';
     $row = $this->db->fetchOne($sql, array($query));
     if ($row) {
         $sql = 'UPDATE ' . $this->table . ' SET ' . " count = count + {$count}, sum_time_ms = sum_time_msg + {$time} " . 'WHERE query = ?';
         $this->db->query($sql, array($query));
     } else {
         $sql = 'INSERT INTO ' . $this->table . '(query, count, sum_time_ms) ' . "VALUES (?, ?, ?)";
         $this->db->query($sql, array($query, $count, $time));
     }
     $generic->commit();
 }
Beispiel #24
0
 public function addRecord($name, $value, $autoload)
 {
     $generic = Factory::getGeneric($this->db);
     $generic->beginTransaction();
     $sql = 'SELECT * FROM ' . $this->table . ' WHERE option_name = ?';
     $row = $this->db->fetchOne($sql, array($name));
     if ($row) {
         $sql = 'UPDATE ' . $this->table . ' SET option_value = ? ' . 'WHERE option_name = ?';
         $bind = array($value, $name);
     } else {
         $sql = 'INSERT INTO ' . $this->table . ' (option_name, option_value, autoload) ' . 'VALUES (?, ?, ?) ';
         $bind = array($name, $value, $autoload);
     }
     $this->db->query($sql, $bind);
     $generic->commit();
 }
Beispiel #25
0
 public function createConversion($conversion)
 {
     $fields = implode(", ", array_keys($conversion));
     $bindFields = Common::getSqlStringFieldsArray($conversion);
     $table = Common::prefixTable('log_conversion');
     $db = $this->getDb();
     $Generic = Factory::getGeneric($db);
     $sql = "INSERT INTO {$table} ({$fields}) VALUES ({$bindFields}) ";
     if (!empty($conversion['idvisitor'])) {
         $conversion['idvisitor'] = $Generic->bin2db($conversion['idvisitor']);
     }
     $bind = array_values($conversion);
     $result = $Generic->insertIgnore($sql, $bind);
     // If a record was inserted, we return true
     return $db->rowCount($result) > 0;
 }
Beispiel #26
0
 private function getFirstTypeIfOnlyOneIsInUse()
 {
     $types = $this->typeManager->getAllTypes();
     if (count($types) === 1) {
         // only one type is in use, use this one for the wording
         return reset($types);
     } else {
         // multiple types are activated, check whether only one is actually in use
         $model = Factory::getModel(__NAMESPACE__);
         $typeIds = $model->getUsedTypeIds();
         if (count($typeIds) === 1) {
             $typeManager = new TypeManager();
             return $typeManager->getType(reset($typeIds));
         }
     }
 }
Beispiel #27
0
 /**
  * Sets the language for the user
  *
  * @param string $login
  * @param string $languageCode
  * @return bool
  */
 public function setLanguageForUser($login, $languageCode)
 {
     $Generic = Factory::getGeneric();
     $Generic->beginTransaction();
     $sql = 'SELECT * FROM ' . $this->table . ' WHERE login = ? FOR UPDATE';
     $row = $this->db->query($sql, array($login));
     if ($row) {
         $sql = 'UPDATE ' . $this->table . ' SET language = ? WHERE login = ?';
         $bind = array($languageCode, $login);
     } else {
         $sql = 'INSERT INTO ' . $this->table . ' (login, language) VALUES (?, ?)';
         $bind = array($login, $languageCode);
     }
     $this->db->query($sql, $bind);
     $Generic->commit();
     return true;
 }
Beispiel #28
0
 /**
  * Write Session - commit data to resource
  *
  * @param string $id
  * @param mixed $data
  * @param integer $maxLifetime
  * @return boolean
  */
 public function write($id, $data, $maxLifetime)
 {
     $Generic = Factory::getGeneric();
     $sql = 'SELECT ' . $this->config['dataColumn'] . ' FROM ' . $this->config['name'] . ' WHERE ' . $this->config['primary'] . ' = ? FOR UPDATE';
     $Generic->beginTransaction();
     $row = $this->db->fetchOne($sql, array($id));
     if ($row) {
         $sql = 'UPDATE ' . $this->config['name'] . ' SET ' . $this->config['modifiedColumn'] . ' = ?,' . $this->config['lifetimeColumn'] . ' = ?,' . $this->config['dataColumn'] . ' = ? ' . ' WHERE ' . $this->config['primary'] . ' = ?';
         $values = array(time(), $maxLifetime, $data, $id);
     } else {
         $sql = 'INSERT INTO ' . $this->config['name'] . ' (' . $this->config['primary'] . ',' . $this->config['modifiedColumn'] . ',' . $this->config['lifetimeColumn'] . ',' . $this->config['dataColumn'] . ')' . ' VALUES (?,?,?,?)';
         $values = array($id, time(), $maxLifetime, $data);
     }
     $this->db->query($sql, $values);
     $Generic->commit();
     return true;
 }
Beispiel #29
0
function prepareTestDatabaseConfig(Config $config)
{
    $testDb = $config->database_tests;
    Factory::setTest(true);
    if ('@USERNAME@' !== $testDb['username']) {
        return;
        // testDb is already configured, we do not want to overwrite any existing settings.
    }
    $db = $config->database;
    $testDb['username'] = $db['username'];
    if (empty($testDb['password'])) {
        $testDb['password'] = $db['password'];
    }
    if (empty($testDb['host'])) {
        $testDb['host'] = $db['host'];
    }
    $testDb['tables_prefix'] = '';
    // tables_prefix has to be empty for UI tests
    $config->database_tests = $testDb;
    $config->forceSave();
}
 protected function paramsRecord($idvisit, $idsite, $idvisitor, $server_time, $url, $name, $ref_url, $ref_name, $time_spent, $custom_value, $custom_variables, $actionIdsCached)
 {
     $Generic = Factory::getGeneric($this->db);
     $insert = array('idvisit' => $idvisit, 'idsite' => $idsite, 'idvisitor' => $Generic->bin2db($idvisitor), 'server_time' => $server_time, 'idaction_url' => $url, 'idaction_name' => $name, 'idaction_url_ref' => $ref_url, 'idaction_name_ref' => $ref_name, 'time_spent_ref_action' => $time_spent);
     $integerCols = array('idsite', 'idvisit', 'idaction_url', 'idaction_url_ref', 'idaction_name', 'idaction_name_ref', 'idaction_event_category', 'idaction_event_action', 'time_spent_ref_action');
     foreach ($actionIdsCached as $field => $idAction) {
         if (in_array($field, $integerCols) && is_bool($idAction)) {
             $insert[$field] = (int) $idAction;
         } else {
             $insert[$field] = $idAction;
         }
     }
     if (!empty($custom_value)) {
         $insert[Action::DB_COLUMN_CUSTOM_FLOAT] = $custom_value;
     }
     $insert = array_merge($insert, $custom_variables);
     $fields = implode(', ', array_keys($insert));
     $bind = array_values($insert);
     $values = Common::getSqlStringFieldsArray($insert);
     $sql = 'INSERT INTO ' . $this->table . '( ' . $fields . ') VALUES ( ' . $values . ')';
     return array($sql, $bind, $insert);
 }