diff --git a/core/DataTable.php b/core/DataTable.php index 023735212a9325b6c0fc6814cb6f8b8f09b14960..0c44b924e720d88e1a619e0b0e22a84e1a13f7c2 100644 --- a/core/DataTable.php +++ b/core/DataTable.php @@ -450,6 +450,25 @@ class Piwik_DataTable return $this->rows[$this->rowsIndexByLabel[$label]]; } + /** + * Returns a Piwik_DataTable that has only the one column that matches $label. + * If no matches are found, an empty data table is returned. + * + * @param string $label Value of the column 'label' to search for + * @return Piwik_DataTable + */ + public function getFilteredTableFromLabel($label) + { + $newTable = new Piwik_DataTable; + $row = $this->getRowFromLabel($label); + if ($row !== false) + { + $newTable->addRow($row); + $newTable->queuedFilters = $this->queuedFilters; + } + return $newTable; + } + /** * Rebuilds the index used to lookup a row by label */ diff --git a/core/DataTable/Array.php b/core/DataTable/Array.php index bfc7d36591a91091b6ce680dd982107bc7644a60..a32288fadabeec2f351d0309664ecfc5ff1e14e1 100644 --- a/core/DataTable/Array.php +++ b/core/DataTable/Array.php @@ -176,4 +176,26 @@ class Piwik_DataTable_Array $table->deleteColumns($columns); } } + + /** + * Returns a Piwik_DataTable_Array whose sub tables are filtered by $label + * @see Piwik_DataTable::getFilteredTableFromLabel + * + * @param string $label Value of the column 'label' to search for + * @return Piwik_DataTable_Array + */ + public function getFilteredTableFromLabel($label) + { + $newTableArray = new Piwik_DataTable_Array; + $newTableArray->metadata = $this->metadata; + + foreach ($this->array as $subTableLabel => $subTable) + { + $subTable = $subTable->getFilteredTableFromLabel($label); + $newTableArray->addTable($subTable, $subTableLabel); + } + + return $newTableArray; + } + } diff --git a/plugins/Actions/API.php b/plugins/Actions/API.php index 9cceb05915df54e46cf76ae6baf8207b7ab7833b..d028b4026d3f88b098180e163f9f1ca6b290f55f 100644 --- a/plugins/Actions/API.php +++ b/plugins/Actions/API.php @@ -116,69 +116,99 @@ class Piwik_Actions_API * Will search in the DataTable for a Label matching the searched string * and return only the matching row, or an empty datatable */ - protected function getFilterPageDatatableSearch( $callBackParameters, $search, $actionType, $table = false, $searchTree = false, $searchCurrentLevel = 0 ) + protected function getFilterPageDatatableSearch($callBackParameters, $search, $actionType, $table = false, + $searchTree = false) { - if($table === false) - { - $table = call_user_func_array(array('Piwik_Archive', 'getDataTableFromArchive'), $callBackParameters); - } - if($searchTree === false) + if ($searchTree === false) { + // build the query parts that are searched inside the tree if($actionType == Piwik_Tracker_Action::TYPE_ACTION_NAME) { $searchedString = Piwik_Common::unsanitizeInputValue($search); } else { - $searchedString = Piwik_Tracker_Action::excludeQueryParametersFromUrl($search, $idSite = $callBackParameters[1]); + $idSite = $callBackParameters[1]; + $searchedString = Piwik_Tracker_Action::excludeQueryParametersFromUrl($search, $idSite); } $searchTree = Piwik_Actions::getActionExplodedNames($searchedString, $actionType); } - if(!($table instanceof Piwik_DataTable)) - { - throw new Exception("For this API function, date=lastN or date=previousM is not supported"); - } - $rows = $table->getRows(); - $labelSearch = $searchTree[$searchCurrentLevel]; - $isEndSearch = ((count($searchTree)-1) == $searchCurrentLevel); - foreach($rows as $key => $row) + + if ($table === false) { - $found = false; - // Found a match at this level - $label = $row->getColumn('label'); - if($label === $labelSearch) + // fetch the data table + $table = call_user_func_array(array('Piwik_Archive', 'getDataTableFromArchive'), $callBackParameters); + + if ($table instanceof Piwik_DataTable_Array) { - // Is this the end of the search tree? then we found the requested row - if($isEndSearch) - { -// var_dump($label); var_dump($labelSearch); exit; - $table = new Piwik_DataTable(); - $table->addRow($row); - return $table; - } + // search an array of tables, e.g. when using date=last30 + // note that if the root is an array, we filter all children + // if an array occurs inside the nested table, we only look for the first match (see below) + $newTableArray = new Piwik_DataTable_Array; + $newTableArray->metadata = $table->metadata; - // If we still need to search deeper, call search - $idSubTable = $row->getIdSubDataTable(); - // Update the idSubtable in the callback parameter list, to fetch this subtable from the archive - $callBackParameters[6] = $idSubTable; - $subTable = call_user_func_array(array('Piwik_Archive', 'getDataTableFromArchive'), $callBackParameters); - $found = $this->getFilterPageDatatableSearch($callBackParameters, $search, $actionType, $subTable, $searchTree, $searchCurrentLevel+1); - if($found) + foreach ($table->getArray() as $label => $subTable) { - return $found; + $subTable = $this->doFilterPageDatatableSearch($callBackParameters, $subTable, $searchTree); + $newTableArray->addTable($subTable, $label); } + + return $newTableArray; } - if(!$found) + + } + + return $this->doFilterPageDatatableSearch($callBackParameters, $table, $searchTree); + } + + protected function doFilterPageDatatableSearch($callBackParameters, $table, $searchTree) + { + // filter a data table array + if ($table instanceof Piwik_DataTable_Array) + { + foreach ($table->getArray() as $subTable) { - $table->deleteRow($key); + $filteredSubTable = $this->doFilterPageDatatableSearch($callBackParameters, $subTable, $searchTree); + + if ($filteredSubTable->getRowsCount() > 0) + { + // match found in a sub table, return and stop searching the others + return $filteredSubTable; + } } + + // nothing found in all sub tables + return new Piwik_DataTable; } - // Case the DataTable was searched but nothing was found, @see getFilterPageDatatableSearch() - if($searchCurrentLevel == 0) + + // filter regular data table + if ($table instanceof Piwik_DataTable) { - return new Piwik_DataTable; + // search for the first part of the tree search + $search = array_shift($searchTree); + $row = $table->getRowFromLabel($search); + if ($row === false) + { + // not found + return new Piwik_DataTable; + } + + // end of tree search reached + if (count($searchTree) == 0) + { + $table = new Piwik_DataTable(); + $table->addRow($row); + return $table; + } + + // match found on this level and more levels remaining: go deeper + $idSubTable = $row->getIdSubDataTable(); + $callBackParameters[6] = $idSubTable; + $table = call_user_func_array(array('Piwik_Archive', 'getDataTableFromArchive'), $callBackParameters); + return $this->doFilterPageDatatableSearch($callBackParameters, $table, $searchTree); } - return false; + + throw new Exception("For this API function, DataTable ".get_class($table)." is not supported"); } /** diff --git a/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getDownload_day.xml b/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getDownload_day.xml index bb2fba3cf81149f33fc0df8e2c41f2fa05e830ef..1c598ec49c01304a54e4e134599ea15cf14792cb 100644 --- a/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getDownload_day.xml +++ b/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getDownload_day.xml @@ -1,4 +1,10 @@ <?xml version="1.0" encoding="utf-8" ?> -<result> - <error message="For this API function, date=lastN or date=previousM is not supported" /> -</result> \ No newline at end of file +<results> + <result defaultKeyName="2009-01-04" /> + <result defaultKeyName="2009-01-05" /> + <result defaultKeyName="2009-01-06" /> + <result defaultKeyName="2009-01-07" /> + <result defaultKeyName="2009-01-08" /> + <result defaultKeyName="2009-01-09" /> + <result defaultKeyName="2009-01-10" /> +</results> \ No newline at end of file diff --git a/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getDownload_week.xml b/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getDownload_week.xml index bb2fba3cf81149f33fc0df8e2c41f2fa05e830ef..7fd44d3e505ff1c1de2985ffc88e4a796ccf7895 100644 --- a/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getDownload_week.xml +++ b/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getDownload_week.xml @@ -1,4 +1,10 @@ <?xml version="1.0" encoding="utf-8" ?> -<result> - <error message="For this API function, date=lastN or date=previousM is not supported" /> -</result> \ No newline at end of file +<results> + <result defaultKeyName="2008-12-29 to 2009-01-04" /> + <result defaultKeyName="2009-01-05 to 2009-01-11" /> + <result defaultKeyName="2009-01-12 to 2009-01-18" /> + <result defaultKeyName="2009-01-19 to 2009-01-25" /> + <result defaultKeyName="2009-01-26 to 2009-02-01" /> + <result defaultKeyName="2009-02-02 to 2009-02-08" /> + <result defaultKeyName="2009-02-09 to 2009-02-15" /> +</results> \ No newline at end of file diff --git a/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getOutlink_day.xml b/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getOutlink_day.xml index bb2fba3cf81149f33fc0df8e2c41f2fa05e830ef..1c598ec49c01304a54e4e134599ea15cf14792cb 100644 --- a/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getOutlink_day.xml +++ b/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getOutlink_day.xml @@ -1,4 +1,10 @@ <?xml version="1.0" encoding="utf-8" ?> -<result> - <error message="For this API function, date=lastN or date=previousM is not supported" /> -</result> \ No newline at end of file +<results> + <result defaultKeyName="2009-01-04" /> + <result defaultKeyName="2009-01-05" /> + <result defaultKeyName="2009-01-06" /> + <result defaultKeyName="2009-01-07" /> + <result defaultKeyName="2009-01-08" /> + <result defaultKeyName="2009-01-09" /> + <result defaultKeyName="2009-01-10" /> +</results> \ No newline at end of file diff --git a/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getOutlink_week.xml b/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getOutlink_week.xml index bb2fba3cf81149f33fc0df8e2c41f2fa05e830ef..7fd44d3e505ff1c1de2985ffc88e4a796ccf7895 100644 --- a/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getOutlink_week.xml +++ b/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getOutlink_week.xml @@ -1,4 +1,10 @@ <?xml version="1.0" encoding="utf-8" ?> -<result> - <error message="For this API function, date=lastN or date=previousM is not supported" /> -</result> \ No newline at end of file +<results> + <result defaultKeyName="2008-12-29 to 2009-01-04" /> + <result defaultKeyName="2009-01-05 to 2009-01-11" /> + <result defaultKeyName="2009-01-12 to 2009-01-18" /> + <result defaultKeyName="2009-01-19 to 2009-01-25" /> + <result defaultKeyName="2009-01-26 to 2009-02-01" /> + <result defaultKeyName="2009-02-02 to 2009-02-08" /> + <result defaultKeyName="2009-02-09 to 2009-02-15" /> +</results> \ No newline at end of file diff --git a/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getPageTitle_day.xml b/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getPageTitle_day.xml index bb2fba3cf81149f33fc0df8e2c41f2fa05e830ef..1c598ec49c01304a54e4e134599ea15cf14792cb 100644 --- a/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getPageTitle_day.xml +++ b/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getPageTitle_day.xml @@ -1,4 +1,10 @@ <?xml version="1.0" encoding="utf-8" ?> -<result> - <error message="For this API function, date=lastN or date=previousM is not supported" /> -</result> \ No newline at end of file +<results> + <result defaultKeyName="2009-01-04" /> + <result defaultKeyName="2009-01-05" /> + <result defaultKeyName="2009-01-06" /> + <result defaultKeyName="2009-01-07" /> + <result defaultKeyName="2009-01-08" /> + <result defaultKeyName="2009-01-09" /> + <result defaultKeyName="2009-01-10" /> +</results> \ No newline at end of file diff --git a/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getPageTitle_week.xml b/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getPageTitle_week.xml index bb2fba3cf81149f33fc0df8e2c41f2fa05e830ef..7fd44d3e505ff1c1de2985ffc88e4a796ccf7895 100644 --- a/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getPageTitle_week.xml +++ b/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getPageTitle_week.xml @@ -1,4 +1,10 @@ <?xml version="1.0" encoding="utf-8" ?> -<result> - <error message="For this API function, date=lastN or date=previousM is not supported" /> -</result> \ No newline at end of file +<results> + <result defaultKeyName="2008-12-29 to 2009-01-04" /> + <result defaultKeyName="2009-01-05 to 2009-01-11" /> + <result defaultKeyName="2009-01-12 to 2009-01-18" /> + <result defaultKeyName="2009-01-19 to 2009-01-25" /> + <result defaultKeyName="2009-01-26 to 2009-02-01" /> + <result defaultKeyName="2009-02-02 to 2009-02-08" /> + <result defaultKeyName="2009-02-09 to 2009-02-15" /> +</results> \ No newline at end of file diff --git a/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getPageUrl_day.xml b/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getPageUrl_day.xml index bb2fba3cf81149f33fc0df8e2c41f2fa05e830ef..1c598ec49c01304a54e4e134599ea15cf14792cb 100644 --- a/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getPageUrl_day.xml +++ b/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getPageUrl_day.xml @@ -1,4 +1,10 @@ <?xml version="1.0" encoding="utf-8" ?> -<result> - <error message="For this API function, date=lastN or date=previousM is not supported" /> -</result> \ No newline at end of file +<results> + <result defaultKeyName="2009-01-04" /> + <result defaultKeyName="2009-01-05" /> + <result defaultKeyName="2009-01-06" /> + <result defaultKeyName="2009-01-07" /> + <result defaultKeyName="2009-01-08" /> + <result defaultKeyName="2009-01-09" /> + <result defaultKeyName="2009-01-10" /> +</results> \ No newline at end of file diff --git a/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getPageUrl_week.xml b/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getPageUrl_week.xml index bb2fba3cf81149f33fc0df8e2c41f2fa05e830ef..7fd44d3e505ff1c1de2985ffc88e4a796ccf7895 100644 --- a/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getPageUrl_week.xml +++ b/tests/integration/expected/test_noVisit_PeriodIsLast__Actions.getPageUrl_week.xml @@ -1,4 +1,10 @@ <?xml version="1.0" encoding="utf-8" ?> -<result> - <error message="For this API function, date=lastN or date=previousM is not supported" /> -</result> \ No newline at end of file +<results> + <result defaultKeyName="2008-12-29 to 2009-01-04" /> + <result defaultKeyName="2009-01-05 to 2009-01-11" /> + <result defaultKeyName="2009-01-12 to 2009-01-18" /> + <result defaultKeyName="2009-01-19 to 2009-01-25" /> + <result defaultKeyName="2009-01-26 to 2009-02-01" /> + <result defaultKeyName="2009-02-02 to 2009-02-08" /> + <result defaultKeyName="2009-02-09 to 2009-02-15" /> +</results> \ No newline at end of file