| <?php |
|
|
| |
| |
| |
| |
| |
| |
|
|
| namespace Piwik\Tracker; |
|
|
| use Piwik\Common; |
| use Piwik\Segment\SegmentExpression; |
|
|
| |
| |
| |
| |
| |
| |
| |
| class TableLogAction |
| { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public static function loadIdsAction($actionsNameAndType) |
| { |
| |
| foreach ($actionsNameAndType as &$action) { |
| if (2 == count($action)) { |
| $action[] = null; |
| } |
| } |
|
|
| $actionIds = self::queryIdsAction($actionsNameAndType); |
|
|
| [$queriedIds, $fieldNamesToInsert] = self::processIdsToInsert($actionsNameAndType, $actionIds); |
|
|
| $insertedIds = self::insertNewIdsAction($actionsNameAndType, $fieldNamesToInsert); |
| $queriedIds = $queriedIds + $insertedIds; |
|
|
| return $queriedIds; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| private static function getSelectQueryWhereNameContains($matchType, $actionType) |
| { |
| |
| |
| $sql = 'SELECT idaction FROM `' . Common::prefixTable('log_action') . '` WHERE %s AND type = ' . $actionType . ' )'; |
|
|
| switch ($matchType) { |
| case SegmentExpression::MATCH_CONTAINS: |
| |
| $where = '( name LIKE CONCAT(\'%\', ?, \'%\') '; |
| break; |
| case SegmentExpression::MATCH_DOES_NOT_CONTAIN: |
| $where = '( name NOT LIKE CONCAT(\'%\', ?, \'%\') '; |
| break; |
| case SegmentExpression::MATCH_STARTS_WITH: |
| |
| $where = '( name LIKE CONCAT(?, \'%\') '; |
| break; |
| case SegmentExpression::MATCH_ENDS_WITH: |
| |
| $where = '( name LIKE CONCAT(\'%\', ?) '; |
| break; |
| default: |
| throw new \Exception("This match type $matchType is not available for action-segments."); |
| break; |
| } |
|
|
| $sql = sprintf($sql, $where); |
|
|
| return $sql; |
| } |
|
|
| private static function insertNewIdsAction($actionsNameAndType, $fieldNamesToInsert) |
| { |
| |
| $inserted = array(); |
|
|
| foreach ($fieldNamesToInsert as $fieldName) { |
| [$name, $type, $urlPrefix] = $actionsNameAndType[$fieldName]; |
|
|
| $actionId = self::getModel()->createNewIdAction($name, $type, $urlPrefix); |
|
|
| Common::printDebug("Recorded a new action (" . Action::getTypeAsString($type) . ") in the lookup table: " . $name . " (idaction = " . $actionId . ")"); |
|
|
| $inserted[$fieldName] = $actionId; |
| } |
|
|
| return $inserted; |
| } |
|
|
| private static function getModel() |
| { |
| return new Model(); |
| } |
|
|
| private static function queryIdsAction($actionsNameAndType) |
| { |
| $toQuery = array(); |
| foreach ($actionsNameAndType as &$actionNameType) { |
| [$name, $type, $urlPrefix] = $actionNameType; |
| $toQuery[] = array('name' => $name, 'type' => $type); |
| } |
|
|
| $actionIds = self::getModel()->getIdsAction($toQuery); |
|
|
| return $actionIds; |
| } |
|
|
| private static function processIdsToInsert($actionsNameAndType, $actionIds) |
| { |
| |
| |
| $fieldNamesToInsert = $fieldNameToActionId = array(); |
|
|
| foreach ($actionsNameAndType as $fieldName => &$actionNameType) { |
| @list($name, $type, $urlPrefix) = $actionNameType; |
| if (empty($name)) { |
| $fieldNameToActionId[$fieldName] = false; |
| continue; |
| } |
|
|
| $found = false; |
| foreach ($actionIds as $row) { |
| if ( |
| $name == $row['name'] |
| && $type == $row['type'] |
| ) { |
| $found = true; |
|
|
| $fieldNameToActionId[$fieldName] = $row['idaction']; |
| continue; |
| } |
| } |
| if (!$found) { |
| $fieldNamesToInsert[] = $fieldName; |
| } |
| } |
|
|
| return array($fieldNameToActionId, $fieldNamesToInsert); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public static function getIdActionFromSegment($valueToMatch, $sqlField, $matchType, $segmentName) |
| { |
| if ($segmentName === 'actionType') { |
| $actionType = (int) $valueToMatch; |
| $valueToMatch = array(); |
| $sql = 'SELECT idaction FROM `' . Common::prefixTable('log_action') . '` WHERE type = ' . $actionType . ' )'; |
| } else { |
| $actionType = self::guessActionTypeFromSegment($segmentName); |
| $valueToMatch = self::removeProtocolIfSegmentStoredWithoutIt($valueToMatch, $actionType, $segmentName); |
|
|
| $unsanitizedValue = $valueToMatch; |
| $valueToMatch = self::normaliseActionString($actionType, $valueToMatch); |
| if ( |
| $matchType == SegmentExpression::MATCH_EQUAL |
| || $matchType == SegmentExpression::MATCH_NOT_EQUAL |
| ) { |
| $idAction = self::getModel()->getIdActionMatchingNameAndType($valueToMatch, $actionType); |
| |
| |
| if (empty($idAction)) { |
| $idAction = self::getModel()->getIdActionMatchingNameAndType($unsanitizedValue, $actionType); |
| |
| if (empty($idAction)) { |
| $idAction = null; |
| } |
| } |
| return $idAction; |
| } |
|
|
| |
| |
| $sql = self::getSelectQueryWhereNameContains($matchType, $actionType); |
| } |
|
|
| return array( |
| |
| 'SQL' => $sql, |
| 'bind' => $valueToMatch, |
| ); |
| } |
|
|
| |
| |
| |
| |
| |
| private static function guessActionTypeFromSegment($segmentName) |
| { |
| $exactMatch = array( |
| 'outlinkUrl' => Action::TYPE_OUTLINK, |
| 'downloadUrl' => Action::TYPE_DOWNLOAD, |
| 'eventUrl' => Action::TYPE_EVENT, |
| 'eventAction' => Action::TYPE_EVENT_ACTION, |
| 'eventCategory' => Action::TYPE_EVENT_CATEGORY, |
| 'eventName' => Action::TYPE_EVENT_NAME, |
| 'contentPiece' => Action::TYPE_CONTENT_PIECE, |
| 'contentTarget' => Action::TYPE_CONTENT_TARGET, |
| 'contentName' => Action::TYPE_CONTENT_NAME, |
| 'contentInteraction' => Action::TYPE_CONTENT_INTERACTION, |
| 'productName' => Action::TYPE_ECOMMERCE_ITEM_NAME, |
| 'productSku' => Action::TYPE_ECOMMERCE_ITEM_SKU, |
| 'productViewName' => Action::TYPE_ECOMMERCE_ITEM_NAME, |
| 'productViewSku' => Action::TYPE_ECOMMERCE_ITEM_SKU, |
| ); |
|
|
| if (!empty($exactMatch[$segmentName])) { |
| return $exactMatch[$segmentName]; |
| } |
|
|
| if (stripos($segmentName, 'pageurl') !== false) { |
| return Action::TYPE_PAGE_URL; |
| } elseif (stripos($segmentName, 'pagetitle') !== false) { |
| return Action::TYPE_PAGE_TITLE; |
| } elseif (stripos($segmentName, 'sitesearch') !== false) { |
| return Action::TYPE_SITE_SEARCH; |
| } elseif ( |
| stripos($segmentName, 'productcategory') !== false |
| || stripos($segmentName, 'productviewcategory') !== false |
| ) { |
| return Action::TYPE_ECOMMERCE_ITEM_CATEGORY; |
| } else { |
| throw new \Exception("We cannot guess the action type from the segment $segmentName."); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| private static function normaliseActionString($actionType, $actionString) |
| { |
| $actionString = Common::unsanitizeInputValue($actionString); |
|
|
| if (self::isActionTypeStoredUnsanitized($actionType)) { |
| return $actionString; |
| } |
|
|
| return Common::sanitizeInputValue($actionString); |
| } |
|
|
| |
| |
| |
| |
| private static function isActionTypeStoredUnsanitized($actionType) |
| { |
| $actionsTypesStoredUnsanitized = array( |
| Action::TYPE_DOWNLOAD, |
| Action::TYPE_OUTLINK, |
| Action::TYPE_PAGE_URL, |
| Action::TYPE_CONTENT, |
| ); |
|
|
| return in_array($actionType, $actionsTypesStoredUnsanitized); |
| } |
|
|
| public static function removeProtocolIfSegmentStoredWithoutIt($url, $actionType, $segmentName) |
| { |
| if ($actionType == Action::TYPE_PAGE_URL || $segmentName == 'eventUrl') { |
| |
| $url = preg_replace('@^http[s]?://(www\.)?@i', '', $url); |
| } |
| return $url; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public static function getOptimizedIdActionSqlMatch($value, $sqlField, $matchType, $segmentName) |
| { |
| if ($matchType == SegmentExpression::MATCH_EQUAL || $matchType == SegmentExpression::MATCH_NOT_EQUAL) { |
| $result = self::getIdActionFromSegment($value, $sqlField, $matchType, $segmentName); |
|
|
| if (is_numeric($result)) { |
| return ['value' => $result, 'joinTable' => false]; |
| } |
|
|
| return $result; |
| } |
|
|
| $actionType = self::guessActionTypeFromSegment($segmentName); |
| $value = self::removeProtocolIfSegmentStoredWithoutIt($value, $actionType, $segmentName); |
|
|
| return $value; |
| } |
| } |
|
|