/** * Convert segment expression to an action ID or an SQL expression. * * This method is used as a sqlFilter-callback for the segments of this plugin. * Usually, these callbacks only return a value that should be compared to the * column in the database. In this case, that doesn't work since multiple IDs * can match an expression (e.g. "pageUrl=@foo"). * @param string $valueToMatch * @param string $sqlField * @param string $matchType * @param string $segmentName * @throws \Exception * @return array|int|string */ public static function getIdActionFromSegment($valueToMatch, $sqlField, $matchType, $segmentName) { $actionType = self::guessActionTypeFromSegment($segmentName); if ($actionType == Action::TYPE_PAGE_URL) { // for urls trim protocol and www because it is not recorded in the db $valueToMatch = preg_replace('@^http[s]?://(www\\.)?@i', '', $valueToMatch); } $valueToMatch = self::normaliseActionString($actionType, $valueToMatch); if ($matchType == SegmentExpression::MATCH_EQUAL || $matchType == SegmentExpression::MATCH_NOT_EQUAL) { $idAction = self::getModel()->getIdActionMatchingNameAndType($valueToMatch, $actionType); // Action is not found (eg. &segment=pageTitle==Větrnásssssss) if (empty($idAction)) { $idAction = null; } return $idAction; } // "name contains $string" match can match several idaction so we cannot return yet an idaction // special case $sql = TableLogAction::getSelectQueryWhereNameContains($matchType, $actionType); return array('SQL' => $sql, 'bind' => $valueToMatch); }
/** * Derive the action ID from the request action name and type. */ private function deriveIdAction($actionName, $actionType) { switch ($actionType) { case 'url': $originalActionName = $actionName; $actionName = Common::unsanitizeInputValue($actionName); $id = TableLogAction::getIdActionFromSegment($actionName, 'idaction_url', SegmentExpression::MATCH_EQUAL, 'pageUrl'); if ($id < 0) { // an example where this is needed is urls containing < or > $actionName = $originalActionName; $id = TableLogAction::getIdActionFromSegment($actionName, 'idaction_url', SegmentExpression::MATCH_EQUAL, 'pageUrl'); } return $id; case 'title': $id = TableLogAction::getIdActionFromSegment($actionName, 'idaction_name', SegmentExpression::MATCH_EQUAL, 'pageTitle'); if ($id < 0) { $unknown = ArchivingHelper::getUnknownActionName(Action::TYPE_PAGE_TITLE); if (trim($actionName) == trim($unknown)) { $id = TableLogAction::getIdActionFromSegment('', 'idaction_name', SegmentExpression::MATCH_EQUAL, 'pageTitle'); } } return $id; default: throw new Exception('Unknown action type'); } }
/** * Convert segment expression to an action ID or an SQL expression. * * This method is used as a sqlFilter-callback for the segments of this plugin. * Usually, these callbacks only return a value that should be compared to the * column in the database. In this case, that doesn't work since multiple IDs * can match an expression (e.g. "pageUrl=@foo"). * @param string $valueToMatch * @param string $sqlField * @param string $matchType * @param string $segmentName * @throws \Exception * @return array|int|string */ public static function getIdActionFromSegment($valueToMatch, $sqlField, $matchType, $segmentName) { $actionType = self::guessActionTypeFromSegment($segmentName); if ($actionType == Action::TYPE_PAGE_URL) { // for urls trim protocol and www because it is not recorded in the db $valueToMatch = preg_replace('@^http[s]?://(www\\.)?@i', '', $valueToMatch); } $valueToMatch = Common::sanitizeInputValue(Common::unsanitizeInputValue($valueToMatch)); if ($matchType == SegmentExpression::MATCH_EQUAL || $matchType == SegmentExpression::MATCH_NOT_EQUAL) { $idAction = self::getIdActionMatchingNameAndType($valueToMatch, $actionType); // if the action is not found, we hack -100 to ensure it tries to match against an integer // otherwise binding idaction_name to "false" returns some rows for some reasons (in case &segment=pageTitle==Větrnásssssss) if (empty($idAction)) { $idAction = -100; } return $idAction; } // "name contains $string" match can match several idaction so we cannot return yet an idaction // special case $sql = TableLogAction::getSelectQueryWhereNameContains($matchType, $actionType); return array('SQL' => $sql, 'bind' => $valueToMatch); }
/** * Reads items from the request, then looks up the names from the lookup table * and returns a clean array of items ready for the database. * * @param array $items * @return array $cleanedItems */ private function getCleanedEcommerceItems($items) { // Clean up the items array $cleanedItems = array(); foreach ($items as $item) { $name = $category = $category2 = $category3 = $category4 = $category5 = false; $price = 0; $quantity = 1; // items are passed in the request as an array: ( $sku, $name, $category, $price, $quantity ) if (empty($item[self::INDEX_ITEM_SKU])) { continue; } $sku = $item[self::INDEX_ITEM_SKU]; if (!empty($item[self::INDEX_ITEM_NAME])) { $name = $item[self::INDEX_ITEM_NAME]; } if (!empty($item[self::INDEX_ITEM_CATEGORY])) { $category = $item[self::INDEX_ITEM_CATEGORY]; } if (isset($item[self::INDEX_ITEM_PRICE]) && is_numeric($item[self::INDEX_ITEM_PRICE])) { $price = $this->getRevenue($item[self::INDEX_ITEM_PRICE]); } if (!empty($item[self::INDEX_ITEM_QUANTITY]) && is_numeric($item[self::INDEX_ITEM_QUANTITY])) { $quantity = (int) $item[self::INDEX_ITEM_QUANTITY]; } // self::INDEX_ITEM_* are in order $cleanedItems[] = array(self::INTERNAL_ITEM_SKU => $sku, self::INTERNAL_ITEM_NAME => $name, self::INTERNAL_ITEM_CATEGORY => $category, self::INTERNAL_ITEM_CATEGORY2 => $category2, self::INTERNAL_ITEM_CATEGORY3 => $category3, self::INTERNAL_ITEM_CATEGORY4 => $category4, self::INTERNAL_ITEM_CATEGORY5 => $category5, self::INTERNAL_ITEM_PRICE => $price, self::INTERNAL_ITEM_QUANTITY => $quantity); } // Lookup Item SKUs, Names & Categories Ids $actionsToLookupAllItems = array(); // Each item has 7 potential "ids" to lookup in the lookup table $columnsInEachRow = 1 + 1 + self::MAXIMUM_PRODUCT_CATEGORIES; foreach ($cleanedItems as $item) { $actionsToLookup = array(); list($sku, $name, $category, $price, $quantity) = $item; $actionsToLookup[] = array(trim($sku), Action::TYPE_ECOMMERCE_ITEM_SKU); $actionsToLookup[] = array(trim($name), Action::TYPE_ECOMMERCE_ITEM_NAME); // Only one category if (!is_array($category)) { $actionsToLookup[] = array(trim($category), Action::TYPE_ECOMMERCE_ITEM_CATEGORY); } else { $countCategories = 0; foreach ($category as $productCategory) { $productCategory = trim($productCategory); if (empty($productCategory)) { continue; } $countCategories++; if ($countCategories > self::MAXIMUM_PRODUCT_CATEGORIES) { break; } $actionsToLookup[] = array($productCategory, Action::TYPE_ECOMMERCE_ITEM_CATEGORY); } } // Ensure that each row has the same number of columns, fill in the blanks for ($i = count($actionsToLookup); $i < $columnsInEachRow; $i++) { $actionsToLookup[] = array(false, Action::TYPE_ECOMMERCE_ITEM_CATEGORY); } $actionsToLookupAllItems = array_merge($actionsToLookupAllItems, $actionsToLookup); } $actionsLookedUp = TableLogAction::loadIdsAction($actionsToLookupAllItems); // Replace SKU, name & category by their ID action foreach ($cleanedItems as $index => &$item) { // SKU $item[0] = $actionsLookedUp[$index * $columnsInEachRow + 0]; // Name $item[1] = $actionsLookedUp[$index * $columnsInEachRow + 1]; // Categories $item[2] = $actionsLookedUp[$index * $columnsInEachRow + 2]; $item[3] = $actionsLookedUp[$index * $columnsInEachRow + 3]; $item[4] = $actionsLookedUp[$index * $columnsInEachRow + 4]; $item[5] = $actionsLookedUp[$index * $columnsInEachRow + 5]; $item[6] = $actionsLookedUp[$index * $columnsInEachRow + 6]; } return $cleanedItems; }
/** * @param $pageUrlFoundInDb * @return string * @throws Exception */ private function insertPageUrlAsAction($pageUrlFoundInDb) { TableLogAction::loadIdsAction(array('idaction_url' => array($pageUrlFoundInDb, Action::TYPE_PAGE_URL))); $actionIdFoundInDb = Db::fetchOne("SELECT idaction from " . Common::prefixTable('log_action') . " WHERE name = ?", $pageUrlFoundInDb); $this->assertNotEmpty($actionIdFoundInDb, "Action {$pageUrlFoundInDb} was not found in the " . Common::prefixTable('log_action') . " table."); return $actionIdFoundInDb; }
/** * Loads the idaction of the current action name and the current action url. * These idactions are used in the visitor logging table to link the visit information * (entry action, exit action) to the actions. * These idactions are also used in the table that links the visits and their actions. * * The methods takes care of creating a new record(s) in the action table if the existing * action name and action url doesn't exist yet. */ public function loadIdsFromLogActionTable() { if (!empty($this->actionIdsCached)) { return; } /** @var ActionDimension[] $dimensions */ $dimensions = ActionDimension::getAllDimensions(); $actions = $this->getActionsToLookup(); foreach ($dimensions as $dimension) { $value = $dimension->onLookupAction($this->request, $this); if (false !== $value) { if (is_float($value)) { $value = Common::forceDotAsSeparatorForDecimalPoint($value); } $field = $dimension->getColumnName(); if (empty($field)) { $dimensionClass = get_class($dimension); throw new Exception('Dimension ' . $dimensionClass . ' does not define a field name'); } $actionId = $dimension->getActionId(); $actions[$field] = array($value, $actionId); Common::printDebug("{$field} = {$value}"); } } $actions = array_filter($actions, 'count'); if (empty($actions)) { return; } $loadedActionIds = TableLogAction::loadIdsAction($actions); $this->actionIdsCached = $loadedActionIds; return $this->actionIdsCached; }
/** * Loads the idaction of the current action name and the current action url. * These idactions are used in the visitor logging table to link the visit information * (entry action, exit action) to the actions. * These idactions are also used in the table that links the visits and their actions. * * The methods takes care of creating a new record(s) in the action table if the existing * action name and action url doesn't exist yet. */ public function loadIdsFromLogActionTable() { if (!empty($this->actionIdsCached)) { return; } $actions = $this->getActionsToLookup(); $actions = array_filter($actions, 'count'); if (empty($actions)) { return; } $loadedActionIds = TableLogAction::loadIdsAction($actions); $this->actionIdsCached = $loadedActionIds; return $this->actionIdsCached; }
/** * Loads the idaction of the current action name and the current action url. * These idactions are used in the visitor logging table to link the visit information * (entry action, exit action) to the actions. * These idactions are also used in the table that links the visits and their actions. * * The methods takes care of creating a new record(s) in the action table if the existing * action name and action url doesn't exist yet. */ public function loadIdsFromLogActionTable() { if (!empty($this->actionIdsCached)) { return; } $actions = $this->getActionsToLookup(); $dimensions = ActionDimension::getAllDimensions(); foreach ($dimensions as $dimension) { $value = $dimension->onLookupAction($this->request, $this); if ($value !== false) { $field = $dimension->getColumnName(); if (empty($field)) { throw new Exception('Dimension ' . get_class($dimension) . ' does not define a field name'); } $actions[$field] = array($value, $dimension->getActionId()); Common::printDebug("{$field} = {$value}"); } } $actions = array_filter($actions, 'count'); if (empty($actions)) { return; } $loadedActionIds = TableLogAction::loadIdsAction($actions); $this->actionIdsCached = $loadedActionIds; return $this->actionIdsCached; }